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>
259 files changed:
AUTHORS [changed mode: 0644->0755]
COPYING.LGPLv2 [new file with mode: 0644]
Makefile.am
Makefile.plugins [changed mode: 0644->0755]
README [changed mode: 0644->0755]
TODO [changed mode: 0644->0755]
acinclude.m4 [changed mode: 0644->0755]
client/agent.c [changed mode: 0644->0755]
client/agent.h [changed mode: 0644->0755]
client/commands.c [changed mode: 0644->0755]
client/commands.h [changed mode: 0644->0755]
client/dbus_helpers.c
client/dbus_helpers.h
client/input.c [changed mode: 0644->0755]
client/input.h [changed mode: 0644->0755]
client/ins.c [new file with mode: 0755]
client/ins.h [new file with mode: 0755]
client/main.c [changed mode: 0644->0755]
client/mesh.c [new file with mode: 0644]
client/mesh.h [new file with mode: 0644]
client/peers.c [changed mode: 0644->0755]
client/peers.h [changed mode: 0644->0755]
client/services.c [changed mode: 0644->0755]
client/services.h [changed mode: 0644->0755]
client/vpnconnections.c [changed mode: 0644->0755]
client/vpnconnections.h [changed mode: 0644->0755]
configure.ac
connman.manifest [new file with mode: 0644]
connman.pc.in
doc/advanced-configuration.txt [changed mode: 0644->0755]
doc/agent-api.txt [changed mode: 0644->0755]
doc/backtrace.txt [changed mode: 0644->0755]
doc/behavior-api.txt [changed mode: 0644->0755]
doc/clock-api.txt [changed mode: 0644->0755]
doc/config-format.txt [changed mode: 0644->0755]
doc/connman-vpn-provider.config.5.in
doc/connman-vpn.8.in
doc/counter-api.txt [changed mode: 0644->0755]
doc/ipconfig-api.txt [changed mode: 0644->0755]
doc/manager-api.txt [changed mode: 0644->0755]
doc/overview-api.txt [changed mode: 0644->0755]
doc/peer-api.txt [changed mode: 0644->0755]
doc/plugin-api.txt [changed mode: 0644->0755]
doc/service-api.txt [changed mode: 0644->0755]
doc/session-api.txt [changed mode: 0644->0755]
doc/session-overview.txt [changed mode: 0644->0755]
doc/session-policy-format.txt [changed mode: 0644->0755]
doc/technology-api.txt [changed mode: 0644->0755]
doc/vpn-connection-api.txt [changed mode: 0644->0755]
doc/vpn-manager-api.txt [changed mode: 0644->0755]
doc/vpn-overview.txt [changed mode: 0644->0755]
gdbus/client.c [changed mode: 0644->0755]
gdbus/gdbus.h [changed mode: 0644->0755]
gdbus/mainloop.c [changed mode: 0644->0755]
gdbus/object.c [changed mode: 0644->0755]
gdbus/polkit.c [changed mode: 0644->0755]
gdbus/watch.c [changed mode: 0644->0755]
gdhcp/client.c [changed mode: 0644->0755]
gdhcp/common.c [changed mode: 0644->0755]
gdhcp/common.h [changed mode: 0644->0755]
gdhcp/gdhcp.h [changed mode: 0644->0755]
gdhcp/ipv4ll.c [changed mode: 0644->0755]
gdhcp/ipv4ll.h [new file with mode: 0755]
gdhcp/server.c [changed mode: 0644->0755]
gsupplicant/dbus.c [changed mode: 0644->0755]
gsupplicant/dbus.h [changed mode: 0644->0755]
gsupplicant/gsupplicant.h [changed mode: 0644->0755]
gsupplicant/supplicant.c [changed mode: 0644->0755]
gweb/giognutls.c [changed mode: 0644->0755]
gweb/giognutls.h [changed mode: 0644->0755]
gweb/gionotls.c [changed mode: 0644->0755]
gweb/gresolv.c [changed mode: 0644->0755]
gweb/gresolv.h [changed mode: 0644->0755]
gweb/gweb.c [changed mode: 0644->0755]
gweb/gweb.h [changed mode: 0644->0755]
include/agent.h [changed mode: 0644->0755]
include/backtrace.h
include/dbus.h
include/device.h [changed mode: 0644->0755]
include/inet.h
include/inotify.h [changed mode: 0644->0755]
include/ipaddress.h [changed mode: 0644->0755]
include/ipconfig.h [changed mode: 0644->0755]
include/log.h [changed mode: 0644->0755]
include/machine.h [changed mode: 0644->0755]
include/mesh-netlink.h [new file with mode: 0644]
include/mesh.h [new file with mode: 0644]
include/network.h [changed mode: 0644->0755]
include/notifier.h [changed mode: 0644->0755]
include/peer.h [changed mode: 0644->0755]
include/plugin.h [changed mode: 0644->0755]
include/provider.h [changed mode: 0644->0755]
include/provision.h [changed mode: 0644->0755]
include/proxy.h [changed mode: 0644->0755]
include/resolver.h [changed mode: 0644->0755]
include/rtnl.h [changed mode: 0644->0755]
include/service.h [changed mode: 0644->0755]
include/session.h [changed mode: 0644->0755]
include/setting.h [changed mode: 0644->0755]
include/storage.h [changed mode: 0644->0755]
include/task.h [changed mode: 0644->0755]
include/technology.h [changed mode: 0644->0755]
include/timeserver.h [changed mode: 0644->0755]
include/utsname.h [changed mode: 0644->0755]
include/version.h.in [changed mode: 0644->0755]
include/vpn-dbus.h [changed mode: 0644->0755]
packaging/connman.spec [new file with mode: 0644]
plugins/bluetooth.c [changed mode: 0644->0755]
plugins/connman-nmcompat.conf [changed mode: 0644->0755]
plugins/dundee.c [changed mode: 0644->0755]
plugins/ethernet.c
plugins/gadget.c [changed mode: 0644->0755]
plugins/hh2serial-gps.c [changed mode: 0644->0755]
plugins/iospm.c [changed mode: 0644->0755]
plugins/iwd.c
plugins/loopback.c [changed mode: 0644->0755]
plugins/mcc.h [changed mode: 0644->0755]
plugins/neard.c [changed mode: 0644->0755]
plugins/nmcompat.c [changed mode: 0644->0755]
plugins/ofono.c [changed mode: 0644->0755]
plugins/pacrunner.c [changed mode: 0644->0755]
plugins/polkit.c [changed mode: 0644->0755]
plugins/polkit.policy [changed mode: 0644->0755]
plugins/session_policy_local.c [changed mode: 0644->0755]
plugins/telephony.c [new file with mode: 0755]
plugins/tist.c [changed mode: 0644->0755]
plugins/vpn.c [changed mode: 0644->0755]
plugins/wifi.c [changed mode: 0644->0755]
resources/usr/share/dbus-1/system-services/net.connman.service [new file with mode: 0644]
resources/var/lib/connman/settings [new file with mode: 0644]
scripts/connman.in [changed mode: 0644->0755]
scripts/ipsec-script.c [new file with mode: 0755]
scripts/libppp-plugin.c [changed mode: 0644->0755]
scripts/openvpn-script.c [changed mode: 0644->0755]
src/6to4.c [changed mode: 0644->0755]
src/agent-connman.c [changed mode: 0644->0755]
src/agent.c [changed mode: 0644->0755]
src/bridge.c [changed mode: 0644->0755]
src/clock.c [changed mode: 0644->0755]
src/config.c
src/connection.c [changed mode: 0644->0755]
src/connman-dbus.conf [changed mode: 0644->0755]
src/connman-polkit.conf [changed mode: 0644->0755]
src/connman-robot.conf [new file with mode: 0644]
src/connman.conf [new file with mode: 0644]
src/connman.h [changed mode: 0644->0755]
src/connman.service.in [changed mode: 0644->0755]
src/connman.socket [new file with mode: 0644]
src/connman_tv.service.in [new file with mode: 0644]
src/counter.c [changed mode: 0644->0755]
src/dbus.c [changed mode: 0644->0755]
src/detect.c [changed mode: 0644->0755]
src/device.c [changed mode: 0644->0755]
src/dhcp.c
src/dhcpv6.c [changed mode: 0644->0755]
src/dnsproxy.c [changed mode: 0644->0755]
src/eduroam.config [changed mode: 0644->0755]
src/error.c
src/inet.c
src/inotify.c [changed mode: 0644->0755]
src/ipaddress.c [changed mode: 0644->0755]
src/ipconfig.c [changed mode: 0644->0755]
src/ippool.c [changed mode: 0644->0755]
src/iptables.c [changed mode: 0644->0755]
src/ipv6pd.c [changed mode: 0644->0755]
src/log.c [changed mode: 0644->0755]
src/machine.c [changed mode: 0644->0755]
src/main.c [changed mode: 0644->0755]
src/main.conf [changed mode: 0644->0755]
src/main_disable_eth.conf [new file with mode: 0755]
src/main_ivi.conf [new file with mode: 0755]
src/main_tv.conf [new file with mode: 0755]
src/manager.c [changed mode: 0644->0755]
src/mesh-netlink.c [new file with mode: 0644]
src/mesh.c [new file with mode: 0644]
src/nat.c [changed mode: 0644->0755]
src/net.connman.service.in [changed mode: 0644->0755]
src/network.c [changed mode: 0644->0755]
src/notifier.c
src/ntp.c [changed mode: 0644->0755]
src/peer.c [changed mode: 0644->0755]
src/peer_service.c [changed mode: 0644->0755]
src/plugin.c [changed mode: 0644->0755]
src/provider.c [changed mode: 0644->0755]
src/proxy.c [changed mode: 0644->0755]
src/resolver.c [changed mode: 0644->0755]
src/rfkill.c [changed mode: 0644->0755]
src/rtnl.c
src/service.c [changed mode: 0644->0755]
src/session.c
src/shared/arp.h [changed mode: 0644->0755]
src/shared/util.c [changed mode: 0644->0755]
src/shared/util.h [changed mode: 0644->0755]
src/stats.c [changed mode: 0644->0755]
src/storage.c [changed mode: 0644->0755]
src/task.c [changed mode: 0644->0755]
src/technology.c
src/tethering.c [changed mode: 0644->0755]
src/timeserver.c [changed mode: 0644->0755]
src/timezone.c [changed mode: 0644->0755]
src/util.c [changed mode: 0644->0755]
src/utsname.c [changed mode: 0644->0755]
src/wispr.c [changed mode: 0644->0755]
src/wpad.c [changed mode: 0644->0755]
tools/dbus-test.c [changed mode: 0644->0755]
tools/dhcp-server-test.c [changed mode: 0644->0755]
tools/dhcp-test.c [changed mode: 0644->0755]
tools/dnsproxy-test.c [changed mode: 0644->0755]
tools/iptables-test.c [changed mode: 0644->0755]
tools/iptables-unit.c [changed mode: 0644->0755]
tools/manager-api.c [changed mode: 0644->0755]
tools/polkit-test.c [changed mode: 0644->0755]
tools/private-network-test.c [changed mode: 0644->0755]
tools/resolv-test.c [changed mode: 0644->0755]
tools/session-api.c [changed mode: 0644->0755]
tools/session-test.c [changed mode: 0644->0755]
tools/session-test.h [changed mode: 0644->0755]
tools/session-utils.c [changed mode: 0644->0755]
tools/stats-tool.c [changed mode: 0644->0755]
tools/supplicant-dbus.c [changed mode: 0644->0755]
tools/supplicant-dbus.h [changed mode: 0644->0755]
tools/supplicant-test.c [changed mode: 0644->0755]
tools/supplicant.c [changed mode: 0644->0755]
tools/supplicant.h [changed mode: 0644->0755]
tools/tap-test.c [changed mode: 0644->0755]
tools/web-test.c [changed mode: 0644->0755]
tools/wispr.c [changed mode: 0644->0755]
tools/wpad-test.c [changed mode: 0644->0755]
unit/test-ippool.c [changed mode: 0644->0755]
vpn/connman-task.te [changed mode: 0644->0755]
vpn/connman-vpn.service.in [changed mode: 0644->0755]
vpn/main.c [changed mode: 0644->0755]
vpn/net.connman.vpn.service.in [changed mode: 0644->0755]
vpn/plugins/ipsec.c [new file with mode: 0644]
vpn/plugins/ipsec.h [new file with mode: 0644]
vpn/plugins/l2tp.c [changed mode: 0644->0755]
vpn/plugins/openconnect.c [changed mode: 0644->0755]
vpn/plugins/openvpn.c [changed mode: 0644->0755]
vpn/plugins/pptp.c [changed mode: 0644->0755]
vpn/plugins/vici-client.c [new file with mode: 0644]
vpn/plugins/vici-client.h [new file with mode: 0644]
vpn/plugins/vpn.c [changed mode: 0644->0755]
vpn/plugins/vpn.h [changed mode: 0644->0755]
vpn/plugins/vpnc.c [changed mode: 0644->0755]
vpn/plugins/wireguard.c
vpn/vpn-agent.c [changed mode: 0644->0755]
vpn/vpn-agent.h [changed mode: 0644->0755]
vpn/vpn-config.c [changed mode: 0644->0755]
vpn/vpn-dbus.conf [changed mode: 0644->0755]
vpn/vpn-ipconfig.c [changed mode: 0644->0755]
vpn/vpn-manager.c [changed mode: 0644->0755]
vpn/vpn-polkit.conf [changed mode: 0644->0755]
vpn/vpn-polkit.policy [changed mode: 0644->0755]
vpn/vpn-provider.c [changed mode: 0644->0755]
vpn/vpn-provider.h [changed mode: 0644->0755]
vpn/vpn-rtnl.c [changed mode: 0644->0755]
vpn/vpn-rtnl.h [changed mode: 0644->0755]
vpn/vpn.h [changed mode: 0644->0755]
vpn/vpn.ver [changed mode: 0644->0755]

diff --git a/AUTHORS b/AUTHORS
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/COPYING.LGPLv2 b/COPYING.LGPLv2
new file mode 100644 (file)
index 0000000..4362b49
--- /dev/null
@@ -0,0 +1,502 @@
+                  GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL.  It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+  This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it.  You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+  When we speak of free software, we are referring to freedom of use,
+not price.  Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+  To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights.  These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+  For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you.  You must make sure that they, too, receive or can get the source
+code.  If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it.  And you must show them these terms so they know their rights.
+
+  We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+  To protect each distributor, we want to make it very clear that
+there is no warranty for the free library.  Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+  Finally, software patents pose a constant threat to the existence of
+any free program.  We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder.  Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+  Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License.  This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License.  We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+  When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library.  The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom.  The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+  We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License.  It also provides other free software developers Less
+of an advantage over competing non-free programs.  These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries.  However, the Lesser license provides advantages in certain
+special circumstances.
+
+  For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard.  To achieve this, non-free programs must be
+allowed to use the library.  A more frequent case is that a free
+library does the same job as widely used non-free libraries.  In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+  In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software.  For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+  Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.  Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library".  The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+                  GNU LESSER GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+  A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+  The "Library", below, refers to any such software library or work
+which has been distributed under these terms.  A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language.  (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+  "Source code" for a work means the preferred form of the work for
+making modifications to it.  For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+  Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it).  Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+  1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+  You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+  2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) The modified work must itself be a software library.
+
+    b) You must cause the files modified to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    c) You must cause the whole of the work to be licensed at no
+    charge to all third parties under the terms of this License.
+
+    d) If a facility in the modified Library refers to a function or a
+    table of data to be supplied by an application program that uses
+    the facility, other than as an argument passed when the facility
+    is invoked, then you must make a good faith effort to ensure that,
+    in the event an application does not supply such function or
+    table, the facility still operates, and performs whatever part of
+    its purpose remains meaningful.
+
+    (For example, a function in a library to compute square roots has
+    a purpose that is entirely well-defined independent of the
+    application.  Therefore, Subsection 2d requires that any
+    application-supplied function or table used by this function must
+    be optional: if the application does not supply it, the square
+    root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library.  To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License.  (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.)  Do not make any other change in
+these notices.
+\f
+  Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+  This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+  4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+  If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library".  Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+  However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library".  The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+  When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library.  The
+threshold for this to be true is not precisely defined by law.
+
+  If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work.  (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+  Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+  6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+  You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License.  You must supply a copy of this License.  If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License.  Also, you must do one
+of these things:
+
+    a) Accompany the work with the complete corresponding
+    machine-readable source code for the Library including whatever
+    changes were used in the work (which must be distributed under
+    Sections 1 and 2 above); and, if the work is an executable linked
+    with the Library, with the complete machine-readable "work that
+    uses the Library", as object code and/or source code, so that the
+    user can modify the Library and then relink to produce a modified
+    executable containing the modified Library.  (It is understood
+    that the user who changes the contents of definitions files in the
+    Library will not necessarily be able to recompile the application
+    to use the modified definitions.)
+
+    b) Use a suitable shared library mechanism for linking with the
+    Library.  A suitable mechanism is one that (1) uses at run time a
+    copy of the library already present on the user's computer system,
+    rather than copying library functions into the executable, and (2)
+    will operate properly with a modified version of the library, if
+    the user installs one, as long as the modified version is
+    interface-compatible with the version that the work was made with.
+
+    c) Accompany the work with a written offer, valid for at
+    least three years, to give the same user the materials
+    specified in Subsection 6a, above, for a charge no more
+    than the cost of performing this distribution.
+
+    d) If distribution of the work is made by offering access to copy
+    from a designated place, offer equivalent access to copy the above
+    specified materials from the same place.
+
+    e) Verify that the user has already received a copy of these
+    materials or that you have already sent this user a copy.
+
+  For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it.  However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+  It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system.  Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+  7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+    a) Accompany the combined library with a copy of the same work
+    based on the Library, uncombined with any other library
+    facilities.  This must be distributed under the terms of the
+    Sections above.
+
+    b) Give prominent notice with the combined library of the fact
+    that part of it is a work based on the Library, and explaining
+    where to find the accompanying uncombined form of the same work.
+
+  8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License.  Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License.  However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+  9. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Library or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+  10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+  11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded.  In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+  13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation.  If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+  14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission.  For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this.  Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+                            NO WARRANTY
+
+  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+\f
+           How to Apply These Terms to Your New Libraries
+
+  If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change.  You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+  To apply these terms, attach the following notices to the library.  It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the library's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Lesser General Public
+    License as published by the Free Software Foundation; either
+    version 2.1 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Lesser General Public License for more details.
+
+    You should have received a copy of the GNU Lesser General Public
+    License along with this library; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the
+  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+  <signature of Ty Coon>, 1 April 1990
+  Ty Coon, President of Vice
+
+That's all there is to it!
index e5718b1..e8662e4 100644 (file)
@@ -14,6 +14,10 @@ include_HEADERS = include/log.h include/plugin.h \
                        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 \
@@ -38,7 +42,7 @@ backtrace_sources = src/backtrace.c
 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
 
@@ -71,29 +75,32 @@ if VPN
 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 =
 
@@ -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) \
@@ -138,18 +153,25 @@ endif
 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
@@ -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-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
@@ -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)"\" \
@@ -243,7 +292,8 @@ AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ \
                                -DSCRIPTDIR=\""$(build_scriptdir)"\" \
                                -DSTORAGEDIR=\""$(storagedir)\"" \
                                -DVPN_STORAGEDIR=\""$(vpn_storagedir)\"" \
-                               -DCONFIGDIR=\""$(configdir)\""
+                               -DCONFIGDIR=\""$(configdir)\"" \
+                               -fPIE
 
 if VPN
 AM_CPPFLAGS = -I$(builddir)/include -I$(srcdir)/gdbus
@@ -251,7 +301,7 @@ else
 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)"\" \
@@ -267,7 +317,7 @@ EXTRA_DIST = src/genbuiltin src/connman-dbus.conf src/connman-polkit.conf \
                                $(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)"\" \
@@ -290,6 +340,14 @@ AM_CFLAGS += @NFTABLES_CFLAGS@ @LIBMNL_CFLAGS@
 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 =
@@ -311,8 +369,16 @@ client_connmanctl_SOURCES = client/dbus_helpers.h client/dbus_helpers.c \
                        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
@@ -320,7 +386,7 @@ 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
 
@@ -345,7 +411,7 @@ tools_supplicant_test_SOURCES = tools/supplicant-test.c \
                        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
@@ -367,17 +433,17 @@ tools_dhcp_server_test_SOURCES =  $(backtrace_sources) src/log.c src/util.c \
 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 \
@@ -391,14 +457,14 @@ tools_ip6tables_test_SOURCES = $(backtrace_sources) src/log.c src/iptables.c \
                                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
 
@@ -459,13 +525,12 @@ EXTRA_DIST += doc/overview-api.txt doc/behavior-api.txt \
                                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)
 
@@ -477,6 +542,7 @@ DISTCHECK_CONFIGURE_FLAGS = --disable-datafiles \
                                --enable-hh2serial-gps \
                                --enable-openconnect \
                                --enable-openvpn \
+                               --enable-ipsec \
                                --enable-vpnc \
                                --enable-session-policy-local \
                                --enable-nmcompat \
old mode 100644 (file)
new mode 100755 (executable)
index 8e32361..a0c17cf
@@ -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,6 +58,18 @@ builtin_modules += dundee
 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
@@ -126,6 +138,25 @@ vpn_plugins_openvpn_la_LDFLAGS = $(plugin_ldflags)
 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
@@ -223,9 +254,7 @@ plugins_iospm_la_LDFLAGS = $(plugin_ldflags)
 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
@@ -237,7 +266,13 @@ endif
 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 --git a/README b/README
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/TODO b/TODO
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 94c375d..dab6209
 #include "dbus_helpers.h"
 #include "input.h"
 #include "services.h"
+#if defined TIZEN_EXT_INS
+#include "ins.h"
+#endif
 #include "tethering.h"
 #include "peers.h"
 #include "commands.h"
 #include "agent.h"
 #include "vpnconnections.h"
+#if defined TIZEN_EXT_WIFI_MESH
+#include "mesh.h"
+#endif
 
 static DBusConnection *connection;
 static GHashTable *service_hash;
@@ -325,6 +331,25 @@ static int services_list(DBusMessageIter *iter, int errnum, const char *error,
        return 0;
 }
 
+#if defined TIZEN_EXT_INS
+static int ins_list(DBusMessageIter *iter, const char *error,
+               void *user_data)
+{
+       char *filter = user_data;
+
+       if (!error) {
+               __connmanctl_ins_list(iter, filter);
+               fprintf(stdout, "\n");
+       } else {
+               fprintf(stderr, "Error: %s\n", error);
+       }
+
+       g_free(filter);
+
+       return 0;
+}
+#endif
+
 static int peers_list(DBusMessageIter *iter, int errnum,
                                        const char *error, void *user_data)
 {
@@ -420,6 +445,24 @@ static int cmd_services(char *args[], int num, struct connman_option *options)
                        object_properties, path, NULL, NULL);
 }
 
+#if defined TIZEN_EXT_INS
+static int cmd_ins(char *args[], int num, struct connman_option *options)
+{
+       char *filter = NULL;
+
+       if (num > 2)
+               return -E2BIG;
+
+       if (num == 2)
+               filter = g_strdup(args[1]);
+
+       return __connmanctl_dbus_method_call(connection,
+                               CONNMAN_SERVICE, CONNMAN_PATH,
+                               "net.connman.Manager", "GetINS",
+                               ins_list, filter, NULL, NULL);
+}
+#endif
+
 static int cmd_peers(char *args[], int num, struct connman_option *options)
 {
        char *peer_name = NULL;
@@ -630,6 +673,578 @@ static int tether_set_ssid(char *ssid, char *passphrase, int set_tethering)
        return -EINPROGRESS;
 }
 
+#if defined TIZEN_EXT_WIFI_MESH
+struct mesh_if_prop {
+       char *ifname;
+       char *parent_ifname;
+       char *bridge_ifname;
+};
+
+struct mesh_create_network {
+       char *name;
+       unsigned int freq;
+       char *sec_type;
+};
+
+struct mesh_specific_scan_params {
+       char *name;
+       unsigned int freq;
+};
+
+struct mesh_gate_params {
+       bool gate_announce;
+       int hwmp_rootmode;
+       int stp;
+};
+
+static int mesh_return(DBusMessageIter *iter, const char *error,
+               void *user_data)
+{
+       char *method = user_data;
+
+       if (error)
+               fprintf(stderr, "Error %s: %s\n", method, error);
+       else
+               fprintf(stderr, "Success %s\n", method);
+
+       g_free(method);
+
+       return 0;
+}
+
+static void mesh_interface_add_append(DBusMessageIter *iter, void *user_data)
+{
+       struct mesh_if_prop *append = user_data;
+
+       /* Append Virtual Interface Name */
+               __connmanctl_dbus_append_dict_entry(iter, "Ifname",
+                               DBUS_TYPE_STRING, &append->ifname);
+
+       /* Append Parent WiFi Interface Name */
+               __connmanctl_dbus_append_dict_entry(iter, "ParentIfname",
+                               DBUS_TYPE_STRING, &append->parent_ifname);
+
+       /* Append Bridge Interface Name */
+               if (append->bridge_ifname)
+                       __connmanctl_dbus_append_dict_entry(iter, "BridgeIfname",
+                                               DBUS_TYPE_STRING, &append->bridge_ifname);
+}
+
+static void mesh_interface_remove_append(DBusMessageIter *iter, void *user_data)
+{
+       struct mesh_if_prop *append = user_data;
+
+       /* Append Virtual Interface Name */
+               __connmanctl_dbus_append_dict_entry(iter, "Ifname",
+                               DBUS_TYPE_STRING, &append->ifname);
+}
+
+static void mesh_create_network_append(DBusMessageIter *iter, void *user_data)
+{
+       struct mesh_create_network *append = user_data;
+
+       /* Append Mesh Network Name */
+               __connmanctl_dbus_append_dict_entry(iter, "Name",
+                               DBUS_TYPE_STRING, &append->name);
+
+       /* Append Mesh Network Frequency */
+               __connmanctl_dbus_append_dict_entry(iter, "Frequency",
+                               DBUS_TYPE_UINT16, &append->freq);
+
+       /* Append Mesh Network Security Type */
+               __connmanctl_dbus_append_dict_entry(iter, "Security",
+                               DBUS_TYPE_STRING, &append->sec_type);
+}
+
+static void mesh_specific_scan_append(DBusMessageIter *iter, void *user_data)
+{
+       struct mesh_specific_scan_params *append = user_data;
+
+       /* Append Mesh Network Name */
+               __connmanctl_dbus_append_dict_entry(iter, "Name",
+                               DBUS_TYPE_STRING, &append->name);
+
+       /* Append Mesh Network Frequency */
+               __connmanctl_dbus_append_dict_entry(iter, "Frequency",
+                               DBUS_TYPE_UINT16, &append->freq);
+}
+
+static void mesh_set_gate_append(DBusMessageIter *iter, void *user_data)
+{
+       struct mesh_gate_params *append = user_data;
+
+       /* Append Gate Announce Protocol */
+               __connmanctl_dbus_append_dict_entry(iter, "GateAnnounce",
+                               DBUS_TYPE_BOOLEAN, &append->gate_announce);
+
+       /* Append HWMP Root Mode */
+               __connmanctl_dbus_append_dict_entry(iter, "HWMPRootMode",
+                               DBUS_TYPE_UINT16, &append->hwmp_rootmode);
+
+       /* Append STP */
+               __connmanctl_dbus_append_dict_entry(iter, "STP", DBUS_TYPE_UINT16,
+                               &append->stp);
+}
+
+static void mesh_peer_append(DBusMessageIter *iter, void *user_data)
+{
+       char *peer_addr = user_data;
+
+       dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &peer_addr);
+
+       g_free(peer_addr);
+}
+
+static int mesh_peers_list(DBusMessageIter *iter,
+                                       const char *error, void *user_data)
+{
+       if (!error) {
+               __connmanctl_mesh_peers_list(iter);
+               fprintf(stdout, "\n");
+       } else
+               fprintf(stderr, "Error: %s\n", error);
+
+       return 0;
+}
+
+static int connected_mesh_peers_list(DBusMessageIter *iter,
+                                       const char *error, void *user_data)
+{
+       if (!error) {
+               __connmanctl_mesh_connected_peers_list(iter);
+               fprintf(stdout, "\n");
+       } else
+               fprintf(stderr, "Error: %s\n", error);
+
+       return 0;
+}
+
+static int disconnected_mesh_peers_list(DBusMessageIter *iter,
+                                       const char *error, void *user_data)
+{
+       if (!error) {
+               __connmanctl_mesh_disconnected_peers_list(iter);
+               fprintf(stdout, "\n");
+       } else
+               fprintf(stderr, "Error: %s\n", error);
+
+       return 0;
+}
+
+static int mesh_connect_return(DBusMessageIter *iter, const char *error,
+               void *user_data)
+{
+       char *path = user_data;
+
+       if (!error) {
+               char *str = strrchr(path, '/');
+               str++;
+               fprintf(stdout, "Connected %s\n", str);
+       } else
+               fprintf(stderr, "Error %s: %s\n", path, error);
+
+       g_free(user_data);
+
+       return 0;
+}
+
+static int mesh_disconnect_return(DBusMessageIter *iter, const char *error,
+               void *user_data)
+{
+       char *path = user_data;
+
+       if (!error) {
+               char *str = strrchr(path, '/');
+               str++;
+               fprintf(stdout, "Disconnected %s\n", str);
+       } else
+               fprintf(stderr, "Error %s: %s\n", path, error);
+
+       g_free(user_data);
+
+       return 0;
+}
+
+static int mesh_remove_return(DBusMessageIter *iter, const char *error,
+               void *user_data)
+{
+       char *path = user_data;
+
+       if (!error) {
+               char *str = strrchr(path, '/');
+               str++;
+               fprintf(stdout, "Removed %s\n", str);
+       } else
+               fprintf(stderr, "Error %s: %s\n", path, error);
+
+       g_free(user_data);
+
+       return 0;
+}
+
+static int mesh_config_return(DBusMessageIter *iter, const char *error,
+               void *user_data)
+{
+       char *path = user_data;
+       char *str = strrchr(path, '/');
+       str++;
+
+       if (error)
+               fprintf(stderr, "Error %s: %s\n", path, error);
+       else
+               fprintf(stdout, "Success SetProperty %s\n", str);
+
+       g_free(user_data);
+
+       return 0;
+}
+
+static int cmd_mesh(char *args[], int num, struct connman_option *options)
+{
+       int result = 0;
+       int c;
+       char *path = NULL;
+       char *method = NULL;
+       char *mesh_peer_name = NULL;
+       char *mesh_peer_path = NULL;
+       char *property = NULL;
+       char *value = NULL;
+       struct mesh_if_prop *append;
+       struct mesh_create_network *network;
+       struct mesh_specific_scan_params *scan_params;
+       struct mesh_gate_params *gate_params;
+       char *mesh_peer_addr = NULL;
+
+       c = parse_args(args[1], options);
+
+       switch (c) {
+       case 'a':
+               if (num < 4 || num > 5) {
+                       result = -EINVAL;
+                       break;
+               }
+               path = g_strdup_printf("/net/connman/technology/mesh");
+
+               append = dbus_malloc0(sizeof(struct mesh_if_prop));
+               append->ifname = g_strdup(args[2]);
+               append->parent_ifname = g_strdup(args[3]);
+               if (num == 5)
+                       append->bridge_ifname = g_strdup(args[4]);
+               method = g_strdup("MeshInterfaceAdd");
+               result = __connmanctl_dbus_mesh_dict(connection, path,
+                                                       "net.connman.Technology", mesh_return, method,
+                                                       "MeshInterfaceAdd", DBUS_TYPE_STRING,
+                                                       mesh_interface_add_append, append);
+               g_free(append->ifname);
+               g_free(append->parent_ifname);
+               g_free(append->bridge_ifname);
+               g_free(append);
+               break;
+
+       case 'r':
+               if (num != 3) {
+                       result = -EINVAL;
+                       break;
+               }
+               path = g_strdup_printf("/net/connman/technology/mesh");
+
+               append = dbus_malloc0(sizeof(struct mesh_if_prop));
+               append->ifname = g_strdup(args[2]);
+               method = g_strdup("MeshInterfaceRemove");
+               result = __connmanctl_dbus_mesh_dict(connection, path,
+                                                       "net.connman.Technology", mesh_return, method,
+                                                       "MeshInterfaceRemove", DBUS_TYPE_STRING,
+                                                       mesh_interface_remove_append, append);
+               g_free(append->ifname);
+               g_free(append);
+               break;
+
+       case 'p':
+               if (num > 3) {
+                       result = -E2BIG;
+                       break;
+               }
+
+               if (num == 3)
+                       mesh_peer_name = args[2];
+
+               if (!mesh_peer_name) {
+                       result = __connmanctl_dbus_method_call(connection,
+                                       CONNMAN_SERVICE, CONNMAN_PATH,
+                                       "net.connman.Manager", "GetMeshPeers",
+                                       mesh_peers_list, NULL, NULL, NULL);
+                       break;
+               }
+
+               if (check_dbus_name(mesh_peer_name) == false) {
+                       result = -EINVAL;
+                       break;
+               }
+
+               mesh_peer_path = g_strdup_printf("/net/connman/mesh/%s",
+                                                                       mesh_peer_name);
+               result = __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
+                                               mesh_peer_path, "net.connman.Mesh", "GetProperties",
+                                               object_properties, mesh_peer_path, NULL, NULL);
+               break;
+
+       case 'c':
+               if (num < 3) {
+                       result = -EINVAL;
+                       break;
+               }
+
+               if (num > 3) {
+                       result = -E2BIG;
+                       break;
+               }
+
+               mesh_peer_name = args[2];
+
+               if (check_dbus_name(mesh_peer_name) == false) {
+                       result = -EINVAL;
+                       break;
+               }
+
+               mesh_peer_path = g_strdup_printf("/net/connman/mesh/%s",
+                                                                       mesh_peer_name);
+               result = __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
+                                               mesh_peer_path, "net.connman.Mesh", "Connect",
+                                               mesh_connect_return, mesh_peer_path, NULL, NULL);
+               break;
+
+       case 'd':
+               if (num < 3) {
+                       result = -EINVAL;
+                       break;
+               }
+
+               if (num > 3) {
+                       result = -E2BIG;
+                       break;
+               }
+
+               mesh_peer_name = args[2];
+
+               if (check_dbus_name(mesh_peer_name) == false) {
+                       result = -EINVAL;
+                       break;
+               }
+
+               mesh_peer_path = g_strdup_printf("/net/connman/mesh/%s",
+                                                                       mesh_peer_name);
+               result = __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
+                                               mesh_peer_path, "net.connman.Mesh", "Disconnect",
+                                               mesh_disconnect_return, mesh_peer_path, NULL, NULL);
+               break;
+
+       case 'f':
+               if (num < 3) {
+                       result = -EINVAL;
+                       break;
+               }
+
+               if (num > 3) {
+                       result = -E2BIG;
+                       break;
+               }
+
+               mesh_peer_name = args[2];
+
+               if (check_dbus_name(mesh_peer_name) == false) {
+                       result = -EINVAL;
+                       break;
+               }
+
+               mesh_peer_path = g_strdup_printf("/net/connman/mesh/%s",
+                                                                       mesh_peer_name);
+               result = __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
+                                               mesh_peer_path, "net.connman.Mesh", "Remove",
+                                               mesh_remove_return, mesh_peer_path, NULL, NULL);
+               break;
+
+       case 'C':
+               if (num > 2) {
+                       result = -E2BIG;
+                       break;
+               }
+
+               result = __connmanctl_dbus_method_call(connection,
+                                                               CONNMAN_SERVICE, CONNMAN_PATH,
+                                                               "net.connman.Manager", "GetConnectedMeshPeers",
+                                                               connected_mesh_peers_list, NULL, NULL, NULL);
+               break;
+
+       case 'D':
+               if (num > 2) {
+                       result = -E2BIG;
+                       break;
+               }
+
+               result = __connmanctl_dbus_method_call(connection,
+                                                               CONNMAN_SERVICE, CONNMAN_PATH,
+                                                               "net.connman.Manager",
+                                                               "GetDisconnectedMeshPeers",
+                                                               disconnected_mesh_peers_list, NULL, NULL, NULL);
+               break;
+
+       case 'n':
+               if (num != 5) {
+                       result = -EINVAL;
+                       break;
+               }
+               path = g_strdup_printf("/net/connman/technology/mesh");
+
+               network = dbus_malloc0(sizeof(struct mesh_create_network));
+               network->name = g_strdup(args[2]);
+               network->freq = atoi(args[3]);
+               network->sec_type = g_strdup(args[4]);
+               method = g_strdup("MeshCreateNetwork");
+               result = __connmanctl_dbus_mesh_dict(connection, path,
+                                                       "net.connman.Technology", mesh_return, method,
+                                                       "MeshCreateNetwork", DBUS_TYPE_STRING,
+                                                       mesh_create_network_append, network);
+               g_free(network->name);
+               g_free(network->sec_type);
+               g_free(network);
+               break;
+
+       case 'A':
+               if (num != 2) {
+                       result = -EINVAL;
+                       break;
+               }
+               path = g_strdup_printf("/net/connman/technology/mesh");
+
+               method = g_strdup("AbortScan");
+               result = __connmanctl_dbus_mesh_dict(connection, path,
+                                                       "net.connman.Technology", mesh_return, method,
+                                                       "AbortScan", DBUS_TYPE_STRING,
+                                                       NULL, NULL);
+               break;
+
+       case 'S':
+               if (num != 4) {
+                       result = -EINVAL;
+                       break;
+               }
+               path = g_strdup_printf("/net/connman/technology/mesh");
+
+               scan_params = dbus_malloc0(sizeof(struct mesh_specific_scan_params));
+               scan_params->name = g_strdup(args[2]);
+               scan_params->freq = atoi(args[3]);
+               method = g_strdup("MeshSpecificScan");
+               result = __connmanctl_dbus_mesh_dict(connection, path,
+                                                       "net.connman.Technology", mesh_return, method,
+                                                       "MeshSpecificScan", DBUS_TYPE_STRING,
+                                                       mesh_specific_scan_append, scan_params);
+               g_free(scan_params->name);
+               g_free(scan_params);
+               break;
+
+       case 'P':
+               if (num != 5) {
+                       result = -EINVAL;
+                       break;
+               }
+
+               mesh_peer_name = args[2];
+               property = args[3];
+               value = args[4];
+
+               if (check_dbus_name(mesh_peer_name) == false) {
+                       result = -EINVAL;
+                       break;
+               }
+
+               mesh_peer_path = g_strdup_printf("/net/connman/mesh/%s",
+                                                                       mesh_peer_name);
+
+               if (g_strcmp0(property, "Passphrase") == 0) {
+                       result = __connmanctl_dbus_set_property(connection,
+                                                               mesh_peer_path, "net.connman.Mesh",
+                                                               mesh_config_return, mesh_peer_path, property,
+                                                               DBUS_TYPE_STRING, &value);
+               } else {
+                       printf("Invalid property %s\n", property);
+                       result = -EINVAL;
+               }
+
+               break;
+
+       case 'G':
+               if (num != 5) {
+                       result = -EINVAL;
+                       break;
+               }
+
+               path = g_strdup_printf("/net/connman/technology/mesh");
+
+               gate_params = dbus_malloc0(sizeof(struct mesh_gate_params));
+               gate_params->gate_announce = atoi(args[2]);
+               gate_params->hwmp_rootmode = atoi(args[3]);
+               gate_params->stp = atoi(args[4]);
+
+               method = g_strdup("SetMeshGate");
+
+               result = __connmanctl_dbus_mesh_dict(connection, path,
+                                                       "net.connman.Technology", mesh_return, method,
+                                                       "SetMeshGate", DBUS_TYPE_STRING,
+                                                       mesh_set_gate_append, gate_params);
+
+               break;
+
+       case 'z':
+               if (num != 3) {
+                       result = -EINVAL;
+                       break;
+               }
+
+               mesh_peer_addr = g_strdup(args[2]);
+               method = g_strdup("MeshAddPeer");
+
+               result = __connmanctl_dbus_method_call(connection,
+                                                               CONNMAN_SERVICE, CONNMAN_PATH,
+                                                               "net.connman.Manager", "MeshAddPeer",
+                                                               mesh_return, method, mesh_peer_append,
+                                                               mesh_peer_addr);
+
+               break;
+
+       case 'y':
+               if (num != 3) {
+                       result = -EINVAL;
+                       break;
+               }
+
+               mesh_peer_addr = g_strdup(args[2]);
+               method = g_strdup("MeshRemovePeer");
+
+               result = __connmanctl_dbus_method_call(connection,
+                                                               CONNMAN_SERVICE, CONNMAN_PATH,
+                                                               "net.connman.Manager", "MeshRemovePeer",
+                                                               mesh_return, method, mesh_peer_append,
+                                                               mesh_peer_addr);
+
+               break;
+
+       default:
+               result = -EINVAL;
+               break;
+       }
+
+       g_free(path);
+
+       if (result < 0) {
+               if (result != -EINPROGRESS)
+                       printf("Error '%s': %s\n", args[1], strerror(-result));
+       }
+
+
+       return result;
+}
+#endif
+
 static int cmd_tether(char *args[], int num, struct connman_option *options)
 {
        char *ssid, *passphrase;
@@ -2393,6 +3008,15 @@ static struct connman_option service_options[] = {
        { NULL, }
 };
 
+#if defined TIZEN_EXT_INS
+static struct connman_option ins_options[] = {
+       {"all",         'a', ""},
+       {"filter-ssid", 's', "ssid"},
+       {"filter-name", 'n', "[<service_name>]"},
+       { NULL, }
+};
+#endif
+
 static struct connman_option config_options[] = {
        {"nameservers", 'n', "<dns1> [<dns2>] [<dns3>]"},
        {"timeservers", 't', "<ntp1> [<ntp2>] [...]"},
@@ -2428,6 +3052,38 @@ static struct connman_option session_options[] = {
        { NULL, }
 };
 
+#if defined TIZEN_EXT_WIFI_MESH
+static struct connman_option mesh_options[] = {
+       {"ifadd", 'a', "<ifname> <wifi_ifname>\n"
+               "                     [bridge_ifname]                Add Virtual Mesh "
+                       "interface"},
+       {"ifrmv", 'r', "<ifname>                       Remove Virtual Mesh "
+               "interface"},
+       {"peers", 'p', "[peer]                         Display Mesh peer "
+               "informations"},
+       {"connect", 'c', "<peer>                         Connect Mesh Peer"},
+       {"disconnect", 'd', "<peer>                         Disconnect Mesh Peer"},
+       {"remove", 'f', "<peer>                         Forget Mesh Peer"},
+       {"connected_peers", 'C', "[]                             Displays connected"
+               " Peer informations"},
+       {"disconnected_peers", 'D', "[]                           Displays "
+               "Disconnected Peer informations"},
+       {"create_network", 'n', "<name> <frequency> <sec_type>  Create New Mesh "
+               "Network"},
+       {"abort_scan", 'A', "                               Abort ongoing mesh "
+               "scan"},
+       {"specific_scan", 'S', "<name> <frequency>             Create New Mesh "
+               "Network"},
+       {"config", 'P', "<peer>                         Set Mesh Network "
+               "Configurations\n          Passphrase    <passphrase>"},
+       {"set_gate", 'G', "<gate_ann> <rootmode> <stp>    Set Mesh Gate "
+               "Option"},
+       {"add_peer", 'z', "<addr>                         Add Mesh Peer"},
+       {"remove_peer", 'y', "<addr>                         Remove Mesh Peer"},
+       { NULL, }
+};
+#endif
+
 static char *lookup_options(struct connman_option *options, const char *text,
                int state)
 {
@@ -2480,6 +3136,13 @@ static char *lookup_session(const char *text, int state)
        return lookup_options(session_options, text, state);
 }
 
+#if defined TIZEN_EXT_WIFI_MESH
+static char *lookup_mesh(const char *text, int state)
+{
+       return lookup_options(mesh_options, text, state);
+}
+#endif
+
 static int peer_service_cb(DBusMessageIter *iter, int errnum,
                        const char *error, void *user_data)
 {
@@ -2572,12 +3235,30 @@ static struct _peer_service *fill_in_peer_service(unsigned char *bjr_query,
 
        service = dbus_malloc0(sizeof(*service));
 
+#if defined TIZEN_EXT
+       if (!service)
+               return NULL;
+#endif
+
        if (bjr_query_len && bjr_response_len) {
                service->bjr_query = dbus_malloc0(bjr_query_len);
+#if defined TIZEN_EXT
+               if(!service->bjr_query) {
+                       dbus_free(service);
+                       return NULL;
+               }
+#endif
                memcpy(service->bjr_query, bjr_query, bjr_query_len);
                service->bjr_query_len = bjr_query_len;
 
                service->bjr_response = dbus_malloc0(bjr_response_len);
+#if defined TIZEN_EXT
+               if(!service->bjr_response) {
+                       dbus_free(service->bjr_query);
+                       dbus_free(service);
+                       return NULL;
+               }
+#endif
                memcpy(service->bjr_response, bjr_response, bjr_response_len);
                service->bjr_response_len = bjr_response_len;
        } else if (upnp_service && version) {
@@ -2585,6 +3266,12 @@ static struct _peer_service *fill_in_peer_service(unsigned char *bjr_query,
                service->version = version;
        } else if (wfd_ies && wfd_ies_len) {
                service->wfd_ies = dbus_malloc0(wfd_ies_len);
+#if defined TIZEN_EXT
+               if (!service->wfd_ies) {
+                       dbus_free(service);
+                       return NULL;
+               }
+#endif
                memcpy(service->wfd_ies, wfd_ies, wfd_ies_len);
                service->wfd_ies_len = wfd_ies_len;
        } else {
@@ -2767,6 +3454,10 @@ static const struct {
        { "disable",      "<technology>|offline", NULL,    cmd_disable,
          "Disables given technology or offline mode",
          lookup_technology_offline },
+#if defined TIZEN_EXT_WIFI_MESH
+       { "mesh",      "", mesh_options, cmd_mesh, "Mesh specific commands",
+               lookup_mesh },
+#endif
        { "tether", "<technology> on|off\n"
                    "            wifi [on|off] <ssid> <passphrase> ",
                                          NULL,            cmd_tether,
@@ -2776,6 +3467,10 @@ static const struct {
          "Display tethering clients", NULL },
        { "services",     "[<service>]",  service_options, cmd_services,
          "Display services", lookup_service_arg },
+#if defined TIZEN_EXT_INS
+       { "ins",                  NULL,      ins_options, cmd_ins,
+         "Display intelligent network selection", NULL },
+#endif
        { "peers",        "[peer]",       NULL,            cmd_peers,
          "Display peers", lookup_peer_arg },
        { "scan",         "<technology>", NULL,            cmd_scan,
old mode 100644 (file)
new mode 100755 (executable)
index 929ebe1..1c68a28 100644 (file)
@@ -253,6 +253,11 @@ static int append_variant(DBusMessageIter *iter, const char *property,
        case DBUS_TYPE_INT32:
                type_str = DBUS_TYPE_INT32_AS_STRING;
                break;
+#if defined TIZEN_EXT_WIFI_MESH
+       case DBUS_TYPE_UINT16:
+               type_str = DBUS_TYPE_UINT16_AS_STRING;
+               break;
+#endif
        default:
                return -EOPNOTSUPP;
        }
@@ -383,6 +388,50 @@ int __connmanctl_dbus_set_property_dict(DBusConnection *connection,
        return send_method_call(connection, message, cb, user_data);
 }
 
+#if defined TIZEN_EXT_WIFI_MESH
+int __connmanctl_dbus_mesh_dict(DBusConnection *connection,
+               const char *path, const char *interface,
+               connmanctl_dbus_method_return_func_t cb, void *user_data,
+               const char *property, int type,
+               connmanctl_dbus_append_func_t append_fn,
+               void *append_user_data)
+{
+       DBusMessage *message;
+       DBusMessageIter iter, variant, dict;
+
+       message = dbus_message_new_method_call(CONNMAN_SERVICE, path,
+                       interface, "MeshCommands");
+
+       if (!message)
+               return -ENOMEM;
+
+       dbus_message_iter_init_append(message, &iter);
+       dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
+       dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
+                       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,
+                       &variant);
+
+       dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
+                       DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                               DBUS_TYPE_STRING_AS_STRING
+                               DBUS_TYPE_VARIANT_AS_STRING
+                       DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+                       &dict);
+
+       if (append_fn)
+               append_fn(&dict, append_user_data);
+
+       dbus_message_iter_close_container(&variant, &dict);
+       dbus_message_iter_close_container(&iter, &variant);
+
+       return send_method_call(connection, message, cb, user_data);
+}
+#endif
+
 static void append_variant_array(DBusMessageIter *iter, const char *property,
                connmanctl_dbus_append_func_t append_fn,
                void *append_user_data)
index d3326a4..85fbdef 100644 (file)
@@ -67,6 +67,15 @@ int __connmanctl_dbus_set_property_dict(DBusConnection *connection,
                connmanctl_dbus_append_func_t append_fn,
                void *append_user_data);
 
+#if defined TIZEN_EXT_WIFI_MESH
+int __connmanctl_dbus_mesh_dict(DBusConnection *connection,
+               const char *path, const char *interface,
+               connmanctl_dbus_method_return_func_t cb, void *user_data,
+               const char *property, int type,
+               connmanctl_dbus_append_func_t append_fn,
+               void *append_user_data);
+#endif
+
 void __connmanctl_dbus_append_dict_string_array(DBusMessageIter *iter,
                const char *property, connmanctl_dbus_append_func_t append_fn,
                void *append_user_data);
old mode 100644 (file)
new mode 100755 (executable)
index 78319ff..d9d2b7b
@@ -273,7 +273,9 @@ int __connmanctl_input_init(int argc, char *argv[])
                __connmanctl_monitor_completions(NULL);
 
                rl_callback_handler_remove();
+#if !defined TIZEN_EXT
                rl_message("");
+#endif
        }
 
        dbus_connection_unref(connection);
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/client/ins.c b/client/ins.c
new file mode 100755 (executable)
index 0000000..6403f61
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *  Copyright (C) 2020  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#include "ins.h"
+
+#define BOOLSTR(s) (((s) == true) ? "TRUE" : "FALSE")
+
+struct ins_info_s {
+       struct {
+               bool last_user_selection;
+               bool last_connected;
+               bool security_priority;
+               bool internet_connection;
+               bool frequency;
+               bool strength;
+       } ssid;
+       struct {
+               bool last_connected;
+               bool assoc_reject;
+               bool frequency;
+               bool strength;
+       } bssid;
+};
+
+struct bssid_info_s {
+       char *bssid;
+       unsigned int strength;
+       unsigned int frequency;
+       int score_ins;
+       int score_last_connected;
+       int score_assoc_reject;
+       int score_frequency;
+       int score_strength;
+};
+
+static void print_bssid_info(gpointer value, gpointer user_data)
+{
+       struct bssid_info_s *bssid_info = value;
+       int *bssid_rank = user_data;
+
+       fprintf(stdout, "     %2d) %-20s total[%2d] last_conn[%2d] "
+                       "assoc_reject[%2d] freq[%2d(%4d)] strength[%2d(%2d)]\n",
+                       *bssid_rank, bssid_info->bssid, bssid_info->score_ins,
+                       bssid_info->score_last_connected, bssid_info->score_assoc_reject,
+                       bssid_info->score_frequency, bssid_info->frequency,
+                       bssid_info->score_strength, bssid_info->strength);
+
+       (*bssid_rank)++;
+}
+
+static GSList *get_bssid_list(DBusMessageIter *iter, struct ins_info_s *ins_info)
+{
+       char *property;
+       DBusMessageIter entry, val;
+       GSList *bssid_list = NULL;
+       struct bssid_info_s *bssid_info = NULL;
+
+       while (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
+               dbus_message_iter_recurse(iter, &entry);
+               dbus_message_iter_get_basic(&entry, &property);
+
+               if (strcmp(property, "BSSID") == 0) {
+                       bssid_info = g_try_new0(struct bssid_info_s, 1);
+                       if (!bssid_info)
+                               continue;
+
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &(bssid_info->bssid));
+
+               } else if (strcmp(property, "ScoreINS") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &(bssid_info->score_ins));
+
+               } else if (strcmp(property, "ScoreLastConnected") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &(bssid_info->score_last_connected));
+                       if (bssid_info->score_last_connected)
+                               ins_info->bssid.last_connected = true;
+
+               } else if (strcmp(property, "ScoreAssocReject") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &(bssid_info->score_assoc_reject));
+                       if (bssid_info->score_assoc_reject)
+                               ins_info->bssid.assoc_reject = true;
+
+               } else if (strcmp(property, "Frequency") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &(bssid_info->frequency));
+
+               } else if (strcmp(property, "ScoreFrequency") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &(bssid_info->score_frequency));
+                       if (bssid_info->score_frequency)
+                               ins_info->bssid.frequency = true;
+
+               } else if (strcmp(property, "Strength") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &(bssid_info->strength));
+
+               } else if (strcmp(property, "ScoreStrength") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &(bssid_info->score_strength));
+                       if (bssid_info->score_strength)
+                               ins_info->bssid.strength = true;
+
+                       bssid_list = g_slist_append(bssid_list, bssid_info);
+               }
+
+               dbus_message_iter_next(iter);
+       }
+
+       return bssid_list;
+}
+
+static void print_ins_info(int *rank, struct ins_info_s *ins_info,
+               char *path, char *filter, DBusMessageIter *iter)
+{
+       char *name = "";
+       char *security;
+       char *str = NULL;
+       int count = 0;
+       char *property;
+       unsigned char strength;
+       unsigned int frequency;
+       int score_INS;
+       int score_last_user_selection;
+       int score_last_connected;
+       int score_frequency;
+       int score_security_priority;
+       int score_internet_connection;
+       int score_strength;
+       GSList *bssid_list = NULL;
+       DBusMessageIter entry, val, dict;
+
+       while (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
+               dbus_message_iter_recurse(iter, &entry);
+               dbus_message_iter_get_basic(&entry, &property);
+
+               if (strcmp(property, "Name") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &name);
+
+               } else if (strcmp(property, "ScoreINS") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &score_INS);
+
+               } else if (strcmp(property, "ScoreLastUserSelection") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &score_last_user_selection);
+                       if (score_last_user_selection)
+                               ins_info->ssid.last_user_selection = true;
+
+               } else if (strcmp(property, "ScoreLastConnected") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &score_last_connected);
+                       if (score_last_connected)
+                               ins_info->ssid.last_connected = true;
+
+               } else if (strcmp(property, "Security") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &security);
+
+               } else if (strcmp(property, "ScoreSecurityPriority") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &score_security_priority);
+                       if (score_security_priority)
+                               ins_info->ssid.security_priority = true;
+
+               } else if (strcmp(property, "Strength") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &strength);
+
+               } else if (strcmp(property, "ScoreStrength") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &score_strength);
+                       if (score_strength)
+                               ins_info->ssid.strength = true;
+
+               } else if (strcmp(property, "ScoreInternetConnection") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &score_internet_connection);
+                       if (score_internet_connection)
+                               ins_info->ssid.internet_connection = true;
+
+               } else if (strcmp(property, "Frequency") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &frequency);
+
+               } else if (strcmp(property, "ScoreFrequency") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &score_frequency);
+                       if (score_frequency)
+                               ins_info->ssid.frequency = true;
+
+               } else if (strcmp(property, "BSSID.List") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       if (dbus_message_iter_get_arg_type(&val)
+                               == DBUS_TYPE_ARRAY) {
+                               dbus_message_iter_recurse(&val, &dict);
+                               bssid_list = get_bssid_list(&dict, ins_info);
+                       }
+
+               }
+
+               count++;
+               dbus_message_iter_next(iter);
+       }
+
+       str = strrchr(path, '/');
+       if (str)
+               str++;
+       else
+               str = path;
+
+       if (count > 0) {
+               if (!filter || strcmp(filter, name) == 0 || strcmp(filter, "ssid") == 0) {
+                       fprintf(stdout, "  [%2d] %-20s total[%2d] last_usr[%2d] last_conn[%2d] "
+                               "internet[%2d] sec[%2d(%9s)] freq[%2d(%4d)] strength[%2d(%2d)]\n  %s\n",
+                               *rank, name, score_INS, score_last_user_selection, score_last_connected,
+                               score_internet_connection, score_security_priority, security,
+                               score_frequency, frequency, score_strength, strength, str);
+
+                       if (!filter || strcmp(filter, "ssid") != 0) {
+                               int bssid_rank = 1;
+                               g_slist_foreach(bssid_list, print_bssid_info, &bssid_rank);
+                       }
+
+                       (*rank)++;
+               }
+
+       } else {
+               fprintf(stdout, "%-24s %s", "unchanged\n", str);
+       }
+
+}
+
+static void list_ins_array(DBusMessageIter *iter, char *filter)
+{
+       DBusMessageIter array, dict;
+       char *path = NULL;
+       int rank = 1;
+       struct ins_info_s ins_info;
+
+       memset(&ins_info, 0, sizeof(ins_info));
+
+       while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
+
+               dbus_message_iter_recurse(iter, &array);
+               if (dbus_message_iter_get_arg_type(&array)
+                               != DBUS_TYPE_OBJECT_PATH)
+                       return;
+
+               dbus_message_iter_get_basic(&array, &path);
+
+               dbus_message_iter_next(&array);
+               if (dbus_message_iter_get_arg_type(&array)
+                               == DBUS_TYPE_ARRAY) {
+                       dbus_message_iter_recurse(&array, &dict);
+                       print_ins_info(&rank, &ins_info, path, filter, &dict);
+               }
+
+               dbus_message_iter_next(iter);
+       }
+
+       fprintf(stdout, "\n");
+       fprintf(stdout, "  [SSID]  last_usr[%s] last_conn[%s] "
+               "sec_priority[%s] internet[%s] freq[%s] strength[%s]\n",
+               BOOLSTR(ins_info.ssid.last_user_selection), BOOLSTR(ins_info.ssid.last_connected),
+               BOOLSTR(ins_info.ssid.security_priority), BOOLSTR(ins_info.ssid.internet_connection),
+               BOOLSTR(ins_info.ssid.frequency), BOOLSTR(ins_info.ssid.strength));
+
+       fprintf(stdout, "  [BSSID] last_conn[%s] assoc_reject[%s] freq[%s] strength[%s]\n",
+               BOOLSTR(ins_info.bssid.last_connected), BOOLSTR(ins_info.bssid.assoc_reject),
+               BOOLSTR(ins_info.bssid.frequency), BOOLSTR(ins_info.bssid.strength));
+}
+
+void __connmanctl_ins_list(DBusMessageIter *iter, char *filter)
+{
+       DBusMessageIter array;
+       char *path;
+
+       if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+               return;
+
+       dbus_message_iter_recurse(iter, &array);
+       list_ins_array(&array, filter);
+
+       dbus_message_iter_next(iter);
+       if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+               return;
+
+       fprintf(stdout, "\n}, {");
+
+       dbus_message_iter_recurse(iter, &array);
+       while (dbus_message_iter_get_arg_type(&array)
+                       == DBUS_TYPE_OBJECT_PATH) {
+               dbus_message_iter_get_basic(&array, &path);
+               fprintf(stdout, "\n%-24s %s", "removed", path);
+
+               dbus_message_iter_next(&array);
+       }
+
+}
diff --git a/client/ins.h b/client/ins.h
new file mode 100755 (executable)
index 0000000..88151af
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *  Copyright (C) 2020  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __CONNMANCTL_INS_H
+#define __CONNMANCTL_INS_H
+
+#include <dbus/dbus.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void __connmanctl_ins_list(DBusMessageIter *iter, char *filter);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CONNMANCTL_INS_H */
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/client/mesh.c b/client/mesh.c
new file mode 100644 (file)
index 0000000..6e57793
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *
+ *  Copyright (C) 2017 Samsung Electronics Co., Ltd.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ *  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "mesh.h"
+#include "dbus_helpers.h"
+
+static void print_mesh_peer(char *path, DBusMessageIter *iter)
+{
+       char *name = "";
+       char state = ' ';
+       char *str, *property;
+       DBusMessageIter entry, val;
+       int count = 0, favorite = 0;
+
+       while (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
+               dbus_message_iter_recurse(iter, &entry);
+               dbus_message_iter_get_basic(&entry, &property);
+
+               if (strcmp(property, "Name") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &name);
+               } else if (strcmp(property, "State") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &str);
+
+                       if (str) {
+                               if (strcmp(str, "online") == 0)
+                                       state = 'O';
+                               else if (strcmp(str, "ready") == 0)
+                                       state = 'R';
+                               else if (!strcmp(str, "association"))
+                                       state = 'a';
+                               else if (!strcmp(str, "configuration"))
+                                       state = 'c';
+                               else if (!strcmp(str, "disconnect"))
+                                       state = 'd';
+                       }
+               } else if (strcmp(property, "Favorite") == 0) {
+                       dbus_message_iter_next(&entry);
+                       dbus_message_iter_recurse(&entry, &val);
+                       dbus_message_iter_get_basic(&val, &favorite);
+               }
+
+               dbus_message_iter_next(iter);
+               count++;
+       }
+
+       str = strrchr(path, '/');
+       if (str)
+               str++;
+       else
+               str = path;
+
+       if (count > 0)
+               fprintf(stdout, "%c%c %-20s %s", favorite != 0 ? 'A' : ' ',
+                               state, name, str);
+       else
+               fprintf(stdout, "%s %s", "unchanged", str);
+}
+
+static void list_mesh_peer_array(DBusMessageIter *iter)
+{
+       DBusMessageIter array, dict;
+       char *path = NULL;
+
+       while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
+               dbus_message_iter_recurse(iter, &array);
+               if (dbus_message_iter_get_arg_type(&array)
+                               != DBUS_TYPE_OBJECT_PATH)
+                       return;
+
+               dbus_message_iter_get_basic(&array, &path);
+
+               dbus_message_iter_next(&array);
+               if (dbus_message_iter_get_arg_type(&array)
+                                               == DBUS_TYPE_ARRAY) {
+                       dbus_message_iter_recurse(&array, &dict);
+                       print_mesh_peer(path, &dict);
+               }
+
+               if (dbus_message_iter_has_next(iter))
+                       fprintf(stdout, "\n");
+
+               dbus_message_iter_next(iter);
+       }
+}
+
+void __connmanctl_mesh_peers_list(DBusMessageIter *iter)
+{
+       DBusMessageIter array;
+       char *path;
+
+       if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+               return;
+
+       dbus_message_iter_recurse(iter, &array);
+       list_mesh_peer_array(&array);
+
+       dbus_message_iter_next(iter);
+       if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+               return;
+
+       fprintf(stdout, "\n}, {");
+
+       dbus_message_iter_recurse(iter, &array);
+       while (dbus_message_iter_get_arg_type(&array)
+                                       == DBUS_TYPE_OBJECT_PATH) {
+               dbus_message_iter_get_basic(&array, &path);
+               fprintf(stdout, "\n%s %s", "removed", path);
+
+               dbus_message_iter_next(&array);
+       }
+
+}
+
+void __connmanctl_mesh_connected_peers_list(DBusMessageIter *iter)
+{
+       DBusMessageIter array;
+
+       if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+               return;
+
+       dbus_message_iter_recurse(iter, &array);
+       __connmanctl_dbus_print(&array, "  ", " = ", "\n");
+       fprintf(stdout, "\n");
+}
+
+void __connmanctl_mesh_disconnected_peers_list(DBusMessageIter *iter)
+{
+       DBusMessageIter array;
+
+       if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+               return;
+
+       dbus_message_iter_recurse(iter, &array);
+       __connmanctl_dbus_print(&array, "  ", " = ", "\n");
+       fprintf(stdout, "\n");
+}
diff --git a/client/mesh.h b/client/mesh.h
new file mode 100644 (file)
index 0000000..8dd413d
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *
+ *  Copyright (C) 2017 Samsung Electronics Co., Ltd.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ *  02110-1301  USA
+ */
+
+#ifndef __CONNMANCTL_MESH_H
+#define __CONNMANCTL_MESH_H
+
+#include <dbus/dbus.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void __connmanctl_mesh_peers_list(DBusMessageIter *iter);
+void __connmanctl_mesh_connected_peers_list(DBusMessageIter *iter);
+void __connmanctl_mesh_disconnected_peers_list(DBusMessageIter *iter);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CONNMANCTL_MESH_H */
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index b55d248..220d62b 100644 (file)
@@ -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}])
 
@@ -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
@@ -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
@@ -108,6 +146,30 @@ 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}])
 
@@ -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
@@ -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)
@@ -144,7 +206,7 @@ if (test "${enable_l2tp}" != "no"); then
        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)
@@ -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)
@@ -169,7 +231,7 @@ if (test "${enable_pptp}" != "no"); then
        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)
@@ -228,16 +290,36 @@ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.40, dummy=yes,
 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
@@ -396,6 +478,11 @@ AC_ARG_ENABLE(wispr, AC_HELP_STRING([--disable-wispr],
                                        [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}])
@@ -408,9 +495,9 @@ AM_CONDITIONAL(STATS, test "${enable_stats}" != "no")
 
 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
@@ -445,7 +532,7 @@ fi
 
 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],
@@ -460,6 +547,7 @@ fi
 
 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 \
@@ -479,4 +567,4 @@ AM_CONDITIONAL(INTERNAL_DNS_BACKEND, test "${dns_backend}" = "internal")
 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 --git a/connman.manifest b/connman.manifest
new file mode 100644 (file)
index 0000000..97e8c31
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_"/>
+       </request>
+</manifest>
index 2af3c2b..0d38a26 100644 (file)
@@ -2,13 +2,13 @@ prefix=@prefix@
 exec_prefix=@exec_prefix@
 libdir=@libdir@
 includedir=@includedir@
+
 plugindir=${libdir}/connman/plugins
 scriptdir=${libdir}/connman/scripts
 
 Name: connman
 Description: Connection Manager
-Requires: glib-2.0 dbus-1
+Requires: dlog glib-2.0 dbus-1
 Version: @VERSION@
 Libs: -module -avoid-version -export-symbols-regex connman_plugin_desc
 Cflags: -I${includedir}
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 036b60c..cea99e6 100644 (file)
@@ -105,7 +105,7 @@ MTU of the tunnel.
 .B OpenVPN.NSCertType=client \fR|\fB server
 Peer certificate type, either \fBclient\fP or \fBserver\fP.
 .TP
-.BI OpenVPN.Proto= protocol
+.BI OpenVPN.Protocol= protocol
 Use \fIprotocol\fP.
 .TP
 .BI OpenVPN.Port= port
index 829c498..6130b3b 100644 (file)
@@ -19,6 +19,7 @@ ConnMan-VPN \- VPN management daemon
 .RB [\| \-P
 .IR plugin [,...]\|]
 .RB [\| \-n \|]
+.RB [\| \-r \|]
 .SH DESCRIPTION
 The \fIConnMan-VPN\fP provides a daemon for managing vpn connections together
 with \fBconnmand\fP(8). The Connection Manager is designed to be slim and to
@@ -53,6 +54,9 @@ present, then only debug prints from that source file are printed. Example:
 .BR \-n ", " \-\-nodaemon
 Do not daemonize. This is useful for debugging, and directs log output to
 the controlling terminal in addition to syslog.
+.TP
+.BR \-r ", " \-\-routes
+Manage VPN routes instead of telling \fBconnmand\fP(8) to do it.
 .SH SEE ALSO
 .BR connmanctl (1), \ connman-vpn.conf (5), \c
 .BR \ connman-vpn-provider.config (5), \ connmand (8)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index c0d5adb..f8dbb96
@@ -200,6 +200,32 @@ Properties string State [readonly]
                        This property might be only present for WiFi
                        services.
 
+               string BSSID [readonly]
+
+                       If the service type is WiFi, then this property
+                       indicates the BSSID of the service.
+
+               uint32 MaxRate [readonly]
+
+                       If the service type is WiFi, then this property
+                       indicates the Maximum speed(bps) of the service.
+
+               uint16 Frequency [readonly]
+
+                       If the service type is WiFi, then this property
+                       indicates the frequency band(MHz) of the service.
+
+               string EncryptionMode [readonly]
+
+                       If the service type is WiFi, then this property
+                       indicates the key encryption mode.
+
+                       Possible values are "none", "wep", "tkip", "aes"
+                       and "mixed".
+
+                       This property might be only present for WiFi
+                       services.
+
                uint8 Strength [readonly]
 
                        Indicates the signal strength of the service. This
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index a011e19..9748ae2
@@ -58,8 +58,10 @@ struct GDBusClient {
        void *signal_data;
        GDBusProxyFunction proxy_added;
        GDBusProxyFunction proxy_removed;
+#if !defined TIZEN_EXT
        GDBusClientFunction ready;
        void *ready_data;
+#endif
        GDBusPropertyFunction property_changed;
        void *user_data;
        GList *proxy_list;
@@ -729,6 +731,7 @@ gboolean g_dbus_proxy_set_property_basic(GDBusProxy *proxy,
        return TRUE;
 }
 
+#if !defined TIZEN_EXT
 gboolean g_dbus_proxy_set_property_array(GDBusProxy *proxy,
                                const char *name, int type, const void *value,
                                size_t size, GDBusResultFunction function,
@@ -815,6 +818,7 @@ gboolean g_dbus_proxy_set_property_array(GDBusProxy *proxy,
 
        return TRUE;
 }
+#endif
 
 struct method_call_data {
        GDBusReturnFunction function;
@@ -1095,8 +1099,10 @@ static void get_managed_objects_reply(DBusPendingCall *call, void *user_data)
        parse_managed_objects(client, reply);
 
 done:
+#if !defined TIZEN_EXT
        if (client->ready)
                client->ready(client, client->ready_data);
+#endif
 
        dbus_message_unref(reply);
 
@@ -1367,6 +1373,7 @@ gboolean g_dbus_client_set_signal_watch(GDBusClient *client,
        return TRUE;
 }
 
+#if !defined TIZEN_EXT
 gboolean g_dbus_client_set_ready_watch(GDBusClient *client,
                                GDBusClientFunction ready, void *user_data)
 {
@@ -1378,6 +1385,7 @@ gboolean g_dbus_client_set_ready_watch(GDBusClient *client,
 
        return TRUE;
 }
+#endif
 
 gboolean g_dbus_client_set_proxy_handlers(GDBusClient *client,
                                        GDBusProxyFunction proxy_added,
old mode 100644 (file)
new mode 100755 (executable)
index 69fbc10..70190b7
@@ -339,10 +339,12 @@ gboolean g_dbus_proxy_set_property_basic(GDBusProxy *proxy,
                                GDBusResultFunction function, void *user_data,
                                GDBusDestroyFunction destroy);
 
+#if !defined TIZEN_EXT
 gboolean g_dbus_proxy_set_property_array(GDBusProxy *proxy,
                                const char *name, int type, const void *value,
                                size_t size, GDBusResultFunction function,
                                void *user_data, GDBusDestroyFunction destroy);
+#endif
 
 typedef void (* GDBusSetupFunction) (DBusMessageIter *iter, void *user_data);
 typedef void (* GDBusReturnFunction) (DBusMessage *message, void *user_data);
@@ -352,7 +354,9 @@ gboolean g_dbus_proxy_method_call(GDBusProxy *proxy, const char *method,
                                GDBusReturnFunction function, void *user_data,
                                GDBusDestroyFunction destroy);
 
+#if !defined TIZEN_EXT
 typedef void (* GDBusClientFunction) (GDBusClient *client, void *user_data);
+#endif
 typedef void (* GDBusProxyFunction) (GDBusProxy *proxy, void *user_data);
 typedef void (* GDBusPropertyFunction) (GDBusProxy *proxy, const char *name,
                                        DBusMessageIter *iter, void *user_data);
@@ -379,8 +383,10 @@ gboolean g_dbus_client_set_disconnect_watch(GDBusClient *client,
                                GDBusWatchFunction function, void *user_data);
 gboolean g_dbus_client_set_signal_watch(GDBusClient *client,
                                GDBusMessageFunction function, void *user_data);
+#if !defined TIZEN_EXT
 gboolean g_dbus_client_set_ready_watch(GDBusClient *client,
                                GDBusClientFunction ready, void *user_data);
+#endif
 gboolean g_dbus_client_set_proxy_handlers(GDBusClient *client,
                                        GDBusProxyFunction proxy_added,
                                        GDBusProxyFunction proxy_removed,
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index a220101..c333d5b
@@ -1248,8 +1248,10 @@ static struct generic_data *object_path_ref(DBusConnection *connection,
 
        if (!dbus_connection_register_object_path(connection, path,
                                                &generic_table, data)) {
+#if !defined TIZEN_EXT
                dbus_connection_unref(data->conn);
                g_free(data->path);
+#endif
                g_free(data->introspect);
                g_free(data);
                return NULL;
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index c7b85e5..cc0379e
 #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,
@@ -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, ...)
@@ -512,6 +537,9 @@ static int send_request(GDHCPClient *dhcp_client)
        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)
@@ -1521,6 +1549,21 @@ static gboolean request_timeout(gpointer user_data)
 {
        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);
 
@@ -2284,6 +2327,14 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
 
        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;
        }
 
@@ -2432,6 +2483,10 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
 
                        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);
@@ -2456,6 +2511,18 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition,
 
                        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,
@@ -2693,6 +2760,11 @@ static gboolean ipv4ll_announce_timeout(gpointer dhcp_data)
        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);
 
@@ -2745,6 +2817,11 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address)
        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) {
@@ -2831,13 +2908,32 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address)
                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);
@@ -2881,7 +2977,11 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address)
 
                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);
@@ -2890,7 +2990,11 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address)
        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);
@@ -3031,9 +3135,20 @@ char *g_dhcp_client_get_server_address(GDHCPClient *dhcp_client)
        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);
@@ -3261,6 +3376,9 @@ void g_dhcp_client_unref(GDHCPClient *dhcp_client)
        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,
@@ -3296,3 +3414,19 @@ GSList *g_dhcpv6_copy_prefixes(GSList *prefixes)
 
        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
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index e3b0131..d994488
@@ -154,6 +154,11 @@ GDHCPClientError g_dhcp_client_set_send(GDHCPClient *client,
                                                const char *option_value);
 
 char *g_dhcp_client_get_server_address(GDHCPClient *client);
+
+#if defined TIZEN_EXT
+int g_dhcp_client_get_dhcp_lease_duration(GDHCPClient *client);
+#endif
+
 char *g_dhcp_client_get_address(GDHCPClient *client);
 char *g_dhcp_client_get_netmask(GDHCPClient *client);
 GList *g_dhcp_client_get_option(GDHCPClient *client,
@@ -233,6 +238,10 @@ void g_dhcp_server_set_save_lease(GDHCPServer *dhcp_server,
 void g_dhcp_server_set_lease_added_cb(GDHCPServer *dhcp_server,
                                                        GDHCPLeaseAddedCb cb);
 
+#if defined TIZEN_EXT
+void g_dhcp_client_set_address_known(GDHCPClient *client, gboolean known);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/gdhcp/ipv4ll.h b/gdhcp/ipv4ll.h
new file mode 100755 (executable)
index 0000000..bee8138
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *
+ *  IPV4 Local Link library with GLib integration
+ *
+ *  Copyright (C) 2009-2010  Aldebaran Robotics. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __G_IPV4LL_H
+#define __G_IPV4LL_H
+
+#include <glib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* 169.254.0.0 */
+#define LINKLOCAL_ADDR 0xa9fe0000
+
+/* See RFC 3927 */
+#define PROBE_WAIT          1
+#define PROBE_NUM           3
+#define PROBE_MIN           1
+#define PROBE_MAX           2
+#define ANNOUNCE_WAIT       2
+#define ANNOUNCE_NUM        2
+#define ANNOUNCE_INTERVAL    2
+#define MAX_CONFLICTS      10
+#define RATE_LIMIT_INTERVAL 60
+#define DEFEND_INTERVAL            10
+
+uint32_t ipv4ll_random_ip(void);
+guint ipv4ll_random_delay_ms(guint secs);
+int ipv4ll_send_arp_packet(uint8_t* source_eth, uint32_t source_ip,
+                   uint32_t target_ip, int ifindex);
+int ipv4ll_arp_socket(int ifindex);
+
+#ifdef __cplusplus
+}
+#endif
+#endif     /* !IPV4LL_H_ */
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 2957979..9ad8e08
@@ -30,6 +30,7 @@
 #include <glib.h>
 
 #include "dbus.h"
+#include <connman/log.h>
 
 #define TIMEOUT 30000
 
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 7935c3a..0823a39
@@ -50,17 +50,30 @@ extern "C" {
 #define G_SUPPLICANT_CAPABILITY_MODE_IBSS              (1 << 1)
 #define G_SUPPLICANT_CAPABILITY_MODE_AP                (1 << 2)
 #define G_SUPPLICANT_CAPABILITY_MODE_P2P       (1 << 3)
+#if defined TIZEN_EXT_WIFI_MESH
+#define G_SUPPLICANT_CAPABILITY_MODE_MESH      (1 << 4)
+#endif
 
 #define G_SUPPLICANT_KEYMGMT_NONE              (1 << 0)
 #define G_SUPPLICANT_KEYMGMT_IEEE8021X (1 << 1)
 #define G_SUPPLICANT_KEYMGMT_WPA_NONE  (1 << 2)
 #define G_SUPPLICANT_KEYMGMT_WPA_PSK   (1 << 3)
 #define G_SUPPLICANT_KEYMGMT_WPA_PSK_256       (1 << 4)
+#if defined TIZEN_EXT
+#define G_SUPPLICANT_KEYMGMT_WPA_FT_EAP        (1 << 5)
+#define G_SUPPLICANT_KEYMGMT_WPA_FT_PSK        (1 << 6)
+#else
 #define G_SUPPLICANT_KEYMGMT_WPA_FT_PSK        (1 << 5)
 #define G_SUPPLICANT_KEYMGMT_WPA_FT_EAP        (1 << 6)
+#endif
 #define G_SUPPLICANT_KEYMGMT_WPA_EAP   (1 << 7)
 #define G_SUPPLICANT_KEYMGMT_WPA_EAP_256       (1 << 8)
 #define G_SUPPLICANT_KEYMGMT_WPS               (1 << 9)
+#if defined TIZEN_EXT
+#define G_SUPPLICANT_KEYMGMT_SAE               (1 << 10)
+#define G_SUPPLICANT_KEYMGMT_OWE               (1 << 22)
+#define G_SUPPLICANT_KEYMGMT_DPP               (1 << 23)
+#endif
 
 #define G_SUPPLICANT_PROTO_WPA         (1 << 0)
 #define G_SUPPLICANT_PROTO_RSN         (1 << 1)
@@ -89,16 +102,53 @@ typedef enum {
        G_SUPPLICANT_MODE_INFRA,
        G_SUPPLICANT_MODE_IBSS,
        G_SUPPLICANT_MODE_MASTER,
+#if defined TIZEN_EXT_WIFI_MESH
+       G_SUPPLICANT_MODE_MESH,
+#endif
 } GSupplicantMode;
 
+#if defined TIZEN_EXT_WIFI_MESH
+typedef enum {
+       G_SUPPLICANT_IEEE80211W_UNKNOWN,
+       G_SUPPLICANT_IEEE80211W_OPTIONAL,
+       G_SUPPLICANT_IEEE80211W_REQUIRED,
+} GSupplicantPmf;
+#endif
+
 typedef enum {
        G_SUPPLICANT_SECURITY_UNKNOWN,
        G_SUPPLICANT_SECURITY_NONE,
        G_SUPPLICANT_SECURITY_WEP,
        G_SUPPLICANT_SECURITY_PSK,
        G_SUPPLICANT_SECURITY_IEEE8021X,
+#if defined TIZEN_EXT
+       G_SUPPLICANT_SECURITY_FT_PSK,
+       G_SUPPLICANT_SECURITY_FT_IEEE8021X,
+       G_SUPPLICANT_SECURITY_SAE,
+       G_SUPPLICANT_SECURITY_OWE,
+       G_SUPPLICANT_SECURITY_DPP,
+#endif
 } GSupplicantSecurity;
 
+#if defined TIZEN_EXT
+typedef enum {
+       G_SUPPLICANT_EAP_KEYMGMT_NONE,
+       G_SUPPLICANT_EAP_KEYMGMT_FT,
+       G_SUPPLICANT_EAP_KEYMGMT_CCKM,
+       G_SUPPLICANT_EAP_KEYMGMT_OKC,
+} GSupplicantEapKeymgmt;
+
+typedef enum {
+       G_SUPPLICANT_MODE_IEEE80211_UNKNOWN,
+       G_SUPPLICANT_MODE_IEEE80211B,
+       G_SUPPLICANT_MODE_IEEE80211BG,
+       G_SUPPLICANT_MODE_IEEE80211BGN,
+       G_SUPPLICANT_MODE_IEEE80211A,
+       G_SUPPLICANT_MODE_IEEE80211AN,
+       G_SUPPLICANT_MODE_IEEE80211ANAC,
+} GSupplicantPhy_mode;
+#endif
+
 typedef enum {
        G_SUPPLICANT_STATE_UNKNOWN,
        G_SUPPLICANT_STATE_DISABLED,
@@ -129,8 +179,20 @@ typedef enum {
        G_SUPPLICANT_PEER_GROUP_FAILED,
 } GSupplicantPeerState;
 
+#if defined TIZEN_EXT
+typedef enum {
+       G_SUPPLICANT_INS_PREFERRED_FREQ_UNKNOWN,
+       G_SUPPLICANT_INS_PREFERRED_FREQ_24GHZ,
+       G_SUPPLICANT_INS_PREFERRED_FREQ_5GHZ,
+} GSupplicantINSPreferredFreq;
+#endif
+
 struct _GSupplicantSSID {
+#if defined TIZEN_EXT
+       void *ssid;
+#else
        const void *ssid;
+#endif
        unsigned int ssid_len;
        unsigned int scan_ssid;
        GSupplicantMode mode;
@@ -155,10 +217,32 @@ struct _GSupplicantSSID {
        dbus_bool_t use_wps;
        const char *pin_wps;
        const char *bgscan;
+#if defined TIZEN_EXT
+       unsigned char *bssid;
+       unsigned int bssid_for_connect_len;
+       unsigned char bssid_for_connect[6];
+       GSupplicantEapKeymgmt eap_keymgmt;
+       const char *phase1;
+       const char *pac_file;
+       uint16_t ieee80211w;
+       unsigned int keymgmt;
+       const char *connector;
+       const char *c_sign_key;
+       const char *net_access_key;
+#endif
 };
 
 typedef struct _GSupplicantSSID GSupplicantSSID;
 
+/*
+ * Max number of SSIDs that can be scanned.
+ * In wpa_s 0.7x the limit is 4.
+ * In wps_s 0.8 or later it is 16.
+ * The value is only used if wpa_supplicant does not return any max limit
+ * for number of scannable SSIDs.
+ */
+#define WPAS_MAX_SCAN_SSIDS 4
+
 struct scan_ssid {
        unsigned char ssid[32];
        uint8_t ssid_len;
@@ -196,6 +280,27 @@ struct _GSupplicantP2PServiceParams {
 
 typedef struct _GSupplicantP2PServiceParams GSupplicantP2PServiceParams;
 
+#if defined TIZEN_EXT
+#define WIFI_BSSID_LEN_MAX 6
+
+struct g_connman_bssids {
+       unsigned char bssid[WIFI_BSSID_LEN_MAX];
+       uint16_t strength;
+       uint16_t frequency;
+       uint16_t assoc_reject_cnt;
+       bool is_last_connected;
+       int score_snr;
+#if defined TIZEN_EXT_INS
+       int score_last_connected_bssid;
+       int score_assoc_reject;
+       int score_frequency;
+       int score_strength;
+       int score_est_throughput;
+#endif
+       int ins_score;
+};
+#endif
+
 /* global API */
 typedef void (*GSupplicantCountryCallback) (int result,
                                                const char *alpha2,
@@ -211,15 +316,28 @@ struct _GSupplicantPeer;
 
 typedef struct _GSupplicantInterface GSupplicantInterface;
 typedef struct _GSupplicantPeer GSupplicantPeer;
+#if defined TIZEN_EXT_WIFI_MESH
+typedef struct _GSupplicantMeshPeer GSupplicantMeshPeer;
+#endif
 
 typedef void (*GSupplicantInterfaceCallback) (int result,
                                        GSupplicantInterface *interface,
                                                        void *user_data);
 
+#if defined TIZEN_EXT
+typedef void (*GSupplicantMaxSpeedCallback) (int result, int maxspeed,
+                                            int strength, int snr, void *user_data);
+#endif
+
 void g_supplicant_interface_cancel(GSupplicantInterface *interface);
 
 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);
 int g_supplicant_interface_remove(GSupplicantInterface *interface,
@@ -230,6 +348,12 @@ int g_supplicant_interface_scan(GSupplicantInterface *interface,
                                        GSupplicantInterfaceCallback callback,
                                                        void *user_data);
 
+#if defined TIZEN_EXT
+int g_supplicant_interface_signalpoll(GSupplicantInterface *interface,
+                                       GSupplicantMaxSpeedCallback callback,
+                                       void *user_data);
+#endif
+
 int g_supplicant_interface_p2p_find(GSupplicantInterface *interface,
                                        GSupplicantInterfaceCallback callback,
                                                        void *user_data);
@@ -278,6 +402,27 @@ void g_supplicant_interface_set_data(GSupplicantInterface *interface,
                                                                void *data);
 void *g_supplicant_interface_get_data(GSupplicantInterface *interface);
 const char *g_supplicant_interface_get_ifname(GSupplicantInterface *interface);
+#if defined TIZEN_EXT
+bool g_supplicant_interface_get_is_5_0_ghz_supported(GSupplicantInterface *interface);
+unsigned char *g_supplicant_interface_get_add_network_bssid(GSupplicantInterface *interface);
+
+typedef void (*GSupplicantMacPolicyCallback) (int result, unsigned int policy, void *user_data);
+int g_supplicant_interface_set_mac_policy(GSupplicantInterface *interface,
+                                       GSupplicantMacPolicyCallback callback,
+                                                       unsigned int policy,
+                                                       void *user_data);
+
+int g_supplicant_interface_set_preassoc_mac_policy(GSupplicantInterface *interface,
+                                       GSupplicantMacPolicyCallback callback,
+                                                       unsigned int policy,
+                                                       void *user_data);
+
+typedef void (*GSupplicantRandomMaclifetimeCallback) (int result, unsigned int lifetime, void *user_data);
+int g_supplicant_interface_set_random_mac_lifetime(GSupplicantInterface *interface,
+                                       GSupplicantRandomMaclifetimeCallback callback,
+                                                       unsigned int lifetime,
+                                                       void *user_data);
+#endif
 const char *g_supplicant_interface_get_driver(GSupplicantInterface *interface);
 GSupplicantState g_supplicant_interface_get_state(GSupplicantInterface *interface);
 const char *g_supplicant_interface_get_wps_key(GSupplicantInterface *interface);
@@ -303,6 +448,26 @@ GSupplicantPeer *g_supplicant_interface_peer_lookup(GSupplicantInterface *interf
                                                const char *identifier);
 bool g_supplicant_interface_is_p2p_finding(GSupplicantInterface *interface);
 
+#if defined TIZEN_EXT_WIFI_MESH
+bool g_supplicant_interface_has_mesh(GSupplicantInterface *interface);
+int g_supplicant_mesh_interface_create(const char *ifname, const char *driver,
+                                               const char *bridge, const char *parent_ifname,
+                                               GSupplicantInterfaceCallback callback, void *user_data);
+const void *g_supplicant_interface_get_mesh_group_ssid(
+                                                       GSupplicantInterface *interface,
+                                                       unsigned int *ssid_len);
+int g_supplicant_mesh_get_disconnect_reason(GSupplicantInterface *interface);
+const char *g_supplicant_mesh_peer_get_address(GSupplicantMeshPeer *mesh_peer);
+int g_supplicant_mesh_peer_get_disconnect_reason(
+                                                       GSupplicantMeshPeer *mesh_peer);
+int g_supplicant_interface_abort_scan(GSupplicantInterface *interface,
+                               GSupplicantInterfaceCallback callback, void *user_data);
+int g_supplicant_interface_mesh_peer_change_status(
+                               GSupplicantInterface *interface,
+                               GSupplicantInterfaceCallback callback, const char *peer_address,
+                               const char *method, void *user_data);
+#endif
+
 /* Network and Peer API */
 struct _GSupplicantNetwork;
 struct _GSupplicantGroup;
@@ -340,6 +505,47 @@ GSupplicantInterface *g_supplicant_peer_get_group_interface(GSupplicantPeer *pee
 bool g_supplicant_peer_is_client(GSupplicantPeer *peer);
 bool g_supplicant_peer_has_requested_connection(GSupplicantPeer *peer);
 
+#if defined TIZEN_EXT
+/*
+* Description: Network client requires additional wifi specific info
+*/
+const unsigned char *g_supplicant_network_get_bssid(
+                                               GSupplicantNetwork *network);
+unsigned int g_supplicant_network_get_maxrate(GSupplicantNetwork *network);
+const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network);
+bool g_supplicant_network_get_rsn_mode(GSupplicantNetwork *network);
+bool g_supplicant_network_is_hs20AP(GSupplicantNetwork *network);
+const char *g_supplicant_network_get_eap(GSupplicantNetwork *network);
+const char *g_supplicant_network_get_identity(GSupplicantNetwork *network);
+const char *g_supplicant_network_get_phase2(GSupplicantNetwork *network);
+unsigned int g_supplicant_network_get_keymgmt(GSupplicantNetwork *network);
+dbus_bool_t g_supplicant_network_get_privacy(GSupplicantNetwork *network);
+void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network);
+const unsigned char *g_supplicant_network_get_countrycode(GSupplicantNetwork
+                                                         *network);
+dbus_bool_t g_supplicant_network_is_pmf_required(GSupplicantNetwork *network);
+void *g_supplicant_network_get_bssid_list(GSupplicantNetwork *network);
+GSupplicantPhy_mode g_supplicant_network_get_phy_mode(GSupplicantNetwork *network);
+dbus_bool_t g_supplicant_network_get_transition_mode(GSupplicantNetwork *network);
+const unsigned char *g_supplicant_network_get_transition_mode_bssid(GSupplicantNetwork *network);
+const void *g_supplicant_network_get_transition_mode_ssid(GSupplicantNetwork *network,
+                                                       unsigned int *transition_mode_ssid_len);
+
+#endif
+#if defined TIZEN_EXT
+void g_supplicant_network_set_last_connected_bssid(GSupplicantNetwork *network, const unsigned char *bssid);
+const unsigned char *g_supplicant_network_get_last_connected_bssid(GSupplicantNetwork *network);
+void g_supplicant_network_update_assoc_reject(GSupplicantInterface *interface,
+               GSupplicantNetwork *network);
+GHashTable *g_supplicant_network_get_assoc_reject_table(GSupplicantNetwork *network);
+GSupplicantNetwork *g_supplicant_interface_get_network(GSupplicantInterface *interface,
+               const char *group);
+#endif
+
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+typedef void (*g_supplicant_eap_callback)(GSupplicantInterface *interface, bool status);
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
 struct _GSupplicantCallbacks {
        void (*system_ready) (void);
        void (*system_killed) (void);
@@ -352,9 +558,17 @@ struct _GSupplicantCallbacks {
        void (*ap_create_fail) (GSupplicantInterface *interface);
        void (*network_added) (GSupplicantNetwork *network);
        void (*network_removed) (GSupplicantNetwork *network);
+#if defined TIZEN_EXT
+       void (*network_merged) (GSupplicantNetwork *network);
+#endif
        void (*network_changed) (GSupplicantNetwork *network,
                                        const char *property);
        void (*network_associated) (GSupplicantNetwork *network);
+#if defined TIZEN_EXT
+       void (*system_power_off) (void);
+       void (*assoc_failed) (void *user_data);
+       void (*scan_done) (GSupplicantInterface *interface);
+#endif
        void (*sta_authorized) (GSupplicantInterface *interface,
                                        const char *addr);
        void (*sta_deauthorized) (GSupplicantInterface *interface,
@@ -369,11 +583,39 @@ struct _GSupplicantCallbacks {
                                int reasoncode);
        void (*assoc_status_code)(GSupplicantInterface *interface,
                                int reasoncode);
+#if defined TIZEN_EXT_WIFI_MESH
+       void (*mesh_support) (GSupplicantInterface *interface);
+       void (*mesh_group_started) (GSupplicantInterface *interface);
+       void (*mesh_group_removed) (GSupplicantInterface *interface);
+       void (*mesh_peer_connected) (GSupplicantMeshPeer *mesh_peer);
+       void (*mesh_peer_disconnected) (GSupplicantMeshPeer *mesh_peer);
+#endif
+
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+       g_supplicant_eap_callback eap;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
 };
 
 typedef struct _GSupplicantCallbacks GSupplicantCallbacks;
 
+#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);
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+void g_supplicant_replace_config_file(const char *ifname, const char *config_file);
+void g_supplicant_register_eap_callback(g_supplicant_eap_callback cb);
+void g_supplicant_unregister_eap_callback(void);
+#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 */
 void g_supplicant_unregister(const GSupplicantCallbacks *callbacks);
 
 static inline
old mode 100644 (file)
new mode 100755 (executable)
index f56b595..c76c142
 #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;
@@ -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
        { }
 };
 
@@ -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;
@@ -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;
@@ -191,6 +262,18 @@ struct _GSupplicantInterface {
        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 {
@@ -215,7 +298,27 @@ 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 {
@@ -234,6 +337,23 @@ 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 {
@@ -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;
@@ -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];
@@ -328,6 +496,10 @@ static GSupplicantMode string2mode(const char *mode)
                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;
 }
@@ -343,6 +515,10 @@ static const char *mode2string(GSupplicantMode mode)
                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;
@@ -361,6 +537,18 @@ static const char *security2string(GSupplicantSecurity security)
                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;
@@ -400,6 +588,11 @@ static GSupplicantState string2state(const char *state)
 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;
 
@@ -418,6 +611,23 @@ static bool compare_network_parameters(GSupplicantInterface *interface,
                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;
 }
 
@@ -426,9 +636,19 @@ static void remove_network_information(GSupplicantInterface * interface)
        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,
@@ -447,6 +667,9 @@ 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);
@@ -525,6 +748,7 @@ static void callback_interface_removed(GSupplicantInterface *interface)
        callbacks_pointer->interface_removed(interface);
 }
 
+#if !defined TIZEN_EXT
 static void callback_p2p_support(GSupplicantInterface *interface)
 {
        SUPPLICANT_DBG("");
@@ -535,6 +759,28 @@ static void callback_p2p_support(GSupplicantInterface *interface)
        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)
 {
@@ -591,6 +837,41 @@ static void callback_network_removed(GSupplicantNetwork *network)
        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)
 {
@@ -638,6 +919,19 @@ static void callback_sta_deauthorized(GSupplicantInterface *interface,
        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)
@@ -752,6 +1046,9 @@ static void remove_interface(gpointer data)
        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);
@@ -768,10 +1065,22 @@ static void remove_network(gpointer data)
        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);
 }
 
@@ -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);
 }
 
@@ -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);
@@ -975,7 +1301,13 @@ static void interface_capability(const char *key, DBusMessageIter *iter,
                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));
@@ -1082,6 +1414,24 @@ const char *g_supplicant_interface_get_ifname(GSupplicantInterface *interface)
        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)
@@ -1145,6 +1495,9 @@ unsigned int g_supplicant_interface_get_max_scan_ssids(
        if (!interface)
                return 0;
 
+       if (interface->max_scan_ssids == 0)
+               return WPAS_MAX_SCAN_SSIDS;
+
        return interface->max_scan_ssids;
 }
 
@@ -1297,6 +1650,16 @@ dbus_bool_t g_supplicant_network_is_wps_advertizing(GSupplicantNetwork *network)
        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)
@@ -1345,6 +1708,73 @@ const char *g_supplicant_peer_get_name(GSupplicantPeer *peer)
        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)
 {
@@ -1427,61 +1857,570 @@ bool g_supplicant_peer_has_requested_connection(GSupplicantPeer *peer)
        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;
        }
 
@@ -1612,7 +2551,63 @@ static char *create_group(struct g_supplicant_bss *bss)
 
        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;
@@ -1661,6 +2656,34 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
                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,
@@ -1669,6 +2692,11 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
        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);
 
@@ -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);
@@ -1844,6 +2879,50 @@ static unsigned int get_tlv(unsigned char *ie, unsigned int ie_size,
        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;
@@ -1852,6 +2931,17 @@ static void bss_process_ies(DBusMessageIter *iter, void *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
@@ -1863,6 +2953,12 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
 #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);
@@ -1875,7 +2971,114 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
 
        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;
@@ -1910,6 +3113,13 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data)
 
                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)
@@ -1921,23 +3131,68 @@ 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
@@ -1952,7 +3207,9 @@ static void bss_property(const char *key, DBusMessageIter *iter,
 
        if (!bss->interface)
                return;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("key %s", key);
 
        if (!key)
@@ -2039,6 +3296,23 @@ static void bss_property(const char *key, DBusMessageIter *iter,
                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
@@ -2053,7 +3327,9 @@ static struct g_supplicant_bss *interface_bss_added(DBusMessageIter *iter,
        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);
@@ -2062,7 +3338,9 @@ static struct g_supplicant_bss *interface_bss_added(DBusMessageIter *iter,
 
        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);
@@ -2087,7 +3365,9 @@ static void interface_bss_added_with_keys(DBusMessageIter *iter,
                                                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);
@@ -2097,7 +3377,15 @@ static void interface_bss_added_with_keys(DBusMessageIter *iter,
        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);
 
@@ -2110,7 +3398,9 @@ static void interface_bss_added_without_keys(DBusMessageIter *iter,
                                                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);
@@ -2132,22 +3422,87 @@ static void update_signal(gpointer key, gpointer value,
        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)
@@ -2173,6 +3528,9 @@ static void interface_current_bss(GSupplicantInterface *interface,
                return;
 
        interface->current_network = network;
+#if defined TIZEN_EXT
+       SUPPLICANT_DBG("current network [%p]", interface->current_network);
+#endif
 
        if (bss != network->best_bss) {
                /*
@@ -2184,6 +3542,11 @@ static void interface_current_bss(GSupplicantInterface *interface,
 
                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);
@@ -2191,6 +3554,10 @@ static void interface_current_bss(GSupplicantInterface *interface,
                        network->signal = bss->signal;
                        callback_network_changed(network, "Signal");
                }
+#if defined TIZEN_EXT
+               else
+                       callback_network_changed(network, "");
+#endif
        }
 
        /*
@@ -2214,6 +3581,9 @@ static void interface_current_bss(GSupplicantInterface *interface,
        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;
        }
 }
@@ -2252,7 +3622,11 @@ static void interface_bss_removed(DBusMessageIter *iter, void *user_data)
                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
        }
 }
 
@@ -2268,7 +3642,9 @@ static void wps_property(const char *key, DBusMessageIter *iter,
 
        if (!interface)
                return;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("key: %s", key);
 
        if (g_strcmp0(key, "ConfigMethods") == 0) {
@@ -2291,6 +3667,21 @@ static void wps_property(const char *key, DBusMessageIter *iter,
 
 }
 
+#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)
 {
@@ -2298,7 +3689,9 @@ static void interface_property(const char *key, DBusMessageIter *iter,
 
        if (!interface)
                return;
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("%s", key);
 
        if (!key) {
@@ -2330,8 +3723,14 @@ static void interface_property(const char *key, DBusMessageIter *iter,
        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;
 
@@ -2341,7 +3740,18 @@ static void interface_property(const char *key, DBusMessageIter *iter,
                                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);
@@ -2408,6 +3818,9 @@ static void interface_property(const char *key, DBusMessageIter *iter,
        } 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,
@@ -2423,12 +3836,18 @@ static void interface_property(const char *key, DBusMessageIter *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",
@@ -2464,15 +3883,32 @@ static void scan_bss_data(const char *key, DBusMessageIter *iter,
 {
        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)
@@ -2680,7 +4116,9 @@ static void signal_interface_removed(const char *path, DBusMessageIter *iter)
 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);
@@ -2730,7 +4168,9 @@ static void signal_scan_done(const char *path, DBusMessageIter *iter)
 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);
@@ -2778,6 +4218,13 @@ static void signal_network_removed(const char *path, DBusMessageIter *iter)
 
        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)
 {
@@ -2815,6 +4262,40 @@ static void signal_sta_deauthorized(const char *path, DBusMessageIter *iter)
        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;
@@ -2823,6 +4304,9 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
        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);
@@ -2839,6 +4323,12 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
 
        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);
 
@@ -2864,6 +4354,9 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
 
                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;
@@ -2902,26 +4395,54 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter)
                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);
@@ -3030,6 +4551,29 @@ static void signal_wps_event(const char *path, DBusMessageIter *iter)
        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] = {};
@@ -3567,9 +5111,217 @@ static void signal_group_peer_disconnected(const char *path, DBusMessageIter *it
        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;
@@ -3596,6 +5348,9 @@ static struct {
 
        { 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  },
@@ -3610,6 +5365,20 @@ static struct {
 
        { 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 */
 
        { }
 };
@@ -3888,6 +5657,9 @@ static void interface_create_data_free(struct interface_create_data *data)
        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);
 }
 
@@ -3912,7 +5684,12 @@ static void interface_create_property(const char *key, DBusMessageIter *iter,
        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);
@@ -3999,9 +5776,80 @@ static void interface_create_params(DBusMessageIter *iter, void *user_data)
                                        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)
 {
@@ -4010,6 +5858,9 @@ static void interface_get_result(const char *error,
        const char *path = NULL;
        int err;
 
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        SUPPLICANT_DBG("");
 
        if (error) {
@@ -4029,9 +5880,24 @@ static void interface_get_result(const char *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);
@@ -4065,14 +5931,132 @@ done:
 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)
 {
@@ -4095,6 +6079,11 @@ int g_supplicant_interface_create(const char *ifname, const char *driver,
        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,
@@ -4150,7 +6139,6 @@ static void interface_remove_params(DBusMessageIter *iter, void *user_data)
                                                        &data->interface->path);
 }
 
-
 int g_supplicant_interface_remove(GSupplicantInterface *interface,
                        GSupplicantInterfaceCallback callback,
                                                        void *user_data)
@@ -4327,6 +6315,10 @@ static void interface_scan_params(DBusMessageIter *iter, void *user_data)
                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",
@@ -4361,8 +6353,14 @@ static int interface_ready_to_scan(GSupplicantInterface *interface)
        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:
@@ -4373,6 +6371,57 @@ static int interface_ready_to_scan(GSupplicantInterface *interface)
        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,
@@ -4391,8 +6440,13 @@ int g_supplicant_interface_scan(GSupplicantInterface *interface,
 
        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;
@@ -4411,6 +6465,104 @@ int g_supplicant_interface_scan(GSupplicantInterface *interface,
        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;
@@ -4447,7 +6599,11 @@ static void interface_select_network_result(const char *error,
 
        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);
        }
 
@@ -4456,6 +6612,13 @@ static void interface_select_network_result(const char *error,
        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);
 }
@@ -4465,9 +6628,16 @@ static void interface_select_network_params(DBusMessageIter *iter,
 {
        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,
@@ -4487,15 +6657,37 @@ 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;
 
@@ -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);
 }
@@ -4661,8 +6860,10 @@ static void add_network_security_tls(DBusMessageIter *dict,
        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",
@@ -4671,9 +6872,11 @@ static void add_network_security_tls(DBusMessageIter *dict,
        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);
@@ -4705,8 +6908,10 @@ static void add_network_security_peap(DBusMessageIter *dict,
                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,
@@ -4716,9 +6921,11 @@ static void add_network_security_peap(DBusMessageIter *dict,
                                                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
 
        }
 
@@ -4746,19 +6953,85 @@ static void add_network_security_peap(DBusMessageIter *dict,
        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;
 
@@ -4767,9 +7040,16 @@ static void add_network_security_eap(DBusMessageIter *dict,
        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,
@@ -4890,6 +7170,83 @@ static void add_network_security_proto(DBusMessageIter *dict,
        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;
@@ -4918,6 +7275,38 @@ static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid)
                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",
@@ -4939,6 +7328,11 @@ static void add_network_mode(DBusMessageIter *dict, GSupplicantSSID *ssid)
        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",
@@ -4950,6 +7344,9 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
        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);
 
@@ -4967,93 +7364,423 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data)
 
        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,
@@ -5138,13 +7865,30 @@ int g_supplicant_interface_connect(GSupplicantInterface *interface,
                        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);
@@ -5190,6 +7934,27 @@ static void network_remove_result(const char *error,
                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,
@@ -5219,6 +7984,16 @@ static int network_remove(struct interface_data *data)
 
        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,
@@ -5285,7 +8060,17 @@ int g_supplicant_interface_disconnect(GSupplicantInterface *interface,
 
        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;
@@ -5777,12 +8562,18 @@ static const char *g_supplicant_rule4 = "type=signal,"
                        "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)
 {
@@ -5801,7 +8592,65 @@ 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)
@@ -5813,7 +8662,9 @@ int g_supplicant_register(const GSupplicantCallbacks *callbacks)
                connection = NULL;
                return -EIO;
        }
-
+#if defined TIZEN_EXT
+       simplified_log = connman_setting_get_bool("SimplifiedLog");
+#endif
        callbacks_pointer = callbacks;
        eap_methods = 0;
 
@@ -5839,9 +8690,19 @@ int g_supplicant_register(const GSupplicantCallbacks *callbacks)
        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,
@@ -5853,6 +8714,7 @@ int g_supplicant_register(const GSupplicantCallbacks *callbacks)
        } else
                invoke_introspect_method();
 
+       SUPPLICANT_DBG("supplicant dbus setup completed");
        return 0;
 }
 
@@ -5883,9 +8745,14 @@ void g_supplicant_unregister(const GSupplicantCallbacks *callbacks)
        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);
@@ -5936,3 +8803,176 @@ void g_supplicant_unregister(const GSupplicantCallbacks *callbacks)
        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
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 12fcb1d..69aea5b
@@ -809,6 +809,10 @@ static void handle_multi_line(struct web_session *session)
                g_string_insert_c(session->current_header, 0, ' ');
        }
 
+#if defined TIZEN_EXT
+       if (session->result.last_key == NULL)
+               return;
+#endif
        value = g_hash_table_lookup(session->result.headers,
                                        session->result.last_key);
        if (value) {
@@ -1257,6 +1261,16 @@ static void resolv_result(GResolvResultStatus status,
                return;
        }
 
+#if defined TIZEN_EXT
+       // check the DNS address validation
+       // if dns is the class c private address
+       // wispr should be stopped - non internet connection
+       if(g_str_has_prefix(results[0],"192.168.")){
+               call_result_func(session, 404);
+               return;
+       }
+#endif
+
        g_free(session->address);
        session->address = g_strdup(results[0]);
 
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 12a202d..65415fb 100644 (file)
@@ -22,7 +22,7 @@
 #ifndef __CONNMAN_BACKTRACE_H
 #define __CONNMAN_BACKTRACE_H
 
-#ifdef HAVE_EXECINFO_H
+#if defined HAVE_EXECINFO_H && defined BACKTRACE
 void print_backtrace(const char* program_path, const char* program_exec,
                unsigned int offset);
 #else
index bcab418..d53037b 100644 (file)
@@ -45,6 +45,9 @@ extern "C" {
 #define CONNMAN_SESSION_INTERFACE      CONNMAN_SERVICE ".Session"
 #define CONNMAN_NOTIFICATION_INTERFACE CONNMAN_SERVICE ".Notification"
 #define CONNMAN_PEER_INTERFACE         CONNMAN_SERVICE ".Peer"
+#if defined TIZEN_EXT_WIFI_MESH
+#define CONNMAN_MESH_INTERFACE         CONNMAN_SERVICE ".Mesh"
+#endif
 
 #define CONNMAN_PRIVILEGE_MODIFY       1
 #define CONNMAN_PRIVILEGE_SECRET       2
old mode 100644 (file)
new mode 100755 (executable)
index 0fc06bd..8cc8cce
@@ -106,6 +106,20 @@ int connman_device_add_network(struct connman_device *device,
                                        struct connman_network *network);
 struct connman_network *connman_device_get_network(struct connman_device *device,
                                                        const char *identifier);
+#if defined TIZEN_EXT
+struct connman_network *connman_device_get_default_network(
+                                                       struct connman_device *device);
+void connman_device_set_pending_reply(struct connman_device *device,
+                                                       DBusMessage *msg);
+void connman_device_send_connected_signal(struct connman_device *device,
+                                                       bool connected);
+void connman_device_set_max_scan_ssids(struct connman_device *device,
+                                                       int max_scan_ssids);
+int connman_device_get_max_scan_ssids(struct connman_device *device);
+void connman_device_set_wifi_5ghz_supported(struct connman_device *device,
+                                                       bool is_5_0_ghz_supported);
+bool connman_device_get_wifi_5ghz_supported(struct connman_device *device);
+#endif
 int connman_device_remove_network(struct connman_device *device,
                                        struct connman_network *network);
 
@@ -123,6 +137,38 @@ struct connman_device *connman_device_create_from_index(int index);
 struct connman_device *connman_device_find_by_index(int index);
 int connman_device_reconnect_service(struct connman_device *device);
 
+#if defined TIZEN_EXT
+bool connman_device_set_last_user_selection_time(struct connman_device *device,
+                                               time_t time);
+time_t connman_device_get_last_user_selection_time(struct connman_device *device);
+bool connman_device_set_last_user_selection_ident(struct connman_device *device,
+                                               const char *ident);
+const char *connman_device_get_last_user_selection_ident(struct connman_device *device);
+bool connman_device_set_last_connected_ident(struct connman_device *device,
+                                               const char *ident);
+const char *connman_device_get_last_connected_ident(struct connman_device *device);
+void connman_device_save_last_user_selection(struct connman_device *device);
+void connman_device_load_last_user_selection(struct connman_device *device);
+void connman_device_save_last_connected(struct connman_device *device);
+void connman_device_load_last_connected(struct connman_device *device);
+
+void connman_device_mac_policy_notify(struct connman_device *device,
+                                       int result, unsigned int policy);
+int connman_device_set_mac_policy(struct connman_device *device,
+                                               unsigned int policy);
+unsigned int connman_device_get_mac_policy(struct connman_device *device);
+void connman_device_preassoc_mac_policy_notify(struct connman_device *device,
+                                       int result, unsigned int policy);
+int connman_device_set_preassoc_mac_policy(struct connman_device *device,
+                                               unsigned int policy);
+unsigned int connman_device_get_preassoc_mac_policy(struct connman_device *device);
+void connman_device_random_mac_lifetime_notify(struct connman_device *device,
+                                       int result, unsigned int lifetime);
+int connman_device_set_random_mac_lifetime(struct connman_device *device,
+                                               unsigned int lifetime);
+unsigned int connman_device_get_random_mac_lifetime(struct connman_device *device);
+#endif
+
 struct connman_device_driver {
        const char *name;
        enum connman_device_type type;
@@ -137,6 +183,21 @@ struct connman_device_driver {
                        struct connman_device *device);
        int (*set_regdom) (struct connman_device *device,
                                                const char *alpha2);
+#if defined TIZEN_EXT
+       int (*specific_scan) (enum connman_service_type type,
+                       struct connman_device *device, int scan_type,
+                       GSList *specific_scan_list, void *user_data);
+       int (*set_mac_policy) (struct connman_device *device, unsigned int policy);
+       int (*set_preassoc_mac_policy) (struct connman_device *device, unsigned int policy);
+       int (*set_random_mac_lifetime) (struct connman_device *device, unsigned int lifetime);
+#endif
+#if defined TIZEN_EXT_WIFI_MESH
+       int (*abort_scan) (enum connman_service_type type,
+                                               struct connman_device *device);
+       int (*mesh_specific_scan) (enum connman_service_type type,
+                       struct connman_device *device, const char *ssid, unsigned int freq,
+                       void *user_data);
+#endif
 };
 
 int connman_device_driver_register(struct connman_device_driver *driver);
index 9245eef..579f7f7 100644 (file)
@@ -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);
@@ -87,6 +91,11 @@ 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
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 8b00e9d..9403633
 #ifndef __CONNMAN_LOG_H
 #define __CONNMAN_LOG_H
 
+#if defined TIZEN_EXT
+#include <stdbool.h>
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -52,7 +56,11 @@ void connman_debug(const char *format, ...)
 struct connman_debug_desc {
        const char *name;
        const char *file;
+#if defined TIZEN_EXT
+#define CONNMAN_DEBUG_FLAG_DEFAULT (1)
+#else
 #define CONNMAN_DEBUG_FLAG_DEFAULT (0)
+#endif
 #define CONNMAN_DEBUG_FLAG_PRINT   (1 << 0)
 #define CONNMAN_DEBUG_FLAG_ALIAS   (1 << 1)
        unsigned int flags;
@@ -82,6 +90,14 @@ struct connman_debug_desc {
                                        __FILE__, __FUNCTION__ , ## arg); \
 } while (0)
 
+#if defined TIZEN_EXT
+#define simplified_log get_simple_log_option()
+bool get_simple_log_option(void);
+void set_simple_log_option(bool option);
+void set_dlog_logging_option(bool option);
+void set_file_logging_option(bool option);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/include/mesh-netlink.h b/include/mesh-netlink.h
new file mode 100644 (file)
index 0000000..78b3e36
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *
+ *  Copyright (C) 2017 Samsung Electronics Co., Ltd.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ *  02110-1301  USA
+ */
+
+#ifndef __CONNMAN_MESH_NETLINK_H
+#define __CONNMAN_MESH_NETLINK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+       int id;
+       struct nl_sock *nl_socket;
+       struct nl_cb *cb;
+} mesh_nl80211_global;
+
+#define MESH_HWMP_ROOTMODE_NO_ROOT                                             0
+#define MESH_HWMP_ROOTMODE_PROACTIVE_PREQ_NO_PREP              2
+#define MESH_HWMP_ROOTMODE_PROACTIVE_PREQ_WITH_PREP            3
+#define MESH_HWMP_ROOTMODE_RANN                                                        4
+
+#define NL80211_ATTR_IFINDEX                                                   3
+#define NL80211_CMD_SET_MESH_CONFIG                                            29
+#define NL80211_ATTR_MESH_CONFIG                                               35
+
+#define NL80211_MESHCONF_HWMP_ROOTMODE                                 14
+#define NL80211_MESHCONF_GATE_ANNOUNCEMENTS                            17
+
+int __connman_mesh_netlink_set_gate_announce(mesh_nl80211_global *global,
+                                       int mesh_if_index, bool gate_announce, int hwmp_rootmode);
+
+mesh_nl80211_global *__connman_mesh_nl80211_global_init(void);
+void __connman_mesh_nl80211_global_deinit(mesh_nl80211_global *global);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CONNMAN_MESH_NETLINK_H */
diff --git a/include/mesh.h b/include/mesh.h
new file mode 100644 (file)
index 0000000..547c237
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *
+ *  Copyright (C) 2017 Samsung Electronics Co., Ltd.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ *  02110-1301  USA
+ */
+
+#ifndef __CONNMAN_MESH_H
+#define __CONNMAN_MESH_H
+
+#include <gdbus.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct connman_mesh;
+
+enum connman_mesh_security {
+       CONNMAN_MESH_SECURITY_UNKNOWN = 0,
+       CONNMAN_MESH_SECURITY_NONE    = 1,
+       CONNMAN_MESH_SECURITY_SAE     = 2,
+};
+
+enum connman_mesh_state {
+       CONNMAN_MESH_STATE_UNKNOWN       = 0,
+       CONNMAN_MESH_STATE_IDLE          = 1,
+       CONNMAN_MESH_STATE_ASSOCIATION   = 2,
+       CONNMAN_MESH_STATE_CONFIGURATION = 3,
+       CONNMAN_MESH_STATE_READY         = 4,
+       CONNMAN_MESH_STATE_DISCONNECT    = 5,
+       CONNMAN_MESH_STATE_FAILURE       = 6,
+};
+
+enum connman_mesh_peer_type {
+       CONNMAN_MESH_PEER_TYPE_CREATED    = 0,
+       CONNMAN_MESH_PEER_TYPE_DISCOVERED = 1,
+};
+
+enum connman_mesh_peer_disconnect_reason {
+       CONNMAN_MESH_REASON_UNKNOWN          = 0,
+       CONNMAN_MESH_DEAUTH_LEAVING          = 1,
+       CONNMAN_MESH_PEERING_CANCELLED       = 2,
+       CONNMAN_MESH_MAX_PEERS               = 3,
+       CONNMAN_MESH_CONFIG_POLICY_VIOLATION = 4,
+       CONNMAN_MESH_CLOSE_RCVD              = 5,
+       CONNMAN_MESH_MAX_RETRIES             = 6,
+       CONNMAN_MESH_CONFIRM_TIMEOUT         = 7,
+       CONNMAN_MESH_INVALID_GTK             = 8,
+       CONNMAN_MESH_INCONSISTENT_PARAMS     = 9,
+       CONNMAN_MESH_INVALID_SECURITY_CAP    = 10,
+};
+
+enum connman_mesh_peer_status {
+       CONNMAN_MESH_PEER_ADD    = 0,
+       CONNMAN_MESH_PEER_REMOVE = 1,
+};
+
+struct connman_mesh *connman_mesh_create(const char *interface_addr,
+                                                                       const char *identifier);
+
+void connman_mesh_set_name(struct connman_mesh *mesh, const char *name);
+const char *connman_mesh_get_name(struct connman_mesh *mesh);
+void connman_mesh_set_passphrase(struct connman_mesh *mesh,
+                                                                const char *passphrase);
+const char *connman_mesh_get_passphrase(struct connman_mesh *mesh);
+void connman_mesh_set_address(struct connman_mesh *mesh, const char *address);
+void connman_mesh_set_security(struct connman_mesh *mesh, const char *security);
+const char *connman_mesh_get_security(struct connman_mesh *mesh);
+void connman_mesh_set_frequency(struct connman_mesh *mesh, uint16_t frequency);
+uint16_t connman_mesh_get_frequency(struct connman_mesh *mesh);
+void connman_mesh_set_ieee80211w(struct connman_mesh *mesh, uint16_t ieee80211w);
+uint16_t connman_mesh_get_ieee80211w(struct connman_mesh *mesh);
+int connman_mesh_peer_set_state(struct connman_mesh *mesh,
+                                                               enum connman_mesh_state new_state);
+void connman_mesh_set_peer_type(struct connman_mesh *mesh,
+                                                               enum connman_mesh_peer_type type);
+bool connman_mesh_peer_is_connected_state(struct connman_mesh *mesh);
+struct connman_mesh *connman_get_connected_mesh_from_name(char *name);
+struct connman_mesh *connman_get_connecting_mesh_from_name(char *name);
+void connman_mesh_set_index(struct connman_mesh *mesh, int index);
+void connman_mesh_set_strength(struct connman_mesh *mesh, uint8_t strength);
+void connman_mesh_peer_set_disconnect_reason(struct connman_mesh *mesh,
+                                               int disconnect_reason);
+void __connman_mesh_add_ethernet_to_bridge(void);
+void __connman_mesh_remove_ethernet_from_bridge(void);
+int __connman_mesh_change_peer_status(DBusMessage *msg,
+                                      const char *peer_address,
+                                      enum connman_mesh_peer_status status);
+
+int connman_mesh_register(struct connman_mesh *mesh);
+void connman_mesh_unregister(struct connman_mesh *mesh);
+
+int __connman_mesh_add_virtual_interface(const char *ifname,
+                                         const char *parent_ifname, const char *bridge_ifname);
+
+int __connman_mesh_remove_virtual_interface(const char *ifname);
+int __connman_mesh_set_stp_gate_announce(bool gate_announce, int hwmp_rootmode,
+                                         int stp);
+
+const char *connman_mesh_get_interface_name(void);
+bool connman_mesh_is_interface_created(void);
+
+struct connman_mesh *connman_mesh_get(const char *interface_addr,
+                                      const char *identifier);
+
+int connman_mesh_notify_interface_create(bool success);
+int connman_mesh_notify_interface_remove(bool success);
+
+int connman_mesh_add_connected_peer(const char *peer_address);
+int connman_mesh_remove_connected_peer(const char *peer_address, int reason);
+
+typedef void (*mesh_change_peer_status_cb_t) (int result, void *user_data);
+
+struct connman_mesh_driver {
+       int (*add_interface) (const char *ifname, const char *parent_ifname);
+       int (*remove_interface) (const char *ifname);
+       int (*connect) (struct connman_mesh *mesh);
+       int (*disconnect) (struct connman_mesh *mesh);
+       int (*change_peer_status) (const char *peer_address,
+                                               enum connman_mesh_peer_status status,
+                                               mesh_change_peer_status_cb_t callback, void *user_data);
+};
+
+int connman_mesh_driver_register(struct connman_mesh_driver *driver);
+void connman_mesh_driver_unregister(struct connman_mesh_driver *driver);
+
+struct connman_mesh_eth_driver {
+       int (*add_to_bridge) (const char *bridge);
+       int (*remove_from_bridge) (const char *bridge);
+};
+
+int connman_mesh_eth_driver_register(struct connman_mesh_eth_driver *driver);
+void connman_mesh_eth_driver_unregister(struct connman_mesh_eth_driver *driver);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CONNMAN_MESH_H */
old mode 100644 (file)
new mode 100755 (executable)
index 8f9dd94..4d09dff
 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
@@ -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
@@ -92,6 +144,12 @@ void connman_network_set_group(struct connman_network *network,
 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);
@@ -121,6 +179,83 @@ int connman_network_set_nameservers(struct connman_network *network,
                                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,
@@ -147,6 +282,10 @@ int connman_network_set_blob(struct connman_network *network,
                        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);
 
@@ -165,6 +304,9 @@ struct connman_network_driver {
        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);
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 8f6b36b..041949f
 
 #include <stdbool.h>
 
+#if defined TIZEN_EXT
+#include <glib.h>
+#include <gdbus.h>
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -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 {
@@ -57,6 +69,14 @@ 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 {
@@ -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 {
@@ -150,6 +173,53 @@ void connman_service_create_ip4config(struct connman_service *service,
 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
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 920e675..f141bf6
@@ -29,6 +29,9 @@ extern "C" {
 #endif
 
 bool connman_setting_get_bool(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);
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 7508a9a..d47f566
@@ -34,6 +34,27 @@ extern "C" {
  * @short_description: Functions for handling technology details
  */
 
+#if defined TIZEN_EXT
+typedef enum {
+       CONNMAN_MULTI_SCAN_SSID = 0x01,
+       CONNMAN_MULTI_SCAN_FREQ,
+       CONNMAN_MULTI_SCAN_SSID_FREQ,
+} connman_multi_scan_type_e;
+
+typedef enum {
+       CONNMAN_SCAN_TYPE_FULL_CHANNEL = 0x00,
+       CONNMAN_SCAN_TYPE_SPECIFIC_AP,
+       CONNMAN_SCAN_TYPE_MULTI_AP,
+       CONNMAN_SCAN_TYPE_WPA_SUPPLICANT,
+       CONNMAN_SCAN_TYPE_UNKNOWN,
+} connman_scan_type_e;
+
+typedef struct {
+       char str[128];
+       gboolean flag;
+} connman_multi_scan_ap_s;
+#endif
+
 struct connman_technology;
 
 int connman_technology_tethering_notify(struct connman_technology *technology,
@@ -68,6 +89,14 @@ struct connman_technology_driver {
 
 int connman_technology_driver_register(struct connman_technology_driver *driver);
 void connman_technology_driver_unregister(struct connman_technology_driver *driver);
+#if defined TIZEN_EXT
+const char *connman_techonology_get_path(enum connman_service_type type);
+void __connman_technology_notify_scan_done(const char *ifname, int val);
+void __connman_technology_append_interfaces(DBusMessageIter *array,
+                               enum connman_service_type type, const char *ifname);
+void __connman_technology_notify_roaming_state(const char *ifname,
+               const char *state, const char *cur_bssid, const char *dst_bssid);
+#endif
 
 #ifdef __cplusplus
 }
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/packaging/connman.spec b/packaging/connman.spec
new file mode 100644 (file)
index 0000000..8fbb03d
--- /dev/null
@@ -0,0 +1,349 @@
+%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
old mode 100644 (file)
new mode 100755 (executable)
index 5336103..a8383e7
@@ -192,8 +192,14 @@ static bool pan_connect(struct bluetooth_pan *pan,
                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;
 }
@@ -262,6 +268,9 @@ static int bluetooth_pan_connect(struct connman_network *network)
                        g_strdup(path), g_free))
                return -EIO;
 
+#if defined TIZEN_EXT
+       if (pan->network)
+#endif
        connman_network_set_associating(pan->network, true);
 
        return -EINPROGRESS;
@@ -286,6 +295,9 @@ static void pan_disconnect_cb(DBusMessage *message, void *user_data)
 
        DBG("network %p", pan->network);
 
+#if defined TIZEN_EXT
+       if (pan->network)
+#endif
        connman_network_set_connected(pan->network, false);
 }
 
@@ -299,6 +311,11 @@ static int bluetooth_pan_disconnect(struct connman_network *network)
        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",
@@ -524,7 +541,9 @@ static void device_enable_cb(const DBusError *error, void *user_data)
                goto out;
        }
 
+#if !defined TIZEN_EXT
        enable_device(device, path);
+#endif
 out:
        g_free(path);
 }
@@ -591,7 +610,9 @@ static void device_disable_cb(const DBusError *error, void *user_data)
                goto out;
        }
 
+#if !defined TIZEN_EXT
        disable_device(device, path);
+#endif
 
 out:
        g_free(path);
old mode 100644 (file)
new mode 100755 (executable)
index 5887a34..a051d92
@@ -5,6 +5,10 @@
         <allow own="org.freedesktop.NetworkManager"/>
         <allow send_destination="org.freedesktop.NetworkManager"/>
     </policy>
+    <policy user="network_fw">
+        <allow own="org.freedesktop.NetworkManager"/>
+        <allow send_destination="org.freedesktop.NetworkManager"/>
+    </policy>
     <policy at_console="true">
         <allow send_destination="org.freedesktop.NetworkManager"/>
     </policy>
old mode 100644 (file)
new mode 100755 (executable)
index 6146b1c..766f8e4 100644 (file)
 #include <connman/rtnl.h>
 #include <connman/log.h>
 #include <connman/setting.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;
 
@@ -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 */
 };
 
 
@@ -141,6 +151,239 @@ static void eth_network_remove(struct connman_network *network)
        DBG("network %p", network);
 }
 
+#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);
@@ -159,6 +402,8 @@ static int eth_network_disconnect(struct connman_network *network)
        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,
@@ -256,6 +501,10 @@ static void ethernet_newlink(unsigned flags, unsigned change, void *user_data)
                } 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
                }
        }
 
@@ -276,6 +525,9 @@ static int eth_dev_probe(struct connman_device *device)
 
        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);
@@ -291,6 +543,16 @@ static void eth_dev_remove(struct connman_device *device)
 
        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);
@@ -434,6 +696,54 @@ static struct connman_technology_driver eth_tech_driver = {
        .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;
@@ -442,6 +752,12 @@ static int ethernet_init(void)
        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;
@@ -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);
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 4ba107f..194a99d 100644 (file)
@@ -1630,6 +1630,86 @@ static void create_network(GDBusProxy *proxy)
        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)
 {
old mode 100644 (file)
new mode 100755 (executable)
index e113887..3809d8f
 #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>
@@ -46,6 +48,39 @@ static in_addr_t loopback_netmask;
 
 static char system_hostname[HOST_NAME_MAX + 1];
 
+#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";
@@ -56,6 +91,8 @@ static void create_hostname(void)
        strncpy(system_hostname, name, HOST_NAME_MAX);
 }
 
+#endif
+
 static int setup_hostname(void)
 {
        char name[HOST_NAME_MAX + 1];
@@ -67,11 +104,20 @@ static int setup_hostname(void)
                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));
 
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/plugins/telephony.c b/plugins/telephony.c
new file mode 100755 (executable)
index 0000000..5c37d88
--- /dev/null
@@ -0,0 +1,1936 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <gdbus.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CONNMAN_API_SUBJECT_TO_CHANGE
+#include <connman/dbus.h>
+#include <connman/inet.h>
+#include <connman/plugin.h>
+#include <connman/network.h>
+#include <connman/setting.h>
+#include <connman/technology.h>
+
+#include <connman.h>
+
+#define PS_DBUS_SERVICE                                "com.tcore.ps"
+#define TELEPHONY_DBUS_SERVICE                 "org.tizen.telephony"
+
+#define PS_MASTER_INTERFACE                    PS_DBUS_SERVICE ".master"
+#define PS_MODEM_INTERFACE                     PS_DBUS_SERVICE ".modem"
+#define PS_SERVICE_INTERFACE           PS_DBUS_SERVICE ".service"
+#define PS_CONTEXT_INTERFACE           PS_DBUS_SERVICE ".context"
+
+/* methods */
+#define GET_MODEMS                             "GetModems"
+#define GET_SERVICES                   "GetServices"
+#define GET_CONTEXTS                   "GetContexts"
+#define ACTIVATE_CONTEXT               "Activate"
+#define DEACTIVATE_CONTEXT             "Deactivate"
+#define GET_PROPERTIES                 "GetProperties"
+#define SET_PROPERTY                   "SetProperties"
+
+/* signals */
+#define MODEM_ADDED                            "ModemAdded"
+#define MODEM_REMOVED                  "ModemRemoved"
+#define SERVICE_ADDED                  "ServiceAdded"
+#define SERVICE_REMOVED                        "ServiceRemoved"
+#define CONTEXT_ADDED                  "ContextAdded"
+#define CONTEXT_REMOVED                        "ContextRemoved"
+#define PROPERTY_CHANGED               "PropertyChanged"
+
+#define TIMEOUT 130000
+
+#define STRING2BOOL(a) (!(g_strcmp0(a, "TRUE")) ? (TRUE):(FALSE))
+
+static DBusConnection *connection;
+static GHashTable      *modem_hash;
+static GHashTable      *service_hash;
+static GHashTable      *network_hash;
+
+struct telephony_service {
+       char *path;
+
+       gpointer p_modem;
+       char *act;
+       gboolean roaming; /* global roaming state */
+       gboolean ps_attached; /* packet service is available */
+};
+
+struct telephony_modem {
+       char *path;
+
+       char *operator;
+       gboolean powered;
+       gboolean sim_init;
+       gboolean flight_mode;
+       gboolean data_allowed;
+       gboolean roaming_allowed;
+
+       struct connman_device *device;
+       struct telephony_service *s_service;
+};
+
+struct telephony_network {
+       char *path;
+       int if_index;
+       gboolean routing_only;
+       gboolean ipv6_link_only;
+
+       struct connman_network *network;
+
+       enum connman_ipconfig_method ipv4_method;
+       struct connman_ipaddress *ipv4_address;
+
+       enum connman_ipconfig_method ipv6_method;
+       struct connman_ipaddress *ipv6_address;
+};
+
+static int telephony_default_subscription_id = 0;
+
+/* function prototype */
+static void telephony_connect(DBusConnection *connection, void *user_data);
+static void telephony_disconnect(DBusConnection *connection, void *user_data);
+static void __remove_modem(gpointer data);
+static void __remove_service(gpointer data);
+static void __remove_network(gpointer data);
+
+static int __modem_probe(struct connman_device *device);
+static void __modem_remove(struct connman_device *device);
+static int __modem_enable(struct connman_device *device);
+static int __modem_disable(struct connman_device *device);
+
+static int __network_probe(struct connman_network *network);
+static void __network_remove(struct connman_network *network);
+static int __network_connect(struct connman_network *network);
+static int __network_disconnect(struct connman_network *network);
+
+
+/* dbus request and reply */
+static int __dbus_request(const char *service, const char *path, const char *interface,
+                       const char *method,
+                       DBusPendingCallNotifyFunction notify, void *user_data,
+                       DBusFreeFunction free_function, int type, ...);
+
+static int __request_get_modems(void);
+static void __response_get_modems(DBusPendingCall *call, void *user_data);
+static int __request_get_services(const char *path);
+static void __response_get_services(DBusPendingCall *call, void *user_data);
+static int __request_get_contexts(struct telephony_modem *modem);
+static void __response_get_contexts(DBusPendingCall *call, void *user_data);
+static int __request_network_activate(struct connman_network *network);
+static void __response_network_activate(DBusPendingCall *call, void *user_data);
+static int __request_network_deactivate(struct connman_network *network);
+
+/* telephony internal function */
+static void __add_modem(const char *path, DBusMessageIter *prop);
+static void __add_service(struct telephony_modem *modem,
+                       const char *service_path, DBusMessageIter *prop);
+static void __add_connman_device(const char *modem_path, const char *operator);
+static void __remove_connman_device(struct telephony_modem *modem);
+static void __remove_connman_networks(struct connman_device *device);
+static int __add_context(struct connman_device *device, const char *path,
+                                                       DBusMessageIter *prop);
+
+/* signal handler */
+static gboolean __changed_modem(DBusConnection *connection,
+                               DBusMessage *message, void *user_data);
+static gboolean __added_modem(DBusConnection *connection,
+                               DBusMessage *message, void *user_data);
+static gboolean __removed_modem(DBusConnection *connection,
+                               DBusMessage *message, void *user_data);
+static gboolean __changed_service(DBusConnection *connection,
+                               DBusMessage *message, void *user_data);
+static gboolean __added_service(DBusConnection *connection,
+                               DBusMessage *message, void *user_data);
+static gboolean __removed_service(DBusConnection *connection,
+                               DBusMessage *message, void *user_data);
+static gboolean __changed_context(DBusConnection *connection,
+                               DBusMessage *message, void *user_data);
+static gboolean __added_context(DBusConnection *connection,
+                               DBusMessage *message, void *user_data);
+static gboolean __removed_context(DBusConnection *connection,
+                               DBusMessage *message, void *user_data);
+
+/* device driver */
+static struct connman_device_driver modem_driver = {
+       .name           = "device",
+       .type           = CONNMAN_DEVICE_TYPE_CELLULAR,
+       .probe          = __modem_probe,
+       .remove         = __modem_remove,
+       .enable         = __modem_enable,
+       .disable        = __modem_disable,
+};
+
+/* network driver */
+static struct connman_network_driver network_driver = {
+       .name           = "network",
+       .type           = CONNMAN_NETWORK_TYPE_CELLULAR,
+       .probe          = __network_probe,
+       .remove         = __network_remove,
+       .connect        = __network_connect,
+       .disconnect     = __network_disconnect,
+};
+
+static int tech_probe(struct connman_technology *technology)
+{
+       return 0;
+}
+
+static void tech_remove(struct connman_technology *technology)
+{
+       return;
+}
+
+static struct connman_technology_driver tech_driver = {
+       .name           = "cellular",
+       .type           = CONNMAN_SERVICE_TYPE_CELLULAR,
+       .probe          = tech_probe,
+       .remove         = tech_remove,
+};
+
+/* local function */
+static void telephony_connect(DBusConnection *connection, void *user_data)
+{
+       DBG("connection %p", connection);
+       modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                               g_free, __remove_modem);
+       service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                               g_free, __remove_service);
+       network_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                               g_free, __remove_network);
+
+       __request_get_modems();
+}
+
+static void telephony_disconnect(DBusConnection *connection, void *user_data)
+{
+       DBG("connection %p", connection);
+
+       if (modem_hash != NULL) {
+               g_hash_table_destroy(modem_hash);
+               modem_hash = NULL;
+       }
+
+       if (network_hash != NULL) {
+               g_hash_table_destroy(network_hash);
+               network_hash = NULL;
+       }
+}
+
+static void __remove_modem(gpointer data)
+{
+       struct telephony_modem *modem = data;
+
+       __remove_connman_device(modem);
+
+       g_free(modem->path);
+       g_free(modem->operator);
+       g_free(modem);
+}
+
+static void __remove_service(gpointer data)
+{
+       struct telephony_service *service = data;
+
+       g_free(service->path);
+       g_free(service->act);
+       g_free(service);
+}
+
+static void __remove_network(gpointer data)
+{
+       struct telephony_network *info = data;
+       struct connman_device *device;
+
+       device = connman_network_get_device(info->network);
+       if (device != NULL)
+               connman_device_remove_network(device, info->network);
+
+       connman_network_unref(info->network);
+
+       g_free(info->path);
+
+       connman_ipaddress_free(info->ipv4_address);
+       connman_ipaddress_free(info->ipv6_address);
+
+       g_free(info);
+}
+
+static void __set_device_powered(struct telephony_modem *modem,
+                                       gboolean powered)
+{
+       DBG("set modem(%s) powered(%d)", modem->path, powered);
+
+       if (modem->device)
+               connman_device_set_powered(modem->device, powered);
+}
+
+static int __check_device_powered(const char *path, gboolean powered)
+{
+       struct telephony_modem *modem = g_hash_table_lookup(modem_hash, path);
+
+       if (modem == NULL)
+               return -ENODEV;
+
+       DBG("check modem (%s) powered (%d)", modem->path, modem->powered);
+
+       if (modem->powered == powered)
+               return -EALREADY;
+
+       return 0;
+}
+
+static int __modem_probe(struct connman_device *device)
+{
+       DBG("device %p", device);
+       return 0;
+}
+
+static void __modem_remove(struct connman_device *device)
+{
+       DBG("device %p", device);
+}
+
+static int __modem_enable(struct connman_device *device)
+{
+       const char *path = connman_device_get_string(device, "Path");
+       DBG("device %p, path, %s", device, path);
+
+       return __check_device_powered(path, TRUE);
+}
+
+static int __modem_disable(struct connman_device *device)
+{
+       const char *path = connman_device_get_string(device, "Path");
+       DBG("device %p, path, %s", device, path);
+
+       return __check_device_powered(path, FALSE);
+}
+
+static int __network_probe(struct connman_network *network)
+{
+       DBG("network_prove network(%p)", network);
+       return 0;
+}
+
+static int __network_connect(struct connman_network *network)
+{
+       DBG("network %p", network);
+
+       return __request_network_activate(network);
+}
+
+static int __network_disconnect(struct connman_network *network)
+{
+       DBG("network %p", network);
+
+       if (connman_network_get_associating(network) == TRUE)
+               connman_network_clear_associating(network);
+
+       connman_network_set_associating(network, FALSE);
+
+       return __request_network_deactivate(network);
+}
+
+static void __network_remove(struct connman_network *network)
+{
+       char const *path = connman_network_get_string(network, "Path");
+       DBG("network %p path %s", network, path);
+
+       g_hash_table_remove(network_hash, path);
+}
+
+static int __dbus_request(const char *service, const char *path, const char *interface,
+               const char *method,
+               DBusPendingCallNotifyFunction notify, void *user_data,
+               DBusFreeFunction free_function, int type, ...)
+{
+       DBusMessage *message;
+       DBusPendingCall *call;
+       dbus_bool_t ok;
+       va_list va;
+
+       DBG("path %s %s.%s", path, interface, method);
+
+       if (path == NULL)
+               return -EINVAL;
+
+       message = dbus_message_new_method_call(service, path, interface, method);
+       if (message == NULL)
+               return -ENOMEM;
+
+       dbus_message_set_auto_start(message, FALSE);
+
+       va_start(va, type);
+       ok = dbus_message_append_args_valist(message, type, va);
+       va_end(va);
+
+       if (!ok) {
+               dbus_message_unref(message);
+               return -ENOMEM;
+       }
+
+       if (dbus_connection_send_with_reply(connection, message,
+                                               &call, TIMEOUT) == FALSE) {
+               connman_error("Failed to call %s.%s", interface, method);
+               dbus_message_unref(message);
+               return -EINVAL;
+       }
+
+       if (call == NULL) {
+               connman_error("D-Bus connection not available");
+               dbus_message_unref(message);
+               return -EINVAL;
+       }
+
+       dbus_pending_call_set_notify(call, notify, user_data, free_function);
+
+       dbus_message_unref(message);
+
+       return -EINPROGRESS;
+}
+
+static int __request_get_modems(void)
+{
+       DBG("request get modem");
+       /* call connect master */
+       return __dbus_request(PS_DBUS_SERVICE, "/", PS_MASTER_INTERFACE, GET_MODEMS,
+                       __response_get_modems, NULL, NULL, DBUS_TYPE_INVALID);
+}
+
+static void __response_get_modems(DBusPendingCall *call, void *user_data)
+{
+       DBusMessage *reply;
+       DBusError error;
+       DBusMessageIter args, dict;
+
+       DBG("");
+
+       reply = dbus_pending_call_steal_reply(call);
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, reply)) {
+               connman_error("GetModems() %s %s", error.name, error.message);
+               dbus_error_free(&error);
+               goto done;
+       }
+
+       DBG("message signature (%s)", dbus_message_get_signature(reply));
+
+       if (dbus_message_iter_init(reply, &args) == FALSE)
+               goto done;
+
+       dbus_message_iter_recurse(&args, &dict);
+
+       /* DBG("message type (%d) dic(%d)",
+        *      dbus_message_iter_get_arg_type(&dict), DBUS_TYPE_DICT_ENTRY);
+        */
+
+       while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
+               DBusMessageIter entry, property;
+               const char *modem_path;
+
+               dbus_message_iter_recurse(&dict, &entry);
+               dbus_message_iter_get_basic(&entry, &modem_path);
+               DBG("modem path (%s)", modem_path);
+
+               dbus_message_iter_next(&entry);
+               dbus_message_iter_recurse(&entry, &property);
+
+               __add_modem(modem_path, &property);
+
+               dbus_message_iter_next(&dict);
+       }
+
+done:
+       dbus_message_unref(reply);
+       dbus_pending_call_unref(call);
+}
+
+static int __request_get_services(const char *path)
+{
+       DBG("request get service");
+       return __dbus_request(PS_DBUS_SERVICE, path, PS_MODEM_INTERFACE, GET_SERVICES,
+                       __response_get_services, g_strdup(path),
+                       g_free, DBUS_TYPE_INVALID);
+}
+
+static void __response_get_services(DBusPendingCall *call, void *user_data)
+{
+       DBusMessage *reply;
+       DBusError error;
+       DBusMessageIter args, dict;
+
+       const char *path = user_data;
+       struct telephony_modem *modem;
+
+       modem = g_hash_table_lookup(modem_hash, path);
+
+       DBG("");
+
+       reply = dbus_pending_call_steal_reply(call);
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, reply)) {
+               connman_error("GetServices() %s %s", error.name, error.message);
+               dbus_error_free(&error);
+               goto done;
+       }
+
+       if (modem == NULL || modem->device == NULL)
+               goto done;
+
+       DBG("message signature (%s)", dbus_message_get_signature(reply));
+
+       if (dbus_message_iter_init(reply, &args) == FALSE)
+               goto done;
+
+       dbus_message_iter_recurse(&args, &dict);
+
+       /* DBG("message type (%d) dic(%d)",
+        *       dbus_message_iter_get_arg_type(&dict), DBUS_TYPE_DICT_ENTRY);
+        */
+
+       while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
+               DBusMessageIter entry, property;
+               const char *service_path;
+
+               dbus_message_iter_recurse(&dict, &entry);
+               dbus_message_iter_get_basic(&entry, &service_path);
+               DBG("service path (%s)", service_path);
+
+               dbus_message_iter_next(&entry);
+               dbus_message_iter_recurse(&entry, &property);
+
+               __add_service(modem, service_path, &property);
+
+               dbus_message_iter_next(&dict);
+       }
+
+done:
+       dbus_message_unref(reply);
+       dbus_pending_call_unref(call);
+}
+
+static int __request_get_contexts(struct telephony_modem *modem)
+{
+       DBG("request get contexts");
+       return __dbus_request(PS_DBUS_SERVICE, modem->s_service->path,
+                       PS_SERVICE_INTERFACE, GET_CONTEXTS,
+                       __response_get_contexts, g_strdup(modem->path),
+                       g_free, DBUS_TYPE_INVALID);
+}
+
+static void __response_get_contexts(DBusPendingCall *call, void *user_data)
+{
+       DBusError error;
+       DBusMessage *reply;
+       DBusMessageIter args, dict;
+
+       const char *path = user_data;
+       struct telephony_modem *modem;
+
+       DBG("");
+
+       modem = g_hash_table_lookup(modem_hash, path);
+       if (modem == NULL)
+               return;
+       if (modem->s_service == NULL)
+                       return;
+       if (modem->device == NULL)
+               return;
+
+       reply = dbus_pending_call_steal_reply(call);
+
+       dbus_error_init(&error);
+
+       if (dbus_set_error_from_message(&error, reply)) {
+               connman_error("GetContexts() %s %s", error.name, error.message);
+               dbus_error_free(&error);
+               goto done;
+       }
+
+       DBG("message signature (%s)", dbus_message_get_signature(reply));
+
+       if (dbus_message_iter_init(reply, &args) == FALSE)
+               goto done;
+
+       dbus_message_iter_recurse(&args, &dict);
+
+       while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
+               DBusMessageIter entry, property;
+               const char *context_path;
+
+               dbus_message_iter_recurse(&dict, &entry);
+               dbus_message_iter_get_basic(&entry, &context_path);
+               DBG("context path (%s)", context_path);
+
+               dbus_message_iter_next(&entry);
+               dbus_message_iter_recurse(&entry, &property);
+
+               __add_context(modem->device, context_path, &property);
+
+               dbus_message_iter_next(&dict);
+       }
+
+done:
+       dbus_message_unref(reply);
+       dbus_pending_call_unref(call);
+}
+
+static int __request_network_activate(struct connman_network *network)
+{
+       int n_modems;
+       const char *path = NULL;
+       struct telephony_modem *modem = NULL;
+
+       n_modems = g_hash_table_size(modem_hash);
+       path = connman_network_get_string(network, "Path");
+       modem = connman_device_get_data(connman_network_get_device(network));
+       DBG("network %p, path %s, modem %s[%d]", network, path, modem->path,
+                       telephony_default_subscription_id);
+
+       if (modem && n_modems > 1 && g_str_has_suffix(path, "_1") == TRUE) {
+               char *subscribe_id = g_strdup_printf("%d", telephony_default_subscription_id);
+
+               if (g_str_has_suffix(modem->path, subscribe_id) != TRUE) {
+                       g_free(subscribe_id);
+                       return -ENOLINK;
+               }
+               g_free(subscribe_id);
+       }
+
+       return __dbus_request(PS_DBUS_SERVICE, path, PS_CONTEXT_INTERFACE, ACTIVATE_CONTEXT,
+                       __response_network_activate,
+                       g_strdup(path), NULL, DBUS_TYPE_INVALID);
+}
+
+static gboolean __check_network_available(struct connman_network *network)
+{
+       if (network == NULL || connman_network_get_device(network) == NULL)
+               return FALSE;
+
+       return TRUE;
+}
+
+static void __response_network_activate(DBusPendingCall *call, void *user_data)
+{
+       DBG("network activation response");
+
+       DBusError error;
+       DBusMessage *reply;
+
+       struct telephony_network *info;
+       const char *path = user_data;
+
+       info = g_hash_table_lookup(network_hash, path);
+       reply = dbus_pending_call_steal_reply(call);
+
+       if (info == NULL)
+               goto done;
+
+       if (__check_network_available(info->network) == FALSE) {
+               g_hash_table_remove(network_hash, path);
+               goto done;
+       }
+
+       dbus_error_init(&error);
+       if (dbus_set_error_from_message(&error, reply)) {
+               connman_error("connection activate() %s %s",
+                                       error.name, error.message);
+
+               if (connman_network_get_associating(info->network) == TRUE)
+                       connman_network_set_error(info->network,
+                                       CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
+
+               if (connman_network_get_connecting(info->network) == TRUE)
+                       connman_network_set_error(info->network,
+                                       CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
+
+               if (connman_network_get_index(info->network) < 0)
+                       connman_network_set_error(info->network,
+                                       CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
+
+               dbus_error_free(&error);
+               goto done;
+       }
+
+done:
+       dbus_message_unref(reply);
+       dbus_pending_call_unref(call);
+}
+
+static int __request_network_deactivate(struct connman_network *network)
+{
+       const char *path = connman_network_get_string(network, "Path");
+       DBG("network %p, path %s", network, path);
+
+       return __dbus_request(PS_DBUS_SERVICE, path, PS_CONTEXT_INTERFACE, DEACTIVATE_CONTEXT,
+                       NULL, NULL, NULL, DBUS_TYPE_INVALID);
+}
+
+static void __response_get_default_subscription_id(DBusPendingCall *call,
+               void *user_data)
+{
+       DBusMessage *reply;
+       DBusError error;
+       DBusMessageIter args;
+
+       DBG("");
+
+       reply = dbus_pending_call_steal_reply(call);
+
+       dbus_error_init(&error);
+       if (dbus_set_error_from_message(&error, reply)) {
+               connman_error("GetDefaultDataSubscription() %s %s", error.name, error.message);
+               dbus_error_free(&error);
+               goto done;
+       }
+
+       DBG("message signature (%s)", dbus_message_get_signature(reply));
+
+       if (dbus_message_iter_init(reply, &args) == FALSE)
+               goto done;
+
+       dbus_message_iter_get_basic(&args, &telephony_default_subscription_id);
+       DBG("default subscription: %d", telephony_default_subscription_id);
+
+done:
+       dbus_message_unref(reply);
+       dbus_pending_call_unref(call);
+}
+
+static int __request_get_default_subscription_id(const char *path)
+{
+       int ret;
+       char *telephony_modem_path = NULL;
+
+       telephony_modem_path = g_strdup_printf("/org/tizen/telephony%s", path);
+       DBG("request get default subscription id %s", telephony_modem_path);
+
+       ret = __dbus_request(TELEPHONY_DBUS_SERVICE, telephony_modem_path,
+                       "org.tizen.telephony.Network", "GetDefaultDataSubscription",
+                       __response_get_default_subscription_id, NULL, NULL, DBUS_TYPE_INVALID);
+
+       g_free(telephony_modem_path);
+       return ret;
+}
+
+static void __add_modem(const char *path, DBusMessageIter *prop)
+{
+       struct telephony_modem *modem;
+
+       modem = g_hash_table_lookup(modem_hash, path);
+       if (modem != NULL)
+               return;
+
+       modem = g_try_new0(struct telephony_modem, 1);
+       if (modem == NULL)
+               return;
+
+       modem->path = g_strdup(path);
+       modem->device = NULL;
+       modem->s_service = NULL;
+
+       g_hash_table_insert(modem_hash, g_strdup(path), modem);
+
+       while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) {
+               DBusMessageIter entry;
+               const char *key, *tmp;
+
+               dbus_message_iter_recurse(prop, &entry);
+               dbus_message_iter_get_basic(&entry, &key);
+
+               dbus_message_iter_next(&entry);
+               dbus_message_iter_get_basic(&entry, &tmp);
+
+               DBG("key (%s) value(%s)", key, tmp);
+
+               if (g_strcmp0(key, "powered") == 0) {
+                       modem->powered = STRING2BOOL(tmp);
+               } else if (g_strcmp0(key, "operator") == 0) {
+                       modem->operator = g_strdup(tmp);
+               } else if (g_strcmp0(key, "sim_init") == 0) {
+                       modem->sim_init = STRING2BOOL(tmp);
+               } else if (g_strcmp0(key, "flight_mode") == 0) {
+                       modem->flight_mode = STRING2BOOL(tmp);
+               } else if (g_strcmp0(key, "roaming_allowed") == 0) {
+                       modem->roaming_allowed = STRING2BOOL(tmp);
+               } else if (g_strcmp0(key, "data_allowed") == 0) {
+                       modem->data_allowed = STRING2BOOL(tmp);
+               }
+               dbus_message_iter_next(prop);
+       }
+
+       __add_connman_device(path, modem->operator);
+       __set_device_powered(modem, modem->powered);
+
+       if (g_hash_table_size(modem_hash) > 1)
+               __request_get_default_subscription_id(modem->path);
+
+       if (modem->powered != TRUE) {
+               DBG("modem is not powered");
+               return;
+       }
+
+       __request_get_services(modem->path);
+}
+
+static void __add_service(struct telephony_modem *modem,
+                               const char *service_path, DBusMessageIter *prop)
+{
+       struct telephony_service *service;
+
+       if (modem->s_service != NULL)
+               return;
+
+       service = g_try_new0(struct telephony_service, 1);
+       if (service == NULL)
+               return;
+
+       service->path = g_strdup(service_path);
+       service->p_modem = modem;
+       g_hash_table_insert(service_hash, g_strdup(service_path), service);
+
+       while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) {
+               DBusMessageIter entry;
+               const char *key, *tmp;
+
+               dbus_message_iter_recurse(prop, &entry);
+               dbus_message_iter_get_basic(&entry, &key);
+
+               dbus_message_iter_next(&entry);
+               dbus_message_iter_get_basic(&entry, &tmp);
+
+               DBG("key (%s) value(%s)", key, tmp);
+
+               if (g_strcmp0(key, "roaming") == 0) {
+                       service->roaming = STRING2BOOL(tmp);
+               } else if (g_strcmp0(key, "act") == 0) {
+                       service->act = g_strdup(tmp);
+               } else if (g_strcmp0(key, "ps_attached") == 0) {
+                       service->ps_attached = STRING2BOOL(tmp);
+               }
+
+               dbus_message_iter_next(prop);
+       }
+
+       modem->s_service = service;
+       __request_get_contexts(modem);
+}
+
+static char *__get_ident(const char *path)
+{
+       char *pos;
+
+       if (*path != '/')
+               return NULL;
+
+       pos = strrchr(path, '/');
+       if (pos == NULL)
+               return NULL;
+
+       return pos + 1;
+}
+
+static void __add_connman_device(const char *modem_path, const char *operator)
+{
+       char* ident = NULL;
+       struct telephony_modem *modem;
+       struct connman_device *device;
+
+       DBG("path %s operator %s", modem_path, operator);
+
+       if (modem_path == NULL)
+               return;
+
+       if (operator == NULL)
+               return;
+
+       modem = g_hash_table_lookup(modem_hash, modem_path);
+       if (modem == NULL)
+               return;
+
+       if (modem->device) {
+               if (!g_strcmp0(operator,
+                               connman_device_get_ident(modem->device)))
+                       return;
+
+               __remove_connman_device(modem);
+       }
+
+       if (strlen(operator) == 0)
+               return;
+
+       device = connman_device_create(operator, CONNMAN_DEVICE_TYPE_CELLULAR);
+       if (device == NULL)
+               return;
+
+       ident = g_strdup_printf("%s_%s", __get_ident(modem_path), operator);
+       connman_device_set_ident(device, ident);
+       g_free(ident);
+
+       connman_device_set_string(device, "Path", modem_path);
+       connman_device_set_data(device, modem);
+
+       if (connman_device_register(device) < 0) {
+               connman_error("Failed to register cellular device");
+               connman_device_unref(device);
+               return;
+       }
+
+       modem->device = device;
+}
+
+static void __remove_connman_device(struct telephony_modem *modem)
+{
+       DBG("modem %p path %s device %p", modem, modem->path, modem->device);
+
+       if (modem->device == NULL)
+               return;
+
+       __remove_connman_networks(modem->device);
+
+       connman_device_unregister(modem->device);
+       connman_device_unref(modem->device);
+
+       modem->device = NULL;
+}
+
+static void __remove_connman_networks(struct connman_device *device)
+{
+       GHashTableIter iter;
+       gpointer key, value;
+       GSList *info_list = NULL;
+       GSList *list;
+
+       if (network_hash == NULL)
+               return;
+
+       g_hash_table_iter_init(&iter, network_hash);
+
+       while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) {
+               struct telephony_network *info = value;
+
+               if (connman_network_get_device(info->network) != device)
+                       continue;
+
+               info_list = g_slist_append(info_list, info);
+       }
+
+       for (list = info_list; list != NULL; list = list->next) {
+               struct telephony_network *info = list->data;
+               connman_device_remove_network(device, info->network);
+       }
+
+       g_slist_free(info_list);
+}
+
+static gboolean connman_ipaddress_updated(struct connman_ipaddress *ipaddress,
+                                       const char *address, const char *gateway)
+{
+       if (ipaddress == NULL || address == NULL)
+               return FALSE;
+
+       if (g_strcmp0(ipaddress->local, address) != 0)
+               return TRUE;
+
+       if (g_strcmp0(ipaddress->gateway, gateway) != 0)
+               return TRUE;
+
+       return FALSE;
+}
+
+static void __set_network_connected(struct telephony_network *network,
+                                       gboolean connected)
+{
+       gboolean setip = FALSE;
+
+       DBG("network %p connected %d", network, connected);
+
+       connman_network_set_index(network->network, network->if_index);
+       if (connman_network_get_connected(network->network) == connected)
+               return;
+
+       switch (network->ipv4_method) {
+       case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+       case CONNMAN_IPCONFIG_METHOD_DHCP:
+       case CONNMAN_IPCONFIG_METHOD_AUTO:
+       case CONNMAN_IPCONFIG_METHOD_OFF:
+               connman_network_set_ipv4_method(network->network,
+                                                       network->ipv4_method);
+               break;
+       case CONNMAN_IPCONFIG_METHOD_MANUAL:
+       case CONNMAN_IPCONFIG_METHOD_FIXED:
+               connman_network_set_ipv4_method(network->network,
+                                                       network->ipv4_method);
+               connman_network_set_ipaddress(network->network,
+                                                       network->ipv4_address);
+               setip = TRUE;
+               break;
+       }
+
+       switch (network->ipv6_method) {
+       case CONNMAN_IPCONFIG_METHOD_UNKNOWN:
+       case CONNMAN_IPCONFIG_METHOD_OFF:
+       case CONNMAN_IPCONFIG_METHOD_DHCP:
+               break;
+       case CONNMAN_IPCONFIG_METHOD_AUTO:
+               connman_network_set_ipv6_method(network->network,
+                                                       network->ipv6_method);
+               setip = TRUE;
+               break;
+       case CONNMAN_IPCONFIG_METHOD_MANUAL:
+       case CONNMAN_IPCONFIG_METHOD_FIXED:
+               connman_network_set_ipv6_method(network->network,
+                                                       network->ipv6_method);
+               connman_network_set_ipaddress(network->network,
+                                                       network->ipv6_address);
+               setip = TRUE;
+               break;
+       }
+
+       if (setip == TRUE)
+               connman_network_set_connected(network->network, connected);
+}
+
+static gboolean __set_network_context(
+                                                       struct telephony_network *network,
+                                                       DBusMessageIter *dict)
+{
+       int index = 0;
+       gboolean active = FALSE;
+       gboolean routing_only = FALSE;
+       gboolean ipv4_updated = FALSE;
+       gboolean ipv6_updated = FALSE;
+       gboolean ipv6_link_only = FALSE;
+       gboolean default_internet = FALSE;
+       gboolean active_proxy = FALSE;
+       char **proxies = NULL;
+       const char *dev_name = NULL;
+       const char *proxy_addr = NULL;
+       char *ipv4_addr = NULL, *ipv4_gw = NULL, *ipv4_netmask = NULL,
+                                       *ipv4_dns1 = NULL, *ipv4_dns2 = NULL;
+       char *ipv6_addr = NULL, *ipv6_gw = NULL, *ipv6_netmask = NULL,
+                                       *ipv6_dns1 = NULL, *ipv6_dns2 = NULL;
+       struct connman_service *service;
+
+       while (dbus_message_iter_get_arg_type(dict) != DBUS_TYPE_INVALID) {
+               DBusMessageIter entry;
+               const char *key, *value;
+
+               dbus_message_iter_recurse(dict, &entry);
+               dbus_message_iter_get_basic(&entry, &key);
+
+               dbus_message_iter_next(&entry);
+
+               if (g_strcmp0(key, "dev_name") == 0) {
+                       dbus_message_iter_get_basic(&entry, &dev_name);
+                       DBG("dev_name (%s)", dev_name);
+               } else if (g_strcmp0(key, "proxy") == 0) {
+                       dbus_message_iter_get_basic(&entry, &proxy_addr);
+                       DBG("proxy_addr (%s)", proxy_addr);
+               } else if (g_strcmp0(key, "ipv4_address") == 0) {
+                       dbus_message_iter_get_basic(&entry, &ipv4_addr);
+                       DBG("ipv4_addr (%s)", ipv4_addr);
+               } else if (g_strcmp0(key, "ipv4_gateway") == 0) {
+                       dbus_message_iter_get_basic(&entry, &ipv4_gw);
+                       DBG("ipv4_gw (%s)", ipv4_gw);
+               } else if (g_strcmp0(key, "ipv4_netmask") == 0) {
+                       dbus_message_iter_get_basic(&entry, &ipv4_netmask);
+                       DBG("ipv4_netmask (%s)", ipv4_netmask);
+               } else if (g_strcmp0(key, "ipv4_dns1") == 0) {
+                       dbus_message_iter_get_basic(&entry, &ipv4_dns1);
+                       DBG("ipv4_dns1 (%s)", ipv4_dns1);
+               } else if (g_strcmp0(key, "ipv4_dns2") == 0) {
+                       dbus_message_iter_get_basic(&entry, &ipv4_dns2);
+                       DBG("ipv4_dns2 (%s)", ipv4_dns2);
+               } else if (g_strcmp0(key, "ipv6_address") == 0) {
+                       dbus_message_iter_get_basic(&entry, &ipv6_addr);
+                       DBG("ipv6 address (%s)", ipv6_addr);
+               } else if (g_strcmp0(key, "ipv6_gateway") == 0) {
+                       dbus_message_iter_get_basic(&entry, &ipv6_gw);
+                       DBG("ipv6_gw (%s)", ipv6_gw);
+               } else if (g_strcmp0(key, "ipv6_netmask") == 0) {
+                       dbus_message_iter_get_basic(&entry, &ipv6_netmask);
+                       DBG("ipv6_netmask (%s)", ipv6_netmask);
+               } else if (g_strcmp0(key, "ipv6_dns1") == 0) {
+                       dbus_message_iter_get_basic(&entry, &ipv6_dns1);
+                       DBG("ipv6_dns1 (%s)", ipv6_dns1);
+               } else if (g_strcmp0(key, "ipv6_dns2") == 0) {
+                       dbus_message_iter_get_basic(&entry, &ipv6_dns2);
+                       DBG("ipv6_dns2 (%s)", ipv6_dns2);
+               } else if (g_strcmp0(key, "active") == 0) {
+                       dbus_message_iter_get_basic(&entry, &value);
+                       DBG("active (%s)", value);
+                       active = STRING2BOOL(value);
+               } else if (g_strcmp0(key, "routing_only") == 0) {
+                       dbus_message_iter_get_basic(&entry, &value);
+                       DBG("routing_only (%s)", value);
+                       routing_only = STRING2BOOL(value);
+                       network->routing_only = routing_only;
+               } else if (g_strcmp0(key, "ipv6_link_only") == 0) {
+                       dbus_message_iter_get_basic(&entry, &value);
+                       DBG("ipv6_link_only (%s)", value);
+                       ipv6_link_only = STRING2BOOL(value);
+                       network->ipv6_link_only = ipv6_link_only;
+               }
+               else if (g_strcmp0(key, "default_internet_conn") == 0) {
+                       dbus_message_iter_get_basic(&entry, &value);
+                       DBG("default_internet (%s)", value);
+                       default_internet = STRING2BOOL(value);
+               }
+
+               dbus_message_iter_next(dict);
+       }
+
+       if(routing_only){
+               //context active does not effect the connman service status.
+               //it only for setting the routing path.
+               DBG("routing_only(%d), active(%d)", routing_only, active);
+               return active;
+       }
+
+       if (g_strcmp0(proxy_addr, ":") == 0)
+               proxy_addr = NULL;
+       if (g_strcmp0(ipv4_addr, "0.0.0.0") == 0)
+               ipv4_addr = NULL;
+       if (g_strcmp0(ipv4_gw, "0.0.0.0") == 0)
+               ipv4_gw = NULL;
+       if (g_strcmp0(ipv4_netmask, "0.0.0.0") == 0)
+               ipv4_netmask = NULL;
+       if (g_strcmp0(ipv4_dns1, "0.0.0.0") == 0)
+               ipv4_dns1 = NULL;
+       if (g_strcmp0(ipv4_dns2, "0.0.0.0") == 0)
+               ipv4_dns2 = NULL;
+       if (g_strcmp0(ipv6_addr, "::") == 0)
+               ipv6_addr = NULL;
+       if (g_strcmp0(ipv6_gw, "::") == 0)
+               ipv6_gw = NULL;
+       if (g_strcmp0(ipv6_netmask, "::") == 0)
+               ipv6_netmask = NULL;
+       if (g_strcmp0(ipv6_dns1, "::") == 0)
+               ipv6_dns1 = NULL;
+       if (g_strcmp0(ipv6_dns2, "::") == 0)
+               ipv6_dns2 = NULL;
+
+       connman_network_set_bool(network->network, "DefaultInternet",
+                                                               (bool)default_internet);
+
+       service = connman_service_lookup_from_network(network->network);
+       if (service == NULL)
+               return FALSE;
+
+       if (connman_setting_get_bool("SingleConnectedTechnology") == TRUE) {
+               /* Wi-Fi technology is always a top priority */
+               if (active == TRUE &&
+                               connman_service_is_no_ref_user_pdn_connection(service) == TRUE &&
+                               connman_service_get_type(connman_service_get_default_connection())
+                                       == CONNMAN_SERVICE_TYPE_WIFI) {
+                       __request_network_deactivate(network->network);
+
+                       return FALSE;
+               }
+       }
+
+       /* interface index set */
+       if (dev_name != NULL) {
+               index = connman_inet_ifindex(dev_name);
+               network->if_index = index;
+               DBG("interface index %d", index);
+       }
+
+       /* proxy set */
+       if (active == TRUE &&
+                       connman_network_get_connected(network->network) == TRUE)
+               active_proxy = TRUE;
+
+       proxies = connman_service_get_proxy_servers(service);
+       if (proxies != NULL) {
+               if (proxy_addr == NULL)
+                       connman_service_set_proxy(service, proxy_addr, active_proxy);
+               else if (g_strcmp0(proxy_addr, proxies[0]) != 0)
+                       connman_service_set_proxy(service, proxy_addr, active_proxy);
+       } else if (proxy_addr != NULL)
+               connman_service_set_proxy(service, proxy_addr, active_proxy);
+
+       if (proxies != NULL)
+               g_strfreev(proxies);
+
+       __connman_service_nameserver_clear(service);
+
+       /* ipv4 set */
+       if (network->ipv4_address == NULL)
+               network->ipv4_address =
+                               connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
+
+       if (network->ipv4_address == NULL)
+               return FALSE;
+
+       if (ipv4_addr == NULL && active == TRUE)
+               network->ipv4_method = CONNMAN_IPCONFIG_METHOD_OFF;
+       else
+               network->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED;
+
+       connman_network_set_ipv4_method(network->network, network->ipv4_method);
+
+       ipv4_updated = connman_ipaddress_updated(network->ipv4_address,
+                                               ipv4_addr, ipv4_gw);
+       if (ipv4_updated == TRUE)
+               connman_ipaddress_set_ipv4(network->ipv4_address, ipv4_addr,
+                                               ipv4_netmask, ipv4_gw);
+
+       if (ipv4_dns1)
+#if defined TIZEN_EXT
+               __connman_service_nameserver_append(service, ipv4_dns1, FALSE,
+                               CONNMAN_IPCONFIG_TYPE_IPV4);
+#else
+               __connman_service_nameserver_append(service, ipv4_dns1, FALSE);
+#endif
+       //if (ipv4_dns2)
+       if (ipv4_dns2 && !ipv4_dns1)
+#if defined TIZEN_EXT
+               __connman_service_nameserver_append(service, ipv4_dns2, FALSE,
+                               CONNMAN_IPCONFIG_TYPE_IPV4);
+#else
+               __connman_service_nameserver_append(service, ipv4_dns2, FALSE);
+#endif
+       /* ipv6 set */
+       if (network->ipv6_address == NULL)
+               network->ipv6_address =
+                               connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
+
+       if (network->ipv6_address == NULL)
+               return FALSE;
+
+       if(ipv6_link_only)
+               network->ipv6_method = CONNMAN_IPCONFIG_METHOD_AUTO;
+       else
+               network->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED;
+
+       if (ipv6_addr == NULL)
+               network->ipv6_method = CONNMAN_IPCONFIG_METHOD_OFF;
+
+       connman_network_set_ipv6_method(network->network, network->ipv6_method);
+
+       ipv6_updated = connman_ipaddress_updated(network->ipv6_address,
+                                               ipv6_addr, ipv6_gw);
+       if (ipv6_updated == TRUE)
+               connman_ipaddress_set_ipv6(network->ipv6_address, ipv6_addr,
+                                               64, ipv6_gw);
+
+       if (ipv6_dns1)
+#if defined TIZEN_EXT
+               __connman_service_nameserver_append(service, ipv6_dns1, FALSE,
+                               CONNMAN_IPCONFIG_TYPE_IPV6);
+#else
+               __connman_service_nameserver_append(service, ipv6_dns1, FALSE);
+#endif
+       //if (ipv6_dns2)
+       if (ipv6_dns2 && !ipv6_dns1)
+#if defined TIZEN_EXT
+               __connman_service_nameserver_append(service, ipv6_dns2, FALSE,
+                               CONNMAN_IPCONFIG_TYPE_IPV6);
+#else
+               __connman_service_nameserver_append(service, ipv6_dns2, FALSE);
+#endif
+
+       if (active == TRUE &&
+                       connman_network_get_connected(network->network) == TRUE) {
+               if (ipv4_updated == TRUE || ipv6_updated == TRUE) {
+                       DBG("IPv4 updated %d, IPv6 updated %d", ipv4_updated, ipv6_updated);
+
+                       __set_network_connected(network, FALSE);
+               } else {
+                       DBG("Already connected");
+
+                       return active;
+               }
+       }
+
+       if (active == TRUE)
+               connman_network_set_associating(network->network, TRUE);
+
+       return active;
+}
+
+static int __add_context(struct connman_device *device, const char *path,
+                               DBusMessageIter *prop)
+{
+       char *ident;
+       gboolean active = FALSE;
+
+       struct telephony_modem *modem = connman_device_get_data(device);
+       struct connman_network *network;
+       struct telephony_network *info;
+
+       DBG("modem %p device %p path %s", modem, device, path);
+
+       ident = __get_ident(path);
+
+       network = connman_device_get_network(device, ident);
+       if (network != NULL)
+               return -EALREADY;
+
+       info = g_hash_table_lookup(network_hash, path);
+       if (info != NULL) {
+               DBG("path %p already exists with device %p", path,
+                       connman_network_get_device(info->network));
+
+               if (connman_network_get_device(info->network))
+                       return -EALREADY;
+
+               g_hash_table_remove(network_hash, path);
+       }
+
+       network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR);
+       if (network == NULL)
+               return -ENOMEM;
+
+       info = g_try_new0(struct telephony_network, 1);
+       if (info == NULL) {
+               connman_network_unref(network);
+               return -ENOMEM;
+       }
+
+       info->path = g_strdup(path);
+
+       connman_ipaddress_clear(info->ipv4_address);
+       connman_ipaddress_clear(info->ipv6_address);
+
+       info->network = network;
+
+       connman_network_set_string(network, "Path", path);
+       connman_network_set_name(network, path);
+
+       connman_network_set_group(network, ident);
+
+       g_hash_table_insert(network_hash, g_strdup(path), info);
+
+       connman_network_set_available(network, TRUE);
+       connman_network_set_bool(network, "Roaming", (bool)modem->s_service->roaming);
+
+       if (connman_device_add_network(device, network) != 0) {
+               g_hash_table_remove(network_hash, path);
+               return -EIO;
+       }
+
+       active = __set_network_context(info, prop);
+       if(info->routing_only){
+               int err = 0;
+               struct connman_service *routing_service;
+               struct connman_ipconfig *routing_ipconfig;
+
+               if(!active)
+                       return TRUE;
+
+               routing_service = connman_service_lookup_from_network(info->network);
+               routing_ipconfig = __connman_service_get_ip4config(routing_service);
+               err = __connman_ipconfig_gateway_add(routing_ipconfig, routing_service);
+
+               DBG("set gateway rv(%d)", err);
+               return TRUE;
+       }
+
+       if (active == TRUE && (connman_network_get_associating(network) == TRUE ||
+                       connman_network_get_connecting(network) == TRUE))
+               __set_network_connected(info, active);
+
+       return 0;
+}
+
+static gboolean __changed_modem(DBusConnection *connection,
+                               DBusMessage *message, void *user_data)
+{
+       gboolean old_powered;
+       DBusMessageIter args, dict;
+       struct telephony_modem *modem;
+       const char *path = dbus_message_get_path(message);
+
+       DBG("modem changed signal %s", path);
+
+       modem = g_hash_table_lookup(modem_hash, path);
+       if (modem == NULL) {
+               DBG("modem object does not exists");
+               return TRUE;
+       }
+
+       old_powered = modem->powered;
+
+       DBG("message signature (%s)", dbus_message_get_signature(message));
+
+       if (dbus_message_iter_init(message, &args) == FALSE) {
+               DBG("error to read message");
+               return TRUE;
+       }
+
+       dbus_message_iter_recurse(&args, &dict);
+
+       while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
+               DBusMessageIter entry;
+               const char *key, *tmp;
+
+               dbus_message_iter_recurse(&dict, &entry);
+               dbus_message_iter_get_basic(&entry, &key);
+
+               dbus_message_iter_next(&entry);
+               dbus_message_iter_get_basic(&entry, &tmp);
+
+               DBG("key(%s), value(%s)", key, tmp);
+
+               if (g_strcmp0(key, "powered") == 0) {
+                       modem->powered = STRING2BOOL(tmp);
+               } else if (g_strcmp0(key, "operator") == 0) {
+                       modem->operator = g_strdup(tmp);
+               } else if (g_strcmp0(key, "sim_init") == 0) {
+                       modem->sim_init = STRING2BOOL(tmp);
+               } else if (g_strcmp0(key, "flight_mode") == 0) {
+                       modem->flight_mode = STRING2BOOL(tmp);
+               } else if (g_strcmp0(key, "roaming_allowed") == 0) {
+                       modem->roaming_allowed = STRING2BOOL(tmp);
+               } else if (g_strcmp0(key, "data_allowed") == 0) {
+                       modem->data_allowed = STRING2BOOL(tmp);
+               }
+
+               dbus_message_iter_next(&dict);
+       }
+
+       if (modem->device == NULL)
+               __add_connman_device(path, modem->operator);
+
+       if (old_powered != modem->powered)
+               __set_device_powered(modem, modem->powered);
+
+       if (modem->powered != TRUE) {
+               DBG("modem is not powered");
+               return TRUE;
+       }
+
+       if (modem->s_service == NULL) {
+               __request_get_services(modem->path);
+               return TRUE;
+       }
+
+       DBG("modem(%s) flight mode(%d) data allowed(%d)",
+                       modem->path, modem->flight_mode, modem->data_allowed);
+
+       return TRUE;
+}
+
+static gboolean __added_modem(DBusConnection *connection,
+                               DBusMessage *message, void *user_data)
+{
+       const char *modem_path = NULL;
+       DBusMessageIter args, dict, tmp;
+
+       DBG("modem added signal (%s)", dbus_message_get_signature(message));
+
+       if (dbus_message_iter_init(message, &args) == FALSE) {
+               DBG("error to read message");
+               return TRUE;
+       }
+
+       dbus_message_iter_recurse(&args, &dict);
+       memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
+
+       while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
+               DBusMessageIter entry;
+               const char *key, *value;
+
+               dbus_message_iter_recurse(&tmp, &entry);
+               dbus_message_iter_get_basic(&entry, &key);
+
+               dbus_message_iter_next(&entry);
+               dbus_message_iter_get_basic(&entry, &value);
+
+               DBG("key (%s) value(%s)", key, value);
+
+               if (g_strcmp0(key, "path") == 0)
+                       modem_path = g_strdup(value);
+
+               dbus_message_iter_next(&tmp);
+       }
+
+       if (modem_path != NULL)
+               __add_modem(modem_path, &dict);
+
+       return TRUE;
+}
+
+static gboolean __removed_modem(DBusConnection *connection,
+                                       DBusMessage *message, void *user_data)
+{
+       DBusMessageIter iter;
+       const char *modem_path;
+
+       DBG("modem removed signal");
+
+       if (dbus_message_iter_init(message, &iter) == FALSE) {
+               DBG("error to read message");
+               return TRUE;
+       }
+
+       dbus_message_iter_get_basic(&iter, &modem_path);
+       g_hash_table_remove(modem_hash, modem_path);
+
+       return TRUE;
+}
+
+static gboolean __changed_service(DBusConnection *connection,
+                                       DBusMessage *message, void *user_data)
+{
+       DBusMessageIter args, dict;
+       struct telephony_modem *modem;
+       gboolean roaming_option = TRUE;
+       struct telephony_service *s_service;
+       const char *service_path = dbus_message_get_path(message);
+
+       DBG("service changed signal %s", service_path);
+
+       s_service = g_hash_table_lookup(service_hash, service_path);
+       if (s_service == NULL) {
+               DBG("service object does not exists");
+               return TRUE;
+       }
+
+       modem = s_service->p_modem;
+       if (modem == NULL) {
+               DBG("modem object does not exists");
+               return TRUE;
+       }
+
+       DBG("message signature (%s)", dbus_message_get_signature(message));
+
+       if (dbus_message_iter_init(message, &args) == FALSE) {
+               DBG("error to read message");
+               return TRUE;
+       }
+
+       dbus_message_iter_recurse(&args, &dict);
+
+       while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) {
+               DBusMessageIter entry;
+               const char *key, *tmp;
+
+               dbus_message_iter_recurse(&dict, &entry);
+               dbus_message_iter_get_basic(&entry, &key);
+
+               dbus_message_iter_next(&entry);
+               dbus_message_iter_get_basic(&entry, &tmp);
+
+               DBG("key(%s), value(%s)", key, tmp);
+
+               if (g_strcmp0(key, "roaming") == 0) {
+                       s_service->roaming = STRING2BOOL(tmp);
+               } else if (g_strcmp0(key, "act") == 0) {
+                       s_service->act = g_strdup(tmp);
+               } else if (g_strcmp0(key, "ps_attached") == 0) {
+                       s_service->ps_attached = STRING2BOOL(tmp);
+               }
+
+               dbus_message_iter_next(&dict);
+       }
+
+       roaming_option &= (!s_service->roaming && !modem->roaming_allowed)
+                               || modem->roaming_allowed;
+
+       return TRUE;
+}
+
+static gboolean __added_service(DBusConnection *connection,
+                               DBusMessage *message, void *user_data)
+{
+       struct telephony_modem *modem;
+       const char *service_path = NULL;
+       DBusMessageIter args, dict, tmp;
+       const char *path = dbus_message_get_path(message);
+
+       DBG("service added signal %s", path);
+
+       modem = g_hash_table_lookup(modem_hash, path);
+       if (modem == NULL || modem->device == NULL)
+               return TRUE;
+
+       DBG("message signature (%s)", dbus_message_get_signature(message));
+       if (dbus_message_iter_init(message, &args) == FALSE) {
+               DBG("error to read message");
+               return TRUE;
+       }
+
+       dbus_message_iter_recurse(&args, &dict);
+       memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
+
+       while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
+               DBusMessageIter entry;
+               const char *key, *value;
+
+               dbus_message_iter_recurse(&tmp, &entry);
+               dbus_message_iter_get_basic(&entry, &key);
+
+               dbus_message_iter_next(&entry);
+               dbus_message_iter_get_basic(&entry, &value);
+
+               DBG("key (%s) value(%s)", key, value);
+
+               if (g_strcmp0(key, "path") == 0)
+                       service_path = value;
+
+               dbus_message_iter_next(&tmp);
+       }
+
+       if (service_path != NULL)
+               __add_service(modem, service_path, &dict);
+
+       return TRUE;
+}
+
+static gboolean __removed_service(DBusConnection *connection,
+                                       DBusMessage *message, void *user_data)
+{
+       DBusMessageIter iter;
+       const char *service_path;
+
+       DBG("service removed signal");
+
+       if (dbus_message_iter_init(message, &iter) == FALSE) {
+               DBG("error to read message");
+               return TRUE;
+       }
+
+       dbus_message_iter_get_basic(&iter, &service_path);
+       g_hash_table_remove(service_hash, service_path);
+
+       return TRUE;
+}
+
+static gboolean __changed_context(DBusConnection *connection,
+                                       DBusMessage *message, void *user_data)
+{
+       gboolean active = FALSE;
+       DBusMessageIter args, dict;
+       struct telephony_network *info;
+       const char *path = dbus_message_get_path(message);
+
+       DBG("network changed signal %s", path);
+
+       info = g_hash_table_lookup(network_hash, path);
+       if (info == NULL)
+               return TRUE;
+
+       if (__check_network_available(info->network) == FALSE) {
+               g_hash_table_remove(network_hash, path);
+               return TRUE;
+       }
+
+       if (dbus_message_iter_init(message, &args) == FALSE) {
+               DBG("error to read message");
+               return TRUE;
+       }
+
+       dbus_message_iter_recurse(&args, &dict);
+
+       active = __set_network_context(info, &dict);
+       if(info->routing_only){
+               int err = 0;
+               struct connman_service *routing_service;
+               struct connman_ipconfig *routing_ipconfig;
+
+               if(!active)
+                       return TRUE;
+
+               routing_service = connman_service_lookup_from_network(info->network);
+               routing_ipconfig = __connman_service_get_ip4config(routing_service);
+               err = __connman_ipconfig_gateway_add(routing_ipconfig, routing_service);
+
+               DBG("set gateway rv(%d)", err);
+               return TRUE;
+       }
+
+       __set_network_connected(info, active);
+
+       if (active == FALSE &&
+                       connman_network_get_connecting(info->network) == TRUE)
+               connman_network_set_connected(info->network, FALSE);
+
+       return TRUE;
+}
+
+static gboolean __added_context(DBusConnection *connection,
+                                       DBusMessage *message, void *user_data)
+{
+       const char *network_path = NULL;
+       DBusMessageIter args, dict, tmp;
+       struct telephony_modem *modem = NULL;
+       struct telephony_service *service = NULL;
+       const char *path = dbus_message_get_path(message);
+
+       DBG("network added signal %s", path);
+
+       service = g_hash_table_lookup(service_hash, path);
+       if (service == NULL || service->p_modem == NULL)
+               return TRUE;
+
+       modem = service->p_modem;
+       if (modem == NULL || modem->device == NULL)
+               return TRUE;
+
+       DBG("message signature (%s)", dbus_message_get_signature(message));
+       if (dbus_message_iter_init(message, &args) == FALSE) {
+               DBG("error to read message");
+               return TRUE;
+       }
+
+       dbus_message_iter_recurse(&args, &dict);
+       memcpy(&tmp, &dict, sizeof(struct DBusMessageIter));
+
+       while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) {
+               DBusMessageIter entry;
+               const char *key, *value;
+
+               dbus_message_iter_recurse(&tmp, &entry);
+               dbus_message_iter_get_basic(&entry, &key);
+
+               dbus_message_iter_next(&entry);
+               dbus_message_iter_get_basic(&entry, &value);
+
+               DBG("key (%s) value(%s)", key, value);
+
+               if (g_strcmp0(key, "path") == 0)
+                       network_path = g_strdup(value);
+
+               dbus_message_iter_next(&tmp);
+       }
+
+       if (network_path != NULL)
+               __add_context(modem->device, network_path, &dict);
+
+       return TRUE;
+}
+
+static gboolean __removed_context(DBusConnection *connection,
+                                       DBusMessage *message, void *user_data)
+{
+       DBusMessageIter iter;
+       const char *network_path = NULL;
+       struct telephony_service *service = NULL;
+       const char *path = dbus_message_get_path(message);
+
+       DBG("network removed signal %s", path);
+
+       service = g_hash_table_lookup(service_hash, path);
+       if (service == NULL || service->p_modem == NULL)
+               return TRUE;
+
+       if (dbus_message_iter_init(message, &iter) == FALSE) {
+               DBG("error to read message");
+               return TRUE;
+       }
+
+       dbus_message_iter_get_basic(&iter, &network_path);
+       g_hash_table_remove(network_hash, network_path);
+
+       return TRUE;
+}
+
+static gboolean __changed_default_subscription(DBusConnection *connection,
+               DBusMessage *message, void *user_data)
+{
+       DBusMessageIter args;
+
+       DBG("message signature (%s)", dbus_message_get_signature(message));
+       if (dbus_message_iter_init(message, &args) == FALSE)
+               return TRUE;
+
+       dbus_message_iter_get_basic(&args, &telephony_default_subscription_id);
+       DBG("default subscription: %d", telephony_default_subscription_id);
+
+       return TRUE;
+}
+
+/* telephony initialization */
+static guint watch = 0;
+static guint modem_watch = 0;
+static guint modem_added_watch = 0;
+static guint modem_removed_watch = 0;
+static guint service_watch = 0;
+static guint service_added_watch = 0;
+static guint service_removed_watch = 0;
+static guint context_watch = 0;
+static guint context_added_watch = 0;
+static guint context_removed_watch = 0;
+static guint default_subscription_watch = 0;
+
+static int telephony_init(void)
+{
+       int err;
+
+       DBG("telephony plugin");
+
+       connection = connman_dbus_get_connection();
+       if (connection == NULL)
+               return -EIO;
+
+       /* telephony watch */
+       watch = g_dbus_add_service_watch(connection, PS_DBUS_SERVICE,
+                                       telephony_connect, telephony_disconnect,
+                                       NULL, NULL);
+
+       modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+                                               PS_MODEM_INTERFACE,
+                                               PROPERTY_CHANGED,
+                                               __changed_modem,
+                                               NULL, NULL);
+
+       modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+                                               PS_MASTER_INTERFACE,
+                                               MODEM_ADDED,
+                                               __added_modem,
+                                               NULL, NULL);
+
+       modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+                                               PS_MASTER_INTERFACE,
+                                               MODEM_REMOVED,
+                                               __removed_modem,
+                                               NULL, NULL);
+
+       service_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+                                               PS_SERVICE_INTERFACE,
+                                               PROPERTY_CHANGED,
+                                               __changed_service,
+                                               NULL, NULL);
+
+       service_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+                                               PS_MODEM_INTERFACE,
+                                               SERVICE_ADDED,
+                                               __added_service,
+                                               NULL, NULL);
+
+       service_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+                                               PS_MODEM_INTERFACE,
+                                               SERVICE_REMOVED,
+                                               __removed_service,
+                                               NULL, NULL);
+
+       context_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+                                               PS_CONTEXT_INTERFACE,
+                                               PROPERTY_CHANGED,
+                                               __changed_context,
+                                               NULL, NULL);
+
+       context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+                                               PS_SERVICE_INTERFACE,
+                                               CONTEXT_ADDED,
+                                               __added_context,
+                                               NULL, NULL);
+
+       context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+                                               PS_SERVICE_INTERFACE,
+                                               CONTEXT_REMOVED,
+                                               __removed_context,
+                                               NULL, NULL);
+
+       default_subscription_watch = g_dbus_add_signal_watch(connection, NULL, NULL,
+                                               "org.tizen.telephony.Network",
+                                               "DefaultDataSubscription",
+                                               __changed_default_subscription,
+                                               NULL, NULL);
+
+       if (watch == 0 || modem_watch == 0 || modem_added_watch == 0
+                       || modem_removed_watch == 0 || service_watch == 0
+                       || service_added_watch == 0 || context_watch == 0
+                       || service_removed_watch == 0
+                       || context_added_watch == 0
+                       || context_removed_watch == 0
+                       || default_subscription_watch == 0) {
+               err = -EIO;
+               goto remove;
+       }
+
+       err = connman_network_driver_register(&network_driver);
+       if (err < 0)
+               goto remove;
+
+       err = connman_device_driver_register(&modem_driver);
+       if (err < 0) {
+               connman_network_driver_unregister(&network_driver);
+               goto remove;
+       }
+
+       err = connman_technology_driver_register(&tech_driver);
+       if (err < 0) {
+               connman_device_driver_unregister(&modem_driver);
+               connman_network_driver_unregister(&network_driver);
+               goto remove;
+       }
+
+       return 0;
+
+remove:
+       g_dbus_remove_watch(connection, watch);
+       g_dbus_remove_watch(connection, modem_watch);
+       g_dbus_remove_watch(connection, modem_added_watch);
+       g_dbus_remove_watch(connection, modem_removed_watch);
+       g_dbus_remove_watch(connection, service_watch);
+       g_dbus_remove_watch(connection, service_added_watch);
+       g_dbus_remove_watch(connection, service_removed_watch);
+       g_dbus_remove_watch(connection, context_watch);
+       g_dbus_remove_watch(connection, context_added_watch);
+       g_dbus_remove_watch(connection, context_removed_watch);
+       g_dbus_remove_watch(connection, default_subscription_watch);
+
+       dbus_connection_unref(connection);
+       return err;
+}
+
+static void telephony_exit(void)
+{
+       g_dbus_remove_watch(connection, watch);
+       g_dbus_remove_watch(connection, modem_watch);
+       g_dbus_remove_watch(connection, modem_added_watch);
+       g_dbus_remove_watch(connection, modem_removed_watch);
+       g_dbus_remove_watch(connection, service_watch);
+       g_dbus_remove_watch(connection, service_added_watch);
+       g_dbus_remove_watch(connection, service_removed_watch);
+       g_dbus_remove_watch(connection, context_watch);
+       g_dbus_remove_watch(connection, context_added_watch);
+       g_dbus_remove_watch(connection, context_removed_watch);
+       g_dbus_remove_watch(connection, default_subscription_watch);
+
+       telephony_disconnect(connection, NULL);
+
+       connman_device_driver_unregister(&modem_driver);
+       connman_network_driver_unregister(&network_driver);
+
+       dbus_connection_unref(connection);
+}
+
+CONNMAN_PLUGIN_DEFINE(telephony, "Samsung Telephony Framework plug-in", VERSION,
+               CONNMAN_PLUGIN_PRIORITY_DEFAULT, telephony_init, telephony_exit)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index e701451..bcb9344
 
 #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;
@@ -162,8 +193,22 @@ 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 {
@@ -171,6 +216,19 @@ struct disconnect_data {
        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;
@@ -182,6 +240,123 @@ static int tech_set_tethering(struct connman_technology *technology,
                                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;
@@ -223,1671 +398,2984 @@ static void add_pending_wifi_device(struct wifi_data *wifi)
        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;
+               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_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;
+       }
+
+       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;
+#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)) {
+               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);
+
+               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);
+       /*
+        * 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 (scanning) {
-               connman_device_set_scanning(device,
-                               CONNMAN_SERVICE_TYPE_WIFI, false);
+       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_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
@@ -1917,6 +3405,11 @@ static int wifi_scan(struct connman_device *device,
        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);
 
@@ -2001,12 +3494,32 @@ static int wifi_scan(struct connman_device *device,
        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);
@@ -2079,6 +3592,16 @@ static struct connman_device_driver wifi_ng_driver = {
        .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)
@@ -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;
@@ -2118,15 +3644,77 @@ static void network_remove(struct connman_network *network)
                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);
@@ -2152,21 +3740,65 @@ static GSupplicantSecurity network_security(const char *security)
                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");
 
@@ -2212,6 +3844,84 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
 
        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;
@@ -2243,10 +3953,16 @@ static int network_connect(struct connman_network *network)
 
        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);
@@ -2260,9 +3976,31 @@ static void disconnect_callback(int result, GSupplicantInterface *interface,
 {
        struct disconnect_data *dd = user_data;
        struct connman_network *network = dd->network;
-       struct wifi_data *wifi = dd->wifi;
+#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;
 
+found:
+#else
+       struct wifi_data *wifi = dd->wifi;
        g_free(dd);
+#endif
 
        DBG("result %d supplicant interface %p wifi %p networks: current %p "
                "pending %p disconnected %p", result, interface, wifi,
@@ -2273,7 +4011,13 @@ static void disconnect_callback(int result, GSupplicantInterface *interface,
                return;
        }
 
+#if defined TIZEN_EXT
+       if (wifi->network &&
+                       (wifi->network != wifi->pending_network ||
+                       connman_network_get_bool(wifi->network, "WiFi.Roaming")))
+#else
        if (g_slist_find(wifi->networks, network))
+#endif
                connman_network_set_connected(network, false);
 
        wifi->disconnecting = false;
@@ -2303,6 +4047,9 @@ static int network_disconnect(struct connman_network *network)
        struct disconnect_data *dd;
        struct wifi_data *wifi;
        int err;
+#if defined TIZEN_EXT
+       struct connman_service *service;
+#endif
 
        DBG("network %p", network);
 
@@ -2310,6 +4057,29 @@ static int network_disconnect(struct connman_network *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)
@@ -2331,6 +4101,176 @@ static int network_disconnect(struct connman_network *network)
        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,
@@ -2345,6 +4285,19 @@ static void interface_added(GSupplicantInterface *interface)
 {
        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);
@@ -2368,6 +4321,12 @@ static void interface_added(GSupplicantInterface *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)
@@ -2454,14 +4413,43 @@ static bool handle_wps_completion(GSupplicantInterface *interface,
                        connman_network_set_associating(network, false);
                        g_supplicant_interface_disconnect(wifi->interface,
                                                disconnect_callback, dd);
+#if defined TIZEN_EXT
+                       connman_network_set_bool(network, "WiFi.UseWPS", false);
+                       connman_network_set_string(network, "WiFi.PinWPS", NULL);
+#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;
@@ -2471,7 +4459,11 @@ static bool handle_assoc_status_code(GSupplicantInterface *interface,
                                      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;
@@ -2486,6 +4478,24 @@ static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
 {
        struct connman_service *service;
 
+#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)))
@@ -2493,6 +4503,7 @@ static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
 
        if (wifi->connected)
                return false;
+#endif
 
        service = connman_service_lookup_from_network(network);
        if (!service)
@@ -2511,12 +4522,73 @@ static bool handle_4way_handshake_failure(GSupplicantInterface *interface,
        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;
 
@@ -2554,6 +4626,13 @@ static void interface_state(GSupplicantInterface *interface)
 
        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);
 
@@ -2561,7 +4640,11 @@ static void interface_state(GSupplicantInterface *interface)
 
        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);
@@ -2569,8 +4652,37 @@ static void interface_state(GSupplicantInterface *interface)
                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;
@@ -2583,6 +4695,16 @@ static void interface_state(GSupplicantInterface *interface)
                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
@@ -2597,8 +4719,39 @@ static void interface_state(GSupplicantInterface *interface)
                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
@@ -2610,6 +4763,10 @@ static void interface_state(GSupplicantInterface *interface)
 
                /* 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);
@@ -2619,6 +4776,21 @@ static void interface_state(GSupplicantInterface *interface)
                        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);
@@ -2630,6 +4802,10 @@ static void interface_state(GSupplicantInterface *interface)
                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);
 
@@ -2685,11 +4861,35 @@ static void interface_removed(GSupplicantInterface *interface)
 {
        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;
 
@@ -2704,6 +4904,9 @@ static void interface_removed(GSupplicantInterface *interface)
        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])
@@ -2735,6 +4938,15 @@ static void p2p_support(GSupplicantInterface *interface)
 {
        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("");
 
@@ -2761,16 +4973,74 @@ static void p2p_support(GSupplicantInterface *interface)
 
 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;
 
@@ -2802,12 +5072,158 @@ static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network)
        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;
@@ -2821,15 +5237,45 @@ static void network_added(GSupplicantNetwork *supplicant_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);
@@ -2868,6 +5314,17 @@ static void network_added(GSupplicantNetwork *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));
@@ -2880,20 +5337,79 @@ static void network_added(GSupplicantNetwork *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,
@@ -2914,7 +5430,25 @@ static void network_removed(GSupplicantNetwork *network)
        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);
@@ -2928,6 +5462,18 @@ static void network_removed(GSupplicantNetwork *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);
@@ -2942,12 +5488,36 @@ static void network_changed(GSupplicantNetwork *network, const char *property)
        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;
@@ -2987,11 +5557,66 @@ static void network_changed(GSupplicantNetwork *network, const char *property)
                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)
@@ -3006,6 +5631,15 @@ 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)
@@ -3024,7 +5658,22 @@ static void network_associated(GSupplicantNetwork *network)
        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.
@@ -3052,6 +5701,15 @@ static void network_associated(GSupplicantNetwork *network)
 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);
@@ -3065,6 +5723,15 @@ static void sta_authorized(GSupplicantInterface *interface,
 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);
@@ -3100,6 +5767,10 @@ static void peer_found(GSupplicantPeer *peer)
        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);
 
@@ -3245,6 +5916,11 @@ static void peer_request(GSupplicantPeer *peer)
        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);
@@ -3256,15 +5932,161 @@ static void peer_request(GSupplicantPeer *peer)
        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) {
@@ -3274,6 +6096,15 @@ static void disconnect_reasoncode(GSupplicantInterface *interface,
 
 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) {
@@ -3281,7 +6112,11 @@ static void assoc_status_code(GSupplicantInterface *interface, int status_code)
        }
 }
 
+#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,
@@ -3301,9 +6136,22 @@ static const GSupplicantCallbacks callbacks = {
        .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
 };
 
 
@@ -3328,7 +6176,11 @@ static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase)
                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;
@@ -3436,6 +6288,9 @@ static void sta_remove_callback(int 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);
 }
@@ -3602,6 +6457,33 @@ static int tech_set_regdom(struct connman_technology *technology, const char *al
        return g_supplicant_set_country(alpha2, regdom_callback, NULL);
 }
 
+#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,
@@ -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;
 }
 
@@ -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 --git a/resources/usr/share/dbus-1/system-services/net.connman.service b/resources/usr/share/dbus-1/system-services/net.connman.service
new file mode 100644 (file)
index 0000000..990eb66
--- /dev/null
@@ -0,0 +1,6 @@
+[D-BUS Service]
+Name=net.connman
+Exec=/bin/false
+User=network_fw
+Group=network_fw
+SystemdService=connman.service
diff --git a/resources/var/lib/connman/settings b/resources/var/lib/connman/settings
new file mode 100644 (file)
index 0000000..ba476b5
--- /dev/null
@@ -0,0 +1,15 @@
+
+[global]
+OfflineMode=false
+
+[WiFi]
+Enable=false
+
+[Bluetooth]
+Enable=true
+
+[Wired]
+Enable=true
+
+[Cellular]
+Enable=true
old mode 100644 (file)
new mode 100755 (executable)
index 0b9f63c..f3d438f
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-DAEMON=@sbindir@/connmand
+DAEMON=@bindir@/connmand
 DESC="Connection Manager"
 
 . /lib/lsb/init-functions
diff --git a/scripts/ipsec-script.c b/scripts/ipsec-script.c
new file mode 100755 (executable)
index 0000000..6ba0d29
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *  Copyright (C) 2007-2012  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2010,2012-2014  BMW Car IT GmbH.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <libgen.h>
+
+#include <dbus/dbus.h>
+
+extern char **environ;
+
+static void print(const char *format, ...)
+{
+       va_list ap;
+
+       va_start(ap, format);
+       vsyslog(LOG_INFO, format, ap);
+       va_end(ap);
+}
+
+static void append(DBusMessageIter *dict, const char *pattern)
+{
+       DBusMessageIter entry;
+       const char *key, *value;
+       char *delim;
+
+       delim = strchr(pattern, '=');
+       *delim = '\0';
+
+       key = pattern;
+       value = delim + 1;
+
+       dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
+                                                       NULL, &entry);
+
+       dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
+
+       dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &value);
+
+       dbus_message_iter_close_container(dict, &entry);
+}
+
+int main(int argc, char *argv[])
+{
+       DBusConnection *conn;
+       DBusError error;
+       DBusMessage *msg;
+       DBusMessageIter iter, dict;
+       char **envp, *busname, *interface, *path, *reason;
+       int ret = 0;
+
+       openlog(basename(argv[0]), LOG_NDELAY | LOG_PID, LOG_DAEMON);
+
+       busname = getenv("CONNMAN_BUSNAME");
+       interface = getenv("CONNMAN_INTERFACE");
+       path = getenv("CONNMAN_PATH");
+
+       reason = getenv("script_type");
+
+       if (!busname || !interface || !path || !reason) {
+               print("Required environment variables not set; "
+                       "bus=%s iface=%s path=%s reason=%s",
+                       busname, interface, path, reason);
+               ret = 1;
+               goto out;
+       }
+       dbus_error_init(&error);
+
+       conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
+       if (!conn) {
+               if (dbus_error_is_set(&error)) {
+                       print("%s", error.message);
+                       dbus_error_free(&error);
+               } else
+                       print("Failed to get on system bus");
+
+               goto out;
+       }
+
+       msg = dbus_message_new_method_call(busname, path,
+                                               interface, "notify");
+       if (!msg) {
+               dbus_connection_unref(conn);
+               print("Failed to allocate method call");
+               goto out;
+       }
+
+       dbus_message_set_no_reply(msg, TRUE);
+
+       dbus_message_append_args(msg,
+                                DBUS_TYPE_STRING, &reason,
+                                DBUS_TYPE_INVALID);
+
+       dbus_message_iter_init_append(msg, &iter);
+
+       dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+                       DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+                       DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING
+                       DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
+
+       for (envp = environ; envp && *envp; envp++)
+               append(&dict, *envp);
+
+       dbus_message_iter_close_container(&iter, &dict);
+
+       if (!dbus_connection_send(conn, msg, NULL)) {
+               print("Failed to send message");
+               goto out;
+       }
+
+       dbus_connection_flush(conn);
+
+       dbus_message_unref(msg);
+
+       dbus_connection_unref(conn);
+
+out:
+       closelog();
+
+       return ret;
+}
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index fca7cc1..e4850a8
@@ -253,6 +253,9 @@ static void request_input_append_passphrase(DBusMessageIter *iter,
                value = "wep";
                break;
        case CONNMAN_SERVICE_SECURITY_PSK:
+#if defined TIZEN_EXT
+       case CONNMAN_SERVICE_SECURITY_RSN:
+#endif
                value = "psk";
                break;
        case CONNMAN_SERVICE_SECURITY_8021X:
@@ -386,6 +389,9 @@ static void previous_passphrase_handler(DBusMessageIter *iter,
                        data.type = "wep";
                        break;
                case CONNMAN_SERVICE_SECURITY_PSK:
+#if defined TIZEN_EXT
+               case CONNMAN_SERVICE_SECURITY_RSN:
+#endif
                        data.type  = "psk";
                        break;
                /*
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 906538a..58a52c0
@@ -39,6 +39,9 @@ static enum time_updates time_updates_config = TIME_UPDATES_AUTO;
 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,6 +179,9 @@ static DBusMessage *get_properties(DBusConnection *conn,
        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);
 
@@ -187,6 +193,12 @@ static DBusMessage *get_properties(DBusConnection *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;
 
@@ -246,6 +258,11 @@ static DBusMessage *set_property(DBusConnection *conn,
        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;
 
@@ -267,6 +284,7 @@ static DBusMessage *set_property(DBusConnection *conn,
                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;
@@ -401,6 +419,13 @@ static const GDBusSignalTable clock_signals[] = {
 
 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("");
index 62023b1..993f4f6 100644 (file)
@@ -78,6 +78,11 @@ struct connman_config_service {
        char **search_domains;
        char **timeservers;
        char *domain_name;
+#if defined TIZEN_EXT
+       char *connector;
+       char *c_sign_key;
+       char *net_access_key;
+#endif
 };
 
 struct connman_config {
@@ -125,6 +130,11 @@ static bool cleanup = false;
 #define SERVICE_KEY_SEARCH_DOMAINS     "SearchDomains"
 #define SERVICE_KEY_TIMESERVERS        "Timeservers"
 #define SERVICE_KEY_DOMAIN             "Domain"
+#if defined TIZEN_EXT
+#define SERVICE_KEY_CONNECTOR          "Connector"
+#define SERVICE_KEY_C_SIGN_KEY         "CSignKey"
+#define SERVICE_KEY_NET_ACCESS_KEY     "NetAccessKey"
+#endif
 
 static const char *config_possible_keys[] = {
        CONFIG_KEY_NAME,
@@ -162,6 +172,11 @@ static const char *service_possible_keys[] = {
        SERVICE_KEY_SEARCH_DOMAINS,
        SERVICE_KEY_TIMESERVERS,
        SERVICE_KEY_DOMAIN,
+#if defined TIZEN_EXT
+       SERVICE_KEY_CONNECTOR,
+       SERVICE_KEY_C_SIGN_KEY,
+       SERVICE_KEY_NET_ACCESS_KEY,
+#endif
        NULL,
 };
 
@@ -269,6 +284,11 @@ free_only:
        g_free(config_service->config_ident);
        g_free(config_service->config_entry);
        g_free(config_service->virtual_file);
+#if defined TIZEN_EXT
+       g_free(config_service->connector);
+       g_free(config_service->c_sign_key);
+       g_free(config_service->net_access_key);
+#endif
        g_free(config_service);
 }
 
@@ -638,7 +658,11 @@ static bool load_service(GKeyFile *keyfile, const char *group,
                unsigned int ssid_len;
 
                ssid_len = strlen(service->name);
+#if defined TIZEN_EXT
+               ssid = g_try_malloc0(ssid_len + 1);
+#else
                ssid = g_try_malloc0(ssid_len);
+#endif
                if (!ssid)
                        goto err;
 
@@ -739,6 +763,29 @@ static bool load_service(GKeyFile *keyfile, const char *group,
                g_free(service->passphrase);
                service->passphrase = str;
        }
+#if defined TIZEN_EXT
+
+       str = __connman_config_get_string(keyfile, group, SERVICE_KEY_CONNECTOR,
+                                       NULL);
+       if (str) {
+               g_free(service->connector);
+               service->connector = str;
+       }
+
+       str = __connman_config_get_string(keyfile, group, SERVICE_KEY_C_SIGN_KEY,
+                                       NULL);
+       if (str) {
+               g_free(service->c_sign_key);
+               service->c_sign_key = str;
+       }
+
+       str = __connman_config_get_string(keyfile, group, SERVICE_KEY_NET_ACCESS_KEY,
+                                       NULL);
+       if (str) {
+               g_free(service->net_access_key);
+               service->net_access_key = str;
+       }
+#endif
 
        str = __connman_config_get_string(keyfile, group, SERVICE_KEY_SECURITY,
                        NULL);
@@ -757,6 +804,10 @@ static bool load_service(GKeyFile *keyfile, const char *group,
 
                if (str) {
                        if (security == CONNMAN_SERVICE_SECURITY_PSK ||
+#if defined TIZEN_EXT
+                           security == CONNMAN_SERVICE_SECURITY_RSN ||
+                           security == CONNMAN_SERVICE_SECURITY_SAE ||
+#endif
                                        security == CONNMAN_SERVICE_SECURITY_WEP) {
                                service->security = security;
                        } else {
@@ -770,6 +821,16 @@ static bool load_service(GKeyFile *keyfile, const char *group,
 
                } else
                        service->security = CONNMAN_SERVICE_SECURITY_PSK;
+#if defined TIZEN_EXT
+       } else if (service->connector) {
+
+               if (str && security != CONNMAN_SERVICE_SECURITY_DPP)
+                       connman_info("Mismatch between DPP configuration and "
+                                       "setting %s = %s",
+                                       SERVICE_KEY_SECURITY, str);
+
+               service->security = CONNMAN_SERVICE_SECURITY_DPP;
+#endif
        } else if (str) {
 
                if (security != CONNMAN_SERVICE_SECURITY_NONE)
@@ -1174,6 +1235,10 @@ static void provision_service_wifi(struct connman_config_service *config,
 
        if (config->phase2)
                __connman_service_set_string(service, "Phase2", config->phase2);
+#if defined TIZEN_EXT
+       else
+               __connman_service_set_string(service, "Phase2", NULL);
+#endif
 
        if (config->passphrase)
                __connman_service_set_string(service, "Passphrase",
@@ -1181,6 +1246,18 @@ static void provision_service_wifi(struct connman_config_service *config,
 
        if (config->hidden)
                __connman_service_set_hidden(service);
+
+#if defined TIZEN_EXT
+       if (config->connector)
+               __connman_service_set_string(service, "Connector",
+                                               config->connector);
+       if (config->c_sign_key)
+               __connman_service_set_string(service, "CSignKey",
+                                               config->c_sign_key);
+       if (config->net_access_key)
+               __connman_service_set_string(service, "NetAccessKey",
+                                               config->net_access_key);
+#endif
 }
 
 struct connect_virtual {
@@ -1201,6 +1278,20 @@ static gboolean remove_virtual_config(gpointer user_data)
        return FALSE;
 }
 
+#if defined TIZEN_EXT
+static bool __check_address_type(int address_family, const char *address)
+{
+       unsigned char buf[sizeof(struct in6_addr)] = {0, };
+       int err = 0;
+
+       err = inet_pton(address_family, address, buf);
+       if(err > 0)
+               return TRUE;
+
+       return FALSE;
+}
+#endif
+
 static int try_provision_service(struct connman_config_service *config,
                                struct connman_service *service)
 {
@@ -1259,6 +1350,9 @@ static int try_provision_service(struct connman_config_service *config,
        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 -ENOENT;
        }
@@ -1300,6 +1394,12 @@ static int try_provision_service(struct connman_config_service *config,
                        return -ENOENT;
        }
 
+#if defined TIZEN_EXT
+       struct connman_ipconfig *ip6config = __connman_service_get_ip6config(service);
+       enum connman_ipconfig_method ipv6_method = __connman_ipconfig_get_method(ip6config);
+       if (ipv6_method == CONNMAN_IPCONFIG_METHOD_MANUAL)
+               goto ipv6_out;
+#endif
        if (!config->ipv6_address) {
                connman_network_set_ipv6_method(network,
                                                CONNMAN_IPCONFIG_METHOD_AUTO);
@@ -1336,6 +1436,9 @@ static int try_provision_service(struct connman_config_service *config,
                connman_ipaddress_free(address);
        }
 
+#if defined TIZEN_EXT
+ipv6_out:
+#endif
        if (config->ipv6_privacy) {
                struct connman_ipconfig *ipconfig;
 
@@ -1345,6 +1448,12 @@ static int try_provision_service(struct connman_config_service *config,
                                                        config->ipv6_privacy);
        }
 
+#if defined TIZEN_EXT
+       struct connman_ipconfig *ip4config = __connman_service_get_ip4config(service);
+       enum connman_ipconfig_method ipv4_method = __connman_ipconfig_get_method(ip4config);
+       if (ipv4_method == CONNMAN_IPCONFIG_METHOD_MANUAL)
+               goto ipv4_out;
+#endif
        if (!config->ipv4_address) {
                connman_network_set_ipv4_method(network,
                                                CONNMAN_IPCONFIG_METHOD_DHCP);
@@ -1381,6 +1490,9 @@ static int try_provision_service(struct connman_config_service *config,
                connman_ipaddress_free(address);
        }
 
+#if defined TIZEN_EXT
+ipv4_out:
+#endif
        __connman_service_disconnect(service);
 
        service_id = connman_service_get_identifier(service);
@@ -1402,8 +1514,19 @@ static int try_provision_service(struct connman_config_service *config,
                __connman_service_nameserver_clear(service);
 
                for (i = 0; config->nameservers[i]; i++) {
+#if defined TIZEN_EXT
+                       if (__check_address_type(AF_INET, config->nameservers[i]))
+                               __connman_service_nameserver_append(service,
+                                               config->nameservers[i], false,
+                                               CONNMAN_IPCONFIG_TYPE_IPV4);
+                       else if (__check_address_type(AF_INET6, config->nameservers[i]))
+                               __connman_service_nameserver_append(service,
+                                               config->nameservers[i], false,
+                                               CONNMAN_IPCONFIG_TYPE_IPV6);
+#else
                        __connman_service_nameserver_append(service,
                                                config->nameservers[i], false);
+#endif
                }
        }
 
@@ -1438,7 +1561,9 @@ static int try_provision_service(struct connman_config_service *config,
                return 0;
        }
 
+#if !defined TIZEN_EXT
        __connman_service_set_immutable(service, true);
+#endif
 
        if (type == CONNMAN_SERVICE_TYPE_ETHERNET ||
                        type == CONNMAN_SERVICE_TYPE_GADGET) {
@@ -1493,7 +1618,9 @@ int __connman_config_provision_service(struct connman_service *service)
 
        /* For now only WiFi, Gadget and Ethernet services are supported */
        type = connman_service_get_type(service);
-
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        DBG("service %p type %d", service, type);
 
        if (type != CONNMAN_SERVICE_TYPE_WIFI &&
@@ -1501,6 +1628,13 @@ int __connman_config_provision_service(struct connman_service *service)
                        type != CONNMAN_SERVICE_TYPE_GADGET)
                return -ENOSYS;
 
+#if defined TIZEN_EXT
+       if(type == CONNMAN_SERVICE_TYPE_WIFI &&
+                       __connman_service_get_security(service) ==
+                       CONNMAN_SERVICE_SECURITY_NONE)
+               return -ENOSYS;
+#endif
+
        return find_and_provision_service(service);
 }
 
old mode 100644 (file)
new mode 100755 (executable)
index 9d2c696..33f6103
@@ -674,8 +674,15 @@ static void connection_newgateway(int index, const char *gateway)
        }
 
        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);
@@ -803,6 +810,32 @@ static void add_host_route(int family, int index, const char *gateway,
        }
 }
 
+#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,
@@ -829,6 +862,28 @@ int __connman_connection_gateway_add(struct connman_service *service,
        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);
 
@@ -873,6 +928,12 @@ int __connman_connection_gateway_add(struct connman_service *service,
        }
 
        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;
        }
@@ -988,6 +1049,9 @@ bool __connman_connection_update_gateway(void)
        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;
@@ -1025,6 +1089,12 @@ bool __connman_connection_update_gateway(void)
                }
        }
 
+#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.
old mode 100644 (file)
new mode 100755 (executable)
index 98a773e..29106dc
@@ -6,6 +6,19 @@
         <allow send_destination="net.connman"/>
         <allow send_interface="net.connman.Agent"/>
         <allow send_interface="net.connman.Counter"/>
+        <allow send_interface="net.connman.Manager"/>
+        <allow send_interface="net.connman.Service"/>
+        <allow send_interface="net.connman.Technology"/>
+        <allow send_interface="net.connman.Notification"/>
+    </policy>
+    <policy user="network_fw">
+        <allow own="net.connman"/>
+        <allow send_destination="net.connman"/>
+        <allow send_interface="net.connman.Agent"/>
+        <allow send_interface="net.connman.Counter"/>
+        <allow send_interface="net.connman.Manager"/>
+        <allow send_interface="net.connman.Service"/>
+        <allow send_interface="net.connman.Technology"/>
         <allow send_interface="net.connman.Notification"/>
     </policy>
     <policy at_console="true">
old mode 100644 (file)
new mode 100755 (executable)
index b13d339..03154fa
@@ -7,6 +7,12 @@
         <allow send_interface="net.connman.Counter"/>
         <allow send_interface="net.connman.Notification"/>
     </policy>
+    <policy user="network_fw">
+        <allow own="net.connman"/>
+        <allow send_interface="net.connman.Agent"/>
+        <allow send_interface="net.connman.Counter"/>
+        <allow send_interface="net.connman.Notification"/>
+    </policy>
     <policy context="default">
         <allow send_destination="net.connman"/>
     </policy>
diff --git a/src/connman-robot.conf b/src/connman-robot.conf
new file mode 100644 (file)
index 0000000..b089f40
--- /dev/null
@@ -0,0 +1,44 @@
+<!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"/>
+               <allow send_destination="net.connman"/>
+       </policy>
+       <policy user="network_fw">
+               <allow own="net.connman"/>
+               <allow send_destination="net.connman"/>
+       </policy>
+       <policy context="default">
+               <deny own="net.connman"/>
+               <deny send_destination="net.connman"/>
+               <allow send_destination="net.connman" send_type="signal"/>
+               <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="GetScanState" />
+               <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="Get5GhzSupported" />
+               <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="GetMaxScanSsid" />
+
+               <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetTechnologies" />
+               <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetProperties" />
+               <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetServices" />
+               <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetDefaultService" />
+               <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetConnectedService" />
+               <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetMeshPeers" />
+               <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetConnectedMeshPeers" />
+               <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetDisconnectedMeshPeers" />
+               <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="MeshAddPeer" />
+               <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="MeshRemovePeer" />
+               <allow send_destination="net.connman" send_interface="net.connman.Service" send_member="Connect" />
+               <allow send_destination="net.connman" send_interface="net.connman.Service" send_member="Disconnect" />
+               <allow send_destination="net.connman" send_interface="net.connman.Service" send_member="SetProperty" />
+               <allow send_destination="net.connman" send_interface="net.connman.Service" send_member="GetProperties" />
+               <allow send_destination="net.connman" send_interface="net.connman.Service" send_member="Remove" />
+               <allow send_destination="net.connman" send_interface="net.connman.Service" send_member="PropertyChanged" />
+               <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="Scan" />
+               <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="SpecificScan" />
+               <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="ScanDevice" />
+               <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="SetDevicePower" />
+               <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="SetBSSID" />
+               <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetInterfaces" />
+               <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="MeshCommands" />
+       </policy>
+</busconfig>
diff --git a/src/connman.conf b/src/connman.conf
new file mode 100644 (file)
index 0000000..267a4fc
--- /dev/null
@@ -0,0 +1,44 @@
+<!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"/>
+               <allow send_destination="net.connman"/>
+       </policy>
+       <policy user="network_fw">
+               <allow own="net.connman"/>
+               <allow send_destination="net.connman"/>
+       </policy>
+       <policy context="default">
+               <deny own="net.connman"/>
+               <deny send_destination="net.connman"/>
+               <allow send_destination="net.connman" send_type="signal"/>
+               <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="GetScanState" />
+               <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="Get5GhzSupported" />
+               <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="GetMaxScanSsid" />
+
+               <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetTechnologies" privilege="http://tizen.org/privilege/network.get" />
+               <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetProperties" privilege="http://tizen.org/privilege/network.get" />
+               <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetServices" privilege="http://tizen.org/privilege/network.get" />
+               <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetDefaultService" privilege="http://tizen.org/privilege/network.get" />
+               <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetConnectedService" privilege="http://tizen.org/privilege/network.get" />
+               <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetMeshPeers" privilege="http://tizen.org/privilege/network.get" />
+               <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetConnectedMeshPeers" privilege="http://tizen.org/privilege/network.get" />
+               <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetDisconnectedMeshPeers" privilege="http://tizen.org/privilege/network.get" />
+               <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="MeshAddPeer" privilege="http://tizen.org/privilege/network.set" />
+               <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="MeshRemovePeer" privilege="http://tizen.org/privilege/network.set" />
+               <check send_destination="net.connman" send_interface="net.connman.Service" send_member="Connect" privilege="http://tizen.org/privilege/network.set" />
+               <check send_destination="net.connman" send_interface="net.connman.Service" send_member="Disconnect" privilege="http://tizen.org/privilege/network.set" />
+               <check send_destination="net.connman" send_interface="net.connman.Service" send_member="SetProperty" privilege="http://tizen.org/privilege/network.profile" />
+               <check send_destination="net.connman" send_interface="net.connman.Service" send_member="GetProperties" privilege="http://tizen.org/privilege/network.get" />
+               <check send_destination="net.connman" send_interface="net.connman.Service" send_member="Remove" privilege="http://tizen.org/privilege/network.profile" />
+               <check send_destination="net.connman" send_interface="net.connman.Service" send_member="PropertyChanged" privilege="http://tizen.org/privilege/network.get" />
+               <check send_destination="net.connman" send_interface="net.connman.Technology" send_member="Scan" privilege="http://tizen.org/privilege/network.set" />
+               <check send_destination="net.connman" send_interface="net.connman.Technology" send_member="SpecificScan" privilege="http://tizen.org/privilege/network.set" />
+               <check send_destination="net.connman" send_interface="net.connman.Technology" send_member="ScanDevice" privilege="http://tizen.org/privilege/network.set" />
+               <check send_destination="net.connman" send_interface="net.connman.Technology" send_member="SetDevicePower" privilege="http://tizen.org/privilege/network.set" />
+               <check send_destination="net.connman" send_interface="net.connman.Technology" send_member="SetBSSID" privilege="http://tizen.org/privilege/network.set" />
+               <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetInterfaces" privilege="http://tizen.org/privilege/network.get" />
+               <check send_destination="net.connman" send_interface="net.connman.Technology" send_member="MeshCommands" privilege="http://tizen.org/privilege/network.set" />
+       </policy>
+</busconfig>
old mode 100644 (file)
new mode 100755 (executable)
index 6817608..18c4fe0
 #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>
 
@@ -54,6 +59,10 @@ DBusMessage *__connman_error_operation_aborted(DBusMessage *msg);
 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);
@@ -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);
@@ -175,6 +187,9 @@ int __connman_inet_ipv6_send_rs(int index, int timeout,
                        __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,
@@ -268,6 +283,10 @@ GKeyFile *__connman_storage_open_global(void);
 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);
@@ -378,6 +397,11 @@ const char *__connman_ipconfig_get_broadcast(struct connman_ipconfig *ipconfig);
 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);
 
@@ -408,7 +432,15 @@ enum connman_ipconfig_method __connman_ipconfig_get_method(
 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,
@@ -461,6 +493,11 @@ enum __connman_dhcpv6_status {
        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);
 
@@ -560,6 +597,18 @@ void __connman_technology_remove_interface(enum connman_service_type type,
 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);
@@ -576,6 +625,12 @@ int __connman_device_request_hidden_scan(struct connman_device *device,
                                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);
 
@@ -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);
@@ -683,6 +745,18 @@ int __connman_service_move(struct connman_service *service,
 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);
@@ -691,6 +765,9 @@ struct connman_service *__connman_service_lookup_from_index(int index);
 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);
@@ -714,6 +791,10 @@ struct connman_network *__connman_service_get_network(struct connman_service *se
 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,
@@ -740,6 +821,10 @@ enum connman_service_state __connman_service_ipconfig_get_state(
                                        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);
@@ -750,6 +835,17 @@ int __connman_service_connect(struct connman_service *service,
 int __connman_service_disconnect(struct connman_service *service);
 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,
@@ -767,10 +863,19 @@ const char *__connman_service_type2string(enum connman_service_type type);
 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);
@@ -786,6 +891,17 @@ void __connman_service_timeserver_changed(struct connman_service *service,
                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);
@@ -860,6 +976,30 @@ int __connman_peer_service_unregister(const char *owner,
                                        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();
@@ -893,16 +1033,29 @@ const char *__connman_notifier_get_state(void);
 
 #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);
@@ -1090,3 +1243,12 @@ int __connman_util_get_random(uint64_t *val);
 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 */
old mode 100644 (file)
new mode 100755 (executable)
index 7376346..6665d4a
@@ -1,21 +1,22 @@
 [Unit]
 Description=Connection service
-DefaultDependencies=false
 Conflicts=shutdown.target
 RequiresMountsFor=@localstatedir@/lib/connman
-After=dbus.service network-pre.target systemd-sysusers.service
+After=dbus.service network-pre.target systemd-sysusers.service net-config.service
 Before=network.target multi-user.target shutdown.target
 Wants=network.target
 
 [Service]
 Type=dbus
+User=network_fw
+Group=network_fw
 BusName=net.connman
 Restart=on-failure
-ExecStart=@sbindir@/connmand -n
+SmackProcessLabel=System
+ExecStart=@bindir@/connmand -n --nobacktrace --noplugin vpn
 StandardOutput=null
-CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SYS_TIME CAP_SYS_MODULE CAP_SYS_ADMIN
-ProtectHome=true
-ProtectSystem=full
+Capabilities=cap_setgid,cap_net_admin,cap_net_bind_service,cap_net_broadcast,cap_net_raw,cap_dac_override=i
+SecureBits=keep-caps
 
 [Install]
 WantedBy=multi-user.target
diff --git a/src/connman.socket b/src/connman.socket
new file mode 100644 (file)
index 0000000..3e1e64d
--- /dev/null
@@ -0,0 +1,13 @@
+[Unit]
+Description=DNS Proxy Socket
+Before=connman.service
+
+[Socket]
+ListenStream=127.0.0.1:53
+ListenDatagram=0.0.0.0:53
+FreeBind=yes
+SmackLabelIPIn=*
+SmackLabelIPOut=@
+
+[Install]
+WantedBy=sockets.target
\ No newline at end of file
diff --git a/src/connman_tv.service.in b/src/connman_tv.service.in
new file mode 100644 (file)
index 0000000..f0bf5c3
--- /dev/null
@@ -0,0 +1,19 @@
+[Unit]
+Description=Connection service
+After=net-config.service
+DefaultDependencies=no
+
+[Service]
+Type=dbus
+User=network_fw
+Group=network_fw
+BusName=net.connman
+Restart=on-failure
+SmackProcessLabel=System
+ExecStart=@bindir@/connmand -n --nobacktrace --noplugin vpn
+StandardOutput=null
+Capabilities=cap_setgid,cap_net_admin,cap_net_bind_service,cap_net_broadcast,cap_net_raw,cap_dac_override=i
+SecureBits=keep-caps
+
+[Install]
+WantedBy=multi-user.target
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 6c03920..7f20870
@@ -67,8 +67,15 @@ static void detect_newlink(unsigned short type, int index,
        }
 
        device = find_device(index);
+#if defined TIZEN_EXT
+       if (device) {
+               connman_inet_update_device_ident(device);
+               return;
+       }
+#else
        if (device)
                return;
+#endif
 
        device = connman_device_create_from_index(index);
        if (!device)
old mode 100644 (file)
new mode 100755 (executable)
index 264c5e2..5116900
@@ -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,
@@ -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;
@@ -166,6 +199,11 @@ static bool device_has_service_type(struct connman_device *device,
        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;
@@ -174,12 +212,34 @@ static bool device_has_service_type(struct connman_device *device,
        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);
 
+#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;
@@ -227,6 +287,13 @@ int __connman_device_enable(struct connman_device *device)
        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;
        }
        /*
@@ -418,9 +485,65 @@ static void device_destruct(struct connman_device *device)
 
        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)
@@ -568,6 +691,11 @@ void connman_device_set_interface(struct connman_device *device,
 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);
 }
@@ -596,6 +724,10 @@ int connman_device_set_powered(struct connman_device *device,
        if (device->powered == powered)
                return -EALREADY;
 
+#if defined TIZEN_EXT
+       device_send_reply(device);
+#endif
+
        clear_pending_trigger(device);
 
        device->powered_pending = PENDING_NONE;
@@ -604,6 +736,11 @@ int connman_device_set_powered(struct connman_device *device,
 
        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;
@@ -691,6 +828,196 @@ int connman_device_reconnect_service(struct connman_device *device)
        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)
 {
@@ -791,6 +1118,11 @@ int connman_device_set_scanning(struct connman_device *device,
 
        __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;
 }
 
@@ -808,6 +1140,11 @@ int connman_device_set_string(struct connman_device *device,
        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")) {
@@ -836,6 +1173,9 @@ int connman_device_set_string(struct connman_device *device,
 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"))
@@ -863,7 +1203,9 @@ int connman_device_add_network(struct connman_device *device,
                                        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)
@@ -889,11 +1231,62 @@ int connman_device_add_network(struct connman_device *device,
 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
@@ -1090,6 +1483,225 @@ void connman_device_regdom_notify(struct connman_device *device,
        __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)
 {
@@ -1110,6 +1722,9 @@ static int connman_device_request_scan(enum connman_service_type type,
                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;
        }
 
@@ -1120,7 +1735,15 @@ static int connman_device_request_scan(enum connman_service_type type,
                        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;
@@ -1183,7 +1806,92 @@ void __connman_device_stop_scan(enum connman_service_type type)
        }
 }
 
+#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;
@@ -1229,7 +1937,11 @@ static char *index2ident(int index, const char *prefix)
        return str;
 }
 
+#if defined TIZEN_EXT
+char *index2addr(int index)
+#else
 static char *index2addr(int index)
+#endif
 {
        struct ifreq ifr;
        struct ether_addr eth;
@@ -1338,6 +2050,10 @@ struct connman_device *connman_device_create_from_index(int index)
 
        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);
@@ -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);
 
                /*
@@ -1484,6 +2203,10 @@ int __connman_device_init(const char *device, const char *nodevice)
 {
        DBG("");
 
+#if defined TIZEN_EXT
+       connection = connman_dbus_get_connection();
+#endif
+
        if (device)
                device_filter = g_strsplit(device, ",", -1);
 
@@ -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
index 2d96c43..5cef038 100644 (file)
@@ -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);
@@ -76,10 +79,16 @@ static void dhcp_free(struct connman_dhcp *dhcp)
        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;
 
@@ -119,8 +128,14 @@ static bool apply_dhcp_invalidate_on_network(struct connman_dhcp *dhcp)
        }
        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;
@@ -193,6 +208,10 @@ static int ipv4ll_start_client(struct connman_dhcp *dhcp)
        int index;
        int err;
 
+#if defined TIZEN_EXT
+       DBG("dhcp %p", dhcp);
+#endif
+
        if (dhcp->ipv4ll_client)
                return -EALREADY;
 
@@ -202,12 +221,16 @@ static int ipv4ll_start_client(struct connman_dhcp *dhcp)
        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);
 
@@ -243,6 +266,10 @@ static gboolean dhcp_retry_cb(gpointer user_data)
 
        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));
 
@@ -257,6 +284,14 @@ static void no_lease_cb(GDHCPClient *dhcp_client, gpointer user_data)
        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);
 
@@ -382,18 +417,32 @@ static bool apply_lease_available_on_network(GDHCPClient *dhcp_client,
 
        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);
@@ -458,6 +507,10 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data)
        __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);
@@ -492,6 +545,10 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_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.
         *
@@ -580,14 +637,25 @@ static int dhcp_initialize(struct connman_dhcp *dhcp)
 
        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);
 
@@ -671,11 +739,48 @@ char *__connman_dhcp_get_server_address(struct connman_ipconfig *ipconfig)
        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;
 
@@ -689,7 +794,9 @@ int __connman_dhcp_start(struct connman_ipconfig *ipconfig,
                        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) {
@@ -721,7 +828,13 @@ int __connman_dhcp_start(struct connman_ipconfig *ipconfig,
        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)
old mode 100644 (file)
new mode 100755 (executable)
index 8b68359..ba54b89
@@ -197,10 +197,23 @@ static int set_duid(struct connman_service *service,
        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);
@@ -322,9 +335,19 @@ static void info_req_cb(GDHCPClient *dhcp_client, gpointer user_data)
        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);
                }
 
@@ -332,9 +355,19 @@ static void info_req_cb(GDHCPClient *dhcp_client, gpointer user_data)
 
                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);
 
@@ -392,7 +425,9 @@ static int dhcpv6_info_request(struct connman_dhcpv6 *dhcp)
                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);
@@ -517,9 +552,19 @@ static int set_other_addresses(GDHCPClient *dhcp_client,
        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);
                }
 
@@ -527,9 +572,19 @@ static int set_other_addresses(GDHCPClient *dhcp_client,
 
                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);
 
@@ -638,6 +693,9 @@ static void set_address(int ifindex, struct connman_ipconfig *ipconfig,
                /* 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);
@@ -645,6 +703,11 @@ static void set_address(int ifindex, struct connman_ipconfig *ipconfig,
                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));
        }
@@ -1713,7 +1776,9 @@ static gboolean timeout_solicitation(gpointer user_data)
 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;
@@ -1728,7 +1793,9 @@ static int dhcpv6_solicitation(struct connman_dhcpv6 *dhcp)
                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);
@@ -1754,8 +1821,20 @@ static int dhcpv6_solicitation(struct connman_dhcpv6 *dhcp)
        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,
@@ -2045,7 +2124,9 @@ static GDHCPClient *create_pd_client(struct connman_dhcpv6 *dhcp, int *err)
                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);
old mode 100644 (file)
new mode 100755 (executable)
index 38dbdd7..18dc648
 
 #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
@@ -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.
  */
@@ -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;
@@ -491,22 +510,30 @@ static void send_response(int sk, unsigned char *buf, size_t len,
                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));
@@ -1652,6 +1679,31 @@ static int ns_resolv(struct server_data *server, struct request_data *req,
                }
        }
 
+#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,
@@ -2135,8 +2187,15 @@ static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol,
                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;
@@ -2257,6 +2316,19 @@ static gboolean udp_server_event(GIOChannel *channel, GIOCondition condition,
        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;
 }
 
@@ -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)
@@ -2857,6 +3100,10 @@ int __connman_dnsproxy_remove(int index, const char *domain,
        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;
 }
 
@@ -3362,6 +3609,23 @@ static gboolean client_timeout(gpointer user_data)
        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)
@@ -3382,11 +3646,17 @@ static bool tcp_listener_event(GIOChannel *channel, GIOCondition condition,
                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;
        }
@@ -3500,7 +3770,11 @@ static bool tcp_listener_event(GIOChannel *channel, GIOCondition condition,
         * 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);
 
@@ -3529,6 +3803,39 @@ static gboolean tcp6_listener_event(GIOChannel *channel, GIOCondition condition,
                                &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)
@@ -3545,8 +3852,14 @@ static bool udp_listener_event(GIOChannel *channel, GIOCondition condition,
        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;
        }
 
@@ -3569,8 +3882,22 @@ static bool udp_listener_event(GIOChannel *channel, GIOCondition condition,
 
        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;
        }
 
@@ -3605,7 +3932,12 @@ static bool udp_listener_event(GIOChannel *channel, GIOCondition condition,
        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;
@@ -3633,14 +3965,24 @@ static GIOChannel *get_listener(int family, int protocol, int index)
 {
        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);
 
@@ -3658,7 +4000,33 @@ static GIOChannel *get_listener(int family, int protocol, int 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");
@@ -3717,15 +4085,29 @@ static GIOChannel *get_listener(int family, int protocol, int index)
                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));
@@ -3733,6 +4115,7 @@ static GIOChannel *get_listener(int family, int protocol, int index)
                        return NULL;
                }
 
+#endif
                fcntl(sk, F_SETFL, O_NONBLOCK);
        }
 
@@ -3765,40 +4148,68 @@ static int create_dns_listener(int protocol, struct listener_data *ifdata)
                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;
        }
old mode 100644 (file)
new mode 100755 (executable)
index a7a8a1d..00791c3 100644 (file)
@@ -189,6 +189,20 @@ DBusMessage *__connman_error_invalid_property(DBusMessage *msg)
                                ".InvalidProperty", "Invalid property");
 }
 
+#if defined TIZEN_EXT_WIFI_MESH
+DBusMessage *__connman_error_invalid_command(DBusMessage *msg)
+{
+       return g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
+                               ".InvalidCommand", "Invalid Mesh Command");
+}
+
+DBusMessage *__connman_error_scan_abort_failed(DBusMessage *msg)
+{
+       return g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
+                               ".ScanAbortFailed", "Scan Abort Failed");
+}
+#endif
+
 DBusMessage *__connman_error_operation_canceled(DBusMessage *msg)
 {
        return g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
index df94d1e..268dc51 100644 (file)
@@ -196,6 +196,78 @@ 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;
@@ -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;
@@ -1556,6 +1668,36 @@ static int icmpv6_recv(int fd, struct xs_cb_data *data)
                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));
@@ -1655,6 +1797,9 @@ static int ndisc_send_unspec(int type, int oif, const struct in6_addr *dest,
        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("");
 
@@ -1733,6 +1878,9 @@ static int ndisc_send_unspec(int type, int oif, const struct in6_addr *dest,
        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;
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 1551826..4a0e4ad
@@ -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;
@@ -585,6 +589,16 @@ void __connman_ipconfig_newlink(int index, unsigned short type,
                                                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);
@@ -1166,16 +1180,32 @@ void __connman_ipconfig_set_gateway(struct connman_ipconfig *ipconfig,
        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;
 
@@ -1250,7 +1280,11 @@ static struct connman_ipconfig *create_ipv6config(int index)
 
        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) {
@@ -1302,6 +1336,9 @@ struct connman_ipconfig *__connman_ipconfig_create(int index,
 
        ipconfig_set_p2p(index, ipconfig);
 
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        DBG("ipconfig %p index %d", ipconfig, index);
 
        return ipconfig;
@@ -1337,7 +1374,9 @@ void __connman_ipconfig_unref_debug(struct connman_ipconfig *ipconfig,
 {
        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);
 
@@ -1486,6 +1525,12 @@ int __connman_ipconfig_address_unset(struct connman_ipconfig *ipconfig)
        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:
@@ -1750,7 +1795,9 @@ int __connman_ipconfig_enable(struct connman_ipconfig *ipconfig)
 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)
@@ -1780,6 +1827,13 @@ int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig)
        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;
@@ -1917,6 +1971,11 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig,
        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;
        }
 
@@ -1941,6 +2000,20 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig,
        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,
@@ -1978,6 +2051,11 @@ 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;
        }
 
@@ -2177,6 +2255,10 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
 
        case CONNMAN_IPCONFIG_METHOD_OFF:
                ipconfig->method = method;
+#if defined TIZEN_EXT
+               if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6)
+                       disable_ipv6(ipconfig);
+#endif
 
                break;
 
@@ -2187,6 +2269,9 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig,
                ipconfig->method = method;
                if (privacy_string)
                        ipconfig->ipv6_privacy_config = privacy;
+#if defined TIZEN_EXT
+               enable_ipv6(ipconfig);
+#endif
 
                break;
 
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 664b27f..90a296e
@@ -452,7 +452,7 @@ static struct connman_iptables *hash_table_lookup(int type,
        case AF_INET6:
                return g_hash_table_lookup(table_hash_ipv6, table_name);
        }
-       
+
        return NULL;
 }
 
@@ -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 @@ static bool hash_table_remove(int type, const char *table_name)
        case AF_INET6:
                return g_hash_table_remove(table_hash_ipv6, table_name);
        }
-       
+
        return false;
 }
 
@@ -534,7 +534,7 @@ static int iterate_entries(struct connman_iptables_entry *entries,
        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 @@ static bool is_chain(struct connman_iptables *table,
                return true;
 
        target = iptables_entry_get_target(e);
-       
+
        if (!target)
                return false;
 
@@ -699,7 +699,7 @@ static GList *find_chain_head(struct connman_iptables *table,
        struct connman_iptables_entry *head;
        struct xt_entry_target *target;
        int builtin;
-       
+
        switch (table->type) {
        case AF_INET:
        case AF_INET6:
@@ -719,7 +719,7 @@ static GList *find_chain_head(struct connman_iptables *table,
 
                /* User defined chain */
                target = iptables_entry_get_target(head);
-               
+
                if (!target)
                        continue;
 
@@ -813,7 +813,7 @@ static void update_targets_reference(struct connman_iptables *table,
        if (is_fallthrough(modified_entry)) {
                t = (struct xt_standard_target *)
                        iptables_entry_get_target(modified_entry);
-               
+
                if (!t)
                        return;
 
@@ -1573,14 +1573,25 @@ static GList *find_existing_rule(struct connman_iptables *table,
 
        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;
        }
 
@@ -2095,7 +2106,7 @@ static void dump_table(struct connman_iptables *table)
        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,
@@ -2234,7 +2245,7 @@ static void dump_replace(struct iptables_replace *repl)
        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);
@@ -2372,7 +2383,7 @@ static int add_entry(struct connman_iptables_entry *entry, int builtin,
        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);
 
@@ -2394,7 +2405,7 @@ static int add_entry(struct connman_iptables_entry *entry, int builtin,
        default:
                return -EINVAL;
        }
-       
+
        return iptables_add_entry(table, &new_entry, NULL, builtin,
                                table->num_entries);
 }
@@ -2418,7 +2429,7 @@ static void table_cleanup(struct connman_iptables *table)
 
        g_list_free(table->entries);
        g_free(table->name);
-       
+
        if (table->type == AF_INET) {
                g_free(table->info);
                g_free(table->blob_entries);
@@ -2458,8 +2469,13 @@ static struct connman_iptables *iptables_init(int type, const char *table_name)
 
        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",
@@ -2690,9 +2706,9 @@ static struct xtables_target *prepare_target(struct connman_iptables *table,
 
        is_builtin = false;
        is_user_defined = false;
-       
+
        DBG("target %s", target_name);
-       
+
        if (!table)
                return NULL;
 
@@ -2715,7 +2731,7 @@ static struct xtables_target *prepare_target(struct connman_iptables *table,
        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();
@@ -3033,7 +3049,7 @@ static struct connman_iptables *get_table(int type, const char *table_name)
                g_free(table->name);
 
        table->name = g_strdup(table_name);
-       
+
        hash_table_replace(type, table->name, table);
 
        return table;
@@ -3385,7 +3401,7 @@ static int parse_rule_spec(struct connman_iptables *table,
                                if (invert)
                                        ctx->ipv6->invflags |= IP6T_INV_DSTIP;
                        }
-                       
+
                        break;
                case 'i':
                        /* In interface specification */
@@ -3401,7 +3417,7 @@ static int parse_rule_spec(struct connman_iptables *table,
                                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);
@@ -3549,7 +3565,7 @@ static int setup_xtables(int type)
        default:
                return -1;
        }
-       
+
        if (!err) {
                current_type = type;
        } else {
@@ -3712,7 +3728,7 @@ int __connman_iptables_find_chain(int type,
 
        if(!find_chain_head(table, chain))
                return -ENOENT; // Not Found
-       
+
        return 0; // Found
 }
 
@@ -3754,7 +3770,7 @@ int __connman_iptables_append(int type,
        int err;
 
        err = setup_xtables(type);
-       
+
        if (err < 0)
                return err;
 
@@ -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);
@@ -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);
@@ -3915,7 +3931,7 @@ int __connman_iptables_commit(int type, const char *table_name)
        unsigned int cnt;
 
        err = setup_xtables(type);
-       
+
        if (err < 0)
                return err;
 
@@ -3932,7 +3948,7 @@ int __connman_iptables_commit(int type, const char *table_name)
                repl.r = iptables_blob(table);
                if (!repl.r)
                        return -ENOMEM;
-               
+
                break;
        case AF_INET6:
                repl.r6 = ip6tables_blob(table);
@@ -3959,7 +3975,7 @@ int __connman_iptables_commit(int type, const char *table_name)
        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] =
@@ -3991,7 +4007,7 @@ out_free:
 
        g_free(repl.r);
        g_free(repl.r6);
-       
+
        reset_xtables();
 
        return err;
@@ -4036,9 +4052,15 @@ int __connman_iptables_iterate_chains(int type, const char *table_name,
        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) {
@@ -4062,7 +4084,7 @@ int __connman_iptables_iterate_chains(int type, const char *table_name,
                        iterate_chains_cb, cbd);
 
        g_free(cbd);
-       
+
        reset_xtables();
 
        return 0;
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 554b046..7a4839b
--- a/src/log.c
+++ b/src/log.c
 static const char *program_exec;
 static const char *program_path;
 
+#if defined TIZEN_EXT
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <stdbool.h>
+#include <dlog.h>
+
+#undef LOG_TAG
+#define LOG_TAG "CONNMAN"
+
+#define LOG_FILE_PATH "/opt/usr/data/network/connman.log"
+#define MAX_LOG_SIZE   1 * 1024 * 1024
+#define MAX_LOG_COUNT  15
+
+#define openlog __connman_log_open
+#define closelog __connman_log_close
+#define vsyslog __connman_log
+#define syslog __connman_log_s
+
+static FILE *log_file = NULL;
+static bool dlog_logging = true;
+static bool file_logging = true;
+static bool simple_log = true;
+
+bool get_simple_log_option(void)
+{
+       return simple_log;
+}
+
+void set_simple_log_option(bool option)
+{
+       simple_log = option;
+}
+
+void set_dlog_logging_option(bool option)
+{
+       dlog_logging = option;
+}
+
+void set_file_logging_option(bool option)
+{
+       file_logging = option;
+}
+
+void __connman_log_open(const char *ident, int option, int facility)
+{
+       if (!log_file)
+               log_file = (FILE *)fopen(LOG_FILE_PATH, "a+");
+}
+
+void __connman_log_close(void)
+{
+       fclose(log_file);
+       log_file = NULL;
+}
+
+static void __connman_log_update_file_revision(int rev)
+{
+       int next_log_rev = 0;
+       char *log_file = NULL;
+       char *next_log_file = NULL;
+
+       next_log_rev = rev + 1;
+
+       log_file = g_strdup_printf("%s.%d", LOG_FILE_PATH, rev);
+       next_log_file = g_strdup_printf("%s.%d", LOG_FILE_PATH, next_log_rev);
+
+       if (next_log_rev >= MAX_LOG_COUNT)
+               if (remove(next_log_file) != 0)
+                       goto error;
+
+       if (access(next_log_file, F_OK) == 0)
+               __connman_log_update_file_revision(next_log_rev);
+
+       if (rename(log_file, next_log_file) != 0)
+               remove(log_file);
+
+error:
+       g_free(log_file);
+       g_free(next_log_file);
+}
+
+static int __connman_log_make_backup(void)
+{
+       const int rev = 0;
+       char *backup = NULL;
+       int ret = 0;
+
+       backup = g_strdup_printf("%s.%d", LOG_FILE_PATH, rev);
+
+       if (access(backup, F_OK) == 0)
+               __connman_log_update_file_revision(rev);
+
+       if (rename(LOG_FILE_PATH, backup) != 0)
+               if (remove(LOG_FILE_PATH) != 0)
+                       ret = -1;
+
+       g_free(backup);
+       return ret;
+}
+
+static void __connman_log_get_local_time(char *strtime, const int size)
+{
+       struct timeval tv;
+       struct tm *local_ptm;
+       char buf[32];
+
+       gettimeofday(&tv, NULL);
+       local_ptm = localtime(&tv.tv_sec);
+
+       strftime(buf, sizeof(buf), "%m/%d %H:%M:%S", local_ptm);
+       snprintf(strtime, size, "%s.%03ld", buf, tv.tv_usec / 1000);
+}
+
+void __connman_log(const int log_priority, const char *format, va_list ap)
+{
+       int log_size = 0;
+       struct stat buf;
+       char str[256];
+       char strtime[64];
+
+       if (!log_file)
+               log_file = (FILE *)fopen(LOG_FILE_PATH, "a+");
+
+       if (!log_file)
+               return;
+
+       if (fstat(fileno(log_file), &buf) < 0) {
+               fclose(log_file);
+               log_file = NULL;
+               return;
+       }
+
+       log_size = buf.st_size;
+
+       if (log_size >= MAX_LOG_SIZE) {
+               fclose(log_file);
+               log_file = NULL;
+
+               if (__connman_log_make_backup() != 0)
+                       return;
+
+               log_file = (FILE *)fopen(LOG_FILE_PATH, "a+");
+
+               if (!log_file)
+                       return;
+       }
+
+       __connman_log_get_local_time(strtime, sizeof(strtime));
+
+       if (vsnprintf(str, sizeof(str), format, ap) > 0)
+               fprintf(log_file, "%s %s\n", strtime, str);
+}
+
+void __connman_log_s(int log_priority, const char *format, ...)
+{
+       va_list ap;
+
+       va_start(ap, format);
+
+       if (dlog_logging)
+               dlog_vprint(DLOG_DEBUG, LOG_TAG, format, ap);
+
+       if (file_logging)
+               vsyslog(LOG_DEBUG, format, ap);
+
+       va_end(ap);
+}
+#endif
+
 /* This makes sure we always have a __debug section. */
 CONNMAN_DEBUG_DEFINE(dummy);
 
@@ -52,7 +221,12 @@ void connman_info(const char *format, ...)
        va_list ap;
 
        va_start(ap, format);
+#if defined TIZEN_EXT
+       if (dlog_logging)
+               dlog_vprint(DLOG_INFO, LOG_TAG, format, ap);
 
+       if (file_logging)
+#endif
        vsyslog(LOG_INFO, format, ap);
 
        va_end(ap);
@@ -70,7 +244,12 @@ void connman_warn(const char *format, ...)
        va_list ap;
 
        va_start(ap, format);
+#if defined TIZEN_EXT
+       if (dlog_logging)
+               dlog_vprint(DLOG_WARN, LOG_TAG, format, ap);
 
+       if (file_logging)
+#endif
        vsyslog(LOG_WARNING, format, ap);
 
        va_end(ap);
@@ -88,7 +267,12 @@ void connman_error(const char *format, ...)
        va_list ap;
 
        va_start(ap, format);
+#if defined TIZEN_EXT
+       if (dlog_logging)
+               dlog_vprint(DLOG_ERROR, LOG_TAG, format, ap);
 
+       if (file_logging)
+#endif
        vsyslog(LOG_ERR, format, ap);
 
        va_end(ap);
@@ -106,7 +290,12 @@ void connman_debug(const char *format, ...)
        va_list ap;
 
        va_start(ap, format);
+#if defined TIZEN_EXT
+       if (dlog_logging)
+               dlog_vprint(DLOG_DEBUG, LOG_TAG, format, ap);
 
+       if (file_logging)
+#endif
        vsyslog(LOG_DEBUG, format, ap);
 
        va_end(ap);
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 6480caa..13e26d4
@@ -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_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
 
@@ -102,6 +109,19 @@ static struct {
        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,
@@ -127,8 +147,77 @@ static struct {
        .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"
@@ -153,6 +242,47 @@ static struct {
 #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,
@@ -179,9 +309,53 @@ static const char *supported_options[] = {
        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;
@@ -265,7 +439,12 @@ static void check_config(GKeyFile *config)
        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);
        }
@@ -291,8 +470,294 @@ static void check_config(GKeyFile *config)
        }
 
        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;
@@ -341,6 +806,8 @@ static void parse_config(GKeyFile *config)
                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",
@@ -531,18 +998,30 @@ static void parse_config(GKeyFile *config)
                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;
 }
 
@@ -715,6 +1194,19 @@ char *connman_setting_get_string(const char *key)
                        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;
 }
 
@@ -753,6 +1245,50 @@ bool connman_setting_get_bool(const char *key)
        if (g_str_equal(key, CONF_USE_GATEWAYS_AS_TIMESERVERS))
                return connman_settings.use_gateways_as_timeservers;
 
+#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 (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;
 }
 
@@ -764,9 +1300,53 @@ unsigned int connman_setting_get_uint(const char *key)
        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))
@@ -781,6 +1361,16 @@ char **connman_setting_get_string_list(const char *key)
        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;
 }
 
@@ -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
@@ -889,6 +1494,9 @@ int main(int argc, char *argv[])
        __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();
@@ -904,7 +1512,11 @@ int main(int argc, char *argv[])
        __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();
@@ -920,8 +1532,10 @@ int main(int argc, char *argv[])
        __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);
@@ -933,8 +1547,10 @@ int main(int argc, char *argv[])
 
        g_source_remove(signal);
 
+#if !defined TIZEN_EXT
        __connman_machine_cleanup();
        __connman_rfkill_cleanup();
+#endif
        __connman_wispr_cleanup();
        __connman_wpad_cleanup();
        __connman_dhcpv6_cleanup();
@@ -959,6 +1575,9 @@ int main(int argc, char *argv[])
        __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();
@@ -990,6 +1609,13 @@ int main(int argc, char *argv[])
        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);
 
old mode 100644 (file)
new mode 100755 (executable)
index df70e17..e734ecf
@@ -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
@@ -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
@@ -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
@@ -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.
@@ -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
 # 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 --git a/src/main_disable_eth.conf b/src/main_disable_eth.conf
new file mode 100755 (executable)
index 0000000..4cc22f1
--- /dev/null
@@ -0,0 +1,114 @@
+[General]
+
+# Set input request timeout. Default is 120 seconds
+# The request for inputs like passphrase will timeout
+# after certain amount of time. Use this setting to
+# increase the value in case of different user
+# interface designs.
+# InputRequestTimeout = 120
+
+# Set browser launch timeout. Default is 300 seconds
+# The request for launching a browser for portal pages
+# will timeout after certain amount of time. Use this
+# setting to increase the value in case of different
+# user interface designs.
+# BrowserLaunchTimeout = 300
+
+# Enable background scanning. Default is true.
+# Background scanning will start every 5 minutes unless
+# the scan list is empty. In that case, a simple backoff
+# mechanism starting from 10s up to 5 minutes will run.
+# BackgroundScanning = true
+BackgroundScanning = false
+
+# List of Fallback timeservers separated by ",".
+# These timeservers are used for NTP sync when there are
+# no timeserver set by the user or by the service.
+# These can contain 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
+# nameserver entries must be in numeric format, host
+# names are ignored.
+# FallbackNameservers =
+
+# List of technologies that are marked autoconnectable
+# by default, separated by commas ",". The default value
+# for this entry when empty is ethernet,wifi,cellular.
+# Services that are automatically connected must have been
+# set up and saved to storage beforehand.
+# DefaultAutoConnectTechnologies =
+
+# List of preferred technologies from the most preferred
+# one to the least preferred one separated by commas ",".
+# Services of the listed technology type will be tried one
+# by one in the order given, until one of them gets connected
+# or they are all tried. A service of a preferred technology
+# type in state 'ready' will get the default route when
+# compared to another preferred type further down the list
+# with state 'ready' or with a non-preferred type; a service
+# of a preferred technology type in state 'online' will get
+# 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
+# not be handled by connman, if their first characters
+# match any of the list entries. Default value is
+# vmnet,vboxnet,virbr,ifb.
+# NetworkInterfaceBlacklist = vmnet,vboxnet,virbr,ifb
+NetworkInterfaceBlacklist = veth, vmnet,vboxnet,virbr,usb,rndis,rmnet,rev_rmnet,dummy,seth_td,seth_w,eth
+
+# Allow connman to change the system hostname. This can
+# happen for example if we receive DHCP hostname option.
+# Default value is true.
+# AllowHostnameUpdates = true
+
+# Keep only a single connected technology at any time. When a new
+# service is connected by the user or a better one is found according
+# to PreferredTechnologies, the new service is kept connected and all
+# the other previously connected services are disconnected. With this
+# setting it does not matter whether the previously connected services
+# are in 'online' or 'ready' states, the newly connected service is
+# the only one that will be kept connected. A service connected by the
+# user will be used until going out of network coverage. With this
+# 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
+# listed here are used for tethering. If ethernet tethering is desired,
+# then ethernet should be added to the list. The technologies listed here
+# have to support tethering, currently tethering is implemented for wifi,
+# bluetooth, gadget and ethernet.
+# NOTE that if ethernet tethering is enabled, then a DHCP server is
+# started on all ethernet interfaces. Tethered ethernet should
+# never be connected to corporate or home network as it will disrupt
+# normal operation of these networks. Due to this ethernet is not
+# tethered by default. Do not activate ethernet tethering unless you
+# really know what you are doing.
+# TetheringTechnologies = wifi,bluetooth,gadget
+
+# Restore earlier tethering status when returning from offline mode,
+# re-enabling a technology, and after restarts and reboots.
+# Default value is false.
+# PersistentTetheringMode = false
+
+# Automatically enable Anycast 6to4 if possible. This is not recommended, as
+# the use of 6to4 will generally lead to a severe degradation of connection
+# quality. See RFC6343. Default value is false (as recommended by RFC6343
+# section 4.1).
+# Enable6to4 = false
+
+NetworkCellularInterfaceList = pdp,rmnet,seth_td,seth_w
+
+# Allow connman to add service gateway to the time server list.
+# Default value is false.
+# UseGatewaysAsTimeservers = false
diff --git a/src/main_ivi.conf b/src/main_ivi.conf
new file mode 100755 (executable)
index 0000000..8ac0d58
--- /dev/null
@@ -0,0 +1,114 @@
+[General]
+
+# Set input request timeout. Default is 120 seconds
+# The request for inputs like passphrase will timeout
+# after certain amount of time. Use this setting to
+# increase the value in case of different user
+# interface designs.
+# InputRequestTimeout = 120
+
+# Set browser launch timeout. Default is 300 seconds
+# The request for launching a browser for portal pages
+# will timeout after certain amount of time. Use this
+# setting to increase the value in case of different
+# user interface designs.
+# BrowserLaunchTimeout = 300
+
+# Enable background scanning. Default is true.
+# Background scanning will start every 5 minutes unless
+# the scan list is empty. In that case, a simple backoff
+# mechanism starting from 10s up to 5 minutes will run.
+# BackgroundScanning = true
+BackgroundScanning = false
+
+# List of Fallback timeservers separated by ",".
+# These timeservers are used for NTP sync when there are
+# no timeserver set by the user or by the service.
+# These can contain 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
+# nameserver entries must be in numeric format, host
+# names are ignored.
+# FallbackNameservers =
+
+# List of technologies that are marked autoconnectable
+# by default, separated by commas ",". The default value
+# for this entry when empty is ethernet,wifi,cellular.
+# Services that are automatically connected must have been
+# set up and saved to storage beforehand.
+# DefaultAutoConnectTechnologies =
+
+# List of preferred technologies from the most preferred
+# one to the least preferred one separated by commas ",".
+# Services of the listed technology type will be tried one
+# by one in the order given, until one of them gets connected
+# or they are all tried. A service of a preferred technology
+# type in state 'ready' will get the default route when
+# compared to another preferred type further down the list
+# with state 'ready' or with a non-preferred type; a service
+# of a preferred technology type in state 'online' will get
+# 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
+# not be handled by connman, if their first characters
+# match any of the list entries. Default value is
+# vmnet,vboxnet,virbr,ifb.
+# NetworkInterfaceBlacklist = vmnet,vboxnet,virbr,ifb
+NetworkInterfaceBlacklist = veth, vmnet,vboxnet,virbr,usb,rndis,rmnet,rev_rmnet,dummy,seth_td,seth_w,eth0
+
+# Allow connman to change the system hostname. This can
+# happen for example if we receive DHCP hostname option.
+# Default value is true.
+# AllowHostnameUpdates = true
+
+# Keep only a single connected technology at any time. When a new
+# service is connected by the user or a better one is found according
+# to PreferredTechnologies, the new service is kept connected and all
+# the other previously connected services are disconnected. With this
+# setting it does not matter whether the previously connected services
+# are in 'online' or 'ready' states, the newly connected service is
+# the only one that will be kept connected. A service connected by the
+# user will be used until going out of network coverage. With this
+# 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
+# listed here are used for tethering. If ethernet tethering is desired,
+# then ethernet should be added to the list. The technologies listed here
+# have to support tethering, currently tethering is implemented for wifi,
+# bluetooth, gadget and ethernet.
+# NOTE that if ethernet tethering is enabled, then a DHCP server is
+# started on all ethernet interfaces. Tethered ethernet should
+# never be connected to corporate or home network as it will disrupt
+# normal operation of these networks. Due to this ethernet is not
+# tethered by default. Do not activate ethernet tethering unless you
+# really know what you are doing.
+# TetheringTechnologies = wifi,bluetooth,gadget
+
+# Restore earlier tethering status when returning from offline mode,
+# re-enabling a technology, and after restarts and reboots.
+# Default value is false.
+# PersistentTetheringMode = false
+
+# Automatically enable Anycast 6to4 if possible. This is not recommended, as
+# the use of 6to4 will generally lead to a severe degradation of connection
+# quality. See RFC6343. Default value is false (as recommended by RFC6343
+# section 4.1).
+# Enable6to4 = false
+
+NetworkCellularInterfaceList = pdp,rmnet,seth_td,seth_w
+
+# Allow connman to add service gateway to the time server list.
+# Default value is false.
+# UseGatewaysAsTimeservers = false
diff --git a/src/main_tv.conf b/src/main_tv.conf
new file mode 100755 (executable)
index 0000000..c7b8e11
--- /dev/null
@@ -0,0 +1,152 @@
+[General]
+
+# Set input request timeout. Default is 120 seconds
+# The request for inputs like passphrase will timeout
+# after certain amount of time. Use this setting to
+# increase the value in case of different user
+# interface designs.
+# InputRequestTimeout = 120
+
+# Set browser launch timeout. Default is 300 seconds
+# The request for launching a browser for portal pages
+# will timeout after certain amount of time. Use this
+# setting to increase the value in case of different
+# user interface designs.
+# BrowserLaunchTimeout = 300
+
+# Enable background scanning. Default is true.
+# Background scanning will start every 5 minutes unless
+# the scan list is empty. In that case, a simple backoff
+# mechanism starting from 10s up to 5 minutes will run.
+# BackgroundScanning = true
+BackgroundScanning = false
+
+# List of Fallback timeservers separated by ",".
+# These timeservers are used for NTP sync when there are
+# no timeserver set by the user or by the service.
+# These can contain 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
+# nameserver entries must be in numeric format, host
+# names are ignored.
+# FallbackNameservers =
+
+# List of technologies that are marked autoconnectable
+# by default, separated by commas ",". The default value
+# for this entry when empty is ethernet,wifi,cellular.
+# Services that are automatically connected must have been
+# set up and saved to storage beforehand.
+# DefaultAutoConnectTechnologies =
+
+# List of preferred technologies from the most preferred
+# one to the least preferred one separated by commas ",".
+# Services of the listed technology type will be tried one
+# by one in the order given, until one of them gets connected
+# or they are all tried. A service of a preferred technology
+# type in state 'ready' will get the default route when
+# compared to another preferred type further down the list
+# with state 'ready' or with a non-preferred type; a service
+# of a preferred technology type in state 'online' will get
+# 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
+# not be handled by connman, if their first characters
+# match any of the list entries. Default value is
+# vmnet,vboxnet,virbr,ifb.
+# NetworkInterfaceBlacklist = vmnet,vboxnet,virbr,ifb
+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.
+# Default value is true.
+# AllowHostnameUpdates = true
+
+# Keep only a single connected technology at any time. When a new
+# service is connected by the user or a better one is found according
+# to PreferredTechnologies, the new service is kept connected and all
+# the other previously connected services are disconnected. With this
+# setting it does not matter whether the previously connected services
+# are in 'online' or 'ready' states, the newly connected service is
+# the only one that will be kept connected. A service connected by the
+# user will be used until going out of network coverage. With this
+# 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
+# listed here are used for tethering. If ethernet tethering is desired,
+# then ethernet should be added to the list. The technologies listed here
+# have to support tethering, currently tethering is implemented for wifi,
+# bluetooth, gadget and ethernet.
+# NOTE that if ethernet tethering is enabled, then a DHCP server is
+# started on all ethernet interfaces. Tethered ethernet should
+# never be connected to corporate or home network as it will disrupt
+# normal operation of these networks. Due to this ethernet is not
+# tethered by default. Do not activate ethernet tethering unless you
+# really know what you are doing.
+# TetheringTechnologies = wifi,bluetooth,gadget
+
+# Restore earlier tethering status when returning from offline mode,
+# re-enabling a technology, and after restarts and reboots.
+# Default value is false.
+# PersistentTetheringMode = false
+
+# Automatically enable Anycast 6to4 if possible. This is not recommended, as
+# the use of 6to4 will generally lead to a severe degradation of connection
+# quality. See RFC6343. Default value is false (as recommended by RFC6343
+# section 4.1).
+# Enable6to4 = false
+
+NetworkCellularInterfaceList = pdp,rmnet,seth_td,seth_w
+
+# Allow connman to add service gateway to the time server list.
+# Default value is false.
+# UseGatewaysAsTimeservers = false
+
+# Enable Tizen TV Profile Features
+TizenTVExtension = true
+
+# This value specifies which will be the default when there are multiple wifi interfaces.
+# Default value is wlan0.
+DefaultWifiInterface = wlan0
+
+[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
old mode 100644 (file)
new mode 100755 (executable)
index 3bf8f4e..0000f78
@@ -41,6 +41,9 @@ static DBusMessage *get_properties(DBusConnection *conn,
        DBusMessageIter array, dict;
        dbus_bool_t offlinemode;
        const char *str;
+#if defined TIZEN_EXT
+       dbus_bool_t autoconnectmode;
+#endif
 
        DBG("conn %p", conn);
 
@@ -63,6 +66,12 @@ static DBusMessage *get_properties(DBusConnection *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);
 
@@ -109,7 +118,17 @@ static DBusMessage *set_property(DBusConnection *conn,
                        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);
 
@@ -126,7 +145,9 @@ static DBusMessage *get_technologies(DBusConnection *conn,
 {
        DBusMessage *reply;
 
+#if !defined TIZEN_EXT
        DBG("");
+#endif
 
        reply = dbus_message_new_method_return(msg);
        if (!reply)
@@ -195,6 +216,80 @@ static DBusMessage *get_services(DBusConnection *conn,
        return reply;
 }
 
+#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);
@@ -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}" }),
@@ -537,6 +740,23 @@ static const GDBusMethodTable manager_methods[] = {
        { 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) },
@@ -583,6 +803,21 @@ static const GDBusMethodTable manager_methods[] = {
        { 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 --git a/src/mesh-netlink.c b/src/mesh-netlink.c
new file mode 100644 (file)
index 0000000..22d6925
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *
+ *  Copyright (C) 2017 Samsung Electronics Co., Ltd.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ *  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "connman.h"
+#include <connman/mesh-netlink.h>
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+#include <netlink/netlink.h>
+
+static int seq_check_cb(struct nl_msg *msg, void *arg)
+{
+       DBG("");
+
+       return NL_OK;
+}
+
+static int finish_cb(struct nl_msg *msg, void *arg)
+{
+       int *ret = arg;
+
+       DBG("");
+
+       *ret = 0;
+
+       return NL_SKIP;
+}
+
+static int ack_cb(struct nl_msg *msg, void *arg)
+{
+       int *ret = arg;
+
+       DBG("");
+
+       *ret = 0;
+
+       return NL_STOP;
+}
+
+static int valid_cb(struct nl_msg *msg, void *arg)
+{
+       DBG("");
+
+       return NL_SKIP;
+}
+
+static int error_cb(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
+{
+       int *ret = arg;
+
+       *ret = err->error;
+
+       DBG("error %d", *ret);
+
+       return NL_STOP;
+}
+
+int __connman_mesh_netlink_set_gate_announce(mesh_nl80211_global *global,
+                                       int mesh_if_index, bool gate_announce, int hwmp_rootmode)
+{
+       struct nl_msg *msg;
+       struct nlattr *container;
+       struct nl_cb *cb;
+       int err = -1;
+
+       msg = nlmsg_alloc();
+       if (!msg)
+               return -1;
+
+       cb = nl_cb_clone(global->cb);
+       if (!cb)
+               goto out;
+
+       genlmsg_put(msg, 0, 0, global->id, 0, 0, NL80211_CMD_SET_MESH_CONFIG, 0);
+       nla_put_u32(msg, NL80211_ATTR_IFINDEX, mesh_if_index);
+
+       container = nla_nest_start(msg, NL80211_ATTR_MESH_CONFIG);
+
+       nla_put_u8(msg, NL80211_MESHCONF_HWMP_ROOTMODE, hwmp_rootmode);
+
+       nla_put_u8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS, gate_announce);
+
+       nla_nest_end(msg, container);
+
+       err = nl_send_auto_complete(global->nl_socket, msg);
+       if (err < 0) {
+               DBG("Failed to send msg");
+               goto out;
+       }
+
+       err = 1;
+
+       nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_cb, &err);
+       nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_cb, &err);
+       nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, valid_cb, &err);
+       nl_cb_err(cb, NL_CB_CUSTOM, error_cb, &err);
+
+       while (err > 0) {
+               int res = nl_recvmsgs(global->nl_socket, cb);
+               if (res < 0)
+                       DBG("nl_recvmsgs failed: %d", res);
+       }
+
+out:
+       nl_cb_put(cb);
+       nlmsg_free(msg);
+       return err;
+}
+
+mesh_nl80211_global *__connman_mesh_nl80211_global_init(void)
+{
+       mesh_nl80211_global *global;
+
+       DBG("");
+
+       global = g_malloc0(sizeof(mesh_nl80211_global));
+
+       global->nl_socket = nl_socket_alloc();
+       if (!global->nl_socket) {
+               DBG("Failed to allocate netlink socket");
+               g_free(global);
+               return NULL;
+       }
+
+       if (genl_connect(global->nl_socket)) {
+               DBG("Failed to connect to generic netlink");
+               nl_socket_free(global->nl_socket);
+               g_free(global);
+               return NULL;
+       }
+
+       nl_socket_set_buffer_size(global->nl_socket, 8192, 8192);
+
+       global->id = genl_ctrl_resolve(global->nl_socket, "nl80211");
+       if (global->id < 0) {
+               DBG("nl80211 generic netlink not found");
+               nl_socket_free(global->nl_socket);
+               g_free(global);
+               return NULL;
+       }
+
+       global->cb = nl_cb_alloc(NL_CB_DEFAULT);
+       if (!global->cb) {
+               DBG("Failed to allocate netwlink callbacks");
+               nl_socket_free(global->nl_socket);
+               g_free(global);
+               return NULL;
+       }
+
+       nl_cb_set(global->cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM, seq_check_cb, NULL);
+
+       return global;
+}
+
+void __connman_mesh_nl80211_global_deinit(mesh_nl80211_global *global)
+{
+       DBG("");
+
+       nl_cb_put(global->cb);
+       nl_socket_free(global->nl_socket);
+       g_free(global);
+}
diff --git a/src/mesh.c b/src/mesh.c
new file mode 100644 (file)
index 0000000..e0e6d2f
--- /dev/null
@@ -0,0 +1,1660 @@
+/*
+ *
+ *  Connection Manager
+ *
+ *
+ *  Copyright (C) 2017 Samsung Electronics Co., Ltd.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ *  02110-1301  USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <gdbus.h>
+
+#include <connman/storage.h>
+#include "connman.h"
+#include <sys/types.h>
+#include <dirent.h>
+#include <linux/if_bridge.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <unistd.h>
+#include "mesh-netlink.h"
+
+static DBusConnection *connection;
+
+static GHashTable *mesh_table;
+static GHashTable *connected_peer_table;
+static GHashTable *disconnected_peer_table;
+
+static struct connman_mesh_driver *mesh_driver;
+static struct connman_mesh_eth_driver *mesh_eth_driver;
+
+char *mesh_ifname;
+char *bridge_interface;
+static unsigned int mesh_autoconnect_timeout;
+static bool is_mesh_if_created;
+bool eth_if_bridged;
+mesh_nl80211_global *nl80211_global;
+
+struct connman_mesh {
+       int refcount;
+       char *identifier;
+       char *name;
+       char *path;
+       char *address;
+       char *interface_addr;
+       enum connman_mesh_security security;
+       char *passphrase;
+       enum connman_mesh_state state;
+       enum connman_mesh_peer_type peer_type;
+       enum connman_mesh_peer_disconnect_reason disconnect_reason;
+       uint16_t frequency;
+       uint8_t strength;
+       bool registered;
+       bool favorite;
+       DBusMessage *pending;
+       int index;
+       int br_index;
+       uint16_t ieee80211w;
+       struct connman_ipconfig *ipconfig;
+};
+
+struct connman_mesh_connected_peer {
+       char *peer_address;
+};
+
+struct connman_mesh_disconnected_peer {
+       char *peer_address;
+       enum connman_mesh_peer_disconnect_reason disconnect_reason;
+};
+
+struct connman_mesh_change_peer_data {
+       DBusMessage *pending;
+       char *peer_address;
+       enum connman_mesh_peer_status status;
+};
+
+static void mesh_dhcp_callback(struct connman_ipconfig *ipconfig,
+                               struct connman_network *network, bool success, gpointer data);
+
+static void mesh_free(gpointer data)
+{
+       struct connman_mesh *mesh = data;
+
+       connman_mesh_unregister(mesh);
+
+       g_free(mesh->path);
+
+       if (mesh->state == CONNMAN_MESH_STATE_CONFIGURATION ||
+                       mesh->state == CONNMAN_MESH_STATE_READY)
+               __connman_dhcp_stop(mesh->ipconfig);
+
+       if (mesh->ipconfig) {
+               __connman_ipconfig_set_ops(mesh->ipconfig, NULL);
+               __connman_ipconfig_set_data(mesh->ipconfig, NULL);
+               __connman_ipconfig_unref(mesh->ipconfig);
+               mesh->ipconfig = NULL;
+       }
+       g_free(mesh->identifier);
+       g_free(mesh->name);
+       g_free(mesh->passphrase);
+       g_free(mesh->interface_addr);
+       g_free(mesh->address);
+       g_free(mesh);
+}
+
+static void mesh_connected_peer_free(gpointer data)
+{
+       struct connman_mesh_connected_peer *peer = data;
+
+       g_free(peer->peer_address);
+       g_free(peer);
+}
+
+static void mesh_disconnected_peer_free(gpointer data)
+{
+       struct connman_mesh_disconnected_peer *peer = data;
+
+       g_free(peer->peer_address);
+       g_free(peer);
+}
+
+static void __mesh_load_and_create_network(char *mesh_id)
+{
+       GKeyFile *keyfile;
+       GString *str;
+       struct connman_mesh *connman_mesh;
+       gchar *name, *passphrase, *peer_type;
+       char *identifier, *group, *address;
+       const char *sec_type, *mesh_ifname;
+       int freq, i;
+
+       keyfile = connman_storage_load_service(mesh_id);
+       if (!keyfile) {
+               DBG("Mesh profile doesn't exist");
+               return;
+       }
+
+       peer_type = g_key_file_get_string(keyfile, mesh_id, "PeerType", NULL);
+       if (g_strcmp0(peer_type, "created")) {
+               DBG("Mesh Profile was not created");
+               goto done;
+       }
+
+       name = g_key_file_get_string(keyfile, mesh_id, "Name", NULL);
+       if (!name) {
+               DBG("Failed to get Mesh Profile Name");
+               goto done;
+       }
+
+       passphrase = g_key_file_get_string(keyfile, mesh_id, "Passphrase", NULL);
+       if (passphrase)
+               sec_type = "sae";
+       else
+               sec_type = "none";
+
+       freq = g_key_file_get_integer(keyfile, mesh_id, "Frequency", NULL);
+
+       mesh_ifname = connman_mesh_get_interface_name();
+
+       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_register(connman_mesh);
+       g_free(group);
+       g_free(identifier);
+       g_free(address);
+done:
+       g_key_file_free(keyfile);
+}
+
+static bool is_connected(struct connman_mesh *mesh)
+{
+       if (mesh->state == CONNMAN_MESH_STATE_READY)
+               return true;
+
+       return false;
+}
+
+static void mesh_peer_dhcp_refresh(gpointer key, gpointer value,
+                                                                  gpointer user_data)
+{
+       struct connman_mesh *mesh = value;
+
+       DBG("mesh %p state %d", mesh, mesh->state);
+
+       if (is_connected(mesh))
+               __connman_mesh_dhcp_start(mesh->ipconfig, mesh_dhcp_callback, mesh);
+}
+
+int connman_inet_set_stp(int stp)
+{
+       int sk, err = 0;
+       struct ifreq ifr;
+       unsigned long args[4];
+
+       if (!bridge_interface)
+               return -EINVAL;
+
+       sk = socket(AF_LOCAL, SOCK_STREAM, 0);
+       if (sk < 0) {
+               err = -errno;
+               goto out;
+       }
+
+       args[0] = BRCTL_SET_BRIDGE_STP_STATE;
+       args[1] = stp;
+       args[2] = args[3] = 0;
+       memset(&ifr, 0, sizeof(struct ifreq));
+       strncpy(ifr.ifr_name, bridge_interface, sizeof(ifr.ifr_name) - 1);
+       ifr.ifr_data = (char *)args;
+
+       if (ioctl(sk, SIOCDEVPRIVATE, &ifr) < 0)
+               err = -errno;
+
+       close(sk);
+
+out:
+       if (err < 0)
+               DBG("Set STP Failed error %s", strerror(-err));
+
+       return err;
+}
+
+int __connman_mesh_set_stp_gate_announce(bool gate_announce, int hwmp_rootmode,
+                                               int stp)
+{
+       int err;
+
+       if (!mesh_ifname)
+               return -EINVAL;
+
+       err = connman_inet_set_stp(stp);
+       if (err < 0)
+               return err;
+
+       err = __connman_mesh_netlink_set_gate_announce(nl80211_global,
+                                               connman_inet_ifindex(mesh_ifname), gate_announce,
+                                               hwmp_rootmode);
+
+       return err;
+}
+
+void __connman_mesh_add_ethernet_to_bridge(void)
+{
+       if (is_mesh_if_created) {
+               DBG("");
+               mesh_eth_driver->add_to_bridge(bridge_interface);
+               eth_if_bridged = true;
+               g_hash_table_foreach(mesh_table, mesh_peer_dhcp_refresh, NULL);
+               connman_inet_set_stp(1);
+               __connman_mesh_netlink_set_gate_announce(nl80211_global,
+                                                       connman_inet_ifindex(mesh_ifname), true,
+                                                       MESH_HWMP_ROOTMODE_RANN);
+       }
+}
+
+void __connman_mesh_remove_ethernet_from_bridge(void)
+{
+       if (eth_if_bridged) {
+               DBG("");
+               mesh_eth_driver->remove_from_bridge(bridge_interface);
+               eth_if_bridged = false;
+               g_hash_table_foreach(mesh_table, mesh_peer_dhcp_refresh, NULL);
+               connman_inet_set_stp(0);
+               __connman_mesh_netlink_set_gate_announce(nl80211_global,
+                                                       connman_inet_ifindex(mesh_ifname), false,
+                                                       MESH_HWMP_ROOTMODE_NO_ROOT);
+       }
+}
+
+int connman_mesh_notify_interface_create(bool success)
+{
+       int ret;
+       int index;
+       const char *error = NULL;
+       DIR *dir;
+       struct dirent *d;
+
+       if (!success) {
+               error = "Operation Failed";
+               goto done;
+       }
+
+       if (!bridge_interface) {
+               DBG("Don't create bridge interface");
+               goto done;
+       }
+
+       DBG("Creating bridge [%s]", bridge_interface);
+
+       /* Create bridge interface */
+       ret = __connman_bridge_create(bridge_interface);
+       if (0 != ret) {
+               DBG("Failed to create bridge [%s] : [%s]", bridge_interface,
+                               strerror(-ret));
+               error = "Bridge Creation";
+               success = false;
+               goto done;
+       }
+
+       /* Get Mesh Interface Index */
+       index = connman_inet_ifindex(mesh_ifname);
+       if (index < 0) {
+               DBG("Failed to get interface index for %s", mesh_ifname);
+               error = "Operation Failed";
+               success = false;
+               goto done;
+       }
+
+       /* Add mesh interface into bridge */
+       ret = connman_inet_add_to_bridge(index, bridge_interface);
+       if (0 != ret) {
+               DBG("Failed to add interface[%s] into bridge[%s]", mesh_ifname,
+                                       bridge_interface);
+               error = "Add Mesh into bridge";
+               success = false;
+               goto done;
+       }
+
+       if (__connman_technology_get_connected(CONNMAN_SERVICE_TYPE_ETHERNET)) {
+               mesh_eth_driver->add_to_bridge(bridge_interface);
+               eth_if_bridged = true;
+       }
+
+       index = connman_inet_ifindex(bridge_interface);
+       if (index < 0) {
+               DBG("Failed to get interface index for %s", bridge_interface);
+               error = "Operation Failed";
+               success = false;
+               goto done;
+       }
+
+       /* Make bridge interface UP */
+       ret = connman_inet_ifup(index);
+       if (0 != ret) {
+               DBG("Failed to change bridge interface state");
+               error = "Make bridge interface UP";
+               success = false;
+       }
+
+done:
+       if (success) {
+               is_mesh_if_created = true;
+
+               /* Load previously created mesh profiles */
+               dir = opendir(STORAGEDIR);
+               if (!dir) {
+                       DBG("Failed to open %s directory", STORAGEDIR);
+                       __connman_technology_mesh_interface_create_finished(
+                               CONNMAN_SERVICE_TYPE_MESH, success, error);
+                       return 0;
+               }
+
+               while ((d = readdir(dir))) {
+                       if (g_str_has_prefix(d->d_name, "mesh_")) {
+                               DBG("%s is a mesh profile", d->d_name);
+                               __mesh_load_and_create_network(d->d_name);
+                               __connman_mesh_auto_connect();
+                       }
+               }
+
+               closedir(dir);
+
+       } else {
+               if (eth_if_bridged)
+                       mesh_eth_driver->remove_from_bridge(bridge_interface);
+
+               __connman_bridge_disable(bridge_interface);
+
+               __connman_bridge_remove(bridge_interface);
+
+               mesh_driver->remove_interface(mesh_ifname);
+       }
+       __connman_technology_mesh_interface_create_finished(
+                           CONNMAN_SERVICE_TYPE_MESH, success, error);
+       return 0;
+}
+
+int __connman_mesh_add_virtual_interface(const char *ifname,
+                                               const char *parent_ifname, const char *bridge_ifname)
+{
+       int ret;
+
+       if (!ifname || !parent_ifname)
+               return -EINVAL;
+
+       ret = mesh_driver->add_interface(ifname, parent_ifname);
+       if (ret != -EINPROGRESS) {
+               DBG("Failed to add virtual mesh interface");
+               return ret;
+       }
+
+       mesh_ifname = g_strdup(ifname);
+       bridge_interface = g_strdup(bridge_ifname);
+       DBG("Success adding virtual mesh interface");
+       return 0;
+}
+
+int connman_mesh_notify_interface_remove(bool success)
+{
+       struct connman_device *device;
+       int index;
+       if (success) {
+               g_free(mesh_ifname);
+               mesh_ifname = NULL;
+               g_hash_table_remove_all(mesh_table);
+               is_mesh_if_created = false;
+
+               if (eth_if_bridged) {
+                       if (bridge_interface)
+                               mesh_eth_driver->remove_from_bridge(bridge_interface);
+
+                       device = __connman_device_find_device(
+                                                                       CONNMAN_SERVICE_TYPE_ETHERNET);
+                       if (device) {
+                               index = connman_device_get_index(device);
+                               connman_inet_ifup(index);
+                       }
+                       eth_if_bridged = false;
+               }
+
+               if (bridge_interface) {
+                       __connman_bridge_disable(bridge_interface);
+                       if (__connman_bridge_remove(bridge_interface))
+                               DBG("Failed to remove bridge [%s]", bridge_interface);
+
+                       g_free(bridge_interface);
+                       bridge_interface = NULL;
+               }
+       }
+
+       __connman_technology_mesh_interface_remove_finished(
+                                               CONNMAN_SERVICE_TYPE_MESH, success);
+       return 0;
+}
+
+int __connman_mesh_remove_virtual_interface(const char *ifname)
+{
+       int ret;
+       int index;
+
+       if (!ifname)
+               return -EINVAL;
+
+       if (bridge_interface) {
+               index = connman_inet_ifindex(mesh_ifname);
+               if (index < 0) {
+                       DBG("Failed to get interface index for %s", mesh_ifname);
+                       return -EINVAL;
+               }
+
+               ret = connman_inet_remove_from_bridge(index, bridge_interface);
+               if (0 != ret) {
+                       DBG("Failed to remove interface[%s] freom bridge[%s]", mesh_ifname,
+                               bridge_interface);
+                       return -EINVAL;
+               }
+
+               if (eth_if_bridged)
+                       mesh_eth_driver->remove_from_bridge(bridge_interface);
+
+               __connman_bridge_disable(bridge_interface);
+
+               ret = __connman_bridge_remove(bridge_interface);
+               if (0 != ret) {
+                       DBG("Failed to remove bridge [%s]", bridge_interface);
+                       return -EINVAL;
+               }
+
+               g_free(bridge_interface);
+               bridge_interface = NULL;
+       }
+
+       ret = mesh_driver->remove_interface(ifname);
+       if (ret != -EINPROGRESS) {
+               DBG("Failed to remove virtual mesh interface");
+               return ret;
+       }
+
+       DBG("Success removing virtual mesh interface");
+       return 0;
+}
+
+const char *connman_mesh_get_interface_name(void)
+{
+       return mesh_ifname;
+}
+
+bool connman_mesh_is_interface_created(void)
+{
+       DBG("Mesh interface is %screated", is_mesh_if_created ? "" : "not ");
+       return is_mesh_if_created;
+}
+
+struct connman_mesh *connman_mesh_create(const char *interface_addr,
+                                         const char *identifier)
+{
+       struct connman_mesh *mesh;
+
+       mesh = g_malloc0(sizeof(struct connman_mesh));
+       mesh->identifier = g_strdup_printf("mesh_%s_%s", interface_addr,
+                                          identifier);
+       mesh->interface_addr = g_strdup(interface_addr);
+       mesh->state = CONNMAN_MESH_STATE_IDLE;
+
+       mesh->refcount = 1;
+
+       return mesh;
+}
+
+void connman_mesh_set_name(struct connman_mesh *mesh, const char *name)
+{
+       g_free(mesh->name);
+       mesh->name = g_strdup(name);
+}
+
+const char *connman_mesh_get_name(struct connman_mesh *mesh)
+{
+       return mesh->name;
+}
+
+void connman_mesh_set_passphrase(struct connman_mesh *mesh,
+                                 const char *passphrase)
+{
+       g_free(mesh->passphrase);
+       mesh->passphrase = g_strdup(passphrase);
+}
+
+const char *connman_mesh_get_passphrase(struct connman_mesh *mesh)
+{
+       return mesh->passphrase;
+}
+
+void connman_mesh_set_address(struct connman_mesh *mesh, const char *address)
+{
+       g_free(mesh->address);
+       mesh->address = g_strdup(address);
+}
+
+void connman_mesh_set_security(struct connman_mesh *mesh, const char *security)
+{
+       if (!g_strcmp0(security, "none"))
+               mesh->security = CONNMAN_MESH_SECURITY_NONE;
+       else if (!g_strcmp0(security, "sae"))
+               mesh->security = CONNMAN_MESH_SECURITY_SAE;
+       else
+               mesh->security = CONNMAN_MESH_SECURITY_UNKNOWN;
+}
+
+static const char *security2string(enum connman_mesh_security security)
+{
+       switch (security) {
+       case CONNMAN_MESH_SECURITY_UNKNOWN:
+               break;
+       case CONNMAN_MESH_SECURITY_NONE:
+               return "none";
+       case CONNMAN_MESH_SECURITY_SAE:
+               return "sae";
+       }
+
+       return NULL;
+}
+
+const char *connman_mesh_get_security(struct connman_mesh *mesh)
+{
+       return security2string(mesh->security);
+}
+
+void connman_mesh_set_frequency(struct connman_mesh *mesh, uint16_t frequency)
+{
+       mesh->frequency = frequency;
+}
+
+uint16_t connman_mesh_get_frequency(struct connman_mesh *mesh)
+{
+       return mesh->frequency;
+}
+
+void connman_mesh_set_ieee80211w(struct connman_mesh *mesh, uint16_t ieee80211w)
+{
+       mesh->ieee80211w = ieee80211w;
+}
+
+uint16_t connman_mesh_get_ieee80211w(struct connman_mesh *mesh)
+{
+       return mesh->ieee80211w;
+}
+
+void connman_mesh_set_index(struct connman_mesh *mesh, int index)
+{
+       mesh->index = index;
+
+       if (bridge_interface)
+               mesh->br_index = connman_inet_ifindex(bridge_interface);
+}
+
+void connman_mesh_set_strength(struct connman_mesh *mesh, uint8_t strength)
+{
+       mesh->strength = strength;
+}
+
+static const char *peertype2string(enum connman_mesh_peer_type type)
+{
+       switch (type) {
+       case CONNMAN_MESH_PEER_TYPE_CREATED:
+               return "created";
+       case CONNMAN_MESH_PEER_TYPE_DISCOVERED:
+               return "discovered";
+       }
+
+       return NULL;
+}
+
+void connman_mesh_set_peer_type(struct connman_mesh *mesh,
+                                                               enum connman_mesh_peer_type type)
+{
+       mesh->peer_type = type;
+}
+
+static const char *state2string(enum connman_mesh_state state)
+{
+       switch (state) {
+       case CONNMAN_MESH_STATE_UNKNOWN:
+               break;
+       case CONNMAN_MESH_STATE_IDLE:
+               return "idle";
+       case CONNMAN_MESH_STATE_ASSOCIATION:
+               return "association";
+       case CONNMAN_MESH_STATE_CONFIGURATION:
+               return "configuration";
+       case CONNMAN_MESH_STATE_READY:
+               return "ready";
+       case CONNMAN_MESH_STATE_DISCONNECT:
+               return "disconnect";
+       case CONNMAN_MESH_STATE_FAILURE:
+               return "failure";
+       }
+
+       return NULL;
+}
+
+static enum connman_mesh_peer_disconnect_reason convert_to_disconnect_reason(
+                                                                       int reason)
+{
+       switch (reason) {
+       case 3:
+               return CONNMAN_MESH_DEAUTH_LEAVING;
+       case 52:
+               return CONNMAN_MESH_PEERING_CANCELLED;
+       case 53:
+               return CONNMAN_MESH_MAX_PEERS;
+       case 54:
+               return CONNMAN_MESH_CONFIG_POLICY_VIOLATION;
+       case 55:
+               return CONNMAN_MESH_CLOSE_RCVD;
+       case 56:
+               return CONNMAN_MESH_MAX_RETRIES;
+       case 57:
+               return CONNMAN_MESH_CONFIRM_TIMEOUT;
+       case 58:
+               return CONNMAN_MESH_INVALID_GTK;
+       case 59:
+               return CONNMAN_MESH_INCONSISTENT_PARAMS;
+       case 60:
+               return CONNMAN_MESH_INVALID_SECURITY_CAP;
+       }
+
+       return CONNMAN_MESH_REASON_UNKNOWN;
+}
+
+void connman_mesh_peer_set_disconnect_reason(struct connman_mesh *mesh,
+                                               int disconnect_reason)
+{
+       mesh->disconnect_reason = convert_to_disconnect_reason(disconnect_reason);
+}
+
+static bool is_connecting(struct connman_mesh *mesh)
+{
+       if (mesh->state == CONNMAN_MESH_STATE_ASSOCIATION ||
+                       mesh->state == CONNMAN_MESH_STATE_CONFIGURATION)
+               return true;
+
+       return false;
+}
+
+static int mesh_load(struct connman_mesh *mesh)
+{
+       GKeyFile *keyfile;
+       bool favorite;
+       GError *error = NULL;
+       gchar *str;
+
+       keyfile = connman_storage_load_service(mesh->identifier);
+       if (!keyfile) {
+               DBG("Mesh profile is new");
+               return -EIO;
+       }
+
+       favorite = g_key_file_get_boolean(keyfile,
+                               mesh->identifier, "Favorite", &error);
+
+       if (!error)
+               mesh->favorite = favorite;
+
+       g_clear_error(&error);
+
+       str = g_key_file_get_string(keyfile, mesh->identifier, "Passphrase", NULL);
+
+       if (str) {
+               g_free(mesh->passphrase);
+               mesh->passphrase = str;
+       }
+
+       return 0;
+}
+
+static int mesh_save(struct connman_mesh *mesh)
+{
+       GKeyFile *keyfile;
+
+       keyfile = g_key_file_new();
+       if (!keyfile)
+               return -EIO;
+
+       g_key_file_set_string(keyfile, mesh->identifier, "Name", mesh->name);
+       g_key_file_set_integer(keyfile, mesh->identifier, "Frequency",
+                                                               mesh->frequency);
+       g_key_file_set_boolean(keyfile, mesh->identifier, "Favorite",
+                                                               mesh->favorite);
+
+       if (mesh->passphrase)
+               g_key_file_set_string(keyfile, mesh->identifier, "Passphrase",
+                                                         mesh->passphrase);
+
+       g_key_file_set_string(keyfile, mesh->identifier, "PeerType",
+                                                               peertype2string(mesh->peer_type));
+
+       __connman_storage_save_service(keyfile, mesh->identifier);
+
+       g_key_file_free(keyfile);
+
+       return 0;
+}
+
+static void reply_pending(struct connman_mesh *mesh, int error)
+{
+       if (!mesh->pending)
+               return;
+
+       connman_dbus_reply_pending(mesh->pending, error, NULL);
+       mesh->pending = NULL;
+}
+
+static void state_changed(struct connman_mesh *mesh)
+{
+       const char *state;
+
+       state = state2string(mesh->state);
+       if (!state)
+               return;
+
+       connman_dbus_property_changed_basic(mesh->path,
+                                        CONNMAN_MESH_INTERFACE, "State",
+                                        DBUS_TYPE_STRING, &state);
+}
+
+static void mesh_dhcp_callback(struct connman_ipconfig *ipconfig,
+                               struct connman_network *network, bool success, gpointer data)
+{
+       struct connman_mesh *mesh = data;
+       int err;
+
+       if (!success)
+               goto error;
+
+       err = __connman_ipconfig_address_add(ipconfig);
+       if (err < 0)
+               goto error;
+
+       return;
+
+error:
+       connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_FAILURE);
+}
+
+static int mesh_start_dhcp_client(struct connman_mesh *mesh)
+{
+       DBG("");
+
+       __connman_ipconfig_enable(mesh->ipconfig);
+
+       return __connman_mesh_dhcp_start(mesh->ipconfig, mesh_dhcp_callback, mesh);
+}
+
+static void mesh_remove_connected_peer(gpointer key, gpointer value,
+                                               gpointer user_data)
+{
+       struct connman_mesh_connected_peer *peer = value;
+
+       DBG("Remove Peer %s", peer->peer_address);
+       g_hash_table_remove(connected_peer_table, key);
+}
+
+static void mesh_remove_disconnected_peer(gpointer key, gpointer value,
+                                               gpointer user_data)
+{
+       struct connman_mesh_disconnected_peer *peer = value;
+
+       DBG("Remove Peer %s", peer->peer_address);
+       g_hash_table_remove(disconnected_peer_table, key);
+}
+
+int connman_mesh_peer_set_state(struct connman_mesh *mesh,
+                                               enum connman_mesh_state new_state)
+{
+       enum connman_mesh_state old_state = mesh->state;
+
+       DBG("mesh peer %s old state %s new state %s", mesh->name,
+                                       state2string(old_state), state2string(new_state));
+
+       if (old_state == new_state)
+               return -EALREADY;
+
+       switch (new_state) {
+       case CONNMAN_MESH_STATE_UNKNOWN:
+               return -EINVAL;
+       case CONNMAN_MESH_STATE_IDLE:
+       case CONNMAN_MESH_STATE_ASSOCIATION:
+               break;
+       case CONNMAN_MESH_STATE_CONFIGURATION:
+               /* Start Link Local IP Address */
+               mesh_start_dhcp_client(mesh);
+               break;
+       case CONNMAN_MESH_STATE_READY:
+               reply_pending(mesh, 0);
+               mesh->favorite = true;
+               __connman_notifier_connect(CONNMAN_SERVICE_TYPE_MESH);
+
+               /* Set Gate Announce option */
+               if (eth_if_bridged) {
+                       connman_inet_set_stp(1);
+                       __connman_mesh_netlink_set_gate_announce(nl80211_global,
+                                                               connman_inet_ifindex(mesh_ifname), true,
+                                                               MESH_HWMP_ROOTMODE_RANN);
+               }
+
+               mesh_save(mesh);
+               break;
+       case CONNMAN_MESH_STATE_DISCONNECT:
+               __connman_dhcp_stop(mesh->ipconfig);
+               g_hash_table_foreach(connected_peer_table, mesh_remove_connected_peer,
+                                                        NULL);
+               g_hash_table_foreach(disconnected_peer_table,
+                                                        mesh_remove_disconnected_peer, NULL);
+               __connman_notifier_disconnect(CONNMAN_SERVICE_TYPE_MESH);
+               break;
+       case CONNMAN_MESH_STATE_FAILURE:
+               reply_pending(mesh, ECONNABORTED);
+               break;
+       }
+
+       mesh->state = new_state;
+       state_changed(mesh);
+
+       return 0;
+}
+
+bool connman_mesh_peer_is_connected_state(struct connman_mesh *mesh)
+{
+       switch (mesh->state) {
+       case CONNMAN_MESH_STATE_UNKNOWN:
+       case CONNMAN_MESH_STATE_IDLE:
+       case CONNMAN_MESH_STATE_ASSOCIATION:
+       case CONNMAN_MESH_STATE_CONFIGURATION:
+       case CONNMAN_MESH_STATE_DISCONNECT:
+       case CONNMAN_MESH_STATE_FAILURE:
+               break;
+       case CONNMAN_MESH_STATE_READY:
+               return true;
+       }
+
+       return false;
+}
+
+struct connman_mesh *connman_get_connected_mesh_from_name(char *name)
+{
+       GList *list, *start;
+
+       list = g_hash_table_get_values(mesh_table);
+       start = list;
+       for (; list; list = list->next) {
+               struct connman_mesh *mesh = list->data;
+
+               if (!g_strcmp0(mesh->name, name) &&
+                                       mesh->state == CONNMAN_MESH_STATE_READY) {
+                       g_list_free(start);
+                       return mesh;
+               }
+       }
+
+       g_list_free(start);
+
+       return NULL;
+}
+
+struct connman_mesh *connman_get_connecting_mesh_from_name(char *name)
+{
+       GList *list, *start;
+
+       list = g_hash_table_get_values(mesh_table);
+       start = list;
+       for (; list; list = list->next) {
+               struct connman_mesh *mesh = list->data;
+
+               if (!g_strcmp0(mesh->name, name) && is_connecting(mesh)) {
+                       g_list_free(start);
+                       return mesh;
+               }
+       }
+
+       g_list_free(start);
+
+       return NULL;
+}
+
+static void mesh_append_ethernet(DBusMessageIter *iter, void *user_data)
+{
+       struct connman_mesh *mesh = user_data;
+
+       if (mesh->ipconfig)
+               __connman_ipconfig_append_ethernet(mesh->ipconfig, iter);
+}
+
+static void mesh_append_ipv4(DBusMessageIter *iter, void *user_data)
+{
+       struct connman_mesh *mesh = user_data;
+
+       if (!is_connected(mesh))
+               return;
+
+       if (mesh->ipconfig)
+               __connman_ipconfig_append_ipv4(mesh->ipconfig, iter);
+}
+
+static void mesh_append_ipv4config(DBusMessageIter *iter, void *user_data)
+{
+       struct connman_mesh *mesh = user_data;
+
+       if (mesh->ipconfig)
+               __connman_ipconfig_append_ipv4config(mesh->ipconfig, iter);
+}
+
+static void append_properties(DBusMessageIter *iter, struct connman_mesh *mesh)
+{
+       const char *state = state2string(mesh->state);
+       const char *security = security2string(mesh->security);
+       const char *peer_type = peertype2string(mesh->peer_type);
+       const char *type = "mesh";
+       DBusMessageIter dict;
+
+       connman_dbus_dict_open(iter, &dict);
+
+       connman_dbus_dict_append_basic(&dict, "Type", DBUS_TYPE_STRING, &type);
+       connman_dbus_dict_append_basic(&dict, "Name",
+                                       DBUS_TYPE_STRING, &mesh->name);
+       connman_dbus_dict_append_basic(&dict, "BSSID",
+                                       DBUS_TYPE_STRING, &mesh->address);
+       connman_dbus_dict_append_basic(&dict, "State", DBUS_TYPE_STRING, &state);
+       if (security)
+               connman_dbus_dict_append_basic(&dict, "Security",
+                                                               DBUS_TYPE_STRING, &security);
+       connman_dbus_dict_append_basic(&dict, "Frequency",
+                                       DBUS_TYPE_UINT16, &mesh->frequency);
+       connman_dbus_dict_append_basic(&dict, "Favorite",
+                                       DBUS_TYPE_BOOLEAN, &mesh->favorite);
+       connman_dbus_dict_append_basic(&dict, "Strength",
+                                       DBUS_TYPE_BYTE, &mesh->strength);
+       connman_dbus_dict_append_basic(&dict, "PeerType",
+                                       DBUS_TYPE_STRING, &peer_type);
+       connman_dbus_dict_append_basic(&dict, "DisconnectReason",
+                                       DBUS_TYPE_INT32, &mesh->disconnect_reason);
+
+       connman_dbus_dict_append_dict(&dict, "Ethernet", mesh_append_ethernet,
+                                       mesh);
+
+       connman_dbus_dict_append_dict(&dict, "IPv4", mesh_append_ipv4, mesh);
+
+       connman_dbus_dict_append_dict(&dict, "IPv4.Configuration",
+                                       mesh_append_ipv4config, mesh);
+
+       connman_dbus_dict_close(iter, &dict);
+}
+
+static void append_mesh_peer_struct(gpointer key, gpointer value,
+                                               gpointer user_data)
+{
+       DBusMessageIter *array = user_data;
+       struct connman_mesh *mesh = value;
+       DBusMessageIter entry;
+
+       DBG("Mesh Peer path %s", mesh->path);
+       dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
+                                                       NULL, &entry);
+       dbus_message_iter_append_basic(&entry, DBUS_TYPE_OBJECT_PATH,
+                                                       &mesh->path);
+       append_properties(&entry, mesh);
+       dbus_message_iter_close_container(array, &entry);
+}
+
+void __connman_mesh_peer_list_struct(DBusMessageIter *array)
+{
+       g_hash_table_foreach(mesh_table, append_mesh_peer_struct, array);
+}
+
+static DBusMessage *get_mesh_peer_properties(DBusConnection *conn,
+                                               DBusMessage *msg, void *data)
+{
+       struct connman_mesh *mesh = data;
+       DBusMessageIter dict;
+       DBusMessage *reply;
+
+       reply = dbus_message_new_method_return(msg);
+       if (!reply)
+               return NULL;
+
+       dbus_message_iter_init_append(reply, &dict);
+       append_properties(&dict, mesh);
+
+       return reply;
+}
+
+static void append_mesh_disconnected_peer_struct(gpointer key, gpointer value,
+                                               gpointer user_data)
+{
+       DBusMessageIter *array = user_data;
+       struct connman_mesh_disconnected_peer *peer = value;
+       DBusMessageIter entry;
+       DBusMessageIter dict;
+
+       dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
+                                                       NULL, &entry);
+
+       connman_dbus_dict_open(&entry, &dict);
+
+       connman_dbus_dict_append_basic(&dict, "PeerAddress",
+                                       DBUS_TYPE_STRING, &peer->peer_address);
+
+       connman_dbus_dict_append_basic(&dict, "DisconnectReason",
+                                       DBUS_TYPE_INT32, &peer->disconnect_reason);
+
+       connman_dbus_dict_close(&entry, &dict);
+       dbus_message_iter_close_container(array, &entry);
+}
+
+void __connman_mesh_disconnected_peer_list_struct(DBusMessageIter *array)
+{
+       g_hash_table_foreach(disconnected_peer_table,
+                                               append_mesh_disconnected_peer_struct, array);
+}
+
+static void append_mesh_connected_peer_struct(gpointer key, gpointer value,
+                                               gpointer user_data)
+{
+       DBusMessageIter *array = user_data;
+       struct connman_mesh_connected_peer *peer = value;
+       DBusMessageIter entry;
+       DBusMessageIter dict;
+
+       dbus_message_iter_open_container(array, DBUS_TYPE_STRUCT,
+                                                       NULL, &entry);
+
+       connman_dbus_dict_open(&entry, &dict);
+
+       connman_dbus_dict_append_basic(&dict, "PeerAddress",
+                                       DBUS_TYPE_STRING, &peer->peer_address);
+
+       connman_dbus_dict_close(&entry, &dict);
+       dbus_message_iter_close_container(array, &entry);
+}
+
+void __connman_mesh_connected_peer_list_struct(DBusMessageIter *array)
+{
+       g_hash_table_foreach(connected_peer_table,
+                                               append_mesh_connected_peer_struct, array);
+}
+
+int connman_mesh_add_connected_peer(const char *peer_address)
+{
+       struct connman_mesh_connected_peer *peer;
+       struct connman_mesh_connected_peer *temp_peer;
+       struct connman_mesh_disconnected_peer *disconn_peer;
+
+       temp_peer = g_hash_table_lookup(connected_peer_table, peer_address);
+
+       if (temp_peer) {
+               DBG("Mesh Peer %s is already connected", peer_address);
+               return 0;
+       }
+
+       peer = g_malloc0(sizeof(struct connman_mesh_connected_peer));
+       peer->peer_address = g_strdup(peer_address);
+       DBG("Peer %s", peer->peer_address);
+
+       g_hash_table_insert(connected_peer_table, peer->peer_address, peer);
+
+       /* Remove from disconnected Peer Table */
+       disconn_peer = g_hash_table_lookup(disconnected_peer_table, peer_address);
+       if (!disconn_peer) {
+               DBG("Peer %s was never disconnected", peer_address);
+               goto done;
+       }
+
+       g_hash_table_remove(disconnected_peer_table, peer_address);
+done:
+       return 0;
+}
+
+int connman_mesh_remove_connected_peer(const char *peer_address, int reason)
+{
+       struct connman_mesh_connected_peer *peer;
+       struct connman_mesh_disconnected_peer *disconn_peer;
+
+       peer = g_hash_table_lookup(connected_peer_table, peer_address);
+
+       if (!peer) {
+               DBG("Peer %s not connected", peer_address);
+               return 0;
+       }
+
+       g_hash_table_remove(connected_peer_table, peer_address);
+
+       /* Add to Disconnected Peer Table */
+       disconn_peer = g_malloc0(sizeof(struct connman_mesh_disconnected_peer));
+       disconn_peer->peer_address = g_strdup(peer_address);
+       disconn_peer->disconnect_reason = convert_to_disconnect_reason(reason);
+
+       g_hash_table_insert(disconnected_peer_table, disconn_peer->peer_address,
+                                               disconn_peer);
+
+       DBG("Mesh Peer %s removed due to reason %d", peer_address, reason);
+       return 0;
+}
+
+static void __mesh_change_peer_status_cb(int result, void *user_data)
+{
+       struct connman_mesh_change_peer_data *data = user_data;
+
+       DBG("Status %d Peer Address %s result %d", data->status, data->peer_address,
+                                                                               result);
+
+       connman_dbus_reply_pending(data->pending, -result, NULL);
+
+       data->pending = NULL;
+       g_free(data->peer_address);
+       g_free(data);
+}
+
+int __connman_mesh_change_peer_status(DBusMessage *msg,
+                                                                         const char *peer_address,
+                                                                         enum connman_mesh_peer_status status)
+{
+       struct connman_mesh_connected_peer *conn_peer;
+       struct connman_mesh_disconnected_peer *disconn_peer;
+       int err = -ENOTSUP;
+       struct connman_mesh_change_peer_data *data;
+
+       switch (status) {
+       case CONNMAN_MESH_PEER_ADD:
+               conn_peer = g_hash_table_lookup(connected_peer_table, peer_address);
+
+               if (conn_peer) {
+                       DBG("Peer %s already connected", peer_address);
+                       return -EEXIST;
+               }
+
+               break;
+
+       case CONNMAN_MESH_PEER_REMOVE:
+               disconn_peer = g_hash_table_lookup(disconnected_peer_table,
+                                                                       peer_address);
+
+               if (disconn_peer) {
+                       DBG("Peer %s already disconnected", peer_address);
+                       return -EEXIST;
+               }
+
+               break;
+
+       default:
+               DBG("Invalid Status type");
+               return err;
+       }
+
+       if (mesh_driver->change_peer_status) {
+               data = g_try_malloc0(sizeof(struct connman_mesh_disconnected_peer));
+               if (data == NULL) {
+                       DBG("Memory allocation failed");
+                       return -ENOMEM;
+               }
+
+               data->pending = dbus_message_ref(msg);
+               data->peer_address = g_strdup(peer_address);
+               data->status = status;
+
+               err = mesh_driver->change_peer_status(peer_address, status,
+                                                               __mesh_change_peer_status_cb, data);
+
+               if (err < 0) {
+                       dbus_message_unref(data->pending);
+                       g_free(data->peer_address);
+                       g_free(data);
+               }
+       }
+
+       return err;
+}
+
+static int mesh_peer_connect(struct connman_mesh *mesh)
+{
+       int err = -ENOTSUP;
+       if (mesh_driver->connect)
+               err = mesh_driver->connect(mesh);
+
+       /* Reset Disconnect Reason */
+       mesh->disconnect_reason = CONNMAN_MESH_REASON_UNKNOWN;
+       return err;
+}
+
+static DBusMessage *connect_mesh_peer(DBusConnection *conn,
+                                       DBusMessage *msg, void *user_data)
+{
+       struct connman_mesh *mesh = user_data;
+       int err;
+
+       DBG("mesh %p", mesh);
+
+       if (mesh->state == CONNMAN_MESH_STATE_READY) {
+               DBG("mesh %s already connected", mesh->name);
+               return __connman_error_already_exists(msg);
+       }
+
+       if (mesh->pending)
+               return __connman_error_in_progress(msg);
+
+       mesh->pending = dbus_message_ref(msg);
+
+       err = mesh_peer_connect(mesh);
+       if (err == -EINPROGRESS)
+               return NULL;
+
+       if (err < 0) {
+               dbus_message_unref(mesh->pending);
+               mesh->pending = NULL;
+               return __connman_error_failed(msg, -err);
+       }
+
+       return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static void auto_connect_mesh_peer(gpointer key, gpointer value,
+                                               gpointer user_data)
+{
+       bool *conn_started = user_data;
+       struct connman_mesh *mesh = value;
+       int err;
+
+       if (*conn_started)
+               return;
+
+       if (!mesh->favorite || mesh->state != CONNMAN_MESH_STATE_IDLE)
+               return;
+
+       err = mesh_peer_connect(mesh);
+       if (err == -EINPROGRESS)
+               *conn_started = 1;
+}
+
+static gboolean run_mesh_auto_connect(gpointer data)
+{
+       bool conn_started;
+
+       mesh_autoconnect_timeout = 0;
+       DBG("");
+
+       conn_started = false;
+       g_hash_table_foreach(mesh_table, auto_connect_mesh_peer, &conn_started);
+       return FALSE;
+}
+
+void __connman_mesh_auto_connect(void)
+{
+       DBG("");
+
+       if (mesh_autoconnect_timeout != 0)
+               return;
+
+       mesh_autoconnect_timeout = g_idle_add(run_mesh_auto_connect, NULL);
+}
+
+static void mesh_peer_up(struct connman_ipconfig *ipconfig, const char *ifname)
+{
+       DBG("%s up", ifname);
+}
+
+static void mesh_peer_down(struct connman_ipconfig *ipconfig,
+                                               const char *ifname)
+{
+       DBG("%s down", ifname);
+}
+
+static void mesh_peer_lower_up(struct connman_ipconfig *ipconfig,
+                                                       const char *ifname)
+{
+       DBG("%s lower up", ifname);
+}
+
+static void mesh_peer_lower_down(struct connman_ipconfig *ipconfig,
+                                                       const char *ifname)
+{
+       DBG("%s lower down", ifname);
+}
+
+static void mesh_peer_ip_bound(struct connman_ipconfig *ipconfig,
+                                                       const char *ifname)
+{
+       struct connman_mesh *mesh = __connman_ipconfig_get_data(ipconfig);
+
+       DBG("%s ip bound", ifname);
+
+       connman_mesh_peer_set_state(mesh, CONNMAN_MESH_STATE_READY);
+}
+
+static void mesh_peer_ip_release(struct connman_ipconfig *ipconfig,
+                                                       const char *ifname)
+{
+       DBG("%s ip release", ifname);
+}
+
+static const struct connman_ipconfig_ops mesh_peer_ip_ops = {
+       .up                     = mesh_peer_up,
+       .down           = mesh_peer_down,
+       .lower_up       = mesh_peer_lower_up,
+       .lower_down     = mesh_peer_lower_down,
+       .ip_bound       = mesh_peer_ip_bound,
+       .ip_release     = mesh_peer_ip_release,
+       .route_set      = NULL,
+       .route_unset    = NULL,
+};
+
+static struct connman_ipconfig *create_ipconfig(int index, void *user_data)
+{
+       struct connman_ipconfig *ipconfig;
+
+       ipconfig = __connman_ipconfig_create(index,
+                                               CONNMAN_IPCONFIG_TYPE_IPV4);
+       if (!ipconfig)
+               return NULL;
+
+       __connman_ipconfig_set_method(ipconfig, CONNMAN_IPCONFIG_METHOD_DHCP);
+       __connman_ipconfig_set_data(ipconfig, user_data);
+       __connman_ipconfig_set_ops(ipconfig, &mesh_peer_ip_ops);
+
+       return ipconfig;
+}
+
+static int __connman_mesh_peer_disconnect(struct connman_mesh *mesh)
+{
+       int err;
+
+       reply_pending(mesh, ECONNABORTED);
+
+       if (!is_connected(mesh) && !is_connecting(mesh))
+               return -ENOTCONN;
+
+       err = mesh_driver->disconnect(mesh);
+       if (err < 0 && err != -EINPROGRESS)
+               return err;
+
+       return err;
+}
+
+static DBusMessage *disconnect_mesh_peer(DBusConnection *conn,
+                                       DBusMessage *msg, void *user_data)
+{
+       struct connman_mesh *mesh = user_data;
+       int err;
+
+       DBG("mesh %p", mesh);
+       err = __connman_mesh_peer_disconnect(mesh);
+       if (err < 0 && err != -EINPROGRESS)
+               return __connman_error_failed(msg, -err);
+
+       return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static bool __connman_mesh_peer_remove(struct connman_mesh *mesh)
+{
+       if (!mesh->favorite)
+               return false;
+
+       __connman_mesh_peer_disconnect(mesh);
+
+       mesh->favorite = false;
+
+       __connman_storage_remove_service(mesh->identifier);
+
+       return true;
+}
+
+static DBusMessage *remove_mesh_peer(DBusConnection *conn,
+                                       DBusMessage *msg, void *user_data)
+{
+       struct connman_mesh *mesh = user_data;
+
+       DBG("mesh %p", mesh);
+
+       if (!__connman_mesh_peer_remove(mesh))
+               return __connman_error_not_supported(msg);
+
+       return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static DBusMessage *set_mesh_peer_property(DBusConnection *conn,
+                                       DBusMessage *msg, void *user_data)
+{
+       struct connman_mesh *mesh = user_data;
+       DBusMessageIter iter, value;
+       const char *name;
+       int type;
+
+       DBG("mesh %p", mesh);
+
+       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_VARIANT)
+               return __connman_error_invalid_arguments(msg);
+
+       dbus_message_iter_recurse(&iter, &value);
+
+       type = dbus_message_iter_get_arg_type(&value);
+
+       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_mesh_set_passphrase(mesh, passphrase);
+       } else {
+               DBG("Invalid Property %s", name);
+               return __connman_error_invalid_property(msg);
+       }
+
+       return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+
+static const GDBusMethodTable mesh_methods[] = {
+       { GDBUS_METHOD("GetProperties",
+                       NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
+                       get_mesh_peer_properties) },
+       { GDBUS_ASYNC_METHOD("Connect", NULL, NULL, connect_mesh_peer) },
+       { GDBUS_METHOD("Disconnect", NULL, NULL, disconnect_mesh_peer) },
+       { GDBUS_METHOD("Remove", NULL, NULL, remove_mesh_peer) },
+       { GDBUS_METHOD("SetProperty",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
+                       NULL, set_mesh_peer_property) },
+       { },
+};
+
+static const GDBusSignalTable mesh_signals[] = {
+       { GDBUS_SIGNAL("PropertyChanged",
+                       GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+       { },
+};
+
+int connman_mesh_register(struct connman_mesh *mesh)
+{
+       struct connman_mesh *temp;
+       DBG("mesh %p", mesh);
+
+       if (mesh->path)
+               return -EALREADY;
+
+       mesh->path = g_strdup_printf("%s/mesh/%s", CONNMAN_PATH,
+                                    mesh->identifier);
+       DBG("path %s", mesh->path);
+
+       temp = g_hash_table_lookup(mesh_table, mesh->path);
+       if (temp) {
+               DBG("mesh path %s already exists", mesh->path);
+
+               if (mesh->frequency != temp->frequency) {
+                       DBG("Update frequency for mesh network %s", mesh->name);
+                       connman_mesh_set_frequency(temp, mesh->frequency);
+               }
+
+               mesh_free(mesh);
+               return -EALREADY;
+       }
+
+       if (mesh->br_index > 0)
+               mesh->ipconfig = create_ipconfig(mesh->br_index, mesh);
+       else
+               mesh->ipconfig = create_ipconfig(mesh->index, mesh);
+
+       if (!mesh->ipconfig)
+               return -ENOMEM;
+
+       g_hash_table_insert(mesh_table, mesh->path, mesh);
+
+       mesh_load(mesh);
+
+       g_dbus_register_interface(connection, mesh->path,
+                                       CONNMAN_MESH_INTERFACE,
+                                       mesh_methods, mesh_signals,
+                                       NULL, mesh, NULL);
+       mesh->registered = true;
+       return 0;
+}
+
+void connman_mesh_unregister(struct connman_mesh *mesh)
+{
+       DBG("mesh %p", mesh);
+
+       if (!mesh->path || !mesh->registered)
+               return;
+
+       g_dbus_unregister_interface(connection, mesh->path,
+                                                               CONNMAN_MESH_INTERFACE);
+       mesh->registered = false;
+
+       g_hash_table_remove(mesh_table, mesh->path);
+}
+
+struct connman_mesh *connman_mesh_get(const char *interface_addr,
+                                                                       const char *identifier)
+{
+       char *ident = g_strdup_printf("%s/mesh/mesh_%s_%s", CONNMAN_PATH,
+                                                                       interface_addr, identifier);
+       struct connman_mesh *mesh;
+
+       mesh = g_hash_table_lookup(mesh_table, ident);
+       g_free(ident);
+
+       return mesh;
+}
+
+int connman_mesh_driver_register(struct connman_mesh_driver *driver)
+{
+       if (mesh_driver && mesh_driver != driver)
+               return -EINVAL;
+
+       mesh_driver = driver;
+
+       return 0;
+}
+
+void connman_mesh_driver_unregister(struct connman_mesh_driver *driver)
+{
+       if (mesh_driver != driver)
+               return;
+
+       mesh_driver = NULL;
+}
+
+int connman_mesh_eth_driver_register(struct connman_mesh_eth_driver *driver)
+{
+       if (mesh_eth_driver && mesh_eth_driver != driver)
+               return -EINVAL;
+
+       mesh_eth_driver = driver;
+
+       return 0;
+}
+
+void connman_mesh_eth_driver_unregister(struct connman_mesh_eth_driver *driver)
+{
+       if (mesh_eth_driver != driver)
+               return;
+
+       mesh_eth_driver = NULL;
+}
+
+int __connman_mesh_init(void)
+{
+       DBG("");
+
+       connection = connman_dbus_get_connection();
+
+       mesh_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                                       NULL, mesh_free);
+
+       connected_peer_table = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+                                                       mesh_connected_peer_free);
+
+       disconnected_peer_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                                       NULL, mesh_disconnected_peer_free);
+
+       nl80211_global = __connman_mesh_nl80211_global_init();
+       return 0;
+}
+
+void __connman_mesh_cleanup(void)
+{
+       DBG("");
+
+       __connman_mesh_nl80211_global_deinit(nl80211_global);
+       g_hash_table_destroy(mesh_table);
+       g_hash_table_destroy(connected_peer_table);
+       g_hash_table_destroy(disconnected_peer_table);
+       dbus_connection_unref(connection);
+}
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index f7f6a7c..990eb66
@@ -1,5 +1,6 @@
 [D-BUS Service]
 Name=net.connman
-Exec=@sbindir@/connmand -n
-User=root
+Exec=/bin/false
+User=network_fw
+Group=network_fw
 SystemdService=connman.service
old mode 100644 (file)
new mode 100755 (executable)
index b12bbc0..7046137
 
 #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;
 
@@ -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)
@@ -204,7 +254,11 @@ static void acd_host_ipv4_available(struct acd_host *acd, gpointer user_data)
        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;
 
@@ -444,7 +498,11 @@ static void dhcp_success(struct connman_network *network)
        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;
 
@@ -503,6 +561,10 @@ static int set_connected_manual(struct connman_network *network)
        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);
 
@@ -518,7 +580,11 @@ static int set_connected_manual(struct connman_network *network)
        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;
 
@@ -619,7 +685,11 @@ static int manual_ipv6_set(struct connman_network *network,
                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;
 
@@ -676,6 +746,10 @@ static int dhcpv6_set_addresses(struct connman_network *network)
        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;
@@ -763,6 +837,9 @@ static void check_dhcpv6(struct nd_router_advert *reply,
                                                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;
        }
@@ -775,6 +852,9 @@ static void check_dhcpv6(struct nd_router_advert *reply,
         */
        if (!network->connected) {
                connman_network_unref(network);
+#if defined TIZEN_EXT
+               DBG("Network is not connected");
+#endif
                return;
        }
 
@@ -803,11 +883,21 @@ static void check_dhcpv6(struct nd_router_advert *reply,
         * 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;
@@ -888,6 +978,11 @@ static void autoconf_ipv6_set(struct connman_network *network)
 
        __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;
@@ -1023,12 +1118,23 @@ static void set_disconnected(struct connman_network *network)
                                        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
@@ -1074,7 +1180,9 @@ static int network_probe(struct connman_network *network)
                        driver = NULL;
                        continue;
                }
-
+#if defined TIZEN_EXT
+               if (!simplified_log)
+#endif
                DBG("driver %p name %s", driver, driver->name);
 
                if (driver->probe(network) == 0)
@@ -1239,6 +1347,10 @@ static void network_destruct(struct connman_network *network)
        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);
@@ -1485,6 +1597,15 @@ bool __connman_network_get_weakness(struct connman_network *network)
        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;
@@ -1500,7 +1621,9 @@ bool connman_network_get_connecting(struct connman_network *network)
 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;
@@ -1521,6 +1644,120 @@ bool connman_network_get_available(struct connman_network *network)
        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
@@ -1550,17 +1787,49 @@ int connman_network_set_associating(struct connman_network *network,
                                        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)
@@ -1579,6 +1848,10 @@ static void set_invalid_key_error(struct connman_network *network)
 
        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);
 }
@@ -1603,6 +1876,22 @@ static void set_blocked_error(struct connman_network *network)
                                        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)
 {
@@ -1657,6 +1946,15 @@ void connman_network_set_error(struct connman_network *network,
        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;
@@ -1797,20 +2095,42 @@ int __connman_network_connect(struct connman_network *network)
        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;
@@ -1825,7 +2145,9 @@ int __connman_network_connect(struct connman_network *network)
 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);
@@ -1841,6 +2163,11 @@ int __connman_network_disconnect(struct connman_network *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);
 
@@ -1897,12 +2224,38 @@ int __connman_network_clear_ipconfig(struct connman_network *network,
        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;
@@ -1930,6 +2283,14 @@ int __connman_network_enable_ipconfig(struct connman_network *network,
                        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;
 
@@ -2006,6 +2367,340 @@ int connman_network_set_ipaddress(struct connman_network *network,
        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)
 {
@@ -2027,8 +2722,14 @@ int connman_network_set_nameservers(struct connman_network *network,
        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);
@@ -2062,6 +2763,9 @@ int connman_network_set_domain(struct connman_network *network,
 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);
@@ -2082,6 +2786,9 @@ int connman_network_set_strength(struct connman_network *network,
                                                uint8_t strength)
 {
        network->strength = strength;
+#if defined TIZEN_EXT
+       __connman_service_notify_strength_changed(network);
+#endif
 
        return 0;
 }
@@ -2159,6 +2866,9 @@ int connman_network_set_string(struct connman_network *network,
                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")) {
@@ -2203,6 +2913,23 @@ int connman_network_set_string(struct connman_network *network,
        } 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;
        }
@@ -2260,6 +2987,18 @@ const char *connman_network_get_string(struct connman_network *network,
                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;
 }
@@ -2283,6 +3022,18 @@ int connman_network_set_bool(struct connman_network *network,
                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;
 }
@@ -2305,10 +3056,48 @@ bool connman_network_get_bool(struct connman_network *network,
                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
@@ -2329,6 +3118,16 @@ int connman_network_set_blob(struct connman_network *network,
                        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;
        }
@@ -2351,6 +3150,12 @@ const void *connman_network_get_blob(struct connman_network *network,
                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;
index a39d54c..2c271ee 100644 (file)
@@ -153,6 +153,9 @@ void __connman_notifier_connect(enum connman_service_type type)
        case CONNMAN_SERVICE_TYPE_BLUETOOTH:
        case CONNMAN_SERVICE_TYPE_CELLULAR:
        case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+       case CONNMAN_SERVICE_TYPE_MESH:
+#endif
                break;
        }
 
@@ -200,6 +203,9 @@ void __connman_notifier_disconnect(enum connman_service_type type)
        case CONNMAN_SERVICE_TYPE_BLUETOOTH:
        case CONNMAN_SERVICE_TYPE_CELLULAR:
        case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+       case CONNMAN_SERVICE_TYPE_MESH:
+#endif
                break;
        }
 
old mode 100644 (file)
new mode 100755 (executable)
index e7fee22..0de4df7
--- a/src/ntp.c
+++ b/src/ntp.c
@@ -253,7 +253,9 @@ static void decode_msg(struct ntp_data *nd, void *base, size_t len,
        double m_delta, org, rec, xmt, dst;
        double delay, offset;
        static guint transmit_delay;
+#if !defined TIZEN_EXT
        struct timex tmx = {};
+#endif
 
        if (len < sizeof(*msg)) {
                connman_error("Invalid response from time server");
@@ -347,6 +349,68 @@ static void decode_msg(struct ntp_data *nd, void *base, size_t len,
 
        nd->poll_id = g_timeout_add_seconds(transmit_delay, next_poll, nd);
 
+#if defined TIZEN_EXT
+       //send the dbus message to alram-manager
+       {
+#define TIME_BUS_NAME "org.tizen.alarm.manager"
+#define TIME_INTERFACE "org.tizen.alarm.manager"
+#define TIME_PATH "/org/tizen/alarm/manager"
+#define TIME_METHOD "alarm_set_time_with_propagation_delay"
+
+               struct timespec cur = {0};
+               struct timespec req = {0};
+               double dtime;
+
+               DBusConnection *connection = NULL;
+               DBusMessage *msg = NULL, *reply = NULL;
+               DBusError error;
+
+               dbus_error_init(&error);
+
+               connection = connman_dbus_get_connection();
+               if(!connection){
+                       DBG("dbus connection does not exist");
+                       return;
+               }
+
+               clock_gettime(CLOCK_REALTIME, &cur);
+               dtime = offset + cur.tv_sec + 1.0e-9 * cur.tv_nsec;
+               cur.tv_sec = (long) dtime;
+               cur.tv_nsec = (dtime - cur.tv_sec) * 1000000000;
+
+               clock_gettime(CLOCK_REALTIME, &req);
+               msg = dbus_message_new_method_call(TIME_BUS_NAME, TIME_PATH,
+                       TIME_INTERFACE, TIME_METHOD);
+               dbus_message_append_args(msg, DBUS_TYPE_INT64, &(cur.tv_sec),
+                       DBUS_TYPE_INT64, &(cur.tv_nsec),
+                       DBUS_TYPE_INT64, &(req.tv_sec),
+                       DBUS_TYPE_INT64, &(req.tv_nsec), DBUS_TYPE_INVALID);
+               reply = dbus_connection_send_with_reply_and_block(connection, msg,
+                               DBUS_TIMEOUT_USE_DEFAULT, &error);
+               if(reply == NULL){
+                       if(dbus_error_is_set(&error)){
+                               DBG("%s", error.message);
+                               dbus_error_free(&error);
+                       }
+                       else{
+                               DBG("Failed to request set time");
+                       }
+                       dbus_connection_unref(connection);
+                       dbus_message_unref(msg);
+                       return;
+               }
+
+               dbus_message_unref(msg);
+               dbus_message_unref(reply);
+               dbus_connection_unref(connection);
+
+               DBG("%lu cur seconds, %lu cur nsecs, %lu req seconds, %lu req nsecs",
+                       cur.tv_sec, cur.tv_nsec, req.tv_sec, req.tv_nsec);
+               DBG("setting time");
+
+               __connman_clock_set_time_updated(true);
+       }
+#else
        if (offset < STEPTIME_MIN_OFFSET && offset > -STEPTIME_MIN_OFFSET) {
                tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_OFFSET | ADJ_TIMECONST | ADJ_MAXERROR | ADJ_ESTERROR;
                tmx.status = STA_PLL;
@@ -389,6 +453,7 @@ static void decode_msg(struct ntp_data *nd, void *base, size_t len,
                LOGTOD(msg->poll), offset, delay, tmx.freq / 65536);
 
        nd->cb(true, nd->user_data);
+#endif
 }
 
 static gboolean received_data(GIOChannel *channel, GIOCondition condition,
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index e209184..195ae22
@@ -257,7 +257,11 @@ static int set_connected(struct connman_provider *provider,
                }
 
                __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);
@@ -596,8 +600,14 @@ int connman_provider_set_nameservers(struct connman_provider *provider,
                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;
 }
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 618353f..8bfea3c
 
 #include "connman.h"
 
+/*
+ * Just to avoid build failure due to missing STATEDIR
+ */
+#if defined TIZEN_EXT
+#ifdef STATEDIR
+#undef STATEDIR
+#endif
+#define STATEDIR "/etc"
+#endif
+
 #define RESOLV_CONF_STATEDIR STATEDIR"/resolv.conf"
 #define RESOLV_CONF_ETC "/etc/resolv.conf"
 
@@ -340,8 +350,14 @@ static gboolean resolver_expire_cb(gpointer user_data)
                struct connman_service *service;
                service = __connman_service_lookup_from_index(entry->index);
                if (service)
+#if defined TIZEN_EXT
+                       __connman_service_nameserver_remove(service,
+                                       entry->server, true,
+                                       CONNMAN_IPCONFIG_TYPE_ALL);
+#else
                        __connman_service_nameserver_remove(service,
                                                        entry->server, true);
+#endif
        }
 
        remove_entries(list);
@@ -395,6 +411,11 @@ static int append_resolver(int index, const char *domain,
        if (!server && !domain)
                return -EINVAL;
 
+#ifdef TIZEN_EXT
+       if (g_strcmp0(server, "0.0.0.0") == 0)
+               return -EINVAL;
+#endif
+
        entry = g_try_new0(struct entry_data, 1);
        if (!entry)
                return -ENOMEM;
@@ -437,8 +458,14 @@ static int append_resolver(int index, const char *domain,
                struct connman_service *service;
                service = __connman_service_lookup_from_index(entry->index);
                if (service)
+#if defined TIZEN_EXT
+                       __connman_service_nameserver_append(service,
+                                       server, true,
+                                       CONNMAN_IPCONFIG_TYPE_ALL);
+#else
                        __connman_service_nameserver_append(service,
                                                        server, true);
+#endif
        }
 
        return 0;
old mode 100644 (file)
new mode 100755 (executable)
index b2514c4..99b337d
@@ -72,6 +72,7 @@ static enum connman_service_type convert_type(uint8_t type)
        return CONNMAN_SERVICE_TYPE_UNKNOWN;
 }
 
+#if !defined TIZEN_EXT
 static enum rfkill_type convert_service_type(enum connman_service_type type)
 {
        switch (type) {
@@ -94,6 +95,7 @@ static enum rfkill_type convert_service_type(enum connman_service_type type)
 
        return NUM_RFKILL_TYPES;
 }
+#endif
 
 static GIOStatus rfkill_process(GIOChannel *chan)
 {
@@ -156,13 +158,20 @@ static guint watch = 0;
 
 int __connman_rfkill_block(enum connman_service_type type, bool block)
 {
+#if !defined TIZEN_EXT
        uint8_t rfkill_type;
        struct rfkill_event event;
        ssize_t len;
        int fd, err = 0;
+#endif
 
        DBG("type %d block %d", type, block);
 
+#if defined TIZEN_EXT
+       DBG("try to set rfkill block %d, but it's not permitted", block);
+
+       return 0;
+#else
        rfkill_type = convert_service_type(type);
        if (rfkill_type == NUM_RFKILL_TYPES)
                return -EINVAL;
@@ -185,6 +194,7 @@ int __connman_rfkill_block(enum connman_service_type type, bool block)
        close(fd);
 
        return err;
+#endif
 }
 
 int __connman_rfkill_init(void)
index c9e84da..40ede4f 100644 (file)
 #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)
 
@@ -94,6 +100,7 @@ static bool ether_blacklisted(const char *name)
        return false;
 }
 
+#if !defined TIZEN_EXT
 static bool wext_interface(char *ifname)
 {
        struct iwreq wrq;
@@ -115,6 +122,30 @@ static bool wext_interface(char *ifname)
 
        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)
 {
@@ -124,6 +155,15 @@ 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;
@@ -191,6 +231,8 @@ static void read_uevent(struct interface_data *interface)
        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;
@@ -198,6 +240,7 @@ static void read_uevent(struct interface_data *interface)
 
                connman_error("%s runs an unsupported 802.11 driver", name);
        }
+#endif
 
 out:
        g_free(name);
@@ -423,6 +466,28 @@ static void process_newlink(unsigned short type, int index, unsigned flags,
        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],
@@ -445,12 +510,25 @@ static void process_newlink(unsigned short type, int index, unsigned flags,
                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;
@@ -475,6 +553,25 @@ static void process_newlink(unsigned short type, int index, unsigned flags,
 
                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
@@ -539,6 +636,13 @@ static void process_dellink(unsigned short type, int index, unsigned flags,
        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;
        }
@@ -1234,6 +1338,37 @@ static void rtnl_newnduseropt(struct nlmsghdr *hdr)
        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,
@@ -1244,7 +1379,12 @@ static void rtnl_newnduseropt(struct nlmsghdr *hdr)
 
                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++) {
@@ -1252,6 +1392,14 @@ static void rtnl_newnduseropt(struct nlmsghdr *hdr)
                                                                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);
                        }
@@ -1442,8 +1590,15 @@ static gboolean netlink_event(GIOChannel *chan, GIOCondition cond, gpointer data
        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));
@@ -1456,11 +1611,21 @@ static gboolean netlink_event(GIOChannel *chan, GIOCondition cond, gpointer data
                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);
@@ -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;
@@ -1626,7 +1806,11 @@ int __connman_rtnl_init(void)
 
        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);
old mode 100644 (file)
new mode 100755 (executable)
index 20917a8..411b617
 
 #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
@@ -58,6 +70,47 @@ 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;
@@ -144,6 +197,64 @@ struct connman_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);
@@ -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;
@@ -225,6 +385,10 @@ const char *__connman_service_type2string(enum connman_service_type type)
                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;
@@ -270,6 +434,16 @@ enum connman_service_security __connman_service_string2security(const char *str)
                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;
 }
@@ -285,8 +459,20 @@ static const char *security2string(enum connman_service_security security)
                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";
        }
@@ -335,6 +521,10 @@ static const char *error2string(enum connman_service_error error)
                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:
@@ -372,6 +562,33 @@ static enum connman_service_proxy_method string2proxymethod(const char *method)
                return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN;
 }
 
+#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;
@@ -428,6 +645,9 @@ 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:
                __connman_service_set_split_routing(service,
@@ -461,6 +681,382 @@ int __connman_service_load_modifiable(struct connman_service *service)
        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;
@@ -470,7 +1066,15 @@ static int service_load(struct connman_service *service)
        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);
@@ -485,6 +1089,9 @@ static int service_load(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:
                __connman_service_set_split_routing(service,
@@ -548,6 +1155,46 @@ static int service_load(struct connman_service *service)
 
                        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:
@@ -564,6 +1211,14 @@ static int service_load(struct connman_service *service)
                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;
        }
 
@@ -598,6 +1253,24 @@ static int service_load(struct connman_service *service)
                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) {
@@ -646,6 +1319,111 @@ static int service_load(struct connman_service *service)
        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);
 
@@ -678,6 +1456,9 @@ static int service_save(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:
                g_key_file_set_boolean(keyfile, service->identifier,
@@ -690,6 +1471,9 @@ static int service_save(struct connman_service *service)
                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);
@@ -718,6 +1502,74 @@ static int service_save(struct connman_service *service)
                        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 */
 
@@ -733,6 +1585,10 @@ static int service_save(struct connman_service *service)
                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;
        }
 
@@ -766,6 +1622,28 @@ static int service_save(struct connman_service *service)
                                (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);
 
@@ -823,6 +1701,110 @@ static int service_save(struct connman_service *service)
                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);
 
@@ -831,12 +1813,110 @@ done:
        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(
@@ -1089,6 +2169,9 @@ static int nameserver_add(struct connman_service *service,
        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);
@@ -1103,14 +2186,115 @@ static int nameserver_add_all(struct connman_service *service,
 
        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++;
                }
        }
@@ -1118,6 +2302,12 @@ static int nameserver_add_all(struct connman_service *service,
        if (!i)
                __connman_resolver_append_fallback_nameservers();
 
+#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;
@@ -1136,6 +2326,9 @@ static int nameserver_remove(struct connman_service *service,
        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);
@@ -1146,6 +2339,15 @@ static int nameserver_remove(struct connman_service *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);
@@ -1154,17 +2356,132 @@ static int nameserver_remove_all(struct connman_service *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++;
        }
 
+#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;
@@ -1175,8 +2492,14 @@ static int nameserver_remove_all(struct connman_service *service,
  * 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;
@@ -1193,6 +2516,9 @@ int __connman_service_nameserver_append(struct connman_service *service,
 
        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;
                }
@@ -1210,6 +2536,16 @@ int __connman_service_nameserver_append(struct connman_service *service,
        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 {
@@ -1224,8 +2560,14 @@ int __connman_service_nameserver_append(struct connman_service *service,
        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;
@@ -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;
@@ -1567,8 +2915,93 @@ static void reset_stats(struct connman_service *service)
        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)
@@ -1580,6 +3013,7 @@ struct connman_service *connman_service_get_default(void)
                return NULL;
 
        return service;
+#endif
 }
 
 bool __connman_service_index_is_default(int index)
@@ -1596,7 +3030,11 @@ 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;
@@ -1605,9 +3043,15 @@ static void default_changed(void)
                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 &&
@@ -1642,6 +3086,31 @@ static void default_changed(void)
        __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;
@@ -1652,13 +3121,90 @@ static void state_changed(struct connman_service *service)
        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)
 {
@@ -1673,6 +3219,27 @@ 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;
@@ -1771,10 +3338,16 @@ static void append_security(DBusMessageIter *iter, void *user_data)
                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:
@@ -1815,6 +3388,57 @@ static void append_ethernet(DBusMessageIter *iter, void *user_data)
                                                                        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;
@@ -1874,20 +3498,143 @@ static void append_nameservers(DBusMessageIter *iter,
        }
 }
 
+#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,
@@ -1909,10 +3656,46 @@ static void append_dnsconfig(DBusMessageIter *iter, void *user_data)
 {
        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)
@@ -2527,6 +4310,154 @@ int connman_service_iterate_services(connman_service_iterate_cb cb,
        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)
 {
@@ -2534,6 +4465,31 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
        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",
@@ -2547,6 +4503,13 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
                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",
@@ -2582,6 +4545,9 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
        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;
@@ -2592,7 +4558,35 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
                                                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",
@@ -2656,6 +4650,99 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
                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)
@@ -2693,6 +4780,34 @@ static void append_struct(gpointer value, gpointer user_data)
        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);
@@ -2849,6 +4964,54 @@ char **connman_service_get_timeservers(struct connman_service *service)
        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)
 {
@@ -2898,6 +5061,54 @@ const char *connman_service_get_proxy_url(struct connman_service *service)
        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)
 {
@@ -2936,6 +5147,18 @@ const char *connman_service_get_proxy_autoconfig(struct connman_service *service
        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)
 {
@@ -3063,6 +5286,22 @@ void __connman_service_set_pac(struct connman_service *service,
        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)
 {
@@ -3182,7 +5421,9 @@ int __connman_service_check_passphrase(enum connman_service_security security,
        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);
@@ -3190,6 +5431,11 @@ int __connman_service_check_passphrase(enum connman_service_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].
@@ -3216,6 +5462,10 @@ int __connman_service_check_passphrase(enum connman_service_security security,
                break;
 
        case CONNMAN_SERVICE_SECURITY_8021X:
+#if defined TIZEN_EXT
+       case CONNMAN_SERVICE_SECURITY_OWE:
+       case CONNMAN_SERVICE_SECURITY_DPP:
+#endif
                break;
        }
 
@@ -3234,6 +5484,19 @@ int __connman_service_set_passphrase(struct connman_service *service,
                        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)
@@ -3257,6 +5520,28 @@ const char *__connman_service_get_passphrase(struct connman_service *service)
        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)
 {
@@ -3663,6 +5948,10 @@ static DBusMessage *set_property(DBusConnection *conn,
                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)
@@ -3679,17 +5968,65 @@ static DBusMessage *set_property(DBusConnection *conn,
                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;
 
@@ -3699,7 +6036,21 @@ static DBusMessage *set_property(DBusConnection *conn,
                                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) {
@@ -3722,7 +6073,12 @@ static DBusMessage *set_property(DBusConnection *conn,
                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,
@@ -3918,6 +6274,28 @@ static DBusMessage *set_property(DBusConnection *conn,
                }
 
                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);
 
@@ -3937,8 +6315,10 @@ static void set_error(struct connman_service *service,
        if (!service->path)
                return;
 
+#if !defined TIZEN_EXT
        if (!allow_property_changed(service))
                return;
+#endif
 
        str = error2string(service->error);
 
@@ -4089,6 +6469,9 @@ void __connman_service_set_active_session(bool enable, GSList *list)
                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;
                }
 
@@ -4121,6 +6504,9 @@ static void preferred_tech_add_by_type(gpointer data, gpointer user_data)
                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);
        }
@@ -4148,6 +6534,17 @@ static GList *preferred_tech_list_get(void)
                                        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;
                        }
                }
@@ -4171,6 +6568,7 @@ static void set_always_connecting_technologies()
                always_connect[always_connected_techs[i]] = 1;
 }
 
+#if !defined TIZEN_EXT
 static bool autoconnect_no_session_active(struct connman_service *service)
 {
        /*
@@ -4183,6 +6581,7 @@ static bool autoconnect_no_session_active(struct connman_service *service)
 
        return false;
 }
+#endif
 
 static bool autoconnect_already_connecting(struct connman_service *service,
                                           bool autoconnecting)
@@ -4209,21 +6608,51 @@ static bool auto_connect_service(GList *services,
        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);
@@ -4233,9 +6662,18 @@ static bool auto_connect_service(GList *services,
                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;
 
@@ -4249,13 +6687,28 @@ static bool auto_connect_service(GList *services,
                        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));
@@ -4265,15 +6718,27 @@ static bool auto_connect_service(GList *services,
                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;
 }
 
@@ -4300,6 +6765,21 @@ static gboolean run_auto_connect(gpointer data)
        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("");
@@ -4307,10 +6787,33 @@ void __connman_service_auto_connect(enum connman_service_connect_reason reason)
        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));
 }
 
@@ -4545,19 +7048,45 @@ static DBusMessage *connect_service(DBusConnection *conn,
                                        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))
                        continue;
 
@@ -4574,6 +7103,7 @@ static DBusMessage *connect_service(DBusConnection *conn,
        }
        if (err == -EINPROGRESS)
                return __connman_error_operation_timeout(msg);
+#endif
 
        service->ignore = false;
 
@@ -4596,6 +7126,20 @@ static DBusMessage *disconnect_service(DBusConnection *conn,
 
        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);
@@ -4605,6 +7149,36 @@ static DBusMessage *disconnect_service(DBusConnection *conn,
        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 ||
@@ -4615,8 +7189,10 @@ bool __connman_service_remove(struct connman_service *service)
                        __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);
 
@@ -4647,13 +7223,65 @@ bool __connman_service_remove(struct connman_service *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;
 }
@@ -4766,6 +7394,9 @@ static void service_append_added_foreach(gpointer data, gpointer user_data)
                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);
@@ -4987,8 +7618,45 @@ static DBusMessage *reset_counters(DBusConnection *conn,
        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);
@@ -5015,6 +7683,10 @@ static void service_schedule_removed(struct connman_service *service)
 
 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;
@@ -5044,12 +7716,22 @@ static const GDBusMethodTable service_methods[] = {
                        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
        { },
 };
 
@@ -5138,6 +7820,16 @@ static void service_free(gpointer user_data)
        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);
@@ -5165,6 +7857,9 @@ static void stats_init(struct connman_service *service)
 
 static void service_initialize(struct connman_service *service)
 {
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        DBG("service %p", service);
 
        service->refcount = 1;
@@ -5194,6 +7889,22 @@ static void service_initialize(struct connman_service *service)
 
        service->wps = false;
        service->wps_advertizing = false;
+#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 */
 }
 
 /**
@@ -5282,6 +7993,186 @@ void connman_service_unref_debug(struct connman_service *service,
        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,
@@ -5322,13 +8213,37 @@ static gint service_compare(gconstpointer a, gconstpointer b)
        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);
 
+#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;
 
@@ -5422,17 +8337,44 @@ static gint service_compare(gconstpointer a, gconstpointer b)
                        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();
        }
 }
@@ -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
@@ -5582,6 +8571,10 @@ int __connman_service_set_favorite_delayed(struct connman_service *service,
                                        bool favorite,
                                        bool delay_ordering)
 {
+#if defined TIZEN_EXT
+       if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
+               return -EIO;
+#endif
        if (service->hidden)
                return -EOPNOTSUPP;
 
@@ -5696,6 +8689,28 @@ void __connman_service_set_string(struct connman_service *service,
                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,
@@ -5731,7 +8746,15 @@ static void report_error_cb(void *user_context, bool retry,
                /* 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();
@@ -5905,21 +8928,154 @@ static int service_update_preferred_order(struct connman_service *default_servic
        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)
 {
@@ -5929,14 +9085,24 @@ 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);
        }
@@ -5945,12 +9111,44 @@ static void single_connected_tech(struct connman_service *allowed)
                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)
@@ -5998,6 +9196,14 @@ static int service_indicate_state(struct connman_service *service)
                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))
@@ -6089,15 +9295,38 @@ static int service_indicate_state(struct connman_service *service)
                        __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:
@@ -6111,8 +9340,20 @@ static int service_indicate_state(struct connman_service *service)
 
                __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
@@ -6125,6 +9366,11 @@ static int service_indicate_state(struct connman_service *service)
                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),
@@ -6139,6 +9385,63 @@ static int service_indicate_state(struct connman_service *service)
 
        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:
@@ -6170,6 +9473,23 @@ int __connman_service_indicate_error(struct connman_service *service,
 
        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);
@@ -6244,6 +9564,15 @@ enum connman_service_state __connman_service_ipconfig_get_state(
        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
@@ -6314,7 +9643,13 @@ static gboolean redo_wispr_ipv4(gpointer user_data)
 {
        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;
 }
@@ -6414,6 +9749,10 @@ 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;
 
@@ -6429,6 +9768,18 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service,
        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),
@@ -6442,6 +9793,30 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service,
        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);
@@ -6479,6 +9854,19 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service,
 
        __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);
 }
 
@@ -6566,8 +9954,42 @@ static void prepare_8021x(struct connman_service *service)
        if (service->phase2)
                connman_network_set_string(service->network, "WiFi.Phase2",
                                                        service->phase2);
+
+#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;
@@ -6575,11 +9997,41 @@ static int service_connect(struct connman_service *service)
        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:
@@ -6591,11 +10043,17 @@ static int service_connect(struct connman_service *service)
                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;
 
@@ -6609,6 +10067,13 @@ static int service_connect(struct connman_service *service)
                        }
                        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. "
@@ -6620,6 +10085,21 @@ static int service_connect(struct connman_service *service)
                                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)
@@ -6627,6 +10107,7 @@ static int service_connect(struct connman_service *service)
                        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
@@ -6654,6 +10135,13 @@ static int service_connect(struct connman_service *service)
                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);
@@ -6711,6 +10199,9 @@ int __connman_service_connect(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
                return -EINVAL;
 
        case CONNMAN_SERVICE_TYPE_ETHERNET:
@@ -6738,6 +10229,9 @@ int __connman_service_connect(struct connman_service *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;
@@ -6819,6 +10313,14 @@ int __connman_service_disconnect(struct connman_service *service)
                __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);
 
@@ -6827,10 +10329,43 @@ int __connman_service_disconnect(struct connman_service *service)
 
        __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
@@ -6921,7 +10456,9 @@ static struct connman_service *service_get(const char *identifier)
        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);
@@ -6936,6 +10473,9 @@ static struct connman_service *service_get(const char *identifier)
 
 static int service_register(struct connman_service *service)
 {
+#if defined TIZEN_EXT
+       if (!simplified_log)
+#endif
        DBG("service %p", service);
 
        if (service->path)
@@ -6946,6 +10486,20 @@ static int service_register(struct connman_service *service)
 
        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,
@@ -7007,6 +10561,9 @@ static void service_ip_bound(struct connman_ipconfig *ipconfig,
        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);
 
@@ -7018,9 +10575,18 @@ static void service_ip_bound(struct connman_ipconfig *ipconfig,
 
        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);
@@ -7284,10 +10850,36 @@ static enum connman_service_security convert_wifi_security(const char *security)
                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)
 {
@@ -7381,6 +10973,9 @@ static void trigger_autoconnect(struct connman_service *service)
        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:
@@ -7400,6 +10995,28 @@ static void trigger_autoconnect(struct connman_service *service)
                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
 }
 
 /**
@@ -7491,6 +11108,31 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne
        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;
@@ -7499,6 +11141,9 @@ void __connman_service_update_from_network(struct connman_network *network)
        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)
@@ -7507,6 +11152,13 @@ void __connman_service_update_from_network(struct connman_network *network)
        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);
@@ -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();
        }
@@ -7730,6 +11392,99 @@ static struct connman_agent_driver agent_driver = {
        .context_unref  = agent_context_unref,
 };
 
+#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;
@@ -7757,6 +11512,10 @@ int __connman_service_init(void)
 
        remove_unprovisioned_services();
 
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+       ins_setting_init();
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
        return 0;
 }
 
index eeefe3f..69adba9 100644 (file)
@@ -195,6 +195,9 @@ static char *service2bearer(enum connman_service_type type)
        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 "";
        }
 
@@ -1753,8 +1756,16 @@ static bool session_match_service(struct connman_session *session,
                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 ||
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 90f03eb..fb6dc14
@@ -27,6 +27,7 @@
 #include <unistd.h>
 #include <sys/stat.h>
 #include <dirent.h>
+#include <stdio.h>
 
 #include <connman/storage.h>
 
@@ -34,6 +35,9 @@
 
 #define SETTINGS       "settings"
 #define DEFAULT                "default.profile"
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+#define INS_SETTINGS   "settings.ins"
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
 
 #define MODE           (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | \
                        S_IXGRP | S_IROTH | S_IXOTH)
@@ -71,6 +75,19 @@ static int storage_save(GKeyFile *keyfile, char *pathname)
                ret = -EIO;
        }
 
+#if defined TIZEN_EXT
+       {
+               FILE *fp = NULL;
+               fp = fopen(pathname, "a+");
+               if(fp){
+                       fflush(fp);
+                       fsync(fp->_fileno);
+                       fclose(fp);
+                       DBG("sync the file to disk");
+               }
+       }
+#endif
+
        g_free(data);
 
        return ret;
@@ -116,6 +133,40 @@ int __connman_storage_save_global(GKeyFile *keyfile)
        return ret;
 }
 
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+GKeyFile *__connman_storage_load_ins(void)
+{
+       gchar *pathname;
+       GKeyFile *keyfile = NULL;
+
+       pathname = g_strdup_printf("%s/%s", STORAGEDIR, INS_SETTINGS);
+       if (!pathname)
+               return NULL;
+
+       keyfile = storage_load(pathname);
+
+       g_free(pathname);
+
+       return keyfile;
+}
+
+int __connman_storage_save_ins(GKeyFile *keyfile)
+{
+       gchar *pathname;
+       int ret;
+
+       pathname = g_strdup_printf("%s/%s", STORAGEDIR, INS_SETTINGS);
+       if (!pathname)
+               return -ENOMEM;
+
+       ret = storage_save(keyfile, pathname);
+
+       g_free(pathname);
+
+       return ret;
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
 void __connman_storage_delete_global(void)
 {
        gchar *pathname;
old mode 100644 (file)
new mode 100755 (executable)
index 672d6ea..7480ce9 100644 (file)
 
 #include <errno.h>
 #include <string.h>
+#if defined TIZEN_EXT
+#include <stdio.h>
+#include <stdlib.h>
+#include <net/if.h>
+#endif
 
 #include <gdbus.h>
 
@@ -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;
@@ -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;
@@ -150,6 +177,10 @@ static const char *get_name(enum connman_service_type type)
                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;
@@ -192,6 +223,19 @@ static void technology_save(struct connman_technology *technology)
                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);
 
@@ -379,6 +423,18 @@ bool connman_technology_get_wifi_tethering(const char **ssid,
        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;
@@ -411,6 +467,16 @@ static void technology_load(struct connman_technology *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;
@@ -443,6 +509,33 @@ static void technology_load(struct connman_technology *technology)
                                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);
 
@@ -509,6 +602,74 @@ static bool connman_technology_load_offlinemode(void)
        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)
 {
@@ -554,6 +715,27 @@ static void append_properties(DBusMessageIter *iter,
                                        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);
 }
 
@@ -656,6 +838,11 @@ static int technology_affect_devices(struct connman_technology *technology,
                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;
 
@@ -690,6 +877,10 @@ static void powered_changed(struct connman_technology *technology)
 
        __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);
@@ -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)
 {
@@ -977,11 +1442,76 @@ static DBusMessage *set_property(DBusConnection *conn,
                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)
 {
@@ -990,114 +1520,1303 @@ 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",
@@ -1107,12 +2826,41 @@ static const GDBusMethodTable technology_methods[] = {
                        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
        { },
 };
 
@@ -1183,7 +2931,9 @@ static void technology_put(struct connman_technology *technology)
         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);
@@ -1207,7 +2957,12 @@ static struct connman_technology *technology_get(enum connman_service_type type)
 
        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;
        }
@@ -1237,6 +2992,16 @@ static struct connman_technology *technology_get(enum connman_service_type type)
        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;
@@ -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;
 }
 
@@ -1352,6 +3124,13 @@ void connman_technology_driver_unregister(struct connman_technology_driver *driv
                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,
@@ -1374,6 +3153,9 @@ 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;
        }
 
@@ -1425,6 +3207,9 @@ void __connman_technology_remove_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;
        }
 
@@ -1480,7 +3265,28 @@ int __connman_technology_add_device(struct connman_device *device)
 
        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
@@ -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;
 }
 
@@ -1520,6 +3336,13 @@ int __connman_technology_remove_device(struct connman_device *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);
 
@@ -1540,11 +3363,13 @@ int __connman_technology_enabled(enum connman_service_type type)
                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);
 }
@@ -1558,9 +3383,11 @@ int __connman_technology_disabled(enum connman_service_type type)
        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;
 
@@ -1619,6 +3446,15 @@ int __connman_technology_set_offlinemode(bool offlinemode)
        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)
 {
@@ -1633,6 +3469,11 @@ void __connman_technology_set_connected(enum connman_service_type type,
 
        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",
@@ -1739,6 +3580,10 @@ int __connman_technology_add_rfkill(unsigned int index,
        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)
@@ -1746,10 +3591,12 @@ done:
 
        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;
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index feef8e8..b2707fa
@@ -118,6 +118,17 @@ static void resolv_result(GResolvResultStatus status, char **results,
 {
        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) {
@@ -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;
        }
 
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index c63dc81..fb101a1
@@ -424,6 +424,10 @@ static void wispr_portal_error(struct connman_wispr_portal_context *wp_context)
        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,
@@ -713,6 +717,9 @@ static bool wispr_portal_web_result(GWebResult *result, gpointer user_data)
        const char *str = NULL;
        guint16 status;
        gsize length;
+#if defined TIZEN_MAINTAIN_ONLINE
+       static int retried = 0;
+#endif
 
        DBG("");
 
@@ -744,6 +751,9 @@ static bool wispr_portal_web_result(GWebResult *result, gpointer user_data)
                                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;
 
@@ -786,7 +796,19 @@ static bool wispr_portal_web_result(GWebResult *result, gpointer user_data)
        case 404:
                __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
                break;
        case 505:
                __connman_agent_request_browser(wp_context->service,
@@ -875,6 +897,9 @@ static int wispr_portal_detect(struct connman_wispr_portal_context *wp_context)
        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;
        }
 
@@ -905,7 +930,9 @@ static int wispr_portal_detect(struct connman_wispr_portal_context *wp_context)
                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) {
@@ -951,6 +978,11 @@ int __connman_wispr_start(struct connman_service *service,
 
        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;
 
old mode 100644 (file)
new mode 100755 (executable)
index 54084ee..f50e4dd
@@ -161,7 +161,9 @@ int __connman_wpad_start(struct connman_service *service)
                return -ENOMEM;
        }
 
+#if !defined TIZEN_EXT
        if (getenv("CONNMAN_RESOLV_DEBUG"))
+#endif
                g_resolv_set_debug(wpad->resolv, resolv_debug, "RESOLV");
 
        for (i = 0; nameservers[i]; i++)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 3bb52e1..a8f2948
@@ -1,12 +1,18 @@
 [Unit]
 Description=ConnMan VPN service
+Requires=dbus.socket
+After=dbus.socket
 
 [Service]
 Type=dbus
+User=network_fw
+Group=network_fw
 BusName=net.connman.vpn
-ExecStart=@sbindir@/connman-vpnd -n
+SmackProcessLabel=System
+ExecStart=@bindir@/connman-vpnd -n
 StandardOutput=null
-CapabilityBoundingSet=CAP_KILL CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_CHOWN CAP_FOWNER
+Capabilities=cap_net_admin,cap_net_bind_service,cap_net_broadcast,cap_net_raw,cap_dac_override=i
+SecureBits=keep-caps
 ProtectHome=read-only
 ProtectSystem=full
 
old mode 100644 (file)
new mode 100755 (executable)
index 92c63e2..e4f4a10
@@ -160,6 +160,43 @@ static GOptionEntry options[] = {
        { NULL },
 };
 
+#if defined TIZEN_EXT
+bool connman_setting_get_bool(const char *key)
+{
+       return false;
+}
+
+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.
old mode 100644 (file)
new mode 100755 (executable)
index e473ea9..c1640cb
@@ -1,5 +1,4 @@
 [D-BUS Service]
 Name=net.connman.vpn
-Exec=@sbindir@/connman-vpnd -n
-User=root
+Exec=/bin/false
 SystemdService=connman-vpn.service
diff --git a/vpn/plugins/ipsec.c b/vpn/plugins/ipsec.c
new file mode 100644 (file)
index 0000000..36502dd
--- /dev/null
@@ -0,0 +1,925 @@
+/*
+ *
+ *  ConnMan VPN daemon
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <net/if.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#define CONNMAN_API_SUBJECT_TO_CHANGE
+#include <connman/plugin.h>
+#include <connman/log.h>
+#include <connman/task.h>
+#include <connman/dbus.h>
+#include <connman/ipconfig.h>
+
+#include "../vpn-provider.h"
+
+#include "vpn.h"
+#include "ipsec.h"
+#include "vici-client.h"
+
+#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
+
+typedef enum {
+       CERT_TYPE_NONE,
+       CERT_TYPE_DER,
+       CERT_TYPE_PEM,
+       CERT_TYPE_PKCS12,
+       CERT_TYPE_MAX,
+} cert_type_e;
+
+static DBusConnection *connection;
+static VICIClient *vici_client;
+static GFileMonitor* monitor;
+
+struct ipsec_private_data {
+       struct vpn_provider *provider;
+       vpn_provider_connect_cb_t connect_cb;
+       void *connect_user_data;
+};
+
+struct ipsec_event_data {
+       vpn_event_callback event_cb;
+       void *event_user_data;
+};
+
+struct {
+       const char *cm_opt;
+       const char *vici_key;
+       const char *subsection;
+       vici_add_element add_elem;
+} ipsec_conn_options[] = {
+       {"IPsec.Version", "version", NULL, vici_add_kv},
+       {"IPsec.LeftAddrs", "local_addrs", NULL, vici_add_kvl},
+       {"IPsec.RightAddrs", "remote_addrs", NULL, vici_add_kvl},
+
+       {"IPsec.LocalAuth", "auth", "local", vici_add_kv},
+       {"IPsec.LocalID", "id", "local", vici_add_kv},
+       {"IPsec.LocalXauthID", "xauth_id", "local", vici_add_kv},
+       {"IPsec.LocalXauthAuth", "auth", "local-xauth", vici_add_kv},
+       {"IPsec.LocalXauthXauthID", "xauth_id", "local-xauth", vici_add_kv},
+       {"IPsec.RemoteAuth", "auth", "remote", vici_add_kv},
+       {"IPsec.RemoteID", "id", "remote", vici_add_kv},
+       {"IPsec.RemoteXauthID", "xauth_id", "remote", vici_add_kv},
+       {"IPsec.RemoteXauthAuth", "auth", "remote-xauth", vici_add_kv},
+       {"IPsec.RemoteXauthXauthID", "xauth_id", "remote-xauth", vici_add_kv},
+       {"IPsec.ChildrenLocalTS", "local_ts", "children", vici_add_kvl},
+       {"IPsec.ChildrenRemoteTS", "remote_ts", "children", vici_add_kvl},
+};
+
+struct {
+       const char *cm_opt;
+       const char *vici_type;
+} ipsec_shared_options[] = {
+       {"IPsec.IKEData", "data"},
+       {"IPsec.IKEOwners", "owners"},
+       {"IPsec.XauthData", "data"},
+       {"IPsec.XauthOwners", "owners"},
+};
+
+struct {
+       const char *cm_opt;
+       const char *vici_type;
+       const char *vici_flag;
+} ipsec_cert_options[] = {
+       {"IPsec.CertType", "type", NULL},
+       {"IPsec.CertFlag", "flag", NULL},
+       {"IPsec.CertData", "data", NULL},
+       {"IPsec.CertPass", "data", NULL},
+};
+
+struct {
+       const char *cm_opt;
+       const char *vici_type;
+} ipsec_pkey_options[] = {
+       {"IPsec.PKeyType", "type"},
+       {"IPsec.PKeyData", "data"},
+};
+
+static const char *ikev1_esp_proposals [] ={
+               "aes256-sha256",
+               "aes128-sha256",
+               "aes256-sha1",
+               "aes128-sha1",
+               "aes256-md5",
+               "aes128-md5",
+               "3des-sha1",
+               "3des-md5",
+               NULL,
+};
+
+static const char *ikev1_proposals [] ={
+               "aes256-sha256-modp1024",
+               "aes128-sha256-modp1024",
+               "aes256-sha1-modp1024",
+               "aes128-sha1-modp1024",
+               "aes256-md5-modp1024",
+               "aes128-md5-modp1024",
+               "3des-sha1-modp1024",
+               "3des-md5-modp1024",
+               NULL,
+};
+
+static const char *ikev2_esp_proposals = "aes256-aes128-sha256-sha1";
+
+static const char *ikev2_proposals = "aes256-aes128-sha512-sha384-sha256-sha1-modp2048-modp1536-modp1024";
+
+static struct ipsec_event_data event_data;
+
+static void free_private_data(struct ipsec_private_data *data)
+{
+       g_free(data);
+}
+
+static int ipsec_notify(DBusMessage *msg, struct vpn_provider *provider)
+{
+       return 0;
+}
+
+static void ipsec_set_event_cb(vpn_event_callback event_cb, struct vpn_provider *provider)
+{
+       DBG("set event cb!");
+       event_data.event_cb = event_cb;
+       event_data.event_user_data = provider;
+       return;
+}
+
+static int ipsec_is_same_auth(const char* req, const char* target)
+{
+       if (req == NULL || target == NULL)
+               return 0;
+       return (g_strcmp0(req, target) == 0);
+}
+
+static int vici_load_cert(const char* type, const char* flag, const char* data)
+{
+       VICISection *sect;
+       int ret = 0;
+
+       sect = vici_create_section(NULL);
+       if (!sect)
+               return -ENOMEM;
+
+       vici_add_kv(sect, "type", type, NULL);
+       vici_add_kv(sect, "flag", flag, NULL);
+       vici_add_kv(sect, "data", data, NULL);
+
+       ret = vici_send_request(vici_client, VICI_CMD_LOAD_CERT, sect);
+       if (ret < 0)
+               connman_error("vici_send_request failed");
+
+       vici_destroy_section(sect);
+
+       return ret;
+}
+
+static void ipsec_add_default_child_sa_data(struct vpn_provider *provider, VICISection *child)
+{
+       const char *version = vpn_provider_get_string(provider, "IPsec.Version");
+       if (g_strcmp0(version, "1") == 0) {
+               int i = 0;
+               GSList *list;
+
+               for (list = NULL; ikev1_esp_proposals[i] != NULL; i++)
+                       list = g_slist_append(list, g_strdup(ikev1_esp_proposals[i]));
+               vici_add_list(child, "esp_proposals", list, "net");
+               g_slist_free_full(list, g_free);
+               list = NULL;
+       } else {
+               vici_add_kvl(child, "esp_proposals", ikev2_esp_proposals, "net");
+       }
+       return;
+}
+
+static void ipsec_add_default_conn_data(struct vpn_provider *provider, VICISection *conn)
+{
+       const char *version = vpn_provider_get_string(provider, "IPsec.Version");
+       const char *remote_addr = vpn_provider_get_string(provider, "Host");
+
+       vici_add_kvl(conn, "remote_addrs", remote_addr, NULL);
+       if (g_strcmp0(version, "1") == 0) {
+               int i = 0;
+               GSList *list;
+
+               for (list = NULL; ikev1_proposals[i] != NULL; i++)
+                       list = g_slist_append(list, g_strdup(ikev1_proposals[i]));
+               vici_add_list(conn, "proposals", list, NULL);
+               g_slist_free_full(list, g_free);
+               list = NULL;
+
+               if (g_strcmp0(vpn_provider_get_string(provider, "IPsec.LocalAuth"), "psk") == 0)
+                       vici_add_kv(conn, "aggressive", "yes", NULL);
+       } else {
+               vici_add_kvl(conn, "proposals", ikev2_proposals, NULL);
+       }
+
+       vici_add_kvl(conn, "vips", "0.0.0.0", NULL);
+       return;
+}
+
+static char *load_file_from_path(const char *path)
+{
+       struct stat st;
+       FILE *fp = NULL;
+       int fd = 0;
+       size_t  file_size = 0;
+       char *file_buff = NULL;
+
+       if (!path) {
+               connman_error("File path is NULL\n");
+               return NULL;
+       }
+
+       fp = fopen(path, "rb");
+       if (!fp) {
+               connman_error("fopen %s is failed\n", path);
+               return NULL;
+       }
+
+       fd = fileno(fp);
+       if (fd == -1) {
+               connman_error("fp is not a valid stream");
+               fclose(fp);
+               return NULL;
+       }
+
+       if (fstat(fd, &st) != 0) {
+               connman_error("fstat failed");
+               fclose(fp);
+               return NULL;
+       }
+
+       file_size = st.st_size;
+       file_buff = g_try_malloc0(sizeof(char)*st.st_size);
+       if (file_buff == NULL) {
+               connman_error("g_try_malloc0 failed\n");
+               fclose(fp);
+               return NULL;
+       }
+
+       if (fread(file_buff, 1, file_size, fp) != file_size) {
+               connman_error("file size not matched\n");
+               g_free(file_buff);
+               file_buff = NULL;
+       }
+
+       fclose(fp);
+       return file_buff;
+}
+
+static char * get_local_cert_str(struct vpn_provider *provider)
+{
+       const char *path;
+
+       if (!provider)
+               return NULL;
+
+       path = vpn_provider_get_string(provider, "IPsec.LocalCerts");
+
+       return load_file_from_path(path);
+}
+
+static int ipsec_load_conn(struct vpn_provider *provider, struct ipsec_private_data *data)
+{
+       const char *key;
+       const char *value;
+       const char *subsection;
+       char *local_cert_str;
+       VICISection *conn;
+       VICISection *children;
+       int i;
+       int ret = 0;
+
+       if (!provider || !data) {
+               connman_error("invalid provider or data");
+               return -EINVAL;
+       }
+
+       value = vpn_provider_get_string(provider, "Name");
+       DBG("Name: %s", value);
+       conn = vici_create_section(value);
+       children = vici_create_section("children");
+       add_subsection("children", children, conn);
+
+       for (i = 0; i < (int)ARRAY_SIZE(ipsec_conn_options); i++) {
+               value = vpn_provider_get_string(provider, ipsec_conn_options[i].cm_opt);
+               if (!value)
+                       continue;
+
+               key = ipsec_conn_options[i].vici_key;
+               subsection = ipsec_conn_options[i].subsection;
+               ipsec_conn_options[i].add_elem(conn, key, value, subsection);
+       }
+
+       local_cert_str = get_local_cert_str(provider);
+       if (local_cert_str) {
+               /* TODO :remove this after debug */
+               DBG("There's local certification to add local section");
+               vici_add_kvl(conn, "certs", local_cert_str, "local");
+               g_free(local_cert_str);
+       }
+
+       ipsec_add_default_conn_data(provider, conn);
+       ipsec_add_default_child_sa_data(provider, children);
+
+       ret = vici_send_request(vici_client, VICI_CMD_LOAD_CONN, conn);
+       if (ret < 0)
+               connman_error("vici_send_request failed");
+
+       vici_destroy_section(conn);
+
+       return ret;
+}
+
+static int ipsec_load_shared_psk(struct vpn_provider *provider)
+{
+       const char *data;
+       const char *owner;
+       VICISection *sect;
+       int ret = 0;
+
+       if (!provider) {
+               connman_error("invalid provider");
+               return -EINVAL;
+       }
+
+       data = vpn_provider_get_string(provider, "IPsec.IKEData");
+       owner = vpn_provider_get_string(provider, "IPsec.IKEOwners");
+       DBG("IKEData: %s, IKEOwners: %s", data, owner);
+
+       if (!data)
+               return 0;
+
+       sect = vici_create_section(NULL);
+       if (!sect) {
+               return -ENOMEM;
+       }
+
+       vici_add_kv(sect, "type", VICI_SHARED_TYPE_PSK, NULL);
+       vici_add_kv(sect, "data", data, NULL);
+       vici_add_kvl(sect, "owners", owner, NULL);
+
+       ret = vici_send_request(vici_client, VICI_CMD_LOAD_SHARED, sect);
+       if (ret < 0)
+               connman_error("vici_send_request failed");
+
+       vici_destroy_section(sect);
+
+       return ret;
+}
+
+static int ipsec_load_shared_xauth(struct vpn_provider *provider)
+{
+       const char *data;
+       const char *owner;
+       VICISection *sect;
+       int ret = 0;
+
+       if (!provider) {
+               connman_error("invalid provider");
+               return -EINVAL;
+       }
+
+       data = vpn_provider_get_string(provider, "IPsec.XauthData");
+       owner = vpn_provider_get_string(provider, "IPsec.XauthOwners");
+       DBG("XauthData: %s, XauthOwners: %s", data, owner);
+
+       if (!data)
+               return 0;
+
+       sect = vici_create_section(NULL);
+
+       vici_add_kv(sect, "type", VICI_SHARED_TYPE_XAUTH, NULL);
+       vici_add_kv(sect, "data", data, NULL);
+       vici_add_kvl(sect, "owners", owner, NULL);
+
+       ret = vici_send_request(vici_client, VICI_CMD_LOAD_SHARED, sect);
+       if (ret < 0)
+               connman_error("vici_send_request failed");
+
+       vici_destroy_section(sect);
+
+       return ret;
+}
+
+static int ipsec_load_key(struct vpn_provider *provider)
+{
+       const char *type;
+       const char *path;
+       char *data;
+       VICISection *sect;
+       int ret = 0;
+
+       if (!provider) {
+               connman_error("invalid provider");
+               return -EINVAL;
+       }
+
+       type = vpn_provider_get_string(provider, "IPsec.PKeyType");
+       path = vpn_provider_get_string(provider, "IPsec.PKeyData");
+       DBG("PKeyType: %s, PKeyData: %s", type, path);
+
+       if (!type || !path)
+               return 0;
+
+       data = load_file_from_path(path);
+       if (!data)
+               return 0;
+
+       sect = vici_create_section(NULL);
+       if (!sect) {
+               g_free(data);
+               return -ENOMEM;
+       }
+
+       vici_add_kv(sect, "type", type, NULL);
+       vici_add_kv(sect, "data", data, NULL);
+
+       ret = vici_send_request(vici_client, VICI_CMD_LOAD_KEY, sect);
+       if (ret < 0)
+               connman_error("vici_send_request failed");
+
+       vici_destroy_section(sect);
+       g_free(data);
+
+       return ret;
+}
+
+static int ipsec_initiate(struct vpn_provider *provider)
+{
+       VICISection *sect;
+       int ret = 0;
+
+       sect = vici_create_section(NULL);
+       if (!sect)
+               return -ENOMEM;
+
+       vici_add_kv(sect, "child", "net", NULL);
+       ret = vici_send_request(vici_client, VICI_CMD_INITIATE, sect);
+       if (ret < 0)
+               connman_error("vici_send_request failed");
+
+       vici_destroy_section(sect);
+
+       return ret;
+}
+
+static int ipsec_load_cert(struct vpn_provider *provider)
+{
+       const char *type;
+       const char *flag;
+       char *data;
+       const char *local_auth_type;
+       const char *remote_auth_type;
+       int ret = 0;
+
+       if (!provider) {
+               connman_error("invalid provider");
+               return -EINVAL;
+       }
+
+       local_auth_type = vpn_provider_get_string(provider, "IPsec.LocalAuth");
+       remote_auth_type = vpn_provider_get_string(provider, "IPsec.RemoteAuth");
+       if (!ipsec_is_same_auth(local_auth_type, "pubkey") &&
+                       !ipsec_is_same_auth(remote_auth_type, "pubkey")) {
+               DBG("invalid auth type");
+               return 0;
+       }
+
+       type = vpn_provider_get_string(provider, "IPsec.CertType");
+       flag = vpn_provider_get_string(provider, "IPsec.CertFlag");
+       data = load_file_from_path(vpn_provider_get_string(provider, "IPsec.CertData"));
+       DBG("CertType: %s, CertFalg: %s,CertData: %s", type, flag, data);
+       if (!type || ! flag || !data) {
+               connman_error("invalid certification information");
+               g_free(data);
+               return -EINVAL;
+       }
+
+       ret = vici_load_cert(type, flag, data);
+       if (ret < 0)
+               connman_error("failed to load cert");
+
+       g_free(data);
+
+       return ret;
+}
+
+static int ipsec_terminate(struct vpn_provider *provider)
+{
+       VICISection *sect;
+       int ret = 0;
+
+       sect = vici_create_section(NULL);
+       if (!sect)
+               return -ENOMEM;
+
+       vici_add_kv(sect, "child", "net", NULL);
+       vici_add_kv(sect, "ike", vpn_provider_get_string(provider, "Name"), NULL);
+       vici_add_kv(sect, "timeout", "-1", NULL);
+       ret = vici_send_request(vici_client, VICI_CMD_TERMINATE, sect);
+       if (ret < 0)
+               connman_error("vici_send_request failed");
+
+       vici_destroy_section(sect);
+
+       return ret;
+}
+
+static void request_reply_cb(int err, void *user_data)
+{
+       struct ipsec_private_data *data;
+
+       data = (struct ipsec_private_data *)user_data;
+       DBG("request reply cb");
+
+       if(err != 0) {
+               if (event_data.event_cb)
+                       event_data.event_cb(event_data.event_user_data, VPN_STATE_FAILURE);
+               /* TODO: Does close socket needed? */
+       } else {
+               DBG("Series of requests are succeeded");
+               /* TODO: Not sure about below */
+               if (event_data.event_cb)
+                       event_data.event_cb(event_data.event_user_data, VPN_STATE_CONNECT);
+       }
+
+       free_private_data(data);
+}
+
+static void ipsec_vici_event_cb(VICIClientEvent event, void *user_data)
+{
+       struct vpn_provider *provider;
+
+       provider = (struct vpn_provider *)user_data;
+       if (!provider) {
+               DBG("Invalid user data");
+               return;
+       }
+
+       if(event == VICI_EVENT_CHILD_UP) {
+               if (event_data.event_cb)
+                       event_data.event_cb(event_data.event_user_data, VPN_STATE_READY);
+       } else if (event == VICI_EVENT_CHILD_DOWN) {
+               if (event_data.event_cb)
+                       event_data.event_cb(event_data.event_user_data, VPN_STATE_DISCONNECT);
+       } else {
+               DBG("Unknown event");
+       }
+
+       return;
+}
+
+static struct ipsec_private_data* create_ipsec_private_data(struct vpn_provider *provider,
+               vpn_provider_connect_cb_t cb, void* user_data)
+{
+       struct ipsec_private_data *data;
+       data = g_try_new0(struct ipsec_private_data, 1);
+       if (!data) {
+               connman_error("out of memory");
+               return NULL;
+       }
+
+       data->provider = provider;
+       data->connect_cb = cb;
+       data->connect_user_data = user_data;
+       return data;
+}
+
+static void vici_connect(struct ipsec_private_data *data)
+{
+       struct vpn_provider *provider = NULL;
+       vpn_provider_connect_cb_t cb = NULL;
+       int err = 0;
+
+       if (!data)
+               IPSEC_ERROR_CHECK_GOTO(-1, done, "Invalid data parameter");
+
+       provider = data->provider;
+       cb = data->connect_cb;
+       if (!provider || !cb)
+               IPSEC_ERROR_CHECK_GOTO(-1, done, "Invalid provider or callback");
+
+       DBG("data %p, provider %p", data, provider);
+
+       /*
+        * Initialize vici client
+        */
+       err = vici_initialize(&vici_client);
+       IPSEC_ERROR_CHECK_GOTO(err, done, "failed to initialize vici_client");
+
+       /* TODO :remove this after debug */
+       DBG("success to initialize vici socket");
+
+       vici_set_request_reply_cb(vici_client, (vici_request_reply_cb)request_reply_cb, data);
+       /*
+        * Sets child-updown event
+        */
+       err = vici_set_event_cb(vici_client, (vici_event_cb)ipsec_vici_event_cb, provider);
+       IPSEC_ERROR_CHECK_GOTO(err, done, "register event failed");
+
+       /* TODO :remove this after debug */
+       DBG("success to vici_set_event_cb");
+       /*
+        * Send the load-conn command
+        */
+       err = ipsec_load_conn(provider, data);
+       IPSEC_ERROR_CHECK_GOTO(err, done, "load-conn failed");
+
+       /* TODO :remove this after debug */
+       DBG("success to ipsec_load_conn");
+
+       /*
+        * Send the load-shared command for PSK
+        */
+       err = ipsec_load_shared_psk(provider);
+       IPSEC_ERROR_CHECK_GOTO(err, done, "load-shared failed");
+
+       /* TODO :remove this after debug */
+       DBG("success to ipsec_load_shared_psk");
+
+       /*
+        * Send the load-shared command for XAUTH
+        */
+       err = ipsec_load_shared_xauth(provider);
+       IPSEC_ERROR_CHECK_GOTO(err, done, "load-shared failed");
+
+       /* TODO :remove this after debug */
+       DBG("success to ipsec_load_shared_xauth");
+       /*
+        * Send the load-cert command
+        */
+       err = ipsec_load_cert(provider);
+       IPSEC_ERROR_CHECK_GOTO(err, done, "load-cert failed");
+
+       /* TODO :remove this after debug */
+       DBG("success to ipsec_load_cert");
+
+       /*
+        * Send the load-key command
+        */
+       err = ipsec_load_key(provider);
+       IPSEC_ERROR_CHECK_GOTO(err, done, "load-key failed");
+
+       /* TODO :remove this after debug */
+       DBG("success to ipsec_load_cert");
+       /*
+        * Send the initiate command
+        */
+       err = ipsec_initiate(provider);
+       IPSEC_ERROR_CHECK_GOTO(err, done, "initiate failed");
+
+       /* TODO :remove this after debug */
+       DBG("success to ipsec_initiate");
+
+done:
+       /* refer to connect_cb on vpn-provider.c for cb */
+       if(cb)
+               cb(provider, data->connect_user_data, -err);
+       /* TODO: Does close socket needed? when err is not zero */
+
+       return;
+}
+
+static void monitor_changed(GFileMonitor *monitor, GFile *file, GFile *other_file,
+               GFileMonitorEvent  event_type, gpointer user_data)
+{
+       DBG("file %s", g_file_get_path(file));
+       if (event_type == G_FILE_MONITOR_EVENT_CREATED) {
+               if (g_file_test(VICI_DEFAULT_URI, G_FILE_TEST_EXISTS)) {
+                       DBG("file created: %s", VICI_DEFAULT_URI);
+                       struct ipsec_private_data *data = user_data;
+                       vici_connect(data);
+                       g_object_unref(monitor);
+               }
+       }
+}
+
+static void monitor_vici_socket(struct ipsec_private_data *data)
+{
+       GError *error = NULL;
+       GFile* file;
+
+       file = g_file_new_for_path(VICI_DEFAULT_URI);
+       monitor = g_file_monitor_file(file, G_FILE_MONITOR_SEND_MOVED, NULL, &error);
+       if (error) {
+               connman_error("g_file_monitor_directory failed: %s / %d", error->message, error->code);
+               g_error_free(error);
+               if(event_data.event_cb)
+                       event_data.event_cb(event_data.event_user_data, VPN_STATE_FAILURE);
+               return;
+       }
+       /* TODO :remove this after debug */
+       DBG("starting to monitor vici socket");
+       g_signal_connect(monitor, "changed", G_CALLBACK(monitor_changed), data);
+       g_object_unref(file);
+}
+
+static void check_vici_socket(struct ipsec_private_data *data)
+{
+       DBG("data %p", data);
+       if (g_file_test(VICI_DEFAULT_URI, G_FILE_TEST_EXISTS)) {
+               DBG("file exists: %s", VICI_DEFAULT_URI);
+               vici_connect(data);
+       } else {
+               monitor_vici_socket(data);
+       }
+}
+
+static void ipsec_died(struct connman_task *task, int exit_code, void *user_data)
+{
+       DBG("task %p exit_code %d", task, exit_code);
+       unlink(VICI_DEFAULT_URI);
+       vpn_died(task, exit_code, user_data);
+}
+
+static int ipsec_connect(struct vpn_provider *provider,
+                       struct connman_task *task, const char *if_name,
+                       vpn_provider_connect_cb_t cb, const char *dbus_sender,
+                       void *user_data)
+{
+       struct ipsec_private_data *data;
+       int err = 0;
+
+       data = create_ipsec_private_data(provider, cb, user_data);
+       if (!data) {
+               connman_error("create ipsec private data failed");
+               return -ENOMEM;
+       }
+       /*
+        * Start charon daemon using ipsec script of strongSwan.
+        */
+       err = connman_task_run(task, ipsec_died, provider, NULL, NULL, NULL);
+       if (err < 0) {
+               connman_error("charon start failed");
+               if (cb)
+                       cb(provider, user_data, err);
+
+               g_free(data);
+               return err;
+       }
+
+       check_vici_socket(data);
+//     g_usleep(G_USEC_PER_SEC);
+
+       return err;
+}
+
+static int ipsec_error_code(struct vpn_provider *provider, int exit_code)
+{
+       return 0;
+}
+
+static int ipsec_save(struct vpn_provider *provider, GKeyFile *keyfile)
+{
+       int i;
+       const char *option;
+
+       DBG("");
+       /*
+        * Save IKE connection configurations
+        */
+       for (i = 0; i < (int)ARRAY_SIZE(ipsec_conn_options); i++) {
+               option = vpn_provider_get_string(provider, ipsec_conn_options[i].cm_opt);
+               if (option)
+                       g_key_file_set_string(keyfile,
+                                       vpn_provider_get_save_group(provider),
+                                       ipsec_conn_options[i].cm_opt,
+                                       option);
+       }
+
+       /*
+        * Save shared IKE PSK, EAP or XAUTH secret
+        */
+       for (i = 0; i < (int)ARRAY_SIZE(ipsec_shared_options); i++) {
+               option = vpn_provider_get_string(provider, ipsec_shared_options[i].cm_opt);
+               if (option)
+                       g_key_file_set_string(keyfile,
+                                       vpn_provider_get_save_group(provider),
+                                       ipsec_shared_options[i].cm_opt,
+                                       option);
+       }
+
+       /*
+        * Save certification
+        */
+       for (i = 0; i < (int)ARRAY_SIZE(ipsec_cert_options); i++) {
+               option = vpn_provider_get_string(provider, ipsec_cert_options[i].cm_opt);
+               if (option)
+                       g_key_file_set_string(keyfile,
+                                       vpn_provider_get_save_group(provider),
+                                       ipsec_cert_options[i].cm_opt,
+                                       option);
+       }
+
+       /*
+        * Save private key
+        */
+       for (i = 0; i < (int)ARRAY_SIZE(ipsec_pkey_options); i++) {
+               option = vpn_provider_get_string(provider, ipsec_pkey_options[i].cm_opt);
+               if (option)
+                       g_key_file_set_string(keyfile,
+                                       vpn_provider_get_save_group(provider),
+                                       ipsec_pkey_options[i].cm_opt,
+                                       option);
+       }
+
+       /*
+        * Save local certification
+        */
+       option = vpn_provider_get_string(provider, "IPsec.LocalCerts");
+       if (option)
+               g_key_file_set_string(keyfile,
+                               vpn_provider_get_save_group(provider),
+                               "IPsec.LocalCerts",
+                               option);
+       option = vpn_provider_get_string(provider, "IPsec.LocalCertPass");
+       if (option)
+               g_key_file_set_string(keyfile,
+                               vpn_provider_get_save_group(provider),
+                               "IPsec.LocalCertPass",
+                               option);
+       /*
+        * Save CA certification directory
+        */
+       option = vpn_provider_get_string(provider, "IPsec.CACertsDir");
+       if (option)
+               g_key_file_set_string(keyfile,
+                               vpn_provider_get_save_group(provider),
+                               "IPsec.CACertsDir",
+                               option);
+
+       return 0;
+}
+
+static void ipsec_disconnect(struct vpn_provider *provider)
+{
+       int err = 0;
+       /*
+        * Send the terminate command
+        */
+       err = ipsec_terminate(provider);
+       IPSEC_ERROR_CHECK_RETURN(err, "terminate failed");
+
+       err = vici_deinitialize(vici_client);
+       IPSEC_ERROR_CHECK_RETURN(err, "failed to deinitialize vici_client");
+
+       return;
+}
+
+static struct vpn_driver vpn_driver = {
+       .flags = VPN_FLAG_NO_TUN,
+       .notify = ipsec_notify,
+       .set_event_cb = ipsec_set_event_cb,
+       .connect = ipsec_connect,
+       .error_code = ipsec_error_code,
+       .save = ipsec_save,
+       .disconnect = ipsec_disconnect,
+};
+
+static int ipsec_init(void)
+{
+       connection = connman_dbus_get_connection();
+
+       event_data.event_cb = NULL;
+       event_data.event_user_data = NULL;
+
+       return vpn_register("ipsec", &vpn_driver, IPSEC);
+}
+
+static void ipsec_exit(void)
+{
+       vpn_unregister("ipsec");
+
+       dbus_connection_unref(connection);
+}
+
+CONNMAN_PLUGIN_DEFINE(ipsec, "IPSec plugin", VERSION,
+       CONNMAN_PLUGIN_PRIORITY_DEFAULT, ipsec_init, ipsec_exit)
diff --git a/vpn/plugins/ipsec.h b/vpn/plugins/ipsec.h
new file mode 100644 (file)
index 0000000..14b9596
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *
+ *  ConnMan VPN daemon
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __CONNMAN_VPND_PLUGIN_IPSEC_H
+#define __CONNMAN_VPND_PLUGIN_IPSEC_H
+
+#define IPSEC_AUTH_PSK         "PSK"
+#define IPSEC_AUTH_RSA         "RSA"
+#define IPSEC_AUTH_XAUTH       "XAUTH"
+
+#define VICI_SHARED_TYPE_PSK   "IKE"
+#define VICI_SHARED_TYPE_XAUTH "xauth"
+
+#define IPSEC_ERROR_CHECK_GOTO(err, target, fmt, arg...) do { \
+       if (err < 0) { \
+               connman_error(fmt, ## arg); \
+               goto target; \
+       } \
+} while (0)
+
+#define IPSEC_ERROR_CHECK_RETURN(err, fmt, arg...) do { \
+       if (err < 0) { \
+               connman_error(fmt, ## arg); \
+               return; \
+       } \
+} while (0)
+
+#define IPSEC_ERROR_CHECK_RETURN_VAL(err, ret, fmt, arg...) do { \
+       if (err < 0) { \
+               connman_error(fmt, ## arg); \
+               return ret; \
+       } \
+} while (0)
+
+#endif /* __CONNMAN_VPND_PLUGIN_IPSEC_H */
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index daf66cd..8c8d316
@@ -154,8 +154,15 @@ static struct nameserver_entry *ov_append_dns_entries(const char *key,
                                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 */
@@ -496,8 +503,10 @@ static int run_connect(struct ov_private_data *data,
 
        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 with TCP because we can't handle this at
old mode 100644 (file)
new mode 100755 (executable)
diff --git a/vpn/plugins/vici-client.c b/vpn/plugins/vici-client.c
new file mode 100644 (file)
index 0000000..67e365a
--- /dev/null
@@ -0,0 +1,1290 @@
+/*
+ *
+ *  ConnMan VPN daemon
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+#include <arpa/inet.h>
+
+#include <glib.h>
+
+#include <connman/log.h>
+#include "ipsec.h"
+#include "vici-client.h"
+
+#define SOCK_FD_MIN 3
+#define VICI_REQUEST_TIMEOUT 5000
+
+enum vici_element {
+       VICI_END = 0,
+       VICI_SECTION_START = 1,
+       VICI_SECTION_END = 2,
+       VICI_KEY_VALUE = 3,
+       VICI_LIST_START = 4,
+       VICI_LIST_ITEM = 5,
+       VICI_LIST_END = 6,
+};
+
+enum vici_packet_type {
+       VICI_CMD_REQUEST = 0,
+       VICI_CMD_RESPONSE = 1,
+       VICI_CMD_UNKNOWN = 2,
+       VICI_EVENT_REGISTER = 3,
+       VICI_EVENT_UNREGISTER = 4,
+       VICI_EVENT_CONFIRM = 5,
+       VICI_EVENT_UNKNOWN = 6,
+       VICI_EVENT = 7,
+};
+
+static const char *vici_cmd_str[] = {
+       "load-conn",
+       "load-shared",
+       "load-cert",
+       "load-authority",
+       "unload-authority",
+       "load-key",
+       "initiate",
+       "terminate",
+       "child-updown",
+       NULL,
+};
+
+struct request {
+       unsigned int allocated;
+       unsigned int used;
+       unsigned int hdr_len;
+       char *sndbuf;
+       int cmd;
+       int err;
+       /* process reply */
+       unsigned int rcv_pkt_size;
+       char *rcvbuf;
+       /* davici_cb cb; */
+       void *user;
+};
+
+struct _VICIClient {
+       /* io data */
+       int client_sock_fd;
+       int client_watch;
+       unsigned int rcv_pkt_size;
+       char *rcvbuf;
+       GSList *request_list;
+       vici_request_reply_cb reply_cb;
+       vici_event_cb event_cb;
+       void *reply_user_data;
+       void *event_user_data;
+};
+
+struct _VICISection {
+       char *name;
+       GHashTable *kvs;
+       GHashTable *kvls;
+       GHashTable *subsection;
+};
+
+static void remove_list(gpointer data)
+{
+       if (data == NULL)
+               return;
+
+       g_slist_free_full((GSList *)data, g_free);
+}
+
+void vici_destroy_section(VICISection* section)
+{
+       g_free(section->name);
+       g_hash_table_destroy(section->kvs);
+       g_hash_table_destroy(section->kvls);
+       g_hash_table_destroy(section->subsection);
+       g_free(section);
+}
+
+static void free_section(gpointer data)
+{
+       VICISection* section = (VICISection*)data;
+       vici_destroy_section(section);
+}
+
+VICISection* vici_create_section(const char* name)
+{
+       VICISection* section;
+
+       section = g_try_new0(VICISection, 1);
+       if (!section) {
+               connman_error("Failed to create section");
+               return NULL;
+       }
+
+       if (name)
+               section->name = g_strdup(name);
+       section->kvs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+       section->kvls = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, remove_list);
+       section->subsection = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_section);
+       return section;
+}
+
+int add_subsection(const char* name, VICISection* child, VICISection* section)
+{
+       if (section == NULL || name == NULL || child == NULL) {
+               connman_error("invalid parameter");
+               return -1;
+       }
+
+       g_hash_table_insert(section->subsection, g_strdup(name), child);
+       return 0;
+}
+
+static int add_kvl_to_section(const char* key, const char* value, VICISection* section)
+{
+       GSList *list = NULL;
+       if (section == NULL || key == NULL || value == NULL) {
+               connman_error("invalid parameter");
+               return -1;
+       }
+
+       list = g_hash_table_lookup(section->kvls, key);
+       if (list == NULL)
+               list = g_slist_alloc();
+
+       list = g_slist_prepend(list, g_strdup(value));
+       g_hash_table_replace(section->kvls, g_strdup(key), list);
+       return 0;
+}
+
+static int add_kv_to_section(const char* key, const char* value, VICISection* section)
+{
+       if (section == NULL || key == NULL || value == NULL) {
+               connman_error("invalid parameter");
+               return -1;
+       }
+
+       g_hash_table_insert(section->kvs, g_strdup(key), g_strdup(value));
+       return 0;
+}
+
+static VICISection* get_subsection(VICISection* section, const char* name)
+{
+       VICISection* sub = g_hash_table_lookup(section->subsection, name);
+       if (sub == NULL) {
+               sub = vici_create_section(name);
+               add_subsection(name, sub, section);
+       }
+       return sub;
+}
+
+int vici_add_kv(VICISection* section, const char* key,
+               const char* value, const char* subsection)
+{
+       VICISection* target = section;
+       DBG("key: %s, value: %s, subsection: %s", key, value, subsection);
+
+       if (section == NULL || key == NULL) {
+               connman_error("invalid parameter");
+               return -1;
+       }
+
+       if (subsection)
+               target = get_subsection(section, subsection);
+
+       add_kv_to_section(key, value, target);
+       return 0;
+}
+
+int vici_add_kvl(VICISection* section, const char* key,
+               const char* value, const char* subsection)
+{
+       VICISection* target = section;
+
+       DBG("key: %s, value: %s, subsection: %s", key, value, subsection);
+       if (section == NULL || key == NULL) {
+               connman_error("invalid parameter");
+               return -1;
+       }
+
+       if (subsection)
+               target = get_subsection(section, subsection);
+
+       if (g_strcmp0(subsection, "children") == 0)
+               target = get_subsection(target, "net");
+
+       add_kvl_to_section(key, value, target);
+       return 0;
+}
+
+static void add_list_to_section(char *key, GSList *list, VICISection *section)
+{
+       if (section == NULL || key == NULL || list == NULL)
+               return;
+
+       g_hash_table_insert(section->kvls, g_strdup(key), g_slist_copy_deep(list, (GCopyFunc)g_strdup, NULL));
+       return;
+}
+
+int vici_add_list(VICISection* section, char *key, GSList *list, const char* subsection)
+{
+       VICISection* target = section;
+
+       DBG("key: %s, subsection: %s", key, subsection);
+       if (section == NULL || key == NULL) {
+               connman_error("invalid parameter");
+               return -1;
+       }
+
+       if (subsection)
+               target = get_subsection(section, subsection);
+
+       if (g_strcmp0(subsection, "children") == 0)
+               target = get_subsection(target, "net");
+
+       add_list_to_section(key, list, target);
+       return 0;
+}
+
+static char *load_cert_from_path(const char *path)
+{
+       struct stat st;
+       FILE *fp = NULL;
+       int fd = 0;
+       size_t file_size = 0;
+       char *file_buff = NULL;
+
+       fp = fopen(path, "rb");
+       if (fp == NULL) {
+               connman_error("fopen failed");
+               return NULL;
+       }
+
+       fd = fileno(fp);
+       if (fd == -1) {
+               connman_error("fp is not a valid stream");
+               fclose(fp);
+               return NULL;
+       }
+
+       if (fstat(fd, &st) != 0) {
+               connman_error("fstat failed");
+               fclose(fp);
+               return NULL;
+       }
+
+       file_size = st.st_size;
+       file_buff = g_try_malloc0(sizeof(char)*st.st_size);
+       if (file_buff == NULL) {
+               connman_error("g_try_malloc0 failed\n");
+               fclose(fp);
+               return NULL;
+       }
+
+       if (fread(file_buff, 1, file_size, fp) != file_size) {
+               connman_error("file size not matched\n");
+               g_free(file_buff);
+               file_buff = NULL;
+       }
+
+       fclose(fp);
+       return file_buff;
+}
+
+int vici_add_cert_kv(VICISection *section, const char *key,
+               const char *value, const char *subsection)
+{
+       char *cert = NULL;
+       int ret = 0;
+
+       if (value == NULL) {
+               DBG("value is null");
+               return 0;
+       }
+
+       cert = load_cert_from_path(value);
+       if (!cert)
+               return -1;
+
+       ret = vici_add_kv(section, key, (const char *)cert, subsection);
+       g_free(cert);
+       return ret;
+}
+
+int vici_add_cert_kvl(VICISection *section, const char *key,
+               const char *value, const char *subsection)
+{
+       char *cert = NULL;
+       int ret = 0;
+
+       cert = load_cert_from_path(value);
+       if (!cert)
+               return -1;
+
+       ret = vici_add_kvl(section, key, (const char *)cert, subsection);
+       g_free(cert);
+       return ret;
+}
+
+static void *add_element(struct request *r, enum vici_element type,
+                                                unsigned int size)
+{
+       unsigned int newlen;
+       void *ret, *new;
+
+       if (r->used + size + 1 > r->allocated) {
+               newlen = r->allocated;
+               while (newlen < r->used + size + 1) {
+                       newlen *= 2;
+               }
+               new = realloc(r->sndbuf, newlen);
+               if (!new) {
+                       r->err = -errno;
+                       return NULL;
+               }
+               r->sndbuf = new;
+               r->allocated = newlen;
+       }
+       r->sndbuf[r->used++] = type;
+       ret = r->sndbuf + r->used;
+       r->used += size;
+       return ret;
+}
+
+static void section_start(struct request *r, const char *name)
+{
+       uint8_t nlen;
+       char *pos;
+
+       nlen = strlen(name);
+       pos = add_element(r, VICI_SECTION_START, 1 + nlen);
+       if (pos) {
+               pos[0] = nlen;
+               memcpy(pos + 1, name, nlen);
+       }
+}
+
+static void section_end(struct request *r)
+{
+       add_element(r, VICI_SECTION_END, 0);
+}
+
+static void key_value(struct request *r, const char *name,
+                          const void *buf, unsigned int buflen)
+{
+       uint8_t nlen;
+       uint16_t vlen;
+       char *pos;
+
+       nlen = strlen(name);
+       pos = add_element(r, VICI_KEY_VALUE, 1 + nlen + sizeof(vlen) + buflen);
+       if (pos) {
+               pos[0] = nlen;
+               memcpy(pos + 1, name, nlen);
+               vlen = htons(buflen);
+               memcpy(pos + 1 + nlen, &vlen, sizeof(vlen));
+               memcpy(pos + 1 + nlen + sizeof(vlen), buf, buflen);
+       }
+}
+
+
+static void list_start(struct request *r, const char *name)
+{
+       uint8_t nlen;
+       char *pos;
+
+       nlen = strlen(name);
+       pos = add_element(r, VICI_LIST_START, 1 + nlen);
+       if (pos) {
+               pos[0] = nlen;
+               memcpy(pos + 1, name, nlen);
+       }
+}
+
+static void list_item(struct request *r, const void *buf,
+                                         unsigned int buflen)
+{
+       uint16_t vlen;
+       char *pos;
+
+       pos = add_element(r, VICI_LIST_ITEM, sizeof(vlen) + buflen);
+       if (pos) {
+               vlen = htons(buflen);
+               memcpy(pos, &vlen, sizeof(vlen));
+               memcpy(pos + sizeof(vlen), buf, buflen);
+       }
+}
+
+static void list_end(struct request *r)
+{
+       add_element(r, VICI_LIST_END, 0);
+}
+
+static void destroy_vici_request(gpointer data)
+{
+       struct request *req = (struct request *)data;
+       if(!req)
+               return;
+
+       g_free(req->sndbuf);
+       g_free(req);
+}
+
+static int create_vici_request(enum vici_packet_type type, VICIClientCmd cmd,
+                                                 struct request **rp)
+{
+       struct request *req = NULL;
+
+       if (cmd >= VICI_CMD_MAX || !rp)
+               return -EINVAL;
+
+       req = g_try_new0(struct request, 1);
+       if (!req) {
+               connman_error("g_try_new0 failed");
+               return -ENOMEM;
+       }
+
+       req->used = 2;
+       req->used += strlen(vici_cmd_str[cmd]);
+       req->allocated = MIN(32, req->used);
+       req->sndbuf = g_try_new0(char, req->allocated);
+       if (!req->sndbuf) {
+               connman_error("g_try_new0 failed");
+               g_free(req);
+               return -ENOMEM;
+       }
+
+       req->sndbuf[0] = type;
+       req->sndbuf[1] = req->used - 2; /* except for type and name length */
+       memcpy(req->sndbuf + 2, vici_cmd_str[cmd], req->used - 2);
+       req->hdr_len = req->used;
+       req->cmd = cmd;
+
+       *rp = req;
+
+       return 0;
+}
+
+static void write_section_kvs(VICISection *section, struct request *req)
+{
+       GHashTableIter iter;
+       gpointer key, value;
+
+       if (section == NULL || req == NULL)
+               return;
+
+       g_hash_table_iter_init (&iter, section->kvs);
+       while (g_hash_table_iter_next (&iter, &key, &value)) {
+               if (!key || !value)
+                       continue;
+               key_value(req, (const char*)key, (const void *)value, strlen((char *)value));
+       }
+
+       return;
+}
+
+static void write_list_item(gpointer data, gpointer user_data)
+{
+       struct request *req = NULL;
+       char *value = NULL;
+
+       if (!data || !user_data)
+               return;
+
+       value = (char *)data;
+       req = (struct request *)user_data;
+       list_item(req, value, strlen(value));
+
+       return;
+}
+
+static void write_section_kvls(VICISection *section, struct request *req)
+{
+       GHashTableIter iter;
+       gpointer key, value;
+
+       if (section == NULL || req == NULL)
+               return;
+
+       g_hash_table_iter_init (&iter, section->kvls);
+       while (g_hash_table_iter_next (&iter, &key, &value)) {
+               if (!key || !value)
+                       continue;
+
+               list_start(req, key);
+               g_slist_foreach((GSList *)value, (GFunc)write_list_item, (gpointer)req);
+               list_end(req);
+       }
+
+       return;
+}
+
+static void write_section(struct request *req, VICISection *section)
+{
+       GHashTableIter iter;
+       gpointer key, value;
+
+       if (req == NULL || section == NULL)
+               return;
+
+       if (section->name)
+               section_start(req, section->name);
+
+       write_section_kvs(section, req);
+       write_section_kvls(section, req);
+
+       g_hash_table_iter_init(&iter, section->subsection);
+       while (g_hash_table_iter_next (&iter, &key, &value)) {
+               if (!key || !value)
+                       continue;
+               write_section(req, (VICISection *)value);
+       }
+
+       if (section->name)
+               section_end(req);
+       return;
+}
+
+static int check_socket(int sock)
+{
+       struct pollfd p_fd;
+       int res = 0;
+
+       p_fd.fd = sock;
+       p_fd.events = POLLIN | POLLOUT | POLLERR | POLLHUP | POLLNVAL;
+       res = poll((struct pollfd *) &p_fd, 1, 1);
+
+       if (res < 0) {
+               connman_error("Polling error from socket\n");
+               return -1;
+       } else if (res == 0) {
+               connman_error( "poll timeout. socket is busy\n");
+               return 1;
+       } else {
+
+               if (p_fd.revents & POLLERR) {
+                       connman_error("Error! POLLERR from socket[%d]\n", sock);
+                       return -1;
+               } else if (p_fd.revents & POLLHUP) {
+                       connman_error("Error! POLLHUP from socket[%d]\n", sock);
+                       return -1;
+               } else if (p_fd.revents & POLLNVAL) {
+                       connman_error("Error! POLLNVAL from socket[%d]\n", sock);
+                       return -1;
+               } else if (p_fd.revents & POLLIN) {
+                       return 0;
+               } else if (p_fd.revents & POLLOUT) {
+                       return 0;
+               }
+       }
+
+       connman_error("Unknown poll event [%d]\n", p_fd.revents);
+       return -1;
+}
+
+static int write_socket(int sock, char *data, int data_len)
+{
+       int wbytes = 0;
+       int left_len = data_len;
+       char *ptr = data;
+       int res = 0;
+
+       if (sock < SOCK_FD_MIN || !data || data_len < 0)
+               return -1;
+
+       res = check_socket(sock);
+       if (res < 0)
+               return -1;
+       else if (res > 0)
+               return -2;
+
+       errno = 0;
+       while (left_len) {
+               wbytes = write(sock, ptr, left_len);
+               if (wbytes <= 0) {
+                       connman_error("Failed to write data into socket[%d].\n", sock);
+                       break;
+               }else if (wbytes < left_len) {
+                       left_len -= wbytes;
+                       ptr += wbytes;
+               } else if (wbytes == left_len) {
+                       left_len = 0;
+               } else {
+                       connman_error("Unknown error occurred.\n");
+                       break;
+               }
+       }
+
+       if (left_len)
+               return -1;
+       else
+               return 0;
+}
+
+int send_vici_command(struct request *req, VICIClient *vici_client)
+{
+       unsigned int size = 0;
+       int sock_fd = 0;
+       int res = 0;
+
+       if (req == NULL ||  vici_client == NULL) {
+               connman_error("request is NULL\n");
+               return -EINVAL;
+       }
+       sock_fd = vici_client->client_sock_fd;
+
+       size = htonl(req->used);
+       res = write_socket(sock_fd, (char *)&size, sizeof(size));
+       if (res != 0) {
+               connman_error("failed to send size with network byte order\n");
+               return -EIO;
+       }
+
+       res = write_socket(sock_fd, req->sndbuf, req->used);
+       if (res != 0) {
+               connman_error("failed to send pkt\n");
+               return -EIO;
+       }
+
+       if(req->cmd != VICI_CMD_REGISTER_CHILD_UPDOWN)
+               vici_client->request_list = g_slist_append(vici_client->request_list, req);
+
+       return res;
+}
+
+static void print_vici_element(int elem_type, char *value, int sections)
+{
+       int i = 0;
+
+
+       switch (elem_type) {
+       case VICI_SECTION_START:
+               for (i = 0; i < sections - 1; i++)
+                       DBG("\t");
+               DBG("%s = {\n", value);
+               break;
+       case VICI_SECTION_END:
+               for (i = 0; i < sections; i++)
+                       DBG("\t");
+               DBG("}\n");
+               break;
+       case VICI_KEY_VALUE:
+               for (i = 0; i < sections; i++)
+                       DBG("\t");
+               DBG("%s\n", value);
+               break;
+       case VICI_LIST_START:
+               for (i = 0; i < sections; i++)
+                       DBG("\t");
+               DBG("%s = [", value);
+               break;
+       case VICI_LIST_ITEM:
+               DBG("%s, ", value);
+               break;
+       case VICI_LIST_END:
+               DBG("]\n");
+               break;
+       default:
+               break;
+       }
+       return;
+}
+
+static void debug_vici_message(char *buf, unsigned int size)
+{
+       char temp[255];
+       unsigned int pos = 0;
+       int len = 0;
+       int sections = 0;
+       int type = -1;
+
+       if (buf == NULL || size == 0)
+               return;
+
+       pos = 1;
+       while (pos < size) {
+
+               type = buf[pos];
+               pos++;
+               switch (type) {
+               case VICI_SECTION_START:
+               {
+                       len = buf[pos];
+                       pos++;
+                       g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
+                       pos += len;
+                       sections++;
+               }
+                       break;
+               case VICI_SECTION_END:
+               {
+                       sections--;
+               }
+                       break;
+               case VICI_KEY_VALUE:
+               {
+                       int key_len = 0;
+                       int value_len = 0;
+
+                       key_len = buf[pos];
+                       pos++;
+                       g_strlcpy(temp, (const gchar *)&buf[pos], key_len + 1);
+                       temp[key_len] = '=';
+                       pos += (key_len + 1);
+                       value_len = buf[pos];
+                       pos++;
+                       g_strlcpy(temp + key_len + 1, (const gchar *)&buf[pos], value_len + 1);
+                       pos += value_len;
+               }
+                       break;
+               case VICI_LIST_START:
+               {
+                       len = buf[pos];
+                       pos++;
+                       g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
+                       pos += len;
+               }
+                       break;
+               case VICI_LIST_ITEM:
+               {
+                       pos++;
+                       len = buf[pos];
+                       pos++;
+                       g_strlcpy(temp, (const gchar *)&buf[pos], len + 1);
+                       pos += len;
+               }
+                       break;
+               case VICI_LIST_END:
+                       break;
+               default:
+                       break;
+               }
+               print_vici_element(type, temp, sections);
+       }
+       return;
+}
+
+static unsigned int extract_key_value(char *buf, unsigned int pos, char **key, char **value)
+{
+       int key_len = 0;
+       int value_len = 0;
+
+       key_len = buf[pos];
+       pos++;
+       *key = g_strndup((const gchar *)&buf[pos], key_len);
+       pos+=(key_len + 1);
+       value_len = buf[pos];
+       pos++;
+       *value = g_strndup((const gchar *)&buf[pos], value_len);
+       pos+=value_len;
+       return pos;
+}
+
+static gboolean extract_request_result(char *buf, unsigned int size, char **err)
+{
+       gboolean success = FALSE;
+       unsigned int pos = 0;
+       int type = -1;
+
+       pos = 1;
+       while (pos < size) {
+
+               type = buf[pos];//3
+               pos++;
+               if (type == VICI_KEY_VALUE) {
+                       char *key = NULL;
+                       char *value = NULL;
+                       pos = extract_key_value(buf, pos, &key, &value);
+                       DBG("pos : %d size : %d\n", pos, size);
+
+                       /* TODO :remove this after debug */
+                       DBG("key : %s value : %s\n", key, value);
+                       if (g_strcmp0(key, "success") == 0)
+                               (g_strcmp0(value, "yes") == 0)?(success = TRUE):(success = FALSE);
+
+                       if (g_strcmp0(key, "errmsg"))
+                               *err = g_strdup(value);
+                       g_free(key);
+                       g_free(value);
+               }
+       }
+       return success;
+}
+
+static int handle_vici_result(gboolean success, int cmd, char * err)
+{
+       int ret = 0;
+       if (success)
+               return 0;
+
+       g_free(err);
+
+       switch (cmd) {
+       case    VICI_CMD_LOAD_CONN:
+               ret = EINVAL;
+               break;
+       case    VICI_CMD_LOAD_SHARED:
+               ret = EINVAL;
+               break;
+       case    VICI_CMD_LOAD_CERT:
+               ret = EINVAL;
+               break;
+       case    VICI_CMD_LOAD_AUTH:
+               ret = 0;
+               break;
+       case    VICI_CMD_LOAD_KEY:
+               ret = EINVAL;
+               break;
+       case    VICI_CMD_INITIATE:
+               ret = ECONNABORTED;
+               break;
+       case    VICI_CMD_TERMINATE:
+               ret = EINVAL;
+               break;
+       default:
+               break;
+       }
+
+       DBG(" %s failed with %d!\n", vici_cmd_str[cmd], ret);
+       return ret;
+}
+
+static int process_vici_response(struct request * req)
+{
+       char *err = NULL;
+       gboolean success = FALSE;
+       int ret = 0;
+
+       if (!req)
+               return -1;
+
+       if (!req->rcvbuf || req->rcvbuf[0] != VICI_CMD_RESPONSE)
+               return -1;
+
+       //TODO: remove below when there's no further problem.
+       debug_vici_message(req->rcvbuf, req->rcv_pkt_size);
+
+       success = extract_request_result(req->rcvbuf, req->rcv_pkt_size, &err);
+       ret = handle_vici_result(success, req->cmd, err);
+
+       return ret;
+}
+
+int vici_send_request(VICIClient *vici_client, VICIClientCmd cmd, VICISection *root)
+{
+       struct request *req = NULL;
+       int ret;
+
+       DBG("%s", vici_cmd_str[cmd]);
+       ret = create_vici_request(VICI_CMD_REQUEST, cmd, &req);
+       if (ret < 0) {
+               connman_error("error on create_request\n");
+               return ret;
+       }
+
+       write_section(req, root);
+       //TODO: remove below when there's no further problem.
+       debug_vici_message(req->sndbuf + req->hdr_len - 1, req->used - req->hdr_len + 1);
+
+       ret = send_vici_command(req, vici_client);
+       if (ret < 0) {
+               destroy_vici_request(req);
+               connman_error("error on send_command\n");
+       }
+
+       return ret;
+}
+
+
+int vici_set_event_cb(VICIClient *vici_client, vici_event_cb cb, gpointer user_data)
+{
+       struct request *req = NULL;
+       int ret;
+
+       DBG("%s",vici_cmd_str[VICI_EVENT_CHILD_UP]);
+       ret = create_vici_request(VICI_EVENT_REGISTER, VICI_CMD_REGISTER_CHILD_UPDOWN, &req);
+       if (ret < 0) {
+               connman_error("error on create_request\n");
+               return ret;
+       }
+
+       ret = send_vici_command(req, vici_client);
+       if (ret < 0) {
+               connman_error("error on send_command\n");
+       }
+
+       destroy_vici_request(req);
+       vici_client->event_cb = cb;
+       vici_client->event_user_data = user_data;
+
+       return ret;
+
+}
+
+static int get_socket_from_source(GIOChannel *source, GIOCondition condition)
+{
+       int sock = -1;
+       /* check socket */
+       sock = g_io_channel_unix_get_fd(source);
+       if (sock < SOCK_FD_MIN)
+               return -1;
+
+       if ((condition & G_IO_ERR) || (condition & G_IO_HUP) || (condition & G_IO_NVAL)) {
+               connman_error("G_IO_ERR/G_IO_HUP/G_IO_NVAL received sock [%d] condition [%d]\n", sock, condition);
+               //TODO: handle the breaking socket
+               return -1;
+       }
+       return sock;
+}
+
+static int read_socket(int sock, char *data, unsigned int data_len)
+{
+       int rbytes = 0;
+       int total_rbytes = 0;
+
+       if (sock < SOCK_FD_MIN || !data || data_len <= 0)
+               return -1;
+
+       while (data_len > 0) {
+               errno = 0;
+               rbytes = read(sock, data, data_len);
+               if (rbytes <= 0)
+                       return -1;
+
+               total_rbytes += rbytes;
+               data += rbytes;
+               data_len -= rbytes;
+       }
+
+       return total_rbytes;
+}
+
+static int recv_vici_pkt(int sock, struct _VICIClient *vici_client)
+{
+       if(!vici_client)
+               return -1;
+
+       if (vici_client->rcv_pkt_size == 0) {
+               unsigned int pkt_size = 0;
+               if (read_socket(sock, (char *)&pkt_size, sizeof(pkt_size)) < 0)
+                       return -1;
+
+               vici_client->rcv_pkt_size = ntohl(pkt_size);
+               /* TODO :REMOVE THIS AFTER DEBUG */
+               DBG("rcv_pkt_size [%d] will be recved\n", vici_client->rcv_pkt_size);
+       } else {
+
+               DBG("rcv_pkt_size [%d] is recved\n", vici_client->rcv_pkt_size);
+               char *buf = NULL;
+               buf = g_try_malloc0(vici_client->rcv_pkt_size);
+               if (buf == NULL)
+                       return -1;
+
+               if (read_socket(sock, buf, vici_client->rcv_pkt_size) < 0) {
+                       g_free(buf);
+                       return -1;
+               }
+               vici_client->rcvbuf = buf;
+       }
+
+       return 0;
+}
+
+static struct request *pop_vici_request(VICIClient *vici_client)
+{
+       GSList *list = NULL;
+
+       if (!vici_client)
+               return NULL;
+
+       list = vici_client->request_list;
+       if(!list)
+               return NULL;
+
+       return list->data;
+}
+
+static void process_vici_reply(VICIClient *vici_client)
+{
+       struct request *req;
+       int ret = 0;
+
+       if (!vici_client)
+               return;
+
+       /* get first request */
+       req = pop_vici_request(vici_client);
+       if (!req)
+               return;
+
+       req->rcvbuf = vici_client->rcvbuf;
+       req->rcv_pkt_size = vici_client->rcv_pkt_size;
+
+       ret = process_vici_response(req);
+       vici_client->request_list = g_slist_remove(vici_client->request_list, req);
+       destroy_vici_request(req);
+
+       /* TODO :remove this after debug */
+       DBG("left request reply : %d", g_slist_length(vici_client->request_list));
+
+       if (ret != 0 || g_slist_length(vici_client->request_list) == 0)
+               vici_client->reply_cb(ret, vici_client->reply_user_data);
+
+}
+
+static int extract_event_name(char *buf, unsigned int size, char *temp)
+{
+       int pos = 1;
+       int name_len = 0;
+       name_len = buf[pos];
+       pos++;
+       DBG("event len: %d", name_len);
+       while(pos <  size && pos - 2 < name_len) {
+               temp[pos - 2] = buf[pos];
+               pos++;
+       }
+       temp[pos] = '\0';
+       DBG("event name: %s", temp);
+       return pos;
+}
+
+static char *vici_get_value(char *buf, unsigned int pos, unsigned int size, char *search_key)
+{
+       int type = -1;
+
+       pos = 1;
+       while (pos < size) {
+
+               type = buf[pos];//3
+               pos++;
+               if (type == VICI_KEY_VALUE) {
+                       char *key = NULL;
+                       char *value = NULL;
+                       pos = extract_key_value(buf, pos, &key, &value);
+                       if (g_strcmp0(search_key, key) == 0) {
+                               g_free(key);
+                               return value;
+                       }
+
+                       g_free(key);
+                       g_free(value);
+               }
+       }
+       return NULL;
+}
+
+static void process_child_updown(VICIClient *vici_client,char *buf, unsigned int size)
+{
+       char *state = NULL;
+
+       state = vici_get_value(buf, 0, size, "state");
+       if (g_strcmp0(state, "ESTABLISHED") == 0) {
+               DBG("ESTABLISHED");
+               vici_client->event_cb(VICI_EVENT_CHILD_UP, vici_client->event_user_data);
+       } else if (g_strcmp0(state, "DELETING") == 0) {
+               DBG("DELETING");
+               vici_client->event_cb(VICI_EVENT_CHILD_DOWN, vici_client->event_user_data);
+       } else {
+               DBG("Unknown event");
+       }
+       g_free(state);
+       return;
+}
+
+static void process_vici_event(VICIClient *vici_client)
+{
+       char *buf = NULL;
+       unsigned int size = 0;
+       unsigned int pos = 0;
+       char temp[256] = {0,};
+       if (!vici_client || !(vici_client->rcvbuf) || vici_client->rcv_pkt_size == 0)
+               return;
+
+       buf = vici_client->rcvbuf;
+       size = vici_client->rcv_pkt_size;
+
+       pos = extract_event_name(buf, size, temp);
+       /* TODO: remove below after debug */
+       /* add parser */
+       if (g_strcmp0(temp, "child-updown") == 0)
+               process_child_updown(vici_client, buf + pos -1, size - pos);
+}
+
+static void process_vici_packet(VICIClient *vici_client, char *buf)
+{
+
+       if (!vici_client || !buf)
+               return;
+
+       if (buf[0] == VICI_CMD_RESPONSE) {
+               DBG("VICI_CMD_RESPONSE\n");
+               process_vici_reply(vici_client);
+       } else if (buf[0] == VICI_EVENT_CONFIRM) {
+               DBG("VICI_EVENT_CONFIRM\n");
+       } else if (buf[0] == VICI_EVENT) {
+               DBG("VICI_EVENT");
+               process_vici_event(vici_client);
+       } else {
+               DBG("Not handled [%u]", buf[0]);
+       }
+       return;
+}
+
+static gboolean process_vici_msg(GIOChannel *source,
+                                          GIOCondition condition,
+                                          gpointer user_data)
+{
+       VICIClient *vici_client = NULL;
+       int sock = 0;
+
+       vici_client = (VICIClient *)user_data;
+       if (!vici_client)
+               return FALSE;
+
+       sock = get_socket_from_source(source, condition);
+       if (sock < 0)
+               return FALSE;
+
+
+       if(recv_vici_pkt(sock, vici_client) < 0)
+               return FALSE;
+
+       if (!vici_client->rcvbuf) {
+               return TRUE;
+       }
+
+       process_vici_packet(vici_client, vici_client->rcvbuf);
+       g_free(vici_client->rcvbuf);
+       vici_client->rcvbuf = NULL;
+       vici_client->rcv_pkt_size = 0;
+
+       return TRUE;
+}
+
+static int str_to_socket_addr(const char *uri, struct sockaddr_un *addr)
+{
+       memset(addr, 0, sizeof(*addr));
+       addr->sun_family = AF_UNIX;
+       strncpy(addr->sun_path, uri, sizeof(addr->sun_path));
+
+       addr->sun_path[sizeof(addr->sun_path)-1] = '\0';
+
+       return offsetof(struct sockaddr_un, sun_path) + strlen(addr->sun_path);
+}
+
+static int connect_socket(const char *uri)
+{
+       struct sockaddr_un addr;
+       int len, fd;
+
+       fd = socket(AF_UNIX, SOCK_STREAM, 0);
+       if (fd < 0) {
+               connman_error("socket() failed");
+               return -errno;
+       }
+
+       len = str_to_socket_addr(uri, &addr);
+       if (len == -1) {
+               connman_error("str_to_socket_addr failed");
+               close(fd);
+               return -1;
+       }
+
+       if (connect(fd, (struct sockaddr*)&addr, len) < 0) {
+               connman_error("connect failed. errno %d/%s", errno, strerror(errno));
+               close(fd);
+               return -errno;
+       }
+
+       return fd;
+}
+
+static int initialize_vici_source(VICIClient *vici_client)
+{
+       GIOChannel *vici_channel;
+       if (!vici_client) {
+               return -ENOMEM;
+       }
+
+       vici_client->client_sock_fd = connect_socket(VICI_DEFAULT_URI);
+       if (vici_client->client_sock_fd < 0) {
+               connman_error("connect_socket failed");
+               return -EIO;
+       }
+
+       vici_channel = g_io_channel_unix_new(vici_client->client_sock_fd);
+       if (!vici_channel) {
+               connman_error("g_io_channel_unix_new failed");
+               close(vici_client->client_sock_fd);
+               return -ENOMEM;
+       }
+
+       vici_client->client_watch = g_io_add_watch_full(vici_channel,
+                                                G_PRIORITY_LOW,
+                                                G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+                                                (GIOFunc)process_vici_msg,
+                                                (gpointer)vici_client,
+                                                NULL);
+       g_io_channel_unref(vici_channel);
+       return 0;
+}
+
+int vici_initialize(VICIClient **vici_client)
+{
+       int ret = 0;
+
+       *vici_client = g_try_new0(VICIClient, 1);
+       if (!*vici_client) {
+               connman_error("out of memory");
+               return -ENOMEM;
+       }
+
+       ret = initialize_vici_source(*vici_client);
+       if (ret != 0) {
+               g_free(*vici_client);
+               return ret;
+       }
+
+       DBG("connected");
+       return 0;
+}
+
+void vici_set_request_reply_cb(VICIClient *vici_client, vici_request_reply_cb reply_cb, gpointer user_data)
+{
+       vici_client->reply_cb = reply_cb;
+       vici_client->reply_user_data = user_data;
+}
+
+int vici_deinitialize(VICIClient *vici_client)
+{
+       if (vici_client->client_watch > 0) {
+               g_source_remove(vici_client->client_watch);
+               vici_client->client_watch = 0;
+       }
+
+       close(vici_client->client_sock_fd);
+       g_slist_free_full(vici_client->request_list, destroy_vici_request);
+       g_free(vici_client->rcvbuf);
+       g_free(vici_client);
+
+       return 0;
+}
diff --git a/vpn/plugins/vici-client.h b/vpn/plugins/vici-client.h
new file mode 100644 (file)
index 0000000..a33a8e4
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ *
+ *  ConnMan VPN daemon
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License version 2 as
+ *  published by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __VICI_CLIENT_H
+#define __VICI_CLIENT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* strongswan VICI plugin client part*/
+struct _VICIClient;
+typedef struct _VICIClient VICIClient;
+
+struct _VICISection;
+typedef struct _VICISection VICISection;
+
+typedef enum {
+       VICI_CMD_LOAD_CONN,
+       VICI_CMD_LOAD_SHARED,
+       VICI_CMD_LOAD_CERT,
+       VICI_CMD_LOAD_AUTH,
+       VICI_CMD_UNLOAD_AUTH,
+       VICI_CMD_LOAD_KEY,
+       VICI_CMD_INITIATE,
+       VICI_CMD_TERMINATE,
+       VICI_CMD_REGISTER_CHILD_UPDOWN,
+       VICI_CMD_MAX,
+} VICIClientCmd;
+
+typedef enum {
+       VICI_EVENT_CHILD_UP,
+       VICI_EVENT_CHILD_DOWN,
+       VICI_EVENT_MAX,
+} VICIClientEvent;
+#define VICI_DEFAULT_URI "/var/run/charon.vici"
+
+typedef int (*vici_add_element)(VICISection *sect, const char *key,
+               const char *value, const char *subsection);
+
+typedef void (*vici_request_reply_cb)(int err, void *user_data);
+typedef void (*vici_event_cb)(VICIClientEvent event, void *user_data);
+
+VICISection* vici_create_section(const char *name);
+int add_subsection(const char* name, VICISection* child, VICISection* section);
+void vici_destroy_section(VICISection *sect);
+int vici_add_kv(VICISection *sect, const char *key,
+               const char *value, const char *subsection);
+int vici_add_kvl(VICISection *sect, const char *key,
+               const char *value, const char *subsection);
+int vici_add_list(VICISection* section, char *key,
+               GSList *list, const char* subsection);
+int vici_add_cert_kv(VICISection *section, const char *key,
+               const char *value, const char *subsection);
+int vici_add_cert_kvl(VICISection *section, const char *key,
+               const char *value, const char *subsection);
+
+int vici_initialize(VICIClient **vici_client);
+int vici_deinitialize(VICIClient *vici_client);
+void vici_set_request_reply_cb(VICIClient *vici_client, vici_request_reply_cb reply_cb, gpointer user_data);
+int vici_send_request(VICIClient *vici_client, VICIClientCmd cmd, VICISection *root);
+int vici_set_event_cb(VICIClient *vici_client, vici_event_cb cb, gpointer user_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __VICI_CLIENT_H */
old mode 100644 (file)
new mode 100755 (executable)
index cb0d304..b89c222
@@ -349,6 +349,56 @@ static DBusMessage *vpn_notify(struct connman_task *task,
        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);
@@ -632,6 +682,11 @@ static int vpn_connect(struct vpn_provider *provider,
                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);
old mode 100644 (file)
new mode 100755 (executable)
index fd10add..7956ffa
@@ -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,
old mode 100644 (file)
new mode 100755 (executable)
index 0365894..6ec18eb 100644 (file)
@@ -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;
@@ -57,6 +60,9 @@ struct wireguard_info {
        char *endpoint_fqdn;
        char *port;
        int reresolve_id;
+#if defined TIZEN_EXT
+       int allowed_ip_route_id;
+#endif /* TIZEN_EXT */
 };
 
 struct sockaddr_u {
@@ -94,14 +100,49 @@ static int parse_allowed_ips(const char *allowed_ips, wg_peer *peer)
        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));
 
@@ -112,7 +153,11 @@ static int parse_allowed_ips(const char *allowed_ips, wg_peer *peer)
                        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;
@@ -126,6 +171,9 @@ static int parse_allowed_ips(const char *allowed_ips, wg_peer *peer)
                        curaip->next_allowedip = allowedip;
 
                curaip = allowedip;
+#if defined TIZEN_EXT
+               g_strfreev(toks);
+#endif
        }
 
        peer->last_allowedip = curaip;
@@ -271,6 +319,143 @@ static bool sockaddr_cmp_addr(struct sockaddr_u *a, struct sockaddr_u *b)
        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;
@@ -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,
@@ -450,6 +653,11 @@ static void wg_disconnect(struct vpn_provider *provider)
        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);
 
@@ -462,10 +670,114 @@ static void wg_disconnect(struct vpn_provider *provider)
        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)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 8c6b068..e412b89
@@ -203,7 +203,11 @@ static int load_provider(GKeyFile *keyfile, const char *group,
                                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 */
@@ -229,8 +233,14 @@ static int load_provider(GKeyFile *keyfile, const char *group,
 
        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);
@@ -252,7 +262,11 @@ static int load_provider(GKeyFile *keyfile, const char *group,
 
                DBG("provider identifier %s", id);
        } else {
+#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;
        }
old mode 100644 (file)
new mode 100755 (executable)
index 0f0c8da..db3d49e
@@ -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>
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index a1dc617..237d21b
@@ -5,6 +5,10 @@
         <allow own="net.connman.vpn"/>
         <allow send_interface="net.connman.vpn.Agent"/>
     </policy>
+    <policy user="network_fw">
+        <allow own="net.connman.vpn"/>
+        <allow send_interface="net.connman.vpn.Agent"/>
+    </policy>
     <policy context="default">
         <allow send_destination="net.connman.vpn"/>
     </policy>
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 59c805c..8092b5d
@@ -2194,6 +2194,7 @@ static void provider_create_all_from_type(const char *provider_type)
        g_strfreev(providers);
 }
 
+#if !defined TIZEN_EXT
 char *__vpn_provider_create_identifier(const char *host, const char *domain)
 {
        char *ident;
@@ -2207,6 +2208,23 @@ char *__vpn_provider_create_identifier(const char *host, const char *domain)
 
        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)
 {
@@ -2266,7 +2284,11 @@ int __vpn_provider_create(DBusMessage *msg)
        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);
@@ -2456,7 +2478,11 @@ int __vpn_provider_create_from_config(GHashTable *settings,
                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);
@@ -2528,7 +2554,11 @@ static void append_connection_structs(DBusMessageIter *iter, void *user_data)
        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;
@@ -2786,6 +2816,10 @@ void vpn_provider_set_data(struct vpn_provider *provider, void *data)
 
 void *vpn_provider_get_plugin_data(struct vpn_provider *provider)
 {
+#if defined TIZEN_EXT
+       if (!provider)
+               return NULL;
+#endif
        return provider->plugin_data;
 }
 
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 477cb22..94cee25
--- a/vpn/vpn.h
+++ b/vpn/vpn.h
@@ -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,
old mode 100644 (file)
new mode 100755 (executable)