--- /dev/null
+ 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!
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 \
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
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 =
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) \
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
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
endif
endif
-AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ \
+AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @LIBSYSTEMD_CFLAGS@ @DLOG_CFLAGS@ \
@GNUTLS_CFLAGS@ $(builtin_cflags) \
-DCONNMAN_PLUGIN_BUILTIN \
-DSTATEDIR=\""$(statedir)"\" \
-DSCRIPTDIR=\""$(build_scriptdir)"\" \
-DSTORAGEDIR=\""$(storagedir)\"" \
-DVPN_STORAGEDIR=\""$(vpn_storagedir)\"" \
- -DCONFIGDIR=\""$(configdir)\""
+ -DCONFIGDIR=\""$(configdir)\"" \
+ -fPIE
if VPN
AM_CPPFLAGS = -I$(builddir)/include -I$(srcdir)/gdbus
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)"\" \
$(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)"\" \
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 =
client/vpnconnections.h client/vpnconnections.c \
client/main.c
-client_connmanctl_LDADD = gdbus/libgdbus-internal.la @DBUS_LIBS@ @GLIB_LIBS@ \
- -lreadline -ldl
+if TIZEN_EXT_WIFI_MESH
+client_connmanctl_SOURCES += client/mesh.c client/mesh.h
+endif
+
+if TIZEN_EXT_INS
+client_connmanctl_SOURCES += client/ins.c client/ins.h
+endif
+
+client_connmanctl_LDADD = gdbus/libgdbus-internal.la @DBUS_LIBS@ @GLIB_LIBS@ @DLOG_LIBS@ \
+ -lreadline -ldl -lncurses
endif
noinst_PROGRAMS += unit/test-ippool
unit_test_ippool_SOURCES = $(backtrace_sources) src/log.c src/dbus.c \
src/error.c src/ippool.c unit/test-ippool.c
unit_test_ippool_LDADD = gdbus/libgdbus-internal.la \
- @GLIB_LIBS@ @DBUS_LIBS@ -ldl
+ @GLIB_LIBS@ @DBUS_LIBS@ @DLOG_LIBS@ -ldl
TESTS = unit/test-ippool
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
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 \
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
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)
--enable-hh2serial-gps \
--enable-openconnect \
--enable-openvpn \
+ --enable-ipsec \
--enable-vpnc \
--enable-session-policy-local \
--enable-nmcompat \
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
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
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
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
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
#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;
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)
{
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;
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;
{ 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>] [...]"},
{ 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)
{
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)
{
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) {
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 {
{ "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,
"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,
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;
}
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)
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);
__connmanctl_monitor_completions(NULL);
rl_callback_handler_remove();
+#if !defined TIZEN_EXT
rl_message("");
+#endif
}
dbus_connection_unref(connection);
--- /dev/null
+/*
+ *
+ * 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);
+ }
+
+}
--- /dev/null
+/*
+ *
+ * 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 */
--- /dev/null
+/*
+ *
+ * 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");
+}
--- /dev/null
+/*
+ *
+ * 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 */
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}])
[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
[enable_openvpn=${enableval}], [enable_openvpn="no"])
if (test "${enable_openvpn}" != "no"); then
if (test -z "${path_openvpn}"); then
- AC_PATH_PROG(OPENVPN, [openvpn], [], $PATH:/sbin:/usr/sbin)
+ AC_PATH_PROG(OPENVPN, [openvpn], [/usr/bin/openvpn], $PATH:/bin:/usr/bin)
if (test -z "${OPENVPN}"); then
AC_MSG_ERROR(openvpn binary not found)
fi
AM_CONDITIONAL(OPENVPN, test "${enable_openvpn}" != "no")
AM_CONDITIONAL(OPENVPN_BUILTIN, test "${enable_openvpn}" = "builtin")
+AC_ARG_WITH(ipsec, AC_HELP_STRING([--with-ipsec=PROGRAM],
+ [specify location of ipsec binary]), [path_ipsec=${withval}])
+
+AC_ARG_ENABLE(ipsec,
+ AC_HELP_STRING([--enable-ipsec], [enable ipsec support]),
+ [enable_ipsec=${enableval}], [enable_ipsec="no"])
+if (test "${enable_ipsec}" != "no"); then
+ PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.28, dummy=yes,
+ AC_MSG_ERROR(GIO >= 2.28 is required))
+ AC_SUBST(GIO_CFLAGS)
+ AC_SUBST(GIO_LIBS)
+ if (test -z "${path_ipsec}"); then
+ AC_PATH_PROG(IPSEC, [charon], [/usr/bin/charon], $PATH:/usr/bin)
+ if (test -z "${IPSEC}"); then
+ AC_MSG_ERROR(ipsec binary not found)
+ fi
+ else
+ IPSEC="${path_ipsec}"
+ AC_SUBST(IPSEC)
+ fi
+fi
+AM_CONDITIONAL(IPSEC, test "${enable_ipsec}" != "no")
+AM_CONDITIONAL(IPSEC_BUILTIN, test "${enable_ipsec}" = "builtin")
+
AC_ARG_WITH(vpnc, AC_HELP_STRING([--with-vpnc=PROGRAM],
[specify location of vpnc binary]), [path_vpnc=${withval}])
[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
[enable_l2tp=${enableval}], [enable_l2tp="no"])
if (test "${enable_l2tp}" != "no"); then
if (test -z "${path_pppd}"); then
- AC_PATH_PROG(PPPD, [pppd], [/usr/sbin/pppd], $PATH:/sbin:/usr/sbin)
+ AC_PATH_PROG(PPPD, [pppd], [/usr/bin/pppd], $PATH:/bin:/usr/bin)
else
PPPD="${path_pppd}"
AC_SUBST(PPPD)
AC_CHECK_HEADERS(pppd/pppd.h, dummy=yes,
AC_MSG_ERROR(ppp header files are required))
if (test -z "${path_l2tp}"); then
- AC_PATH_PROG(L2TP, [xl2tpd], [/usr/sbin/xl2tpd], $PATH:/sbin:/usr/sbin)
+ AC_PATH_PROG(L2TP, [xl2tpd], [/usr/bin/xl2tpd], $PATH:/bin:/usr/bin)
else
L2TP="${path_l2tp}"
AC_SUBST(L2TP)
[enable_pptp=${enableval}], [enable_pptp="no"])
if (test "${enable_pptp}" != "no"); then
if (test -z "${path_pppd}"); then
- AC_PATH_PROG(PPPD, [pppd], [/usr/sbin/pppd], $PATH:/sbin:/usr/sbin)
+ AC_PATH_PROG(PPPD, [pppd], [/usr/bin/pppd], $PATH:/bin:/usr/bin)
else
PPPD="${path_pppd}"
AC_SUBST(PPPD)
AC_CHECK_HEADERS(pppd/pppd.h, dummy=yes,
AC_MSG_ERROR(ppp header files are required))
if (test -z "${path_pptp}"); then
- AC_PATH_PROG(PPTP, [pptp], [/usr/sbin/pptp], $PATH:/sbin:/usr/sbin)
+ AC_PATH_PROG(PPTP, [pptp], [/usr/bin/pptp], $PATH:/bin:/usr/bin)
else
PPTP="${path_pptp}"
AC_SUBST(PPTP)
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
[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}])
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
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],
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 \
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)
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
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}
.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
.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
.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)
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
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;
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,
return TRUE;
}
+#endif
struct method_call_data {
GDBusReturnFunction function;
parse_managed_objects(client, reply);
done:
+#if !defined TIZEN_EXT
if (client->ready)
client->ready(client, client->ready_data);
+#endif
dbus_message_unref(reply);
return TRUE;
}
+#if !defined TIZEN_EXT
gboolean g_dbus_client_set_ready_watch(GDBusClient *client,
GDBusClientFunction ready, void *user_data)
{
return TRUE;
}
+#endif
gboolean g_dbus_client_set_proxy_handlers(GDBusClient *client,
GDBusProxyFunction proxy_added,
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);
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);
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,
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;
#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,
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, ...)
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)
{
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);
if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
dhcp_client->listener_watch = 0;
+#if defined TIZEN_EXT
+ /* re-register event listener when socket failed */
+ int retry_count = 0;
+ int ret = -1;
+ while (retry_count++ < GIO_SOCKET_RETRY_COUNT && ret < 0)
+ ret = switch_listening_mode(dhcp_client,
+ dhcp_client->type);
+#endif /* defined TIZEN_EXT */
return FALSE;
}
dhcp_client->lease_seconds = get_lease(&packet, pkt_len);
+#if defined TIZEN_EXT
+ dhcp_client->dhcp_lease_seconds = dhcp_client->lease_seconds;
+#endif
+
get_request(dhcp_client, &packet, pkt_len);
switch_listening_mode(dhcp_client, L_NONE);
remove_timeouts(dhcp_client);
+#if defined TIZEN_EXT
+ if (dhcp_client->init_reboot) {
+ g_dhcp_client_set_address_known(dhcp_client, FALSE);
+ dhcp_client->timeout = g_idle_add_full(
+ G_PRIORITY_HIGH,
+ restart_dhcp_timeout,
+ dhcp_client,
+ NULL);
+
+ break;
+ }
+#endif
dhcp_client->timeout = g_timeout_add_seconds_full(
G_PRIORITY_HIGH, 3,
restart_dhcp_timeout,
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);
uint64_t rand;
ClientState oldstate = dhcp_client->state;
+#if defined TIZEN_EXT
+ int discover_retry = 0;
+ int timeout = 0;
+#endif
+
remove_timeouts(dhcp_client);
if (dhcp_client->type == G_DHCP_IPV6) {
return 0;
}
+#if defined TIZEN_EXT
+ if (g_ascii_strncasecmp(dhcp_client->interface, "wlan", 4)
+ == 0) {
+ discover_retry = DISCOVER_RETRIES_WIFI;
+ timeout = DISCOVER_TIMEOUT_WIFI;
+ } else {
+ discover_retry = DISCOVER_RETRIES;
+ timeout = DISCOVER_TIMEOUT;
+ }
+
+ debug(dhcp_client, "[DHCPC] Discover retry/total : [%d]/[%d] timeout [%d]",
+ dhcp_client->retry_times, discover_retry, timeout);
+#endif
+
+
if (dhcp_client->type == G_DHCP_IPV4LL) {
dhcp_client->state = INIT_SELECTING;
ipv4ll_start(dhcp_client);
return 0;
}
+#if defined TIZEN_EXT
+ if (dhcp_client->retry_times == discover_retry) {
+#else
if (dhcp_client->retry_times == DISCOVER_RETRIES) {
+#endif
if (dhcp_client->no_lease_cb)
dhcp_client->no_lease_cb(dhcp_client,
dhcp_client->no_lease_data);
dhcp_client->timeout = g_timeout_add_seconds_full(
G_PRIORITY_HIGH,
+#if defined TIZEN_EXT
+ timeout,
+#else
REQUEST_TIMEOUT,
+#endif
reboot_timeout,
dhcp_client,
NULL);
send_discover(dhcp_client, addr);
dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH,
+#if defined TIZEN_EXT
+ timeout,
+#else
DISCOVER_TIMEOUT,
+#endif
discover_timeout,
dhcp_client,
NULL);
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);
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,
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
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,
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
--- /dev/null
+/*
+ *
+ * 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_ */
#include <glib.h>
#include "dbus.h"
+#include <connman/log.h>
#define TIMEOUT 30000
#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)
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,
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;
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;
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,
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,
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);
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);
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;
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);
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,
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
#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;
{ "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
{ }
};
{ "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;
GSupplicantSecurity security;
char * passphrase;
char * private_passphrase;
+#if defined TIZEN_EXT
+ char *connector;
+ char *c_sign_key;
+ char *net_access_key;
+#endif
};
+#if defined TIZEN_EXT_WIFI_MESH
+struct _GSupplicantMeshGroupInfo {
+ unsigned char ssid[32];
+ unsigned int ssid_len;
+ int disconnect_reason;
+};
+#endif
+
struct _GSupplicantInterface {
char *path;
char *network_path;
const char *pending_peer_path;
GSupplicantNetwork *current_network;
struct added_network_information network_info;
+#if defined TIZEN_EXT
+ dbus_bool_t is_5_0_Ghz_supported;
+ int disconnect_reason;
+#endif
+#if defined TIZEN_EXT
+ unsigned char add_network_bssid[WIFI_BSSID_LEN_MAX];
+ unsigned char connected_bssid[WIFI_BSSID_LEN_MAX];
+#endif
+#if defined TIZEN_EXT_WIFI_MESH
+ bool mesh_support;
+ struct _GSupplicantMeshGroupInfo group_info;
+#endif
};
struct g_supplicant_bss {
dbus_bool_t privacy;
dbus_bool_t psk;
dbus_bool_t ieee8021x;
+#if defined TIZEN_EXT
+ dbus_bool_t ft_psk;
+ dbus_bool_t ft_ieee8021x;
+ GSList *vsie_list;
+ dbus_bool_t hs20;
+ unsigned char country_code[COUNTRY_CODE_LENGTH];
+ GSupplicantPhy_mode phy_mode;
+ dbus_int16_t snr;
+ dbus_uint32_t est_throughput;
+#endif
unsigned int wps_capabilities;
+#if defined TIZEN_EXT
+ dbus_bool_t sae;
+ dbus_bool_t owe;
+ dbus_bool_t dpp;
+ dbus_bool_t owe_transition_mode;
+ unsigned int transition_mode_ssid_len;
+ unsigned char transition_mode_bssid[6];
+ unsigned char transition_mode_ssid[32];
+ dbus_bool_t pmf_required;
+#endif
};
struct _GSupplicantNetwork {
unsigned int wps_capabilities;
GHashTable *bss_table;
GHashTable *config_table;
+#if defined TIZEN_EXT
+ bool isHS20AP;
+ char *eap;
+ char *identity;
+ char *phase2;
+ unsigned int keymgmt;
+ GSList *vsie_list;
+ unsigned char country_code[COUNTRY_CODE_LENGTH];
+ GSupplicantPhy_mode phy_mode;
+ dbus_bool_t owe_transition_mode;
+ dbus_bool_t privacy;
+ unsigned int transition_mode_ssid_len;
+ unsigned char transition_mode_bssid[6];
+ unsigned char transition_mode_ssid[32];
+ unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
+ GHashTable *assoc_reject_table;
+#endif
};
struct _GSupplicantPeer {
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;
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];
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;
}
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;
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;
static bool compare_network_parameters(GSupplicantInterface *interface,
GSupplicantSSID *ssid)
{
+#if defined TIZEN_EXT
+ if (!interface->network_info.ssid)
+ return FALSE;
+#endif
+
if (memcmp(interface->network_info.ssid, ssid->ssid, ssid->ssid_len))
return FALSE;
return FALSE;
}
+#if defined TIZEN_EXT
+ if (interface->network_info.connector &&
+ g_strcmp0(interface->network_info.connector,
+ ssid->connector) != 0) {
+ return FALSE;
+ }
+ if (interface->network_info.c_sign_key &&
+ g_strcmp0(interface->network_info.c_sign_key,
+ ssid->c_sign_key) != 0) {
+ return FALSE;
+ }
+ if (interface->network_info.net_access_key &&
+ g_strcmp0(interface->network_info.net_access_key,
+ ssid->net_access_key) != 0) {
+ return FALSE;
+ }
+#endif
return TRUE;
}
g_free(interface->network_info.ssid);
g_free(interface->network_info.passphrase);
g_free(interface->network_info.private_passphrase);
+#if defined TIZEN_EXT
+ g_free(interface->network_info.connector);
+ g_free(interface->network_info.c_sign_key);
+ g_free(interface->network_info.net_access_key);
+#endif
interface->network_info.ssid = NULL;
interface->network_info.passphrase = NULL;
interface->network_info.private_passphrase = NULL;
+#if defined TIZEN_EXT
+ interface->network_info.connector = NULL;
+ interface->network_info.c_sign_key = NULL;
+ interface->network_info.net_access_key = NULL;
+#endif
}
static int store_network_information(GSupplicantInterface * interface,
if ((ssid->security == G_SUPPLICANT_SECURITY_WEP ||
ssid->security == G_SUPPLICANT_SECURITY_PSK ||
+#if defined TIZEN_EXT
+ ssid->security == G_SUPPLICANT_SECURITY_SAE ||
+#endif
ssid->security == G_SUPPLICANT_SECURITY_NONE) &&
ssid->passphrase) {
interface->network_info.passphrase = g_strdup(ssid->passphrase);
callbacks_pointer->interface_removed(interface);
}
+#if !defined TIZEN_EXT
static void callback_p2p_support(GSupplicantInterface *interface)
{
SUPPLICANT_DBG("");
if (callbacks_pointer && callbacks_pointer->p2p_support)
callbacks_pointer->p2p_support(interface);
}
+#endif
+
+#if defined TIZEN_EXT_WIFI_MESH
+static void callback_mesh_support(GSupplicantInterface *interface)
+{
+ SUPPLICANT_DBG("");
+
+ if (!interface->mesh_support)
+ return;
+
+ if (callbacks_pointer && callbacks_pointer->mesh_support)
+ callbacks_pointer->mesh_support(interface);
+}
+
+bool g_supplicant_interface_has_mesh(GSupplicantInterface *interface)
+{
+ if (!interface)
+ return false;
+
+ return interface->mesh_support;
+}
+#endif
static void callback_scan_started(GSupplicantInterface *interface)
{
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)
{
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)
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);
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);
}
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);
}
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);
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));
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)
if (!interface)
return 0;
+ if (interface->max_scan_ssids == 0)
+ return WPAS_MAX_SCAN_SSIDS;
+
return interface->max_scan_ssids;
}
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)
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)
{
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;
}
return g_string_free(str, FALSE);
}
+#if defined TIZEN_EXT
+static void update_network_with_best_bss(GSupplicantNetwork *network,
+ struct g_supplicant_bss *best_bss)
+{
+ /*
+ * Do not change best BSS if we are connected.
+ */
+ if (network->interface->state == G_SUPPLICANT_STATE_COMPLETED)
+ return;
+
+ network->signal = best_bss->signal;
+ network->frequency = best_bss->frequency;
+ network->best_bss = best_bss;
+}
+
+static bool update_best_bss(GSupplicantNetwork *network,
+ struct g_supplicant_bss *bss, struct g_supplicant_bss *best_bss)
+{
+ int score_new;
+ int score_best;
+
+ if (network->best_bss == NULL) {
+ update_network_with_best_bss(network, bss);
+ return true;
+ }
+#if defined TIZEN_EXT_INS
+ score_new = calculate_score(
+ compare_bssid(bss->bssid, network->last_connected_bssid),
+ get_assoc_reject_cnt(network->assoc_reject_table, bss->bssid),
+ bss->frequency, bss->signal, bss->snr, bss->est_throughput);
+
+ score_best = calculate_score(
+ compare_bssid(network->best_bss->bssid, network->last_connected_bssid),
+ get_assoc_reject_cnt(network->assoc_reject_table, network->best_bss->bssid),
+ network->best_bss->frequency, network->best_bss->signal,
+ network->best_bss->snr, network->best_bss->est_throughput);
+#else
+ score_new = bss->signal;
+ score_best = network->best_bss->signal;
+#endif
+
+ if (score_new > score_best) {
+ SUPPLICANT_DBG("new[" MACSTR "][%u] : best[" MACSTR "][%u]",
+ MAC2STR(bss->bssid), score_new,
+ MAC2STR(network->best_bss->bssid), score_best);
+
+ update_network_with_best_bss(network, bss);
+
+ SUPPLICANT_DBG("Update best BSS for %s", network->name);
+
+ return true;
+ }
+
+ return false;
+}
+#endif
static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss)
{
GSupplicantInterface *interface = bss->interface;
network->wps_capabilities = bss->wps_capabilities;
}
+#if defined TIZEN_EXT
+ network->owe_transition_mode = bss->owe_transition_mode;
+ network->privacy = bss->privacy;
+ memcpy(network->transition_mode_ssid, bss->transition_mode_ssid, bss->transition_mode_ssid_len);
+ memcpy(network->transition_mode_bssid, bss->transition_mode_bssid, WIFI_BSSID_LEN_MAX);
+
+ network->keymgmt = bss->keymgmt;
+
+ if (g_slist_length(bss->vsie_list) > 0) {
+ GSList *list = NULL;
+ unsigned char *vsie = NULL;
+ for (list = bss->vsie_list; list; list = list->next) {
+ unsigned char *ie = (unsigned char *)list->data;
+ vsie = (unsigned char *)g_try_malloc0(ie[1]+2); // tag number size(1), tag length size(1)
+
+ if (vsie) {
+ memcpy(vsie, ie, ie[1]+2);
+ network->vsie_list = g_slist_append(network->vsie_list, vsie);
+ } else
+ SUPPLICANT_DBG("Failed to allocate memory.");
+ }
+ }
+
+ network->isHS20AP = bss->hs20;
+ memcpy(network->country_code, bss->country_code, COUNTRY_CODE_LENGTH);
+ network->phy_mode = bss->phy_mode;
+#endif
+
SUPPLICANT_DBG("New network %s created", network->name);
network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal,
network->config_table = g_hash_table_new_full(g_str_hash, g_str_equal,
g_free, g_free);
+#if defined TIZEN_EXT
+ network->assoc_reject_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+ NULL, remove_assoc_data);
+#endif
+
g_hash_table_replace(interface->network_table,
network->group, network);
* 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);
return 0;
}
+#if defined TIZEN_EXT
+static void get_bss_phy_mode(unsigned int max_rate,
+ unsigned int max_ext_rate, bool ht, bool vht, void *data)
+{
+ struct g_supplicant_bss *bss = data;
+ unsigned int freq = bss->frequency;
+
+ /* Following conditions are used to determine
+ * IEEE 802.11 Protocol Modes:-
+ *
+ * 1. If “Supported rates” is only till 11 Mbps,
+ * and frequency is in 2.4GHz band, then protocol is 11B.
+ * 2. If “Supported rates” is till 54Mbps or
+ * “Extended supported rates” are present,
+ * and frequency is in 2.4GHz band, then protocol is 11G.
+ * 3. If “Supported rates” is only till 54 Mbps,
+ * frequency is in 5GHz band , then protocol is 11A.
+ * 4. If “HT capabilities” is supported , then protocol is 11N.
+ * 5. If “HT capabilities” & “VHT” is supported and
+ * frequency is in 5 GHz band, then protocol is 11AC.
+ * */
+
+ if (freq >= 2412 && freq <= 2484) { /* 2.4 Ghz Band */
+ if (max_rate <= 11 && max_ext_rate <= 0 && !ht)
+ bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211B;
+ else if ((max_rate <= 54 || max_ext_rate > 0) && !ht)
+ bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211BG;
+ else if ((max_rate >= 54 || max_ext_rate > 0) && ht)
+ bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211BGN;
+ else
+ bss->phy_mode = G_SUPPLICANT_MODE_UNKNOWN;
+ } else if (freq >= 5180 && freq <= 5825) { /* 5 Ghz Band */
+ if (max_rate <= 54 && !ht)
+ bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211A;
+ else if ((max_rate >= 54 || max_ext_rate > 0) && ht && !vht)
+ bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211AN;
+ else if ((max_rate >= 54 || max_ext_rate > 0) && ht && vht)
+ bss->phy_mode = G_SUPPLICANT_MODE_IEEE80211ANAC;
+ else
+ bss->phy_mode = G_SUPPLICANT_MODE_UNKNOWN;
+ }
+}
+#endif
+
static void bss_process_ies(DBusMessageIter *iter, void *user_data)
{
struct g_supplicant_bss *bss = user_data;
DBusMessageIter array;
unsigned int value;
int ie_len;
+#if defined TIZEN_EXT
+ const unsigned char OWE_WFA_OUI[] = { 0x50, 0x6f, 0x9a, 0x1c };
+ int r_len, j;
+ unsigned char *rates = NULL;
+ unsigned char *ext_rates = NULL;
+ unsigned int max_rate = 0;
+ unsigned int max_ext_rate = 0;
+ unsigned int offset = 0;
+ bool ht = false;
+ bool vht = false;
+#endif
#define WMM_WPA1_WPS_INFO 221
#define WPS_INFO_MIN_LEN 6
#define WPS_PBC 0x04
#define WPS_PIN 0x00
#define WPS_CONFIGURED 0x02
+#if defined TIZEN_EXT
+#define VENDOR_SPECIFIC_INFO 0xDD
+#define WLAN_EID_COUNTRY 7
+#define WLAN_EID_RSN_INFO 48
+#define RSN_CAPABILITY_MFP_REQ (1 << 6)
+#endif
dbus_message_iter_recurse(iter, &array);
dbus_message_iter_get_fixed_array(&array, &ie, &ie_len);
for (ie_end = ie + ie_len; ie < ie_end && ie + ie[1] + 1 <= ie_end;
ie += ie[1] + 2) {
+#if defined TIZEN_EXT
+ unsigned char *vsie;
+ int vsie_len = 0;
+
+ if (ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, OWE_WFA_OUI, sizeof(OWE_WFA_OUI)) == 0) {
+ SUPPLICANT_DBG("IE: match vendor specific data : OWE Transition Mode");
+
+/*
+ Tag: Vendor Specific: Wi-Fi Alliance: OWE Transition Mode
+ Tag Number: Vendor Specific (221) -> ie[0]
+ Tag length: 26 -> ie[1]
+ OUI: 50:6f:9a (Wi-Fi Alliance) -> ie[2]
+ Vendor Specific OUI Type: 28 -> ie[5]
+ BSSID: 92:fd:f0:20:2b:09 -> ie[6]
+ SSID length: 15 -> ie[12]
+ SSID: Wi-Fi-5.2.3-owe -> ie[13]
+
+0000 dd 1a 50 6f 9a 1c 92 fd f0 20 2b 09 0f 57 69 2d ..Po..... +..Wi-
+0010 46 69 2d 35 2e 32 2e 33 2d 6f 77 65 Fi-5.2.3-owe
+
+*/
+ bss->owe_transition_mode = TRUE;
+ if (ie[1] >= 11) { // Tag length is at least up to ssid length position.
+ memcpy(bss->transition_mode_bssid, ie+6, WIFI_BSSID_LEN_MAX);
+ if (ie[12] > 0 && ie[12] < 32) {
+ memcpy(bss->transition_mode_ssid, ie+13, ie[12]);
+ bss->transition_mode_ssid_len = ie[12];
+ } else
+ bss->transition_mode_ssid_len = 0;
+ } else
+ bss->owe_transition_mode = FALSE;
+ continue;
+ }
+
+ if (ie[0] == VENDOR_SPECIFIC_INFO && memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0) {
+ if (!simplified_log)
+ SUPPLICANT_DBG("IE: match vendor specific data");
+
+ vsie_len = ie[1]+2; // tag number size(1), tag length size(1)
+ vsie = (unsigned char *)g_try_malloc0(vsie_len);
+
+ if (vsie) {
+ memcpy(vsie, ie, vsie_len);
+ bss->vsie_list = g_slist_append(bss->vsie_list, vsie);
+ } else
+ SUPPLICANT_DBG("Failed to allocate memory");
+ continue;
+ }
+
+ if (ie[0] == WLAN_EID_COUNTRY && ie[1] >= 2) {
+ /* Add country code only if it is a valid alphabet */
+ if (ie[2] >= 65 && ie[2] <= 90 && ie[3] >= 65 && ie[3] <= 90) {
+ memcpy(bss->country_code, ie+2, COUNTRY_CODE_LENGTH);
+ continue;
+ }
+ }
+
+ if (ie[0] == WLAN_EID_HT_CAP && ie[1]) {
+ ht = true;
+ continue;
+ }
+
+ if (ie[0] == WLAN_EID_VHT_CAP && ie[1]) {
+ vht = true;
+ continue;
+ }
+
+ if (ie[0] == WLAN_EID_SUPP_RATES && ie[1]) {
+ r_len = ie[1];
+ rates = g_malloc0(r_len);
+ if (!rates)
+ continue;
+
+ for (j = 0; ie && j < r_len; j++) {
+ rates[j] = ((ie[j + 2] & 0x7f) * 500000)/1000000;
+ if (max_rate < rates[j])
+ max_rate = rates[j];
+ }
+ continue;
+ }
+
+ if (ie[0] == WLAN_EID_EXT_SUPP_RATES && ie[1] > 0) {
+ r_len = ie[1];
+ ext_rates = g_malloc0(r_len);
+ if (!ext_rates)
+ continue;
+
+ for (j = 0; ie && j < r_len; j++) {
+ ext_rates[j] = ((ie[j + 2] & 0x7f) * 500000)/1000000;
+ if (max_ext_rate < ext_rates[j])
+ max_ext_rate = ext_rates[j];
+ }
+ continue;
+ }
+
+ if (ie[0] == WLAN_EID_RSN_INFO && ie[1] >= 20) {
+ r_len = ie[1];
+ offset = 10 + ie[8] * 4;
+ offset += ie[offset] * 4 + 2;
+
+ if (offset <= r_len + 1 &&
+ (ie[offset] & RSN_CAPABILITY_MFP_REQ) != 0)
+ bss->pmf_required = TRUE;
+
+ continue;
+ }
+#endif
if (ie[0] != WMM_WPA1_WPS_INFO || ie[1] < WPS_INFO_MIN_LEN ||
memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0)
continue;
SUPPLICANT_DBG("WPS Methods 0x%x", bss->wps_capabilities);
}
+#ifdef TIZEN_EXT
+ get_bss_phy_mode(max_rate, max_ext_rate, ht, vht, user_data);
+ if (rates)
+ g_free(rates);
+ if (ext_rates)
+ g_free(ext_rates);
+#endif
}
static void bss_compute_security(struct g_supplicant_bss *bss)
bss->ieee8021x = FALSE;
bss->psk = FALSE;
+#if defined TIZEN_EXT
+ bss->ft_ieee8021x = FALSE;
+ bss->ft_psk = FALSE;
+#endif
+#if defined TIZEN_EXT
+ if (bss->keymgmt &
+ (G_SUPPLICANT_KEYMGMT_WPA_EAP |
+ G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
+ bss->ieee8021x = TRUE;
+ else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_EAP)
+ bss->ft_ieee8021x = TRUE;
+#else
if (bss->keymgmt &
(G_SUPPLICANT_KEYMGMT_WPA_EAP |
G_SUPPLICANT_KEYMGMT_WPA_FT_EAP |
G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
bss->ieee8021x = TRUE;
+#endif
+#if defined TIZEN_EXT
+ if (bss->keymgmt &
+ (G_SUPPLICANT_KEYMGMT_WPA_PSK |
+ G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
+ bss->psk = TRUE;
+ else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK)
+ bss->ft_psk = TRUE;
+#else
if (bss->keymgmt &
(G_SUPPLICANT_KEYMGMT_WPA_PSK |
G_SUPPLICANT_KEYMGMT_WPA_FT_PSK |
G_SUPPLICANT_KEYMGMT_WPA_PSK_256))
bss->psk = TRUE;
+#endif
+
+#if defined TIZEN_EXT
+ if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_SAE)
+ bss->sae = TRUE;
+ if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_OWE)
+ bss->owe = TRUE;
+ if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_DPP)
+ bss->dpp = TRUE;
+#endif
if (bss->ieee8021x)
bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
+#if defined TIZEN_EXT
+ else if (bss->ft_ieee8021x)
+ bss->security = G_SUPPLICANT_SECURITY_IEEE8021X;
+ else if (bss->sae)
+ bss->security = G_SUPPLICANT_SECURITY_SAE;
+#endif
else if (bss->psk)
bss->security = G_SUPPLICANT_SECURITY_PSK;
+#if defined TIZEN_EXT
+ else if (bss->ft_psk)
+ bss->security = G_SUPPLICANT_SECURITY_FT_PSK;
+ else if (bss->owe || bss->owe_transition_mode)
+ bss->security = G_SUPPLICANT_SECURITY_OWE;
+ else if (bss->dpp)
+ bss->security = G_SUPPLICANT_SECURITY_DPP;
+#endif
else if (bss->privacy)
bss->security = G_SUPPLICANT_SECURITY_WEP;
else
if (!bss->interface)
return;
-
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
SUPPLICANT_DBG("key %s", key);
if (!key)
bss->rsn_selected = FALSE;
supplicant_dbus_property_foreach(iter, bss_wpa, bss);
+#if defined TIZEN_EXT
+ } else if (g_strcmp0(key, "HS20") == 0) {
+ dbus_bool_t hs20 = FALSE;
+ dbus_message_iter_get_basic(iter, &hs20);
+ bss->hs20 = hs20;
+ } else if (g_strcmp0(key, "SNR") == 0) {
+ dbus_int16_t snr = 0;
+
+ dbus_message_iter_get_basic(iter, &snr);
+ bss->snr = snr;
+ } else if (g_strcmp0(key, "EstThroughput") == 0) {
+ dbus_uint32_t est_throughput = 0;
+
+ dbus_message_iter_get_basic(iter, &est_throughput);
+ if (est_throughput != 0)
+ bss->est_throughput = est_throughput;
+#endif
} else if (g_strcmp0(key, "IEs") == 0)
bss_process_ies(iter, bss);
else
GSupplicantNetwork *network;
struct g_supplicant_bss *bss;
const char *path = NULL;
-
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
SUPPLICANT_DBG("");
dbus_message_iter_get_basic(iter, &path);
if (g_strcmp0(path, "/") == 0)
return NULL;
-
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
SUPPLICANT_DBG("%s", path);
network = g_hash_table_lookup(interface->bss_mapping, path);
void *user_data)
{
struct g_supplicant_bss *bss;
-
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
SUPPLICANT_DBG("");
bss = interface_bss_added(iter, user_data);
dbus_message_iter_next(iter);
if (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_INVALID)
+#if defined TIZEN_EXT
+ {
+ g_free(bss->path);
+ g_free(bss);
+ return;
+ }
+#else
return;
+#endif
supplicant_dbus_property_foreach(iter, bss_property, bss);
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);
struct g_supplicant_bss *bss = value;
GSupplicantNetwork *network = user_data;
+#if defined TIZEN_EXT
+ if (!network->best_bss || (network->best_bss == bss)) {
+ if (bss->signal > network->signal) {
+ network->signal = bss->signal;
+ network->best_bss = bss;
+ }
+ return;
+ }
+
+ update_best_bss(network, bss, network->best_bss);
+#else
if (bss->signal > network->signal) {
network->signal = bss->signal;
network->best_bss = bss;
}
+#endif
+}
+
+static void update_network_signal(GSupplicantNetwork *network)
+{
+ if (g_hash_table_size(network->bss_table) <= 1 && network->best_bss)
+ return;
+
+ g_hash_table_foreach(network->bss_table,
+ update_signal, network);
+
+ SUPPLICANT_DBG("New network signal %d", network->signal);
+}
+
+#if defined TIZEN_EXT
+static gboolean last_connected_timeout(gpointer data)
+{
+ GSupplicantInterface *interface = data;
+ GSupplicantNetwork *current_network = interface->current_network;
+
+ SUPPLICANT_DBG("Timeout last connected bss");
+
+ if (current_network && current_network->best_bss) {
+ if (compare_bssid(current_network->best_bss->bssid, interface->connected_bssid)) {
+ g_supplicant_network_set_last_connected_bssid(current_network, interface->connected_bssid);
+ callback_network_changed(current_network, "LastConnectedBSSID");
+ }
+ }
+
+ last_connected_bss_timeout = 0;
+ return FALSE;
+}
+
+static void add_timer_for_last_connected(GSupplicantInterface *interface)
+{
+ GSupplicantNetwork *current_network = interface->current_network;
+
+ if (interface->state == G_SUPPLICANT_STATE_COMPLETED) {
+ if (current_network) {
+ struct g_supplicant_bss *best_bss = current_network->best_bss;
+
+ memcpy(interface->connected_bssid, best_bss->bssid, WIFI_BSSID_LEN_MAX);
+
+ if (last_connected_bss_timeout)
+ g_source_remove(last_connected_bss_timeout);
+
+ last_connected_bss_timeout = g_timeout_add_seconds(LAST_CONNECTED_TIMEOUT,
+ last_connected_timeout, interface);
+
+ SUPPLICANT_DBG("Add timer for last connected bssid [" MACSTR "]",
+ MAC2STR(best_bss->bssid));
+ }
+ }
}
-static void update_network_signal(GSupplicantNetwork *network)
+static void remove_timer_for_last_connected(GSupplicantInterface *interface)
{
- if (g_hash_table_size(network->bss_table) <= 1 && network->best_bss)
- return;
-
- g_hash_table_foreach(network->bss_table,
- update_signal, network);
-
- SUPPLICANT_DBG("New network signal %d", network->signal);
+ if (interface->state == G_SUPPLICANT_STATE_DISCONNECTED) {
+ if (last_connected_bss_timeout != 0) {
+ g_source_remove(last_connected_bss_timeout);
+ last_connected_bss_timeout = 0;
+ SUPPLICANT_DBG("Remove timer for last connected bss");
+ }
+ }
}
+#endif
static void interface_current_bss(GSupplicantInterface *interface,
DBusMessageIter *iter)
return;
interface->current_network = network;
+#if defined TIZEN_EXT
+ SUPPLICANT_DBG("current network [%p]", interface->current_network);
+#endif
if (bss != network->best_bss) {
/*
network->best_bss = bss;
+#if defined TIZEN_EXT
+ if (network->frequency != bss->frequency)
+ network->frequency = bss->frequency;
+#endif
+
if (network->signal != bss->signal) {
SUPPLICANT_DBG("New network signal %d dBm",
bss->signal);
network->signal = bss->signal;
callback_network_changed(network, "Signal");
}
+#if defined TIZEN_EXT
+ else
+ callback_network_changed(network, "");
+#endif
}
/*
case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
case G_SUPPLICANT_STATE_COMPLETED:
callback_network_associated(network);
+#if defined TIZEN_EXT
+ add_timer_for_last_connected(interface);
+#endif
break;
}
}
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
}
}
if (!interface)
return;
-
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
SUPPLICANT_DBG("key: %s", key);
if (g_strcmp0(key, "ConfigMethods") == 0) {
}
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+void g_supplicant_replace_config_file(const char *ifname, const char *config_file)
+{
+ if (!ifname)
+ return;
+
+ if (!config_file)
+ return;
+
+ SUPPLICANT_DBG("New {%s, %s}", ifname, config_file);
+ g_hash_table_replace(config_file_table,
+ g_strdup(ifname), g_strdup(config_file));
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
static void interface_property(const char *key, DBusMessageIter *iter,
void *user_data)
{
if (!interface)
return;
-
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
SUPPLICANT_DBG("%s", key);
if (!key) {
if (g_strcmp0(key, "Capabilities") == 0) {
supplicant_dbus_property_foreach(iter, interface_capability,
interface);
+#if !defined TIZEN_EXT
if (interface->mode_capa & G_SUPPLICANT_CAPABILITY_MODE_P2P)
interface->p2p_support = true;
+#endif
+#if defined TIZEN_EXT_WIFI_MESH
+ if (interface->mode_capa & G_SUPPLICANT_CAPABILITY_MODE_MESH)
+ interface->mesh_support = true;
+#endif
} else if (g_strcmp0(key, "State") == 0) {
const char *str = NULL;
interface->state = string2state(str);
callback_interface_state(interface);
}
-
+#if defined TIZEN_EXT
+ switch (interface->state) {
+ case G_SUPPLICANT_STATE_COMPLETED:
+ add_timer_for_last_connected(interface);
+ break;
+ case G_SUPPLICANT_STATE_DISCONNECTED:
+ remove_timer_for_last_connected(interface);
+ break;
+ default:
+ break;
+ }
+#endif
if (interface->ap_create_in_progress) {
if (interface->state == G_SUPPLICANT_STATE_DISCONNECTED)
callback_ap_create_fail(interface);
} else if (g_strcmp0(key, "CurrentBSS") == 0) {
interface_current_bss(interface, iter);
} else if (g_strcmp0(key, "CurrentNetwork") == 0) {
+#if defined TIZEN_EXT
+ if (interface->state != G_SUPPLICANT_STATE_COMPLETED)
+#endif
interface_network_added(iter, interface);
} else if (g_strcmp0(key, "BSSs") == 0) {
supplicant_dbus_array_foreach(iter,
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
dbus_message_iter_get_basic(iter, &reason_code);
callback_disconnect_reason_code(interface, reason_code);
+#if defined TIZEN_EXT
+ SUPPLICANT_DBG("reason code (%d)", reason_code);
+#endif
}
} else if (g_strcmp0(key, "AssocStatusCode") == 0) {
int status_code;
if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
dbus_message_iter_get_basic(iter, &status_code);
callback_assoc_status_code(interface, status_code);
+#if defined TIZEN_EXT
+ SUPPLICANT_DBG("status code (%d)", status_code);
+#endif
}
} else {
SUPPLICANT_DBG("key %s type %c",
{
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)
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);
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);
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)
{
callback_sta_deauthorized(interface, addr);
}
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+static void signal_eap(const char *path, DBusMessageIter *iter)
+{
+ GSupplicantInterface *interface;
+ const char *str = NULL;
+
+ SUPPLICANT_DBG("EAPOL_DEBUG callback eap signal");
+
+ interface = g_hash_table_lookup(interface_table, path);
+ if (!interface)
+ return;
+
+ // TODO: Identify EAP fail condition, currently timeout is used for failure.
+
+ dbus_message_iter_get_basic(iter, &str);
+ if (!str)
+ return;
+
+ if (g_strcmp0("completion", str))
+ return;
+
+ dbus_message_iter_next(iter);
+
+ dbus_message_iter_get_basic(iter, &str);
+ if (!str)
+ return;
+
+ if (!g_strcmp0("success", str))
+ callback_eap(interface, true);
+ else
+ callback_eap(interface, false);
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
static void signal_bss_changed(const char *path, DBusMessageIter *iter)
{
GSupplicantInterface *interface;
unsigned int old_wps_capabilities;
struct g_supplicant_bss *bss;
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
SUPPLICANT_DBG("");
interface = g_hash_table_lookup(bss_mapping, path);
supplicant_dbus_property_foreach(iter, bss_property, bss);
+#if defined TIZEN_EXT
+ if (network->interface->state != G_SUPPLICANT_STATE_COMPLETED) {
+ network->frequency = bss->frequency;
+ network->phy_mode = bss->phy_mode;
+ }
+#endif
old_security = network->security;
bss_compute_security(bss);
memcpy(new_bss, bss, sizeof(struct g_supplicant_bss));
new_bss->path = g_strdup(bss->path);
+#if defined TIZEN_EXT
+ new_bss->vsie_list = g_slist_copy_deep(bss->vsie_list, copy_vsie_list, NULL);
+#endif
if (network->best_bss == bss) {
network->best_bss = NULL;
callback_network_changed(network, "WPSCapabilities");
}
+#if defined TIZEN_EXT
+ if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) {
+ network->wps = TRUE;
+ network->wps_capabilities |= bss->wps_capabilities;
+ } else
+ network->wps = FALSE;
+#endif
+
/* Consider only property changes of the connected BSS */
if (network == interface->current_network && bss != network->best_bss)
return;
if (bss->signal == network->signal)
+#ifndef TIZEN_EXT
return;
+#else
+ {
+ callback_network_changed(network, "");
+ return;
+ }
+#endif
/*
* If the new signal is lower than the SSID signal, we need
* to check for the new maximum.
*/
+#if defined TIZEN_EXT
+ if (!update_best_bss(network, bss, network->best_bss)) {
+ if (bss != network->best_bss) {
+ callback_network_changed(network, "");
+ return;
+ }
+
+ network->signal = bss->signal;
+ update_network_signal(network);
+ }
+#else
if (bss->signal < network->signal) {
if (bss != network->best_bss)
return;
+
network->signal = bss->signal;
update_network_signal(network);
} else {
network->signal = bss->signal;
network->best_bss = bss;
}
+#endif
SUPPLICANT_DBG("New network signal for %s %d dBm", network->ssid,
network->signal);
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] = {};
if (!peer)
return;
- callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_DISCONNECTED);
- peer->connection_requested = false;
+ callback_peer_changed(peer, G_SUPPLICANT_PEER_GROUP_DISCONNECTED);
+ peer->connection_requested = false;
+}
+
+#if defined TIZEN_EXT_WIFI_MESH
+const void *g_supplicant_interface_get_mesh_group_ssid(
+ GSupplicantInterface *interface,
+ unsigned int *ssid_len)
+{
+ if (!ssid_len)
+ return NULL;
+
+ if (!interface || interface->group_info.ssid_len == 0) {
+ *ssid_len = 0;
+ return NULL;
+ }
+
+ *ssid_len = interface->group_info.ssid_len;
+ return interface->group_info.ssid;
+}
+
+int g_supplicant_mesh_get_disconnect_reason(GSupplicantInterface *interface)
+{
+ if (!interface)
+ return -EINVAL;
+
+ return interface->group_info.disconnect_reason;
+}
+
+const char *g_supplicant_mesh_peer_get_address(GSupplicantMeshPeer *mesh_peer)
+{
+ if (!mesh_peer || !mesh_peer->peer_address)
+ return NULL;
+
+ return mesh_peer->peer_address;
+}
+
+int g_supplicant_mesh_peer_get_disconnect_reason(GSupplicantMeshPeer *mesh_peer)
+{
+ if (!mesh_peer)
+ return -EINVAL;
+
+ return mesh_peer->disconnect_reason;
+}
+
+static void callback_mesh_group_started(GSupplicantInterface *interface)
+{
+ if (!callbacks_pointer)
+ return;
+
+ if (!callbacks_pointer->mesh_group_started)
+ return;
+
+ callbacks_pointer->mesh_group_started(interface);
+}
+
+static void callback_mesh_group_removed(GSupplicantInterface *interface)
+{
+ if (!callbacks_pointer)
+ return;
+
+ if (!callbacks_pointer->mesh_group_removed)
+ return;
+
+ callbacks_pointer->mesh_group_removed(interface);
+}
+
+static void mesh_group_info(const char *key, DBusMessageIter *iter,
+ void *user_data)
+{
+ GSupplicantInterface *interface = user_data;
+ if (!key)
+ return;
+
+ if (g_strcmp0(key, "SSID") == 0) {
+ DBusMessageIter array;
+ unsigned char *ssid;
+ int ssid_len;
+
+ dbus_message_iter_recurse(iter, &array);
+ dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
+
+ if (ssid_len > 0 && ssid_len < 33) {
+ memcpy(interface->group_info.ssid, ssid, ssid_len);
+ interface->group_info.ssid_len = ssid_len;
+ } else {
+ memset(interface->group_info.ssid, 0, 32);
+ interface->group_info.ssid_len = 0;
+ }
+ } else if (g_strcmp0(key, "DisconnectReason") == 0) {
+ int disconnect_reason = 0;
+ dbus_message_iter_get_basic(iter, &disconnect_reason);
+ interface->group_info.disconnect_reason = disconnect_reason;
+ }
+}
+
+static void signal_mesh_group_started(const char *path, DBusMessageIter *iter)
+{
+ GSupplicantInterface *interface;
+
+ interface = g_hash_table_lookup(interface_table, path);
+ if (!interface)
+ return;
+
+ supplicant_dbus_property_foreach(iter, mesh_group_info, interface);
+
+ callback_mesh_group_started(interface);
+}
+
+static void signal_mesh_group_removed(const char *path, DBusMessageIter *iter)
+{
+ GSupplicantInterface *interface;
+
+ interface = g_hash_table_lookup(interface_table, path);
+ if (!interface)
+ return;
+
+ supplicant_dbus_property_foreach(iter, mesh_group_info, interface);
+
+ callback_mesh_group_removed(interface);
+}
+
+static void callback_mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
+{
+ if (!callbacks_pointer)
+ return;
+
+ if (!callbacks_pointer->mesh_peer_connected)
+ return;
+
+ callbacks_pointer->mesh_peer_connected(mesh_peer);
+}
+
+static void callback_mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
+{
+ if (!callbacks_pointer)
+ return;
+
+ if (!callbacks_pointer->mesh_peer_disconnected)
+ return;
+
+ callbacks_pointer->mesh_peer_disconnected(mesh_peer);
+}
+
+static void mesh_peer_info(const char *key, DBusMessageIter *iter,
+ void *user_data)
+{
+ GSupplicantMeshPeer *mesh_peer = user_data;
+ if (!key)
+ return;
+
+ if (g_strcmp0(key, "PeerAddress") == 0) {
+ DBusMessageIter array;
+ unsigned char *addr;
+ int addr_len;
+
+ dbus_message_iter_recurse(iter, &array);
+ dbus_message_iter_get_fixed_array(&array, &addr, &addr_len);
+
+ if (addr_len == 6) {
+ mesh_peer->peer_address = g_malloc0(19);
+ snprintf(mesh_peer->peer_address, 19,
+ "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1],
+ addr[2], addr[3], addr[4], addr[5]);
+ }
+ } else if (g_strcmp0(key, "DisconnectReason") == 0) {
+ int disconnect_reason = 0;
+ dbus_message_iter_get_basic(iter, &disconnect_reason);
+ mesh_peer->disconnect_reason = disconnect_reason;
+ }
+}
+
+static void signal_mesh_peer_connected(const char *path, DBusMessageIter *iter)
+{
+ GSupplicantInterface *interface;
+ GSupplicantMeshPeer *mesh_peer;
+
+ interface = g_hash_table_lookup(interface_table, path);
+ if (!interface)
+ return;
+
+ mesh_peer = dbus_malloc0(sizeof(GSupplicantMeshPeer));
+ mesh_peer->interface = interface;
+
+ supplicant_dbus_property_foreach(iter, mesh_peer_info, mesh_peer);
+
+ callback_mesh_peer_connected(mesh_peer);
+ g_free(mesh_peer->peer_address);
+ g_free(mesh_peer);
+}
+
+static void signal_mesh_peer_disconnected(const char *path,
+ DBusMessageIter *iter)
+{
+ GSupplicantInterface *interface;
+ GSupplicantMeshPeer *mesh_peer;
+
+ interface = g_hash_table_lookup(interface_table, path);
+ if (!interface)
+ return;
+
+ mesh_peer = dbus_malloc0(sizeof(GSupplicantMeshPeer));
+ mesh_peer->interface = interface;
+
+ supplicant_dbus_property_foreach(iter, mesh_peer_info, mesh_peer);
+
+ callback_mesh_peer_disconnected(mesh_peer);
+ g_free(mesh_peer->peer_address);
+ g_free(mesh_peer);
}
+#endif
static struct {
const char *interface;
{ SUPPLICANT_INTERFACE ".Interface.WPS", "Credentials", signal_wps_credentials },
{ SUPPLICANT_INTERFACE ".Interface.WPS", "Event", signal_wps_event },
+#if defined TIZEN_EXT
+ { "org.tizen.system.deviced.PowerOff", "ChangeState", signal_power_off },
+#endif
{ SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceFound", signal_peer_found },
{ SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceLost", signal_peer_lost },
{ SUPPLICANT_INTERFACE ".Group", "PeerJoined", signal_group_peer_joined },
{ SUPPLICANT_INTERFACE ".Group", "PeerDisconnected", signal_group_peer_disconnected },
+#if defined TIZEN_EXT_WIFI_MESH
+ { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshGroupStarted",
+ signal_mesh_group_started },
+ { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshGroupRemoved",
+ signal_mesh_group_removed },
+ { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshPeerConnected",
+ signal_mesh_peer_connected },
+ { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshPeerDisconnected",
+ signal_mesh_peer_disconnected },
+#endif
+
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ { SUPPLICANT_INTERFACE ".Interface", "EAP", signal_eap },
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
{ }
};
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);
}
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);
DBUS_TYPE_STRING, &config_file);
}
+#ifdef TIZEN_EXT
+ if (data->driver && g_strstr_len(data->driver, strlen(data->driver), "nl80211")) {
+ supplicant_dbus_dict_append_basic(&dict, "MacAddr",
+ DBUS_TYPE_UINT32, &data->mac_addr);
+
+ supplicant_dbus_dict_append_basic(&dict, "PreassocMacAddr",
+ DBUS_TYPE_UINT32, &data->preassoc_mac_addr);
+
+ supplicant_dbus_dict_append_basic(&dict, "RandAddrLifetime",
+ DBUS_TYPE_UINT32, &data->random_mac_lifetime);
+ }
+#endif /* TIZEN_EXT */
+
+#if defined TIZEN_EXT_WIFI_MESH
+ if (data->is_mesh_interface) {
+ if (data->parent_ifname)
+ supplicant_dbus_dict_append_basic(&dict, "ParentIfname",
+ DBUS_TYPE_STRING, &data->parent_ifname);
+
+ supplicant_dbus_dict_append_basic(&dict, "IsMeshInterface",
+ DBUS_TYPE_BOOLEAN, &data->is_mesh_interface);
+ }
+#endif
+
supplicant_dbus_dict_close(iter, &dict);
}
+#if defined TIZEN_EXT
+static void interface_get_state(const char *key, DBusMessageIter *iter,
+ void *user_data)
+{
+ struct interface_create_data *data = user_data;
+ GSupplicantInterface *interface = NULL;
+ const char *str = NULL;
+
+ SUPPLICANT_DBG("key[%s]", key);
+
+ if (!data) {
+ SUPPLICANT_DBG("data is NULL");
+ return;
+ }
+
+ interface = data->interface;
+ if (!interface) {
+ SUPPLICANT_DBG("interface is NULL");
+ return;
+ }
+
+ if (iter)
+ dbus_message_iter_get_basic(iter, &str);
+
+ if (str) {
+ if (string2state(str) != interface->state)
+ interface->state = string2state(str);
+ }
+
+ if (interface->state == G_SUPPLICANT_STATE_DISABLED)
+ interface->ready = FALSE;
+ else
+ interface->ready = TRUE;
+
+ SUPPLICANT_DBG("state %s (%d)", str, interface->state);
+
+ if (data->callback) {
+ data->callback(0, interface, data->user_data);
+#if defined TIZEN_EXT_WIFI_MESH
+ callback_mesh_support(interface);
+#endif
+ }
+
+ interface_create_data_free(data);
+}
+#endif
+
static void interface_get_result(const char *error,
DBusMessageIter *iter, void *user_data)
{
const char *path = NULL;
int err;
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
SUPPLICANT_DBG("");
if (error) {
goto done;
}
+#if defined TIZEN_EXT
+ data->interface = interface;
+ err = supplicant_dbus_property_get(path,
+ SUPPLICANT_INTERFACE ".Interface",
+ "State", interface_get_state, data, NULL);
+
+ if (err == 0)
+ return;
+#endif
+
if (data->callback) {
data->callback(0, interface, data->user_data);
+#if !defined TIZEN_EXT
callback_p2p_support(interface);
+#endif
+#if defined TIZEN_EXT_WIFI_MESH
+ callback_mesh_support(interface);
+#endif
}
interface_create_data_free(data);
static void interface_get_params(DBusMessageIter *iter, void *user_data)
{
struct interface_create_data *data = user_data;
-
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
SUPPLICANT_DBG("");
dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &data->ifname);
}
+#if defined TIZEN_EXT_WIFI_MESH
+int g_supplicant_mesh_interface_create(const char *ifname, const char *driver,
+ const char *bridge, const char *parent_ifname,
+ GSupplicantInterfaceCallback callback, void *user_data)
+{
+ struct interface_create_data *data;
+ int ret;
+
+ SUPPLICANT_DBG("ifname %s", ifname);
+
+ if (!ifname || !parent_ifname)
+ return -EINVAL;
+
+ if (!system_available)
+ return -EFAULT;
+
+ data = dbus_malloc0(sizeof(*data));
+ if (!data)
+ return -ENOMEM;
+
+ data->ifname = g_strdup(ifname);
+ data->driver = g_strdup(driver);
+ data->bridge = g_strdup(bridge);
+ data->is_mesh_interface = true;
+ data->parent_ifname = g_strdup(parent_ifname);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
+ SUPPLICANT_INTERFACE,
+ "CreateInterface",
+ interface_create_params,
+ interface_create_result, data,
+ NULL);
+ return ret;
+}
+
+struct interface_mesh_peer_data {
+ char *peer_address;
+ char *method;
+ GSupplicantInterface *interface;
+ GSupplicantInterfaceCallback callback;
+ void *user_data;
+};
+
+static void interface_mesh_change_peer_params(DBusMessageIter *iter,
+ void *user_data)
+{
+ struct interface_mesh_peer_data *data = user_data;
+
+ SUPPLICANT_DBG("");
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &data->peer_address);
+}
+
+static void interface_mesh_change_peer_result(const char *error,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct interface_mesh_peer_data *data = user_data;
+ int err = 0;
+
+ SUPPLICANT_DBG("%s", data->method);
+
+ if (error) {
+ err = -EIO;
+ SUPPLICANT_DBG("error %s", error);
+ }
+
+ if (data->callback)
+ data->callback(err, data->interface, data->user_data);
+
+ g_free(data->peer_address);
+ g_free(data->method);
+ dbus_free(data);
+}
+
+int g_supplicant_interface_mesh_peer_change_status(
+ GSupplicantInterface *interface,
+ GSupplicantInterfaceCallback callback, const char *peer_address,
+ const char *method, void *user_data)
+{
+ struct interface_mesh_peer_data *data;
+ int ret;
+
+ if (!peer_address)
+ return -EINVAL;
+
+ data = dbus_malloc0(sizeof(*data));
+ if (!data)
+ return -ENOMEM;
+
+ data->peer_address = g_strdup(peer_address);
+ data->method = g_strdup(method);
+ data->interface = interface;
+ data->callback = callback;
+ data->user_data = user_data;
+
+ ret = supplicant_dbus_method_call(interface->path,
+ SUPPLICANT_INTERFACE ".Interface.Mesh",
+ method, interface_mesh_change_peer_params,
+ interface_mesh_change_peer_result, data, NULL);
+ if (ret < 0) {
+ g_free(data->peer_address);
+ g_free(data->method);
+ dbus_free(data);
+ }
+
+ return ret;
+}
+#endif
+
int g_supplicant_interface_create(const char *ifname, const char *driver,
const char *bridge,
+#ifdef TIZEN_EXT
+ unsigned int mac_policy,
+ unsigned int preassoc_mac_policy,
+ unsigned int random_mac_lifetime,
+#endif /* TIZEN_EXT */
GSupplicantInterfaceCallback callback,
void *user_data)
{
data->driver = g_strdup(driver);
data->bridge = g_strdup(bridge);
data->callback = callback;
+#ifdef TIZEN_EXT
+ data->mac_addr = mac_policy;
+ data->preassoc_mac_addr = preassoc_mac_policy;
+ data->random_mac_lifetime = random_mac_lifetime;
+#endif /* TIZEN_EXT */
data->user_data = user_data;
ret = supplicant_dbus_method_call(SUPPLICANT_PATH,
&data->interface->path);
}
-
int g_supplicant_interface_remove(GSupplicantInterface *interface,
GSupplicantInterfaceCallback callback,
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",
case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
return -EBUSY;
+#if defined TIZEN_EXT
+ case G_SUPPLICANT_STATE_DISABLED:
+ return -ENOLINK;
+ case G_SUPPLICANT_STATE_UNKNOWN:
+#else
case G_SUPPLICANT_STATE_UNKNOWN:
case G_SUPPLICANT_STATE_DISABLED:
+#endif
case G_SUPPLICANT_STATE_DISCONNECTED:
case G_SUPPLICANT_STATE_INACTIVE:
case G_SUPPLICANT_STATE_SCANNING:
return 0;
}
+#if defined TIZEN_EXT_WIFI_MESH
+static void interface_abort_scan_result(const char *error,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct interface_scan_data *data = user_data;
+ int err = 0;
+
+ if (error) {
+ SUPPLICANT_DBG("error %s", error);
+ err = -EIO;
+ }
+
+ g_free(data->path);
+
+ if (data->callback)
+ data->callback(err, data->interface, data->user_data);
+
+ dbus_free(data);
+}
+
+int g_supplicant_interface_abort_scan(GSupplicantInterface *interface,
+ GSupplicantInterfaceCallback callback, void *user_data)
+{
+ struct interface_scan_data *data;
+ int ret;
+
+ if (!interface->scanning)
+ return -EEXIST;
+
+ data = dbus_malloc0(sizeof(*data));
+ if (!data)
+ return -ENOMEM;
+
+ data->interface = interface;
+ data->path = g_strdup(interface->path);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ ret = supplicant_dbus_method_call(interface->path,
+ SUPPLICANT_INTERFACE ".Interface", "AbortScan", NULL,
+ interface_abort_scan_result, data, interface);
+
+ if (ret < 0) {
+ g_free(data->path);
+ dbus_free(data);
+ }
+
+ return ret;
+}
+#endif
+
int g_supplicant_interface_scan(GSupplicantInterface *interface,
GSupplicantScanParams *scan_data,
GSupplicantInterfaceCallback callback,
data->interface = interface;
data->path = g_strdup(interface->path);
+#if defined TIZEN_EXT
+ data->interface->scan_callback = data->callback = callback;
+ data->interface->scan_data = data->user_data = user_data;
+#else
data->callback = callback;
data->user_data = user_data;
+#endif
data->scan_params = scan_data;
interface->scan_callback = callback;
return ret;
}
+#if defined TIZEN_EXT
+static void interface_signalpoll_result(const char *error,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct interface_signalpoll_data *data = user_data;
+ int err = 0;
+ dbus_int32_t maxspeed = 0;
+ dbus_int32_t strength = 0;
+ dbus_int32_t snr = 0;
+ DBusMessageIter sub_iter, dict;
+
+ if (error) {
+ err = -EIO;
+ SUPPLICANT_DBG("error: %s", error);
+ goto out;
+ }
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_VARIANT) {
+ err = -EINVAL;
+ SUPPLICANT_DBG("invalid reply");
+ goto out;
+ }
+
+ dbus_message_iter_recurse(iter, &sub_iter);
+ dbus_message_iter_recurse(&sub_iter, &dict);
+
+ while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter entry, value;
+ const char *key;
+
+ dbus_message_iter_recurse(&dict, &entry);
+ dbus_message_iter_get_basic(&entry, &key);
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_recurse(&entry, &value);
+
+ switch (dbus_message_iter_get_arg_type(&value)) {
+ case DBUS_TYPE_INT32:
+ if (g_strcmp0(key, "linkspeed") == 0) {
+ dbus_message_iter_get_basic(&value, &maxspeed);
+ SUPPLICANT_DBG("linkspeed = %d", maxspeed);
+ break;
+ } else if (g_strcmp0(key, "rssi") == 0) {
+ dbus_message_iter_get_basic(&value, &strength);
+ SUPPLICANT_DBG("Strength = %d", strength);
+ break;
+ } else if (g_strcmp0(key, "SNR") == 0) {
+ dbus_message_iter_get_basic(&value, &snr);
+ SUPPLICANT_DBG("SNR = %d", snr);
+ break;
+ }
+ }
+ dbus_message_iter_next(&dict);
+ }
+
+out:
+ if(data->callback)
+ data->callback(err, maxspeed, strength, snr, data->user_data);
+
+ g_free(data->path);
+ dbus_free(data);
+}
+
+int g_supplicant_interface_signalpoll(GSupplicantInterface *interface,
+ GSupplicantMaxSpeedCallback callback,
+ void *user_data)
+{
+ struct interface_signalpoll_data *data;
+ int ret;
+
+ if (!interface)
+ return -EINVAL;
+
+ if (!system_available)
+ return -EFAULT;
+
+ data = dbus_malloc0(sizeof(*data));
+ if (!data)
+ return -ENOMEM;
+
+ data->interface = interface;
+ data->path = g_strdup(interface->path);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ ret = supplicant_dbus_method_call(interface->path,
+ SUPPLICANT_INTERFACE ".Interface", "SignalPoll",
+ NULL, interface_signalpoll_result, data,
+ interface);
+
+ if (ret < 0) {
+ g_free(data->path);
+ dbus_free(data);
+ }
+
+ return ret;
+}
+#endif
+
static int parse_supplicant_error(DBusMessageIter *iter)
{
int err = -ECONNABORTED;
err = 0;
if (error) {
+#if defined TIZEN_EXT
+ SUPPLICANT_DBG("SelectNetwork errorFreq %s", error);
+#else
SUPPLICANT_DBG("SelectNetwork error %s", error);
+#endif
err = parse_supplicant_error(iter);
}
if (data->callback)
data->callback(err, data->interface, data->user_data);
+#if defined TIZEN_EXT
+ g_free(data->ssid->ssid);
+ g_free((char *)data->ssid->passphrase);
+ g_free((char *)data->ssid->connector);
+ g_free((char *)data->ssid->c_sign_key);
+ g_free((char *)data->ssid->net_access_key);
+#endif
g_free(data->ssid);
dbus_free(data);
}
{
struct interface_connect_data *data = user_data;
GSupplicantInterface *interface = data->interface;
+#if defined TIZEN_EXT
+ GSupplicantSSID *ssid = data->ssid;
+#endif
dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
&interface->network_path);
+#if defined TIZEN_EXT
+ if (!ssid->bssid_for_connect_len)
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &ssid->freq);
+#endif
}
static void interface_add_network_result(const char *error,
SUPPLICANT_DBG("PATH: %s", path);
+#if defined TIZEN_EXT
+ if (interface->network_path)
+ g_free(interface->network_path);
+#endif
interface->network_path = g_strdup(path);
store_network_information(interface, data->ssid);
+#if defined TIZEN_EXT
+ SUPPLICANT_DBG(".Interface.SelectNetworkFreq");
+ GSupplicantSSID *ssid = data->ssid;
+
+ if (!ssid->bssid_for_connect_len)
+ supplicant_dbus_method_call(data->interface->path,
+ SUPPLICANT_INTERFACE ".Interface", "SelectNetworkFreq",
+ interface_select_network_params,
+ interface_select_network_result, data,
+ interface);
+ else
+ supplicant_dbus_method_call(data->interface->path,
+ SUPPLICANT_INTERFACE ".Interface", "SelectNetwork",
+ interface_select_network_params,
+ interface_select_network_result, data,
+ interface);
+#else
supplicant_dbus_method_call(data->interface->path,
SUPPLICANT_INTERFACE ".Interface", "SelectNetwork",
interface_select_network_params,
interface_select_network_result, data,
interface);
+#endif
return;
}
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);
}
if (!ssid->private_key_path)
return;
+#if !defined TIZEN_EXT
if (!ssid->private_key_passphrase)
return;
+#endif
if (ssid->ca_cert_path)
supplicant_dbus_dict_append_basic(dict, "ca_cert",
supplicant_dbus_dict_append_basic(dict, "private_key",
DBUS_TYPE_STRING,
&ssid->private_key_path);
+#if !defined TIZEN_EXT
supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
DBUS_TYPE_STRING,
&ssid->private_key_passphrase);
+#endif
supplicant_dbus_dict_append_basic(dict, "client_cert",
DBUS_TYPE_STRING,
&ssid->client_cert_path);
if (!ssid->private_key_path)
return;
+#if !defined TIZEN_EXT
if (!ssid->private_key_passphrase)
return;
+#endif
supplicant_dbus_dict_append_basic(dict, "client_cert",
DBUS_TYPE_STRING,
DBUS_TYPE_STRING,
&ssid->private_key_path);
+#if !defined TIZEN_EXT
supplicant_dbus_dict_append_basic(dict, "private_key_passwd",
DBUS_TYPE_STRING,
&ssid->private_key_passphrase);
+#endif
}
g_free(phase2_auth);
}
+#if defined TIZEN_EXT
+static void add_network_security_aka_sim(DBusMessageIter *dict,
+ GSupplicantSSID *ssid)
+{
+ if (!ssid->passphrase)
+ return;
+
+ supplicant_dbus_dict_append_basic(dict, "password",
+ DBUS_TYPE_STRING,
+ &ssid->passphrase);
+}
+
+static void add_network_security_fast(DBusMessageIter *dict,
+ GSupplicantSSID *ssid)
+{
+ /*
+ * For FAST, we at least need:
+ * id / password
+ * phase1 (provisiong information)
+ * pac_file
+ */
+
+ /* Allow provisioing both authenticated and unauthenticated */
+ const char *phase1 = "fast_provisioning=2";
+ supplicant_dbus_dict_append_basic(dict, "phase1",
+ DBUS_TYPE_STRING,
+ &phase1);
+
+ SUPPLICANT_DBG("pac_file [%s]", ssid->pac_file);
+ if(ssid->pac_file)
+ supplicant_dbus_dict_append_basic(dict, "pac_file",
+ DBUS_TYPE_STRING,
+ &ssid->pac_file);
+
+ supplicant_dbus_dict_append_basic(dict, "password",
+ DBUS_TYPE_STRING,
+ &ssid->passphrase);
+}
+#endif
+
static void add_network_security_eap(DBusMessageIter *dict,
GSupplicantSSID *ssid)
{
char *eap_value;
+#if defined TIZEN_EXT
+ if (!ssid->eap)
+#else
if (!ssid->eap || !ssid->identity)
+#endif
return;
if (g_strcmp0(ssid->eap, "tls") == 0) {
add_network_security_tls(dict, ssid);
} else if (g_strcmp0(ssid->eap, "peap") == 0 ||
g_strcmp0(ssid->eap, "ttls") == 0) {
+#if defined TIZEN_EXT
+ if (!ssid->identity)
+ return;
+#endif
add_network_security_peap(dict, ssid);
+
+#if defined TIZEN_EXT
+ } else if (g_strcmp0(ssid->eap, "sim") == 0 ||
+ g_strcmp0(ssid->eap, "aka") == 0 ||
+ g_strcmp0(ssid->eap, "aka'") == 0) {
+ add_network_security_aka_sim(dict, ssid);
+ } else if (g_strcmp0(ssid->eap, "pwd") == 0) {
+ if(!ssid->passphrase)
+ return;
+ supplicant_dbus_dict_append_basic(dict, "password",
+ DBUS_TYPE_STRING,
+ &ssid->passphrase);
+ } else if (g_strcmp0(ssid->eap, "fast") == 0){
+ if (!ssid->identity || !ssid->passphrase)
+ return;
+
+ add_network_security_fast(dict, ssid);
+#endif
} else
return;
supplicant_dbus_dict_append_basic(dict, "eap",
DBUS_TYPE_STRING,
&eap_value);
+#if defined TIZEN_EXT
+ if (ssid->identity != NULL)
+ supplicant_dbus_dict_append_basic(dict, "identity",
+ DBUS_TYPE_STRING,
+ &ssid->identity);
+#else
supplicant_dbus_dict_append_basic(dict, "identity",
DBUS_TYPE_STRING,
&ssid->identity);
+#endif
if(ssid->anonymous_identity)
supplicant_dbus_dict_append_basic(dict, "anonymous_identity",
DBUS_TYPE_STRING,
g_free(proto);
}
+#if defined TIZEN_EXT
+static void add_network_ieee80211w(DBusMessageIter *dict, GSupplicantSSID *ssid)
+{
+ if (ssid->security != G_SUPPLICANT_SECURITY_SAE
+ && ssid->security != G_SUPPLICANT_SECURITY_OWE
+ && ssid->security != G_SUPPLICANT_SECURITY_DPP)
+ return;
+
+ supplicant_dbus_dict_append_basic(dict, "ieee80211w", DBUS_TYPE_UINT32,
+ &ssid->ieee80211w);
+}
+
+static void add_network_security_connector(DBusMessageIter *dict, GSupplicantSSID *ssid)
+{
+ if (ssid->connector && strlen(ssid->connector) > 0) {
+ const char *key = "dpp_connector";
+
+ supplicant_dbus_dict_append_basic(dict,
+ key, DBUS_TYPE_STRING,
+ &ssid->connector);
+ }
+}
+
+static size_t convert_hexstr_to_bin(const char *hex_str, unsigned char **bin)
+{
+ unsigned char *bin_res = NULL;
+ unsigned int i, j, hex;
+ size_t hex_str_len;
+
+ if (!hex_str || strlen(hex_str) == 0)
+ return 0;
+
+ hex_str_len = strlen(hex_str);
+ bin_res = g_try_malloc0(hex_str_len / 2);
+ if (!bin_res)
+ return 0;
+
+ j = 0;
+ for (i = 0; i < hex_str_len; i+=2) {
+ sscanf(hex_str + i, "%02x", &hex);
+ bin_res[j++] = hex;
+ }
+
+ *bin = bin_res;
+ return hex_str_len / 2;
+}
+
+static void add_network_security_c_sign_key(DBusMessageIter *dict, GSupplicantSSID *ssid)
+{
+ if (ssid->c_sign_key && strlen(ssid->c_sign_key) > 0) {
+ const char *key = "dpp_csign";
+ unsigned char *bin_csign = NULL;
+ size_t bin_csign_len = convert_hexstr_to_bin(ssid->c_sign_key, &bin_csign);
+ if (bin_csign_len != 0)
+ supplicant_dbus_dict_append_fixed_array(dict,
+ key, DBUS_TYPE_BYTE,
+ &bin_csign, bin_csign_len);
+ g_free(bin_csign);
+ }
+}
+
+static void add_network_security_net_access_key(DBusMessageIter *dict, GSupplicantSSID *ssid)
+{
+ if (ssid->net_access_key && strlen(ssid->net_access_key) > 0) {
+ const char *key = "dpp_netaccesskey";
+ unsigned char *bin_netaccesskey = NULL;
+ size_t bin_netaccesskey_len = convert_hexstr_to_bin(ssid->net_access_key, &bin_netaccesskey);
+ if (bin_netaccesskey_len != 0)
+ supplicant_dbus_dict_append_fixed_array(dict,
+ key, DBUS_TYPE_BYTE,
+ &bin_netaccesskey, bin_netaccesskey_len);
+ g_free(bin_netaccesskey);
+ }
+}
+
+#endif
+
static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid)
{
char *key_mgmt;
add_network_security_ciphers(dict, ssid);
add_network_security_proto(dict, ssid);
break;
+#if defined TIZEN_EXT
+ case G_SUPPLICANT_SECURITY_FT_PSK:
+ key_mgmt = "FT-PSK";
+ add_network_security_psk(dict, ssid);
+ add_network_security_ciphers(dict, ssid);
+ add_network_security_proto(dict, ssid);
+ break;
+ case G_SUPPLICANT_SECURITY_FT_IEEE8021X:
+ key_mgmt = "FT-EAP";
+ add_network_security_eap(dict, ssid);
+ add_network_security_ciphers(dict, ssid);
+ add_network_security_proto(dict, ssid);
+ break;
+ case G_SUPPLICANT_SECURITY_SAE:
+ if (ssid->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_PSK)
+ key_mgmt = "SAE WPA-PSK"; // WFA (WPA3 & WPA2 Mixed -> WPA2 only)
+ else
+ key_mgmt = "SAE";
+ add_network_security_psk(dict, ssid);
+ break;
+ case G_SUPPLICANT_SECURITY_OWE:
+ key_mgmt = "OWE";
+ add_network_security_ciphers(dict, ssid);
+ add_network_security_proto(dict, ssid);
+ break;
+ case G_SUPPLICANT_SECURITY_DPP:
+ key_mgmt = "DPP";
+ add_network_security_connector(dict, ssid);
+ add_network_security_c_sign_key(dict, ssid);
+ add_network_security_net_access_key(dict, ssid);
+ break;
+#endif
}
supplicant_dbus_dict_append_basic(dict, "key_mgmt",
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",
DBusMessageIter dict;
struct interface_connect_data *data = user_data;
GSupplicantSSID *ssid = data->ssid;
+#if defined TIZEN_EXT
+ GSupplicantInterface *interface = data->interface;
+#endif
supplicant_dbus_dict_open(iter, &dict);
add_network_mode(&dict, ssid);
- add_network_security(&dict, ssid);
+ add_network_security(&dict, ssid);
+
+#if defined TIZEN_EXT
+ add_network_ieee80211w(&dict, ssid);
+#endif
+
+ supplicant_dbus_dict_append_fixed_array(&dict, "ssid",
+ DBUS_TYPE_BYTE, &ssid->ssid,
+ ssid->ssid_len);
+
+#if defined TIZEN_EXT
+ bool owe_transition_mode = FALSE;
+ if ((ssid->security == G_SUPPLICANT_SECURITY_OWE) && !(ssid->keymgmt & G_SUPPLICANT_KEYMGMT_OWE))
+ owe_transition_mode = TRUE;
+
+ if (ssid->bssid && !owe_transition_mode) {
+ char *bssid = NULL;
+ bssid = g_try_malloc0(18);
+ if (bssid == NULL) {
+ SUPPLICANT_DBG("memory allocation error");
+ supplicant_dbus_dict_close(iter, &dict);
+ return;
+ }
+
+ if (ssid->bssid_for_connect_len) {
+ snprintf(bssid, 18, MACSTR, MAC2STR(ssid->bssid_for_connect));
+ memcpy(interface->add_network_bssid, ssid->bssid_for_connect, WIFI_BSSID_LEN_MAX);
+ } else {
+ snprintf(bssid, 18, MACSTR, MAC2STR(ssid->bssid));
+ memcpy(interface->add_network_bssid, ssid->bssid, WIFI_BSSID_LEN_MAX);
+ }
+
+ SUPPLICANT_DBG("bssid [" MACSTR "]", MAC2STR(interface->add_network_bssid));
+
+ supplicant_dbus_dict_append_basic(&dict, "bssid",
+ DBUS_TYPE_STRING, &bssid);
+ g_free(bssid);
+ }
+#endif
+
+ supplicant_dbus_dict_close(iter, &dict);
+}
+
+static void interface_wps_start_result(const char *error,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct interface_connect_data *data = user_data;
+ int err;
+
+ SUPPLICANT_DBG("");
+
+ err = 0;
+ if (error) {
+ SUPPLICANT_DBG("error: %s", error);
+ err = parse_supplicant_error(iter);
+ }
+
+ if(data->callback)
+ data->callback(err, data->interface, data->user_data);
+
+ g_free(data->path);
+ g_free(data->ssid);
+ dbus_free(data);
+}
+
+static void interface_add_wps_params(DBusMessageIter *iter, void *user_data)
+{
+ struct interface_connect_data *data = user_data;
+ GSupplicantSSID *ssid = data->ssid;
+ const char *role = "enrollee", *type;
+ DBusMessageIter dict;
+
+ SUPPLICANT_DBG("");
+
+ supplicant_dbus_dict_open(iter, &dict);
+
+ supplicant_dbus_dict_append_basic(&dict, "Role",
+ DBUS_TYPE_STRING, &role);
+
+ type = "pbc";
+ if (ssid->pin_wps) {
+ type = "pin";
+ supplicant_dbus_dict_append_basic(&dict, "Pin",
+ DBUS_TYPE_STRING, &ssid->pin_wps);
+ }
+
+ supplicant_dbus_dict_append_basic(&dict, "Type",
+ DBUS_TYPE_STRING, &type);
+
+#if defined TIZEN_EXT
+ if (ssid->bssid)
+ supplicant_dbus_dict_append_fixed_array(&dict, "Bssid",
+ DBUS_TYPE_BYTE, &ssid->bssid, 6);
+#endif
+
+ supplicant_dbus_dict_close(iter, &dict);
+}
+
+static void wps_start(const char *error, DBusMessageIter *iter, void *user_data)
+{
+ struct interface_connect_data *data = user_data;
+
+ SUPPLICANT_DBG("");
+
+ if (error) {
+ SUPPLICANT_DBG("error: %s", error);
+ g_free(data->path);
+ g_free(data->ssid);
+ dbus_free(data);
+ return;
+ }
+
+#if defined TIZEN_EXT
+ GSupplicantSSID *ssid = data->ssid;
+ if (ssid->pin_wps != NULL) {
+ if (!g_utf8_validate(ssid->pin_wps, 8, NULL)) {
+ SUPPLICANT_DBG("Invalid characters in WPS_PIN");
+ g_free(data->ssid);
+ dbus_free(data);
+ return;
+ }
+ }
+#endif
+ supplicant_dbus_method_call(data->interface->path,
+ SUPPLICANT_INTERFACE ".Interface.WPS", "Start",
+ interface_add_wps_params,
+ interface_wps_start_result, data, NULL);
+}
+
+static void wps_process_credentials(DBusMessageIter *iter, void *user_data)
+{
+ dbus_bool_t credentials = TRUE;
+
+ SUPPLICANT_DBG("");
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &credentials);
+}
+
+
+#if defined TIZEN_EXT
+#define NETCONFIG_SERVICE "net.netconfig"
+#define NETCONFIG_WIFI_PATH "/net/netconfig/wifi"
+#define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi"
+
+struct dec_method_call_data {
+ struct interface_connect_data *data;
+ DBusPendingCall *pending_call;
+};
+
+static struct dec_method_call_data decrypt_request_data;
+
+static void crypt_method_call_cancel(void)
+{
+ if (decrypt_request_data.pending_call) {
+ dbus_pending_call_cancel(decrypt_request_data.pending_call);
+ dbus_pending_call_unref(decrypt_request_data.pending_call);
+ decrypt_request_data.pending_call = NULL;
+ }
+
+ g_free(decrypt_request_data.data->path);
+ g_free(decrypt_request_data.data->ssid);
+ dbus_free(decrypt_request_data.data);
+ decrypt_request_data.data = NULL;
+}
+
+static void decryption_request_reply(DBusPendingCall *call,
+ void *user_data)
+{
+ DBusMessage *reply;
+ DBusError error;
+ DBusMessageIter args;
+ char *out_data;
+ int ret;
+ struct interface_connect_data *data = user_data;
+
+ SUPPLICANT_DBG("");
+
+ reply = dbus_pending_call_steal_reply(call);
+
+ dbus_error_init(&error);
+ if (dbus_set_error_from_message(&error, reply)) {
+ SUPPLICANT_DBG("decryption_request_reply() %s %s", error.name, error.message);
+ dbus_error_free(&error);
+ ret = -EINVAL;
+ goto done;
+ }
+
+ if (dbus_message_iter_init(reply, &args) == FALSE) {
+ SUPPLICANT_DBG("dbus_message_iter_init() failed");
+ ret = -EINVAL;
+ goto done;
+ }
+
+ dbus_message_iter_get_basic(&args, &out_data);
+ data->ssid->passphrase = g_strdup((const gchar *)out_data);
+
+ ret = supplicant_dbus_method_call(data->interface->path,
+ SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
+ interface_add_network_params,
+ interface_add_network_result, data,
+ data->interface);
+
+done:
+ if (ret < 0) {
+ SUPPLICANT_DBG("AddNetwork failed %d", ret);
+ callback_assoc_failed(decrypt_request_data.data->user_data);
+ g_free(data->path);
+ g_free(data->ssid->ssid);
+ g_free((char *)data->ssid->passphrase);
+ g_free((char *)data->ssid->connector);
+ g_free((char *)data->ssid->c_sign_key);
+ g_free((char *)data->ssid->net_access_key);
+ g_free(data->ssid);
+ dbus_free(data);
+ }
+
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(call);
+
+ decrypt_request_data.pending_call = NULL;
+ decrypt_request_data.data = NULL;
+}
+
+static int send_decryption_request(const char *passphrase,
+ struct interface_connect_data *data)
+{
+ DBusMessage *msg = NULL;
+ DBusPendingCall *call;
+
+ SUPPLICANT_DBG("Decryption request");
+
+ if (!passphrase) {
+ SUPPLICANT_DBG("Invalid parameter");
+ return -EINVAL;
+ }
+
+ if (!connection)
+ return -EINVAL;
+
+ msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
+ NETCONFIG_WIFI_INTERFACE, "DecryptPassphrase");
+ if (!msg)
+ return -EINVAL;
+
+#if defined TIZEN_EXT
+ if (!dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
+ DBUS_TYPE_INVALID)) {
+ SUPPLICANT_DBG("Could not fulfill decryption request");
+ return -ENOMEM;
+ }
+#else
+ dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase,
+ DBUS_TYPE_INVALID);
+#endif
+
+ if (!dbus_connection_send_with_reply(connection, msg,
+ &call, DBUS_TIMEOUT_USE_DEFAULT)) {
+ dbus_message_unref(msg);
+ return -EIO;
+ }
+
+ if (!call) {
+ dbus_message_unref(msg);
+ return -EIO;
+ }
+
+ decrypt_request_data.pending_call = call;
+ decrypt_request_data.data = data;
+
+ dbus_pending_call_set_notify(call, decryption_request_reply, data, NULL);
+ dbus_message_unref(msg);
- supplicant_dbus_dict_append_fixed_array(&dict, "ssid",
- DBUS_TYPE_BYTE, &ssid->ssid,
- ssid->ssid_len);
+ SUPPLICANT_DBG("Decryption request succeeded");
- supplicant_dbus_dict_close(iter, &dict);
+ return 0;
}
-static void interface_wps_start_result(const char *error,
- DBusMessageIter *iter, void *user_data)
+static void decrypt_conf_obj_reply(DBusPendingCall *call,
+ void *user_data)
{
+ DBusMessage *reply;
+ DBusError error;
+ DBusMessageIter iter, dict;
+ char *out_data;
+ int ret;
struct interface_connect_data *data = user_data;
- int err;
- SUPPLICANT_DBG("");
+ reply = dbus_pending_call_steal_reply(call);
- err = 0;
- if (error) {
- SUPPLICANT_DBG("error: %s", error);
- err = parse_supplicant_error(iter);
+ dbus_error_init(&error);
+ if (dbus_set_error_from_message(&error, reply)) {
+ SUPPLICANT_DBG("decryption_conf_obj_reply() %s %s", error.name, error.message);
+ dbus_error_free(&error);
+ ret = -EINVAL;
+ goto done;
}
- if(data->callback)
- data->callback(err, data->interface, data->user_data);
+ if (dbus_message_iter_init(reply, &iter) == FALSE) {
+ SUPPLICANT_DBG("dbus_message_iter_init() failed");
+ ret = -EINVAL;
+ goto done;
+ }
- g_free(data->path);
- g_free(data->ssid);
- dbus_free(data);
-}
+ dbus_message_iter_recurse(&iter, &dict);
+
+ while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter entry, value;
+ const char *key;
+
+ dbus_message_iter_recurse(&dict, &entry);
+ dbus_message_iter_get_basic(&entry, &key);
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_recurse(&entry, &value);
+ if (dbus_message_iter_get_arg_type(&value) == DBUS_TYPE_STRING) {
+ if (g_strcmp0(key, "connector") == 0) {
+ dbus_message_iter_get_basic(&value, &out_data);
+ data->ssid->connector = g_strdup((const gchar *)out_data);
+ SUPPLICANT_DBG("connector %s", data->ssid->connector);
+ } else if (g_strcmp0(key, "c_sign_key") == 0) {
+ dbus_message_iter_get_basic(&value, &out_data);
+ data->ssid->c_sign_key = g_strdup((const gchar *)out_data);
+ SUPPLICANT_DBG("c_sign_key %s", data->ssid->c_sign_key);
+ } else if (g_strcmp0(key, "net_access_key") == 0) {
+ dbus_message_iter_get_basic(&value, &out_data);
+ data->ssid->net_access_key = g_strdup((const gchar *)out_data);
+ SUPPLICANT_DBG("net_access_key %s", data->ssid->net_access_key);
+ }
+ }
+ dbus_message_iter_next(&dict);
+ }
-static void interface_add_wps_params(DBusMessageIter *iter, void *user_data)
-{
- struct interface_connect_data *data = user_data;
- GSupplicantSSID *ssid = data->ssid;
- const char *role = "enrollee", *type;
- DBusMessageIter dict;
+ ret = supplicant_dbus_method_call(data->interface->path,
+ SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
+ interface_add_network_params,
+ interface_add_network_result, data,
+ data->interface);
- SUPPLICANT_DBG("");
+done:
+ if (ret < 0) {
+ SUPPLICANT_DBG("AddNetwork failed %d", ret);
+ callback_assoc_failed(decrypt_request_data.data->user_data);
+ g_free(data->path);
+ g_free(data->ssid->ssid);
+ g_free((char *)data->ssid->connector);
+ g_free((char *)data->ssid->c_sign_key);
+ g_free((char *)data->ssid->net_access_key);
+ g_free(data->ssid);
+ dbus_free(data);
+ }
- supplicant_dbus_dict_open(iter, &dict);
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(call);
- supplicant_dbus_dict_append_basic(&dict, "Role",
- DBUS_TYPE_STRING, &role);
+ decrypt_request_data.pending_call = NULL;
+ decrypt_request_data.data = NULL;
+}
- type = "pbc";
- if (ssid->pin_wps) {
- type = "pin";
- supplicant_dbus_dict_append_basic(&dict, "Pin",
- DBUS_TYPE_STRING, &ssid->pin_wps);
+static int send_decryption_conf_obj_request(GSupplicantSSID *ssid,
+ struct interface_connect_data *data)
+{
+ DBusMessage *msg = NULL;
+ DBusPendingCall *call;
+
+ SUPPLICANT_DBG("Decryption configuration object request");
+
+ if (!ssid) {
+ SUPPLICANT_DBG("Invalid parameter");
+ return -EINVAL;
}
- supplicant_dbus_dict_append_basic(&dict, "Type",
- DBUS_TYPE_STRING, &type);
+ if (!connection)
+ return -EINVAL;
- supplicant_dbus_dict_close(iter, &dict);
-}
+ msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH,
+ NETCONFIG_WIFI_INTERFACE, "DecryptConfObj");
+ if (!msg)
+ return -EINVAL;
-static void wps_start(const char *error, DBusMessageIter *iter, void *user_data)
-{
- struct interface_connect_data *data = user_data;
+ dbus_message_append_args(msg, DBUS_TYPE_STRING, &ssid->connector,
+ DBUS_TYPE_INVALID);
+ dbus_message_append_args(msg, DBUS_TYPE_STRING, &ssid->c_sign_key,
+ DBUS_TYPE_INVALID);
+ dbus_message_append_args(msg, DBUS_TYPE_STRING, &ssid->net_access_key,
+ DBUS_TYPE_INVALID);
- SUPPLICANT_DBG("");
+ if (!dbus_connection_send_with_reply(connection, msg,
+ &call, DBUS_TIMEOUT_USE_DEFAULT)) {
+ dbus_message_unref(msg);
+ return -EIO;
+ }
- if (error) {
- SUPPLICANT_DBG("error: %s", error);
- g_free(data->path);
- g_free(data->ssid);
- dbus_free(data);
- return;
+ if (!call) {
+ dbus_message_unref(msg);
+ return -EIO;
}
- supplicant_dbus_method_call(data->interface->path,
- SUPPLICANT_INTERFACE ".Interface.WPS", "Start",
- interface_add_wps_params,
- interface_wps_start_result, data, NULL);
-}
+ decrypt_request_data.pending_call = call;
+ decrypt_request_data.data = data;
-static void wps_process_credentials(DBusMessageIter *iter, void *user_data)
-{
- dbus_bool_t credentials = TRUE;
+ dbus_pending_call_set_notify(call, decrypt_conf_obj_reply, data, NULL);
+ dbus_message_unref(msg);
- SUPPLICANT_DBG("");
+ SUPPLICANT_DBG("Decrypt Conf Obj request succeeded");
- dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &credentials);
+ return 0;
}
+static bool is_valid_config_object(GSupplicantSSID *ssid)
+{
+ return ((ssid->connector &&
+ g_strcmp0(ssid->connector, "") != 0) &&
+ (ssid->c_sign_key &&
+ g_strcmp0(ssid->c_sign_key, "") != 0) &&
+ (ssid->net_access_key &&
+ g_strcmp0(ssid->net_access_key, "") != 0));
+}
+#endif
int g_supplicant_interface_connect(GSupplicantInterface *interface,
GSupplicantSSID *ssid,
intf_data->network_remove_in_progress = TRUE;
network_remove(intf_data);
} else {
+#if defined TIZEN_EXT
+ if (ssid->passphrase &&
+ g_strcmp0(ssid->passphrase, "") != 0 &&
+#if defined TIZEN_EXT_WIFI_MESH
+ ssid->mode != G_SUPPLICANT_MODE_MESH &&
+#endif
+ !ssid->eap) {
+ ret = send_decryption_request(ssid->passphrase, data);
+ if (ret < 0)
+ SUPPLICANT_DBG("Decryption request failed %d", ret);
+ } else if (is_valid_config_object(ssid)) {
+ ret = send_decryption_conf_obj_request(ssid, data);
+ if (ret < 0)
+ SUPPLICANT_DBG("Decryption Conf Obj request failed %d", ret);
+
+ } else
+#endif
ret = supplicant_dbus_method_call(interface->path,
SUPPLICANT_INTERFACE ".Interface", "AddNetwork",
interface_add_network_params,
interface_add_network_result, data,
interface);
}
- }
+ }
if (ret < 0) {
g_free(data->path);
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,
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,
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;
"interface=" SUPPLICANT_INTERFACE ".BSS";
static const char *g_supplicant_rule5 = "type=signal,"
"interface=" SUPPLICANT_INTERFACE ".Network";
+#if !defined TIZEN_EXT
static const char *g_supplicant_rule6 = "type=signal,"
"interface=" SUPPLICANT_INTERFACE ".Interface.P2PDevice";
static const char *g_supplicant_rule7 = "type=signal,"
"interface=" SUPPLICANT_INTERFACE ".Peer";
static const char *g_supplicant_rule8 = "type=signal,"
"interface=" SUPPLICANT_INTERFACE ".Group";
+#endif
+#if defined TIZEN_EXT_WIFI_MESH
+static const char *g_supplicant_rule9 = "type=signal,"
+ "interface=" SUPPLICANT_INTERFACE ".Interface.Mesh";
+#endif
static void invoke_introspect_method(void)
{
dbus_message_unref(message);
}
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+void g_supplicant_set_ins_settings(GSupplicantINSPreferredFreq preferred_freq_bssid,
+ bool last_connected_bssid, bool assoc_reject, bool signal_bssid,
+ unsigned int preferred_freq_bssid_score, unsigned int last_connected_bssid_score,
+ unsigned int assoc_reject_score, int signal_level3_5ghz, int signal_level3_24ghz)
+{
+ ins_settings.preferred_freq_bssid = preferred_freq_bssid;
+ ins_settings.last_connected_bssid = last_connected_bssid;
+ ins_settings.assoc_reject = assoc_reject;
+ ins_settings.signal_bssid = signal_bssid;
+ ins_settings.preferred_freq_bssid_score = preferred_freq_bssid_score;
+ ins_settings.last_connected_bssid_score = last_connected_bssid_score;
+ ins_settings.assoc_reject_score = assoc_reject_score;
+ ins_settings.signal_level3_5ghz = signal_level3_5ghz;
+ ins_settings.signal_level3_24ghz = signal_level3_24ghz;
+
+ SUPPLICANT_DBG("preferred_freq_bssid [%s]", preferred_freq_bssid ? "true" : "false");
+ SUPPLICANT_DBG("preferred_freq_bssid_score [%d]", preferred_freq_bssid_score);
+ SUPPLICANT_DBG("last_connected_bssid [%s]", last_connected_bssid ? "true" : "false");
+ SUPPLICANT_DBG("last_connected_bssid_score [%d]", last_connected_bssid_score);
+ SUPPLICANT_DBG("assoc_reject [%s]", assoc_reject ? "true" : "false");
+ SUPPLICANT_DBG("assoc_reject_score [%d]", assoc_reject_score);
+ SUPPLICANT_DBG("signal_bssid [%s]", signal_bssid ? "true" : "false");
+ SUPPLICANT_DBG("signal_level3_5ghz [%d]", signal_level3_5ghz);
+ SUPPLICANT_DBG("signal_level3_24ghz [%d]", signal_level3_24ghz);
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+void g_supplicant_register_eap_callback(g_supplicant_eap_callback cb)
+{
+ SUPPLICANT_DBG("g_supplicant_register_eap_callback %p", cb);
+
+ if (!callbacks_pointer) {
+ SUPPLICANT_DBG("callbacks_pointer is NULL");
+ return;
+ }
+
+ callbacks_pointer->eap = cb;
+}
+
+void g_supplicant_unregister_eap_callback(void)
+{
+ SUPPLICANT_DBG("g_supplicant_unregister_eap_callback");
+
+ if (!callbacks_pointer) {
+ SUPPLICANT_DBG("callbacks_pointer is NULL");
+ return;
+ }
+
+ callbacks_pointer->eap = NULL;
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+int g_supplicant_register(GSupplicantCallbacks *callbacks)
+#else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
int g_supplicant_register(const GSupplicantCallbacks *callbacks)
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
{
connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
if (!connection)
connection = NULL;
return -EIO;
}
-
+#if defined TIZEN_EXT
+ simplified_log = connman_setting_get_bool("SimplifiedLog");
+#endif
callbacks_pointer = callbacks;
eap_methods = 0;
dbus_bus_add_match(connection, g_supplicant_rule3, NULL);
dbus_bus_add_match(connection, g_supplicant_rule4, NULL);
dbus_bus_add_match(connection, g_supplicant_rule5, NULL);
+#if defined TIZEN_EXT
+ dbus_bus_add_match(connection,
+ "type=signal,interface=org.tizen.system.deviced.PowerOff,"
+ "member=ChangeState", NULL);
+#endif
+#if !defined TIZEN_EXT
dbus_bus_add_match(connection, g_supplicant_rule6, NULL);
dbus_bus_add_match(connection, g_supplicant_rule7, NULL);
dbus_bus_add_match(connection, g_supplicant_rule8, NULL);
+#endif
+#if defined TIZEN_EXT_WIFI_MESH
+ dbus_bus_add_match(connection, g_supplicant_rule9, NULL);
+#endif
dbus_connection_flush(connection);
if (dbus_bus_name_has_owner(connection,
} else
invoke_introspect_method();
+ SUPPLICANT_DBG("supplicant dbus setup completed");
return 0;
}
SUPPLICANT_DBG("");
if (connection) {
+#if defined TIZEN_EXT_WIFI_MESH
+ dbus_bus_remove_match(connection, g_supplicant_rule9, NULL);
+#endif
+#if !defined TIZEN_EXT
dbus_bus_remove_match(connection, g_supplicant_rule8, NULL);
dbus_bus_remove_match(connection, g_supplicant_rule7, NULL);
dbus_bus_remove_match(connection, g_supplicant_rule6, NULL);
+#endif
dbus_bus_remove_match(connection, g_supplicant_rule5, NULL);
dbus_bus_remove_match(connection, g_supplicant_rule4, NULL);
dbus_bus_remove_match(connection, g_supplicant_rule3, NULL);
callbacks_pointer = NULL;
eap_methods = 0;
}
+
+#ifdef TIZEN_EXT
+struct supplicant_mac_policy {
+ GSupplicantMacPolicyCallback callback;
+ dbus_uint32_t policy;
+ const void *user_data;
+};
+
+static void mac_policy_result(const char *error,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct supplicant_mac_policy *data = user_data;
+ int result = 0;
+
+ if (!user_data)
+ return;
+
+ if (error) {
+ SUPPLICANT_DBG("Mac policy setting failure %s", error);
+ result = -EINVAL;
+ }
+
+ if (data->callback)
+ data->callback(result, data->policy,
+ (void *) data->user_data);
+
+ dbus_free(data);
+}
+
+static void mac_policy_params(DBusMessageIter *iter, void *user_data)
+{
+ struct supplicant_mac_policy *data = user_data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &(data->policy));
+}
+
+int g_supplicant_interface_set_mac_policy(GSupplicantInterface *interface,
+ GSupplicantMacPolicyCallback callback,
+ unsigned int policy,
+ void *user_data)
+{
+ struct supplicant_mac_policy *data = NULL;
+ int ret;
+
+ if (!system_available)
+ return -EFAULT;
+
+ if (!interface)
+ return -EINVAL;
+
+ data = dbus_malloc0(sizeof(*data));
+ if (!data)
+ return -ENOMEM;
+
+ data->callback = callback;
+ data->policy = policy;
+ data->user_data = user_data;
+
+ ret = supplicant_dbus_property_set(interface->path,
+ SUPPLICANT_INTERFACE ".Interface",
+ "MacAddr", DBUS_TYPE_INT32_AS_STRING,
+ mac_policy_params, mac_policy_result, data, NULL);
+ if (ret < 0) {
+ SUPPLICANT_DBG("Unable to set MacAddr configuration");
+ dbus_free(data);
+ }
+
+ return ret;
+}
+
+int g_supplicant_interface_set_preassoc_mac_policy(GSupplicantInterface *interface,
+ GSupplicantMacPolicyCallback callback,
+ unsigned int policy,
+ void *user_data)
+{
+ struct supplicant_mac_policy *data;
+ int ret;
+
+ if (!system_available)
+ return -EFAULT;
+
+ if (!interface)
+ return -EINVAL;
+
+ data = dbus_malloc0(sizeof(*data));
+ if (!data)
+ return -ENOMEM;
+
+ data->callback = callback;
+ data->policy = policy;
+ data->user_data = user_data;
+
+ ret = supplicant_dbus_property_set(interface->path,
+ SUPPLICANT_INTERFACE ".Interface",
+ "PreassocMacAddr", DBUS_TYPE_INT32_AS_STRING,
+ mac_policy_params, mac_policy_result, data, NULL);
+ if (ret < 0) {
+ SUPPLICANT_DBG("Unable to set PreassocMacAddr configuration");
+ dbus_free(data);
+ }
+
+ return ret;
+}
+
+struct supplicant_random_mac_lifetime {
+ GSupplicantRandomMaclifetimeCallback callback;
+ dbus_uint32_t lifetime;
+ const void *user_data;
+};
+
+static void random_mac_lifetime_result(const char *error,
+ DBusMessageIter *iter, void *user_data)
+{
+ struct supplicant_random_mac_lifetime *data = user_data;
+ int result = 0;
+
+ if (!user_data)
+ return;
+
+ if (error) {
+ SUPPLICANT_DBG("Random Mac lifetime setting failure %s", error);
+ result = -EINVAL;
+ }
+
+ if (data->callback)
+ data->callback(result, data->lifetime,
+ (void *) data->user_data);
+
+ dbus_free(data);
+}
+
+static void random_mac_lifetime_params(DBusMessageIter *iter, void *user_data)
+{
+ struct supplicant_random_mac_lifetime *data = user_data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &(data->lifetime));
+}
+
+int g_supplicant_interface_set_random_mac_lifetime(GSupplicantInterface *interface,
+ GSupplicantRandomMaclifetimeCallback callback,
+ unsigned int lifetime,
+ void *user_data)
+{
+ struct supplicant_random_mac_lifetime *data;
+ int ret;
+
+ if (!system_available)
+ return -EFAULT;
+
+ if (!interface)
+ return -EINVAL;
+
+ data = dbus_malloc0(sizeof(*data));
+ if (!data)
+ return -ENOMEM;
+
+ data->callback = callback;
+ data->lifetime = lifetime;
+ data->user_data = user_data;
+
+ ret = supplicant_dbus_property_set(interface->path,
+ SUPPLICANT_INTERFACE ".Interface",
+ "RandAddrLifetime", DBUS_TYPE_UINT32_AS_STRING,
+ random_mac_lifetime_params, random_mac_lifetime_result,
+ data, NULL);
+ if (ret < 0) {
+ SUPPLICANT_DBG("Unable to set RandAddrLifetime configuration");
+ dbus_free(data);
+ }
+
+ return ret;
+}
+#endif
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) {
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]);
#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
#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
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);
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;
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);
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);
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
#ifndef __CONNMAN_LOG_H
#define __CONNMAN_LOG_H
+#if defined TIZEN_EXT
+#include <stdbool.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
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;
__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
--- /dev/null
+/*
+ *
+ * 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 */
--- /dev/null
+/*
+ *
+ * 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 */
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
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
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);
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,
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);
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);
#include <stdbool.h>
+#if defined TIZEN_EXT
+#include <glib.h>
+#include <gdbus.h>
+#endif
+
#ifdef __cplusplus
extern "C" {
#endif
CONNMAN_SERVICE_TYPE_VPN = 7,
CONNMAN_SERVICE_TYPE_GADGET = 8,
CONNMAN_SERVICE_TYPE_P2P = 9,
+#if defined TIZEN_EXT_WIFI_MESH
+ CONNMAN_SERVICE_TYPE_MESH = 10,
+#endif
};
+#if defined TIZEN_EXT_WIFI_MESH
+#define MAX_CONNMAN_SERVICE_TYPES 11
+#else
#define MAX_CONNMAN_SERVICE_TYPES 10
+#endif
enum connman_service_security {
CONNMAN_SERVICE_SECURITY_8021X = 4,
CONNMAN_SERVICE_SECURITY_WPA = 8,
CONNMAN_SERVICE_SECURITY_RSN = 9,
+#if defined TIZEN_EXT
+ CONNMAN_SERVICE_SECURITY_SAE = 10,
+ CONNMAN_SERVICE_SECURITY_OWE = 11,
+ CONNMAN_SERVICE_SECURITY_DPP = 12,
+#endif
+#if defined TIZEN_EXT
+ CONNMAN_SERVICE_SECURITY_MAX
+#endif
};
enum connman_service_state {
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 {
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
#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);
* @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,
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
}
--- /dev/null
+%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
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;
}
g_strdup(path), g_free))
return -EIO;
+#if defined TIZEN_EXT
+ if (pan->network)
+#endif
connman_network_set_associating(pan->network, true);
return -EINPROGRESS;
DBG("network %p", pan->network);
+#if defined TIZEN_EXT
+ if (pan->network)
+#endif
connman_network_set_connected(pan->network, false);
}
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",
goto out;
}
+#if !defined TIZEN_EXT
enable_device(device, path);
+#endif
out:
g_free(path);
}
goto out;
}
+#if !defined TIZEN_EXT
disable_device(device, path);
+#endif
out:
g_free(path);
<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>
#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;
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 */
};
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);
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,
} 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
}
}
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);
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);
.set_tethering = eth_tech_set_tethering,
};
+#if defined TIZEN_EXT_WIFI_MESH
+static int eth_mesh_add_to_bridge(const char *bridge)
+{
+ GList *list;
+ struct ethernet_data *ethernet;
+
+ DBG("Add ethernet to bridge %s", bridge);
+
+ for (list = eth_interface_list; list; list = list->next) {
+ int index = GPOINTER_TO_INT(list->data);
+ struct connman_device *device =
+ connman_device_find_by_index(index);
+
+ if (device) {
+ ethernet = connman_device_get_data(device);
+ if (ethernet)
+ remove_network(device, ethernet);
+ }
+
+ connman_inet_ifup(index);
+
+ connman_inet_add_to_bridge(index, bridge);
+ }
+
+ return 0;
+}
+
+static int eth_mesh_remove_from_bridge(const char *bridge)
+{
+ GList *list;
+
+ DBG("Remove ethernet from bridge %s", bridge);
+
+ for (list = eth_interface_list; list; list = list->next) {
+ int index = GPOINTER_TO_INT(list->data);
+
+ connman_inet_remove_from_bridge(index, bridge);
+ }
+
+ return 0;
+}
+
+static struct connman_mesh_eth_driver eth_mesh_driver = {
+ .add_to_bridge = eth_mesh_add_to_bridge,
+ .remove_from_bridge = eth_mesh_remove_from_bridge,
+};
+#endif
+
static int ethernet_init(void)
{
int err;
if (err < 0)
return err;
+#if defined TIZEN_EXT_WIFI_MESH
+ err = connman_mesh_eth_driver_register(ð_mesh_driver);
+ if (err < 0)
+ return err;
+#endif
+
err = connman_network_driver_register(ð_network_driver);
if (err < 0)
return err;
{
connman_technology_driver_unregister(ð_tech_driver);
+#if defined TIZEN_EXT_WIFI_MESH
+ connman_mesh_eth_driver_unregister(ð_mesh_driver);
+#endif
+
connman_network_driver_unregister(ð_network_driver);
connman_device_driver_unregister(ð_dev_driver);
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)
{
#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>
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";
strncpy(system_hostname, name, HOST_NAME_MAX);
}
+#endif
+
static int setup_hostname(void)
{
char name[HOST_NAME_MAX + 1];
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));
--- /dev/null
+/*
+ *
+ * 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)
#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;
bool p2p_connecting;
bool p2p_device;
int servicing;
+#if defined TIZEN_EXT
+ int assoc_retry_count;
+ struct connman_network *scan_pending_network;
+ bool allow_full_scan;
+ unsigned int automaxspeed_timeout;
+ GSupplicantScanParams *hidden_scan_params;
+ unsigned int mac_policy;
+ unsigned int preassoc_mac_policy;
+ unsigned int mac_lifetime;
+#endif
int disconnect_code;
int assoc_code;
+#if defined TIZEN_EXT_WIFI_MESH
+ bool mesh_interface;
+ struct wifi_mesh_info *mesh_info;
+#endif
};
struct disconnect_data {
struct 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;
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;
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(¬ifier);
+ 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(¬ifier);
+ 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(¬ifier);
+ 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
if (params->type == CONNMAN_SERVICE_TYPE_P2P)
return p2p_find(device);
+#if defined TIZEN_EXT_WIFI_MESH
+ if (params->type == CONNMAN_SERVICE_TYPE_MESH)
+ return mesh_scan(device);
+#endif
+
DBG("device %p wifi %p hidden ssid %s", device, wifi->interface,
params->ssid);
connman_device_ref(device);
reset_autoscan(device);
-
+#if defined TIZEN_EXT
+ /*
+ * When doing a full scan, stored hidden networks also need to be scanned
+ * so that we can autoconnect to them.
+ */
+ if (params->force_full_scan)
+ ret = g_supplicant_interface_scan(wifi->interface, scan_params,
+ scan_callback_hidden, device);
+ else
+#endif
ret = g_supplicant_interface_scan(wifi->interface, scan_params,
scan_callback, device);
if (ret == 0) {
connman_device_set_scanning(device,
CONNMAN_SERVICE_TYPE_WIFI, true);
+#if defined TIZEN_EXT
+ /*
+ * To allow the Full Scan after ssid based scan, set the flag here
+ * It is required because Tizen does not use the ConnMan specific
+ * backgroung Scan feature.Tizen has added the BG Scan feature in
+ * net-config. To sync with up ConnMan, we need to issue the Full Scan
+ * after SSID specific scan.
+ */
+ if (!params->force_full_scan && !do_hidden)
+ wifi->allow_full_scan = TRUE;
+#endif
} else {
g_supplicant_free_scan_params(scan_params);
connman_device_unref(device);
.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)
static int network_probe(struct connman_network *network)
{
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
DBG("network %p", network);
return 0;
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);
return G_SUPPLICANT_SECURITY_PSK;
else if (g_str_equal(security, "ieee8021x"))
return G_SUPPLICANT_SECURITY_IEEE8021X;
+#if defined TIZEN_EXT
+ else if (g_str_equal(security, "ft_psk") == TRUE)
+ return G_SUPPLICANT_SECURITY_FT_PSK;
+ else if (g_str_equal(security, "ft_ieee8021x") == TRUE)
+ return G_SUPPLICANT_SECURITY_FT_IEEE8021X;
+ else if (g_str_equal(security, "sae"))
+ return G_SUPPLICANT_SECURITY_SAE;
+ else if (g_str_equal(security, "owe"))
+ return G_SUPPLICANT_SECURITY_OWE;
+ else if (g_str_equal(security, "dpp"))
+ return G_SUPPLICANT_SECURITY_DPP;
+#endif
return G_SUPPLICANT_SECURITY_UNKNOWN;
}
+#if defined TIZEN_EXT
+static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security)
+{
+ if (security == NULL)
+ return G_SUPPLICANT_EAP_KEYMGMT_NONE;
+
+ if (g_str_equal(security, "FT") == TRUE)
+ return G_SUPPLICANT_EAP_KEYMGMT_FT;
+ else if (g_str_equal(security, "CCKM") == TRUE)
+ return G_SUPPLICANT_EAP_KEYMGMT_CCKM;
+
+ return G_SUPPLICANT_EAP_KEYMGMT_NONE;
+}
+#endif
+
static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network)
{
const char *security;
+#if defined TIZEN_EXT
+ const void *ssid_data;
+#endif
memset(ssid, 0, sizeof(*ssid));
ssid->mode = G_SUPPLICANT_MODE_INFRA;
+#if defined TIZEN_EXT
+ ssid_data = connman_network_get_blob(network, "WiFi.SSID",
+ &ssid->ssid_len);
+ ssid->ssid = g_try_malloc0(ssid->ssid_len);
+
+ if (!ssid->ssid)
+ ssid->ssid_len = 0;
+ else
+ memcpy(ssid->ssid, ssid_data, ssid->ssid_len);
+#else
ssid->ssid = connman_network_get_blob(network, "WiFi.SSID",
&ssid->ssid_len);
+#endif
ssid->scan_ssid = 1;
security = connman_network_get_string(network, "WiFi.Security");
ssid->security = network_security(security);
+#if defined TIZEN_EXT
+ ssid->ieee80211w = 1;
+#endif
ssid->passphrase = connman_network_get_string(network,
"WiFi.Passphrase");
ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS");
ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS");
+#if defined TIZEN_EXT
+ ssid->connector = connman_network_get_string(network,
+ "WiFi.Connector");
+ ssid->c_sign_key = connman_network_get_string(network,
+ "WiFi.CSignKey");
+ ssid->net_access_key = connman_network_get_string(network,
+ "WiFi.NetAccessKey");
+#endif
+
+#if defined TIZEN_EXT
+ const char *ifname = connman_device_get_string(
+ connman_network_get_device(network), "Interface");
+ if (set_connman_bssid(CHECK_BSSID, NULL, ifname) == 6) {
+ ssid->bssid_for_connect_len = 6;
+ set_connman_bssid(GET_BSSID, (char *)ssid->bssid_for_connect, ifname);
+ DBG("BSSID : %02x:%02x:%02x:%02x:%02x:%02x",
+ ssid->bssid_for_connect[0], ssid->bssid_for_connect[1],
+ ssid->bssid_for_connect[2], ssid->bssid_for_connect[3],
+ ssid->bssid_for_connect[4], ssid->bssid_for_connect[5]);
+ } else {
+ ssid->freq = connman_network_get_frequency(network);
+ }
+
+ GSList *bssid_list = (GSList *)connman_network_get_bssid_list(network);
+ if (bssid_list && g_slist_length(bssid_list) > 1) {
+
+ /* If there are more than one bssid,
+ * the user-specified bssid is tried only once at the beginning.
+ * After that, the bssids in the list are tried in order.
+ */
+ if (set_connman_bssid(CHECK_BSSID, NULL, ifname) == 6) {
+ set_connman_bssid(RESET_BSSID, NULL, ifname);
+ goto done;
+ }
+
+ GSList *list;
+ char buff[MAC_ADDRESS_LENGTH];
+ for (list = bssid_list; list; list = list->next) {
+ struct connman_bssids * bssids = (struct connman_bssids *)list->data;
+
+ g_snprintf(buff, MAC_ADDRESS_LENGTH, "%02x:%02x:%02x:%02x:%02x:%02x",
+ bssids->bssid[0], bssids->bssid[1], bssids->bssid[2],
+ bssids->bssid[3], bssids->bssid[4], bssids->bssid[5]);
+ buff[MAC_ADDRESS_LENGTH - 1] = '\0';
+
+ gchar *curr_bssid = g_strdup((const gchar *)buff);
+
+ if (g_hash_table_contains(failed_bssids, curr_bssid)) {
+ DBG("bssid match, try next bssid");
+ g_free(curr_bssid);
+ continue;
+ } else {
+ g_hash_table_add(failed_bssids, curr_bssid);
+
+ memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX);
+ ssid->bssid = buff_bssid;
+ ssid->freq = (unsigned int)bssids->frequency;
+ break;
+ }
+ }
+
+ if (!list) {
+ ssid->bssid = connman_network_get_bssid(network);
+ g_hash_table_remove_all(failed_bssids);
+ }
+ } else
+ ssid->bssid = connman_network_get_bssid(network);
+
+done:
+ ssid->eap_keymgmt = network_eap_keymgmt(
+ connman_network_get_string(network, "WiFi.KeymgmtType"));
+ ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1");
+
+ if(g_strcmp0(ssid->eap, "fast") == 0)
+ ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE);
+
+ ssid->keymgmt = connman_network_get_keymgmt(network);
+#endif
if (connman_setting_get_bool("BackgroundScanning"))
ssid->bgscan = BGSCAN_DEFAULT;
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);
{
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,
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;
struct disconnect_data *dd;
struct wifi_data *wifi;
int err;
+#if defined TIZEN_EXT
+ struct connman_service *service;
+#endif
DBG("network %p", network);
if (!wifi || !wifi->interface)
return -ENODEV;
+#if defined TIZEN_EXT
+ if (connman_network_get_associating(network) == true) {
+ connman_network_clear_associating(network);
+ connman_network_set_bool(network, "WiFi.UseWPS", false);
+ } else {
+ service = connman_service_lookup_from_network(network);
+
+ if (service != NULL &&
+ (__connman_service_is_connected_state(service,
+ CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
+ __connman_service_is_connected_state(service,
+ CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
+ (connman_service_get_favorite(service) == false))
+ __connman_service_set_passphrase(service, NULL);
+ }
+
+ if (wifi->pending_network == network)
+ wifi->pending_network = NULL;
+
+ if (wifi->scan_pending_network == network)
+ wifi->scan_pending_network = NULL;
+
+#endif
connman_network_set_associating(network, false);
if (wifi->disconnecting)
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,
{
const char *ifname = g_supplicant_interface_get_ifname(interface);
const char *driver = g_supplicant_interface_get_driver(interface);
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
+#if defined TIZEN_EXT
+ bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface);
+#endif
+
struct wifi_data *wifi;
wifi = g_supplicant_interface_get_data(interface);
}
connman_device_set_powered(wifi->device, true);
+#if defined TIZEN_EXT
+ connman_device_set_wifi_5ghz_supported(wifi->device, is_5_0_ghz_supported);
+ /* Max number of SSIDs supported by wlan chipset that can be scanned */
+ int max_scan_ssids = g_supplicant_interface_get_max_scan_ssids(interface);
+ connman_device_set_max_scan_ssids(wifi->device, max_scan_ssids);
+#endif
}
static bool is_idle(struct wifi_data *wifi)
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;
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;
{
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)))
if (wifi->connected)
return false;
+#endif
service = connman_service_lookup_from_network(network);
if (!service)
return false;
}
+#if defined TIZEN_EXT
+static bool handle_wifi_assoc_retry(struct connman_network *network,
+ struct wifi_data *wifi)
+{
+ const char *security;
+
+ if (!wifi->network || wifi->connected || wifi->disconnecting ||
+ connman_network_get_connecting(network) != true) {
+ wifi->assoc_retry_count = 0;
+ return false;
+ }
+
+ if (wifi->state != G_SUPPLICANT_STATE_AUTHENTICATING &&
+ wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
+ wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
+ wifi->assoc_retry_count = 0;
+ return false;
+ }
+
+ security = connman_network_get_string(network, "WiFi.Security");
+ if (security && g_str_equal(security, "ieee8021x") == true &&
+ wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
+ wifi->assoc_retry_count = 0;
+ return false;
+ }
+
+ if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
+ wifi->assoc_retry_count = 0;
+
+ /* Honestly it's not an invalid-key error,
+ * however QA team recommends that the invalid-key error
+ * might be better to display for user experience.
+ */
+ switch (wifi->state) {
+ case G_SUPPLICANT_STATE_AUTHENTICATING:
+ connman_network_set_error(network, CONNMAN_NETWORK_ERROR_AUTHENTICATE_FAIL);
+ break;
+ case G_SUPPLICANT_STATE_ASSOCIATED:
+ connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
+ break;
+ default:
+ connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
+ break;
+ }
+
+ return false;
+ }
+
+ return true;
+}
+#endif
+
static void interface_state(GSupplicantInterface *interface)
{
struct connman_network *network;
struct connman_device *device;
struct wifi_data *wifi;
GSupplicantState state = g_supplicant_interface_get_state(interface);
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
bool wps;
bool old_connected;
switch (state) {
case G_SUPPLICANT_STATE_SCANNING:
+#if defined TIZEN_EXT
+ if (wifi->automaxspeed_timeout != 0) {
+ g_source_remove(wifi->automaxspeed_timeout);
+ wifi->automaxspeed_timeout = 0;
+ DBG("Remove signalpoll timer!!");
+ }
+#endif
if (wifi->connected)
connman_network_set_connected(network, false);
case G_SUPPLICANT_STATE_AUTHENTICATING:
case G_SUPPLICANT_STATE_ASSOCIATING:
+#if defined TIZEN_EXT
+ reset_autoscan(device);
+#else
stop_autoscan(device);
+#endif
if (!wifi->connected)
connman_network_set_associating(network, true);
break;
case G_SUPPLICANT_STATE_COMPLETED:
+#if defined TIZEN_EXT
+ /* though it should be already reset: */
+ reset_autoscan(device);
+
+ wifi->assoc_retry_count = 0;
+
+ wifi->scan_pending_network = NULL;
+
+ /* should be cleared scanning flag */
+ bool scanning = connman_device_get_scanning(device,
+ CONNMAN_SERVICE_TYPE_WIFI);
+ if (scanning){
+ connman_device_set_scanning(device,
+ CONNMAN_SERVICE_TYPE_WIFI, false);
+ connman_device_unref(device);
+ }
+
+ if (!wifi->automaxspeed_timeout) {
+ DBG("Going to start signalpoll timer!!");
+ int ret = network_signalpoll(wifi);
+ if (ret < 0)
+ DBG("Fail to get max speed !!");
+ else
+ wifi->automaxspeed_timeout = g_timeout_add_seconds(10, autosignalpoll_timeout, wifi);
+ }
+
+ g_hash_table_remove_all(failed_bssids);
+#else
/* though it should be already stopped: */
stop_autoscan(device);
+#endif
if (!handle_wps_completion(interface, network, device, wifi))
break;
break;
case G_SUPPLICANT_STATE_DISCONNECTED:
+#if defined TIZEN_EXT
+ connman_network_set_strength(network, 0);
+ connman_network_set_maxspeed(network, 0);
+
+ if (wifi->automaxspeed_timeout != 0) {
+ g_source_remove(wifi->automaxspeed_timeout);
+ wifi->automaxspeed_timeout = 0;
+ DBG("Remove signalpoll timer!!");
+ }
+#endif
/*
* If we're in one of the idle modes, we have
* not started association yet and thus setting
if (is_idle(wifi))
break;
+#if defined TIZEN_EXT
+ if (handle_assoc_status_code(interface, wifi)) {
+ const char *group = connman_network_get_group(network);
+ GSupplicantNetwork *supplicant_network;
+ GSList *bssid_list = NULL;
+ guint bssid_length = 0;
+
+ if (group) {
+ supplicant_network = g_supplicant_interface_get_network(interface, group);
+
+ connman_network_set_assoc_reject_table(network,
+ g_supplicant_network_get_assoc_reject_table(supplicant_network));
+
+ g_supplicant_network_update_assoc_reject(interface, supplicant_network);
+ }
+
+ bssid_list = (GSList *)connman_network_get_bssid_list(network);
+ if (bssid_list)
+ bssid_length = g_slist_length(bssid_list);
+
+ if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
+ network_connect(network);
+ break;
+ }
+
+ wifi->load_shaping_retries = 0;
+ }
+
+ g_hash_table_remove_all(failed_bssids);
+#else
if (handle_assoc_status_code(interface, wifi))
break;
+#endif
/* If previous state was 4way-handshake, then
* it's either: psk was incorrect and thus we retry
/* See table 8-36 Reason codes in IEEE Std 802.11 */
switch (wifi->disconnect_code) {
+#if defined TIZEN_EXT
+ case 1: /* Unspecified reason */
+ /* Let's assume it's because we got blocked */
+#endif
case 6: /* Class 2 frame received from nonauthenticated STA */
connman_network_set_error(network,
CONNMAN_NETWORK_ERROR_BLOCKED);
break;
}
+#if defined TIZEN_EXT
+ /* Some of Wi-Fi networks are not comply Wi-Fi specification.
+ * Retry association until its retry count is expired */
+ if (handle_wifi_assoc_retry(network, wifi) == true) {
+ throw_wifi_scan(wifi->device, scan_callback);
+ wifi->scan_pending_network = wifi->network;
+ break;
+ }
+
+ if(wifi->disconnect_code > 0){
+ DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
+ connman_network_set_disconnect_reason(network, wifi->disconnect_code);
+ }
+#endif
+
if (network != wifi->pending_network) {
connman_network_set_connected(network, false);
connman_network_set_associating(network, false);
break;
case G_SUPPLICANT_STATE_INACTIVE:
+#if defined TIZEN_EXT
+ if (handle_wps_completion(interface, network, device, wifi) == false)
+ break;
+#endif
connman_network_set_associating(network, false);
start_autoscan(device);
{
const char *ifname = g_supplicant_interface_get_ifname(interface);
struct wifi_data *wifi;
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
DBG("ifname %s", ifname);
wifi = g_supplicant_interface_get_data(interface);
+#if defined TIZEN_EXT_WIFI_MESH
+ if (wifi && wifi->mesh_interface) {
+ DBG("Notify mesh interface remove");
+ connman_mesh_notify_interface_remove(true);
+ struct wifi_mesh_info *mesh_info = wifi->mesh_info;
+ g_free(mesh_info->parent_ifname);
+ g_free(mesh_info->ifname);
+ g_free(mesh_info->identifier);
+ g_free(mesh_info);
+ wifi->mesh_interface = false;
+ wifi->mesh_info = NULL;
+ return;
+ }
+#endif
+
if (wifi)
wifi->interface = NULL;
connman_device_set_powered(wifi->device, false);
check_p2p_technology();
+#if defined TIZEN_EXT_WIFI_MESH
+ check_mesh_technology();
+#endif
}
static void set_device_type(const char *type, char dev_type[17])
{
char dev_type[17] = {};
const char *hostname;
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
DBG("");
static void scan_started(GSupplicantInterface *interface)
{
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
DBG("");
}
static void scan_finished(GSupplicantInterface *interface)
{
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
+#if defined TIZEN_EXT
+ struct wifi_data *wifi;
+ bool is_associating = false;
+ static bool is_scanning = true;
+#endif
+
DBG("");
+
+#if defined TIZEN_EXT
+ wifi = g_supplicant_interface_get_data(interface);
+ if (wifi && wifi->scan_pending_network) {
+ network_connect(wifi->scan_pending_network);
+ wifi->scan_pending_network = NULL;
+ }
+
+ //service state - associating
+ if(!wifi || !wifi->network)
+ return;
+
+ is_associating = connman_network_get_associating(wifi->network);
+ if(is_associating && is_scanning){
+ is_scanning = false;
+ DBG("send scan for connecting");
+ throw_wifi_scan(wifi->device, scan_callback);
+
+ return;
+ }
+ is_scanning = true;
+
+ //go scan
+
+#endif
}
static void ap_create_fail(GSupplicantInterface *interface)
{
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
int ret;
unsigned char strength;
strength = 120 + g_supplicant_network_get_signal(supplicant_network);
+#if !defined TIZEN_EXT
if (strength > 100)
strength = 100;
+#endif
return strength;
}
+#if defined TIZEN_EXT_WIFI_MESH
+static void mesh_peer_added(GSupplicantNetwork *supplicant_network)
+{
+ GSupplicantInterface *interface;
+ struct wifi_data *wifi;
+ const char *name, *security;
+ struct connman_mesh *connman_mesh;
+ struct wifi_mesh_info *mesh_info;
+ const unsigned char *bssid;
+ const char *identifier;
+ char *address;
+ uint16_t frequency;
+ int ret;
+
+ interface = g_supplicant_network_get_interface(supplicant_network);
+ wifi = g_supplicant_interface_get_data(interface);
+ if (!wifi || !wifi->mesh_interface) {
+ DBG("Virtual Mesh interface not created");
+ return;
+ }
+
+ bssid = g_supplicant_network_get_bssid(supplicant_network);
+ address = g_malloc0(19);
+ snprintf(address, 19, "%02x:%02x:%02x:%02x:%02x:%02x", bssid[0], bssid[1],
+ bssid[2], bssid[3], bssid[4], bssid[5]);
+
+ identifier = g_supplicant_network_get_identifier(supplicant_network);
+ name = g_supplicant_network_get_name(supplicant_network);
+ security = g_supplicant_network_get_security(supplicant_network);
+ frequency = g_supplicant_network_get_frequency(supplicant_network);
+
+ mesh_info = wifi->mesh_info;
+ connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
+ if (connman_mesh)
+ goto done;
+
+ DBG("Mesh Peer name %s identifier %s security %s added", name, identifier,
+ security);
+ connman_mesh = connman_mesh_create(mesh_info->identifier, identifier);
+ connman_mesh_set_name(connman_mesh, name);
+ connman_mesh_set_security(connman_mesh, security);
+ connman_mesh_set_frequency(connman_mesh, frequency);
+ connman_mesh_set_address(connman_mesh, address);
+ connman_mesh_set_index(connman_mesh, mesh_info->index);
+ connman_mesh_set_strength(connman_mesh,
+ calculate_strength(supplicant_network));
+ connman_mesh_set_peer_type(connman_mesh, CONNMAN_MESH_PEER_TYPE_DISCOVERED);
+
+ ret = connman_mesh_register(connman_mesh);
+ if (ret == -EALREADY)
+ DBG("Mesh Peer is already registered");
+
+done:
+ g_free(address);
+}
+
+static void mesh_peer_removed(GSupplicantNetwork *supplicant_network)
+{
+ GSupplicantInterface *interface;
+ struct wifi_data *wifi;
+ struct connman_mesh *connman_mesh;
+ struct wifi_mesh_info *mesh_info;
+ const char *identifier;
+
+ interface = g_supplicant_network_get_interface(supplicant_network);
+ wifi = g_supplicant_interface_get_data(interface);
+ if (!wifi || !wifi->mesh_interface) {
+ DBG("Virtual Mesh interface not created");
+ return;
+ }
+
+ identifier = g_supplicant_network_get_identifier(supplicant_network);
+ if (!identifier) {
+ DBG("Failed to get Mesh Peer identifier");
+ return;
+ }
+
+ mesh_info = wifi->mesh_info;
+ connman_mesh = connman_mesh_get(mesh_info->identifier, identifier);
+ if (connman_mesh) {
+ /* Do not unregister connected mesh peer */
+ if (connman_mesh_peer_is_connected_state(connman_mesh)) {
+ DBG("Mesh Peer %s is connected", identifier);
+ return;
+ }
+ DBG("Mesh Peer identifier %s removed", identifier);
+ connman_mesh_unregister(connman_mesh);
+ }
+}
+#endif
+
+
+#if defined TIZEN_EXT
+static GSList *get_supported_security_list(unsigned int keymgmt,
+ bool owe_transition_mode,
+ GSupplicantNetwork *supplicant_network)
+{
+ GSList *sec_list = NULL;
+ dbus_bool_t privacy = g_supplicant_network_get_privacy(supplicant_network);
+ const char *enc_mode = g_supplicant_network_get_enc_mode(supplicant_network);
+
+ if (keymgmt &
+ (G_SUPPLICANT_KEYMGMT_WPA_EAP |
+ G_SUPPLICANT_KEYMGMT_WPA_EAP_256))
+ sec_list = g_slist_prepend (sec_list, "ieee8021x");
+ else if (keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_EAP)
+ sec_list = g_slist_prepend (sec_list, "ft_ieee8021x");
+
+ if (sec_list)
+ return sec_list;
+
+ if (keymgmt &
+ (G_SUPPLICANT_KEYMGMT_WPA_PSK |
+ G_SUPPLICANT_KEYMGMT_WPA_PSK_256)) {
+ if (!g_strcmp0(enc_mode, "aes"))
+ sec_list = g_slist_prepend (sec_list, "rsn");
+ else if (!g_strcmp0(enc_mode, "tkip"))
+ sec_list = g_slist_prepend (sec_list, "psk");
+ else if (!g_strcmp0(enc_mode, "mixed")) {
+ sec_list = g_slist_prepend (sec_list, "psk");
+ sec_list = g_slist_prepend (sec_list, "rsn");
+ }
+ } else if (keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK)
+ sec_list = g_slist_prepend (sec_list, "ft_psk");
+
+ if (keymgmt & G_SUPPLICANT_KEYMGMT_SAE)
+ sec_list = g_slist_prepend (sec_list, "sae");
+ if (keymgmt & G_SUPPLICANT_KEYMGMT_OWE || owe_transition_mode)
+ sec_list = g_slist_prepend (sec_list, "owe");
+ if (keymgmt & G_SUPPLICANT_KEYMGMT_DPP)
+ sec_list = g_slist_prepend (sec_list, "dpp");
+
+ if (sec_list)
+ return sec_list;
+
+ if (privacy)
+ sec_list = g_slist_prepend (sec_list, "wep");
+ else
+ sec_list = g_slist_prepend (sec_list, "none");
+
+ return sec_list;
+}
+#endif
+
static void network_added(GSupplicantNetwork *supplicant_network)
{
struct connman_network *network;
bool wps_ready;
bool wps_advertizing;
+#if defined TIZEN_EXT
+ bool owe_transition_mode;
+ const unsigned char *transition_mode_ssid;
+ const unsigned char *transition_mode_bssid;
+ unsigned int transition_mode_ssid_len;
+ unsigned int keymgmt;
+ GSList *vsie_list = NULL;
+ GSList *sec_list = NULL;
+ const unsigned char *country_code;
+ ieee80211_modes_e phy_mode;
+#endif
+
mode = g_supplicant_network_get_mode(supplicant_network);
identifier = g_supplicant_network_get_identifier(supplicant_network);
-
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
DBG("%s", identifier);
if (!g_strcmp0(mode, "adhoc"))
return;
+#if defined TIZEN_EXT_WIFI_MESH
+ if (!g_strcmp0(mode, "mesh")) {
+ mesh_peer_added(supplicant_network);
+ return;
+ }
+#endif
+
interface = g_supplicant_network_get_interface(supplicant_network);
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
wifi = g_supplicant_interface_get_data(interface);
name = g_supplicant_network_get_name(supplicant_network);
security = g_supplicant_network_get_security(supplicant_network);
connman_network_set_blob(network, "WiFi.SSID",
ssid, ssid_len);
+#if defined TIZEN_EXT
+ vsie_list = (GSList *)g_supplicant_network_get_wifi_vsie(supplicant_network);
+ if (vsie_list)
+ connman_network_set_vsie_list(network, vsie_list);
+ else
+ DBG("vsie_list is NULL");
+ country_code = g_supplicant_network_get_countrycode(supplicant_network);
+ connman_network_set_countrycode(network, country_code);
+ phy_mode = g_supplicant_network_get_phy_mode(supplicant_network);
+ connman_network_set_phy_mode(network, phy_mode);
+#endif
connman_network_set_string(network, "WiFi.Security", security);
connman_network_set_strength(network,
calculate_strength(supplicant_network));
* If so, we decide to use WPS by default */
if (wps_ready && wps_pbc &&
wps_advertizing)
+#if !defined TIZEN_EXT
connman_network_set_bool(network, "WiFi.UseWPS", true);
+#else
+ DBG("wps is activating by ap but ignore it.");
+#endif
}
connman_network_set_frequency(network,
g_supplicant_network_get_frequency(supplicant_network));
+#if defined TIZEN_EXT
+ keymgmt = g_supplicant_network_get_keymgmt(supplicant_network);
+ connman_network_set_bssid(network,
+ g_supplicant_network_get_bssid(supplicant_network));
+ owe_transition_mode = (bool)g_supplicant_network_get_transition_mode(supplicant_network);
+ connman_network_set_bool(network, "WiFi.TRANSITION_MODE", owe_transition_mode);
+ if (owe_transition_mode) {
+ transition_mode_ssid = (unsigned char *)g_supplicant_network_get_transition_mode_ssid(supplicant_network, &transition_mode_ssid_len);
+ connman_network_set_blob(network, "WiFi.TRANSITION_MODE_SSID",
+ transition_mode_ssid, transition_mode_ssid_len);
+ transition_mode_bssid = g_supplicant_network_get_transition_mode_bssid(supplicant_network);
+ connman_network_set_transition_mode_bssid(network, transition_mode_bssid);
+ }
+
+ sec_list = get_supported_security_list(keymgmt,
+ owe_transition_mode, supplicant_network);
+
+ connman_network_set_sec_list(network, sec_list);
+ connman_network_set_maxrate(network,
+ g_supplicant_network_get_maxrate(supplicant_network));
+ connman_network_set_enc_mode(network,
+ g_supplicant_network_get_enc_mode(supplicant_network));
+ connman_network_set_rsn_mode(network,
+ g_supplicant_network_get_rsn_mode(supplicant_network));
+ connman_network_set_bool(network, "WiFi.PMFRequired",
+ (bool)g_supplicant_network_is_pmf_required(supplicant_network));
+ connman_network_set_keymgmt(network, keymgmt);
+ connman_network_set_bool(network, "WiFi.HS20AP",
+ g_supplicant_network_is_hs20AP(supplicant_network));
+ connman_network_set_bssid_list(network,
+ (GSList *)g_supplicant_network_get_bssid_list(supplicant_network));
+ connman_network_set_last_connected_bssid(network,
+ g_supplicant_network_get_last_connected_bssid(supplicant_network));
+ connman_network_set_assoc_reject_table(network,
+ g_supplicant_network_get_assoc_reject_table(supplicant_network));
+#endif
connman_network_set_available(network, true);
connman_network_set_string(network, "WiFi.Mode", mode);
+#if defined TIZEN_EXT
+ if (group)
+#else
if (ssid)
+#endif
connman_network_set_group(network, group);
+#if defined TIZEN_EXT
+ g_supplicant_network_set_last_connected_bssid(supplicant_network,
+ connman_network_get_last_connected_bssid(network));
+#endif
+
+#if defined TIZEN_EXT
+ if (wifi_first_scan == true)
+ found_with_first_scan = true;
+#endif
+
if (wifi->hidden && ssid) {
+#if defined TIZEN_EXT
+ if (network_security(wifi->hidden->security) ==
+ network_security(security) &&
+#else
if (!g_strcmp0(wifi->hidden->security, security) &&
+#endif
wifi->hidden->ssid_len == ssid_len &&
!memcmp(wifi->hidden->ssid, ssid, ssid_len)) {
connman_network_connect_hidden(network,
const char *name, *identifier;
struct connman_network *connman_network;
+#if defined TIZEN_EXT_WIFI_MESH
+ const char *mode;
+ mode = g_supplicant_network_get_mode(network);
+ if (!g_strcmp0(mode, "mesh")) {
+ mesh_peer_removed(network);
+ return;
+ }
+#endif
+
interface = g_supplicant_network_get_interface(network);
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
wifi = g_supplicant_interface_get_data(interface);
identifier = g_supplicant_network_get_identifier(network);
name = g_supplicant_network_get_name(network);
if (!connman_network)
return;
+#if defined TIZEN_EXT
+ if (connman_network == wifi->scan_pending_network)
+ wifi->scan_pending_network = NULL;
+
+ if (connman_network == wifi->pending_network)
+ wifi->pending_network = NULL;
+
+ if(connman_network_get_connecting(connman_network) == true){
+ connman_network_set_connected(connman_network, false);
+ }
+#endif
+
wifi->networks = g_slist_remove(wifi->networks, connman_network);
connman_device_remove_network(wifi->device, connman_network);
struct connman_network *connman_network;
bool update_needed;
+#if defined TIZEN_EXT
+ const unsigned char *bssid;
+ unsigned int maxrate;
+ uint16_t frequency;
+ bool wps;
+ const unsigned char *country_code;
+ ieee80211_modes_e phy_mode;
+ GSList *bssid_list;
+#endif
+
interface = g_supplicant_network_get_interface(network);
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
wifi = g_supplicant_interface_get_data(interface);
identifier = g_supplicant_network_get_identifier(network);
name = g_supplicant_network_get_name(network);
+#if defined TIZEN_EXT
+ if (!simplified_log)
+ DBG("name %s property %s", name, property);
+#else
DBG("name %s", name);
+#endif
if (!wifi)
return;
connman_network_set_strength(connman_network,
calculate_strength(network));
update_needed = true;
- } else
+ }
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+ else if (g_str_equal(property, "LastConnectedBSSID")) {
+ const char *ident, *group;
+ char *service_ident;
+ bool need_save;
+
+ ident = connman_device_get_ident(wifi->device);
+ group = connman_network_get_group(connman_network);
+ if (ident && group) {
+ service_ident = g_strdup_printf("%s_%s_%s",
+ __connman_network_get_type(connman_network), ident, group);
+
+ need_save = connman_device_set_last_connected_ident(wifi->device, service_ident);
+ if (need_save)
+ connman_device_save_last_connected(wifi->device);
+
+ g_free(service_ident);
+ }
+
+ connman_network_set_last_connected_bssid(connman_network,
+ g_supplicant_network_get_last_connected_bssid(network));
+
+ update_needed = true;
+ }
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+#if defined TIZEN_EXT
+ else if (g_str_equal(property, "UpdateAssocReject")) {
+ connman_network_set_assoc_reject_table(connman_network,
+ g_supplicant_network_get_assoc_reject_table(network));
+ update_needed = true;
+ }
+#endif
+ else
update_needed = false;
if (update_needed)
connman_network_update(connman_network);
+
+#if defined TIZEN_EXT
+ bssid = g_supplicant_network_get_bssid(network);
+ maxrate = g_supplicant_network_get_maxrate(network);
+ frequency = g_supplicant_network_get_frequency(network);
+ wps = g_supplicant_network_get_wps(network);
+ phy_mode = g_supplicant_network_get_phy_mode(network);
+
+ connman_network_set_bssid(connman_network, bssid);
+ connman_network_set_maxrate(connman_network, maxrate);
+ connman_network_set_frequency(connman_network, frequency);
+ connman_network_set_bool(connman_network, "WiFi.WPS", wps);
+ country_code = g_supplicant_network_get_countrycode(network);
+ connman_network_set_countrycode(connman_network, country_code);
+ bssid_list = (GSList *)g_supplicant_network_get_bssid_list(network);
+ connman_network_set_bssid_list(connman_network, bssid_list);
+ connman_network_set_phy_mode(connman_network, phy_mode);
+
+ if (g_str_equal(property, "CheckMultiBssidConnect") &&
+ connman_network_get_associating(connman_network))
+ network_connect(connman_network);
+#endif
}
static void network_associated(GSupplicantNetwork *network)
interface = g_supplicant_network_get_interface(network);
if (!interface)
return;
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
wifi = g_supplicant_interface_get_data(interface);
if (!wifi)
if (wifi->network) {
if (wifi->network == connman_network)
return;
-
+#if TIZEN_EXT
+ unsigned int ssid_len;
+ DBG("network1 ssid[%s] , OWE[%d],ssid[%s]",
+ (char *)connman_network_get_blob(wifi->network,"WiFi.SSID", &ssid_len),
+ connman_network_get_bool(wifi->network,"WiFi.TRANSITION_MODE"),
+ (char *)connman_network_get_blob(wifi->network,"WiFi.TRANSITION_MODE_SSID", &ssid_len));
+
+ DBG("network1 ssid[%s], OWE[%d], ssid[%s]",
+ (char *)connman_network_get_blob(connman_network,"WiFi.SSID",&ssid_len),
+ connman_network_get_bool(connman_network,"WiFi.TRANSITION_MODE"),
+ (char *)connman_network_get_blob(connman_network,"WiFi.TRANSITION_MODE_SSID", &ssid_len));
+ if (connman_network_check_transition_mode(wifi->network, connman_network)) {//OWE trasition mode check
+ DBG("OWE transition mode is TRUE");
+ return;
+ }
+#endif
/*
* This should never happen, we got associated with
* a network different than the one we were expecting.
static void sta_authorized(GSupplicantInterface *interface,
const char *addr)
{
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
DBG("wifi %p station %s authorized", wifi, addr);
static void sta_deauthorized(GSupplicantInterface *interface,
const char *addr)
{
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
DBG("wifi %p station %s deauthorized", wifi, addr);
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);
struct connman_peer *connman_peer;
const char *identifier;
+#if defined TIZEN_EXT
+ if (!wifi)
+ return;
+#endif
+
identifier = g_supplicant_peer_get_identifier(peer);
DBG("ident: %s", identifier);
connman_peer_request_connection(connman_peer);
}
+#if defined TIZEN_EXT
+static void system_power_off(void)
+{
+ GList *list;
+ struct wifi_data *wifi;
+ struct connman_service *service;
+ struct connman_ipconfig *ipconfig_ipv4;
+
+ if (connman_setting_get_bool("WiFiDHCPRelease") == true) {
+ for (list = iface_list; list; list = list->next) {
+ wifi = list->data;
+
+ if (wifi->network != NULL) {
+ service = connman_service_lookup_from_network(wifi->network);
+ ipconfig_ipv4 = __connman_service_get_ip4config(service);
+ __connman_dhcp_stop(ipconfig_ipv4);
+ }
+ }
+ }
+}
+
+static void network_merged(GSupplicantNetwork *network)
+{
+ GSupplicantInterface *interface;
+ GSupplicantState state;
+ struct wifi_data *wifi;
+ const char *identifier;
+ struct connman_network *connman_network;
+ bool ishs20AP = 0;
+ char *temp = NULL;
+
+ interface = g_supplicant_network_get_interface(network);
+ if (!interface)
+ return;
+
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
+ state = g_supplicant_interface_get_state(interface);
+ if (state < G_SUPPLICANT_STATE_AUTHENTICATING)
+ return;
+
+ wifi = g_supplicant_interface_get_data(interface);
+ if (!wifi)
+ return;
+
+ identifier = g_supplicant_network_get_identifier(network);
+
+ connman_network = connman_device_get_network(wifi->device, identifier);
+ if (!connman_network)
+ return;
+
+ DBG("merged identifier %s", identifier);
+
+ if (wifi->connected == FALSE) {
+ switch (state) {
+ case G_SUPPLICANT_STATE_AUTHENTICATING:
+ case G_SUPPLICANT_STATE_ASSOCIATING:
+ case G_SUPPLICANT_STATE_ASSOCIATED:
+ case G_SUPPLICANT_STATE_4WAY_HANDSHAKE:
+ case G_SUPPLICANT_STATE_GROUP_HANDSHAKE:
+ connman_network_set_associating(connman_network, TRUE);
+ break;
+ case G_SUPPLICANT_STATE_COMPLETED:
+ connman_network_set_connected(connman_network, TRUE);
+ break;
+ default:
+ DBG("Not handled the state : %d", state);
+ break;
+ }
+ }
+
+ ishs20AP = g_supplicant_network_is_hs20AP(network);
+
+ if (ishs20AP &&
+ g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) {
+ temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1);
+ connman_network_set_string(connman_network, "WiFi.EAP",
+ temp);
+ connman_network_set_string(connman_network, "WiFi.Identity",
+ g_supplicant_network_get_identity(network));
+ connman_network_set_string(connman_network, "WiFi.Phase2",
+ g_supplicant_network_get_phase2(network));
+
+ g_free(temp);
+ }
+
+ wifi->network = connman_network;
+}
+
+static void assoc_failed(void *user_data)
+{
+ struct connman_network *network = user_data;
+ connman_network_set_associating(network, false);
+}
+
+static void scan_done(GSupplicantInterface *interface)
+{
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
+ GList *list;
+ int scan_type = CONNMAN_SCAN_TYPE_WPA_SUPPLICANT;
+ struct wifi_data *wifi;
+ bool scanning;
+
+ for (list = iface_list; list; list = list->next) {
+ wifi = list->data;
+
+ if (interface == wifi->interface) {
+ scanning = connman_device_get_scanning(wifi->device,
+ CONNMAN_SERVICE_TYPE_WIFI);
+ if (!scanning)
+ __connman_technology_notify_scan_done(
+ connman_device_get_string(wifi->device, "Interface"), scan_type);
+ break;
+ }
+ }
+}
+#endif
+
static void debug(const char *str)
{
+#if defined TIZEN_EXT
+ if (connman_setting_get_bool("ConnmanSupplicantDebug"))
+#else
if (getenv("CONNMAN_SUPPLICANT_DEBUG"))
+#endif
connman_debug("%s", str);
}
static void disconnect_reasoncode(GSupplicantInterface *interface,
int reasoncode)
{
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
if (wifi != NULL) {
static void assoc_status_code(GSupplicantInterface *interface, int status_code)
{
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
struct wifi_data *wifi = g_supplicant_interface_get_data(interface);
if (wifi != NULL) {
}
}
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+static GSupplicantCallbacks callbacks = {
+#else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
static const GSupplicantCallbacks callbacks = {
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
.system_ready = system_ready,
.system_killed = system_killed,
.interface_added = interface_added,
.peer_lost = peer_lost,
.peer_changed = peer_changed,
.peer_request = peer_request,
+#if defined TIZEN_EXT
+ .system_power_off = system_power_off,
+ .network_merged = network_merged,
+ .assoc_failed = assoc_failed,
+ .scan_done = scan_done,
+#endif
.debug = debug,
.disconnect_reasoncode = disconnect_reasoncode,
.assoc_status_code = assoc_status_code,
+#if defined TIZEN_EXT_WIFI_MESH
+ .mesh_support = mesh_support,
+ .mesh_group_started = mesh_group_started,
+ .mesh_group_removed = mesh_group_removed,
+ .mesh_peer_connected = mesh_peer_connected,
+ .mesh_peer_disconnected = mesh_peer_disconnected,
+#endif
};
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;
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);
}
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,
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;
}
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,
--- /dev/null
+[D-BUS Service]
+Name=net.connman
+Exec=/bin/false
+User=network_fw
+Group=network_fw
+SystemdService=connman.service
--- /dev/null
+
+[global]
+OfflineMode=false
+
+[WiFi]
+Enable=false
+
+[Bluetooth]
+Enable=true
+
+[Wired]
+Enable=true
+
+[Cellular]
+Enable=true
#!/bin/sh
-DAEMON=@sbindir@/connmand
+DAEMON=@bindir@/connmand
DESC="Connection Manager"
. /lib/lsb/init-functions
--- /dev/null
+/*
+ *
+ * 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;
+}
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:
data.type = "wep";
break;
case CONNMAN_SERVICE_SECURITY_PSK:
+#if defined TIZEN_EXT
+ case CONNMAN_SERVICE_SECURITY_RSN:
+#endif
data.type = "psk";
break;
/*
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)
{
dbus_bool_t is_synced;
struct timeval tv;
const char *str;
+#if defined TIZEN_EXT
+ dbus_bool_t val = time_updated;
+#endif
DBG("conn %p", conn);
connman_dbus_dict_open(&array, &dict);
+#if defined TIZEN_EXT
+ connman_dbus_dict_append_basic(&dict, "TimeUpdated",
+ DBUS_TYPE_BOOLEAN,
+ &val);
+#endif
+
if (gettimeofday(&tv, NULL) == 0) {
dbus_uint64_t val = tv.tv_sec;
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;
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;
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("");
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 {
#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,
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,
};
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);
}
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;
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);
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 {
} 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)
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",
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 {
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)
{
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;
}
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);
connman_ipaddress_free(address);
}
+#if defined TIZEN_EXT
+ipv6_out:
+#endif
if (config->ipv6_privacy) {
struct connman_ipconfig *ipconfig;
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);
connman_ipaddress_free(address);
}
+#if defined TIZEN_EXT
+ipv4_out:
+#endif
__connman_service_disconnect(service);
service_id = connman_service_get_identifier(service);
__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
}
}
return 0;
}
+#if !defined TIZEN_EXT
__connman_service_set_immutable(service, true);
+#endif
if (type == CONNMAN_SERVICE_TYPE_ETHERNET ||
type == CONNMAN_SERVICE_TYPE_GADGET) {
/* 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 &&
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);
}
}
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);
}
}
+#if defined TIZEN_EXT
+static bool __connman_service_is_not_cellular_internet_profile(
+ struct connman_service *cellular)
+{
+ char *suffix;
+ const char *path;
+ const char internet_suffix[] = "_1";
+ const char prepaid_internet_suffix[] = "_3";
+
+ if (connman_service_get_type(cellular) != CONNMAN_SERVICE_TYPE_CELLULAR)
+ return FALSE;
+
+ path = __connman_service_get_path(cellular);
+
+ suffix = strrchr(path, '_');
+
+ if (g_strcmp0(suffix, internet_suffix) != 0 &&
+ g_strcmp0(suffix, prepaid_internet_suffix) != 0) {
+ DBG("not internet service profile: %s", path);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+#endif
+
int __connman_connection_gateway_add(struct connman_service *service,
const char *gateway,
enum connman_ipconfig_type type,
if (!gateway && type == CONNMAN_IPCONFIG_TYPE_IPV6)
gateway = "::";
+#if defined TIZEN_EXT
+ if (__connman_service_is_not_cellular_internet_profile(service) == TRUE) {
+ /* not internet service should not be default gateway */
+
+ DBG("no internet service %p index %d gateway %s vpn ip %s type %d",
+ service, index, gateway, peer, type);
+
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
+ add_host_route(AF_INET, index, gateway, service_type);
+ __connman_service_nameserver_add_routes(service, gateway);
+ type4 = CONNMAN_IPCONFIG_TYPE_IPV4;
+ }
+
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV6) {
+ add_host_route(AF_INET6, index, gateway, service_type);
+ __connman_service_nameserver_add_routes(service, gateway);
+ type6 = CONNMAN_IPCONFIG_TYPE_IPV6;
+ }
+
+ goto done;
+ }
+#endif
DBG("service %p index %d gateway %s vpn ip %s type %d",
service, index, gateway, peer, type);
}
if (!active_gateway) {
+#if defined TIZEN_EXT
+ if(new_gateway->ipv4_gateway)
+ DBG("ConnMan, Set default gateway[%s], active[%d]",
+ new_gateway->ipv4_gateway->gateway,
+ new_gateway->ipv4_gateway->active);
+#endif
set_default_gateway(new_gateway, type);
goto done;
}
bool updated = false;
GHashTableIter iter;
gpointer value, key;
+#if defined TIZEN_EXT
+ static struct gateway_data *old_default = NULL;
+#endif
if (!gateway_hash)
return updated;
}
}
+#if defined TIZEN_EXT
+ if (updated == false && old_default != default_gateway) {
+ updated = true;
+ old_default = default_gateway;
+ }
+#endif
/*
* Set default gateway if it has been updated or if it has not been
* set as active yet.
<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">
<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>
--- /dev/null
+<!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>
--- /dev/null
+<!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>
#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>
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);
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);
__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,
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);
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);
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,
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);
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);
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);
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);
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);
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);
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,
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);
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,
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);
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);
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();
#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);
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 */
[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
--- /dev/null
+[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
--- /dev/null
+[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
}
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)
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,
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;
if (device_service_type == CONNMAN_SERVICE_TYPE_UNKNOWN)
return true;
+#if defined TIZEN_EXT_WIFI_MESH
+ if (device_service_type == CONNMAN_SERVICE_TYPE_MESH)
+ return service_type != CONNMAN_SERVICE_TYPE_MESH;
+#endif
+
if (device_service_type == CONNMAN_SERVICE_TYPE_WIFI) {
return service_type == CONNMAN_SERVICE_TYPE_WIFI ||
service_type == CONNMAN_SERVICE_TYPE_P2P;
return service_type == device_service_type;
}
+#if defined TIZEN_EXT
+static void __device_pending_reset(gpointer data, gpointer user_data)
+{
+ DBusMessage *msg = (DBusMessage *)data;
+ DBusMessage *reply;
+
+ reply = __connman_error_failed(msg, ETIMEDOUT);
+ if (reply)
+ g_dbus_send_message(connection, reply);
+
+ dbus_message_unref(msg);
+}
+#endif
+
static gboolean device_pending_reset(gpointer user_data)
{
struct connman_device *device = user_data;
DBG("device %p", device);
+#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;
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;
}
/*
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)
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);
}
if (device->powered == powered)
return -EALREADY;
+#if defined TIZEN_EXT
+ device_send_reply(device);
+#endif
+
clear_pending_trigger(device);
device->powered_pending = PENDING_NONE;
type = __connman_device_get_service_type(device);
+#if defined TIZEN_EXT
+ device_send_changed(device->interface, type, "Powered", powered);
+ technology_save_device(device);
+#endif
+
if (!device->powered) {
__connman_technology_disabled(type);
return 0;
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)
{
__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;
}
DBG("device %p key %s value %s", device, key, value);
if (g_str_equal(key, "Address")) {
+#ifdef TIZEN_EXT
+ if (device->address && device->powered)
+ return 0;
+ else
+#endif
g_free(device->address);
device->address = g_strdup(value);
} else if (g_str_equal(key, "Name")) {
const char *connman_device_get_string(struct connman_device *device,
const char *key)
{
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
DBG("device %p key %s", device, key);
if (g_str_equal(key, "Address"))
struct connman_network *network)
{
const char *identifier = connman_network_get_identifier(network);
-
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
DBG("device %p network %p", device, network);
if (!identifier)
struct connman_network *connman_device_get_network(struct connman_device *device,
const char *identifier)
{
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
DBG("device %p identifier %s", device, identifier);
return g_hash_table_lookup(device->networks, identifier);
}
+#if defined TIZEN_EXT
+struct connman_network *connman_device_get_default_network(
+ struct connman_device *device)
+{
+ return device->network;
+}
+
+void connman_device_set_pending_reply(struct connman_device *device,
+ DBusMessage *msg)
+{
+ device->pending_reply_list = g_list_prepend(device->pending_reply_list, dbus_message_ref(msg));
+}
+
+void connman_device_send_connected_signal(struct connman_device *device,
+ bool connected)
+{
+ enum connman_service_type type;
+
+ if (!device)
+ return;
+
+ type = __connman_device_get_service_type(device);
+ device_send_changed(device->interface, type, "Connected", connected);
+}
+
+void connman_device_set_max_scan_ssids(struct connman_device *device,
+ int max_scan_ssids)
+{
+ device->max_scan_ssids = max_scan_ssids;
+}
+
+int connman_device_get_max_scan_ssids(struct connman_device *device)
+{
+ return device->max_scan_ssids;
+}
+
+void connman_device_set_wifi_5ghz_supported(struct connman_device *device,
+ bool is_5_0_ghz_supported)
+{
+ device->is_5_0_ghz_supported = is_5_0_ghz_supported;
+}
+
+bool connman_device_get_wifi_5ghz_supported(struct connman_device *device)
+{
+ return device->is_5_0_ghz_supported;
+}
+#endif
+
/**
* connman_device_remove_network:
* @device: device structure
__connman_technology_notify_regdom_by_device(device, result, alpha2);
}
+#if defined TIZEN_EXT
+static int device_specific_scan(enum connman_service_type type,
+ struct connman_device *device,
+ int scan_type, GSList *specific_scan_list)
+{
+ if (!device->driver || !device->driver->specific_scan)
+ return -EOPNOTSUPP;
+
+ if (!device->powered)
+ return -ENOLINK;
+
+ return device->driver->specific_scan(type, device, scan_type,
+ specific_scan_list, NULL);
+}
+
+int __connman_device_request_specific_scan(enum connman_service_type type,
+ const char *ifname, int scan_type, GSList *specific_scan_list)
+{
+ bool success = false;
+ int last_err = -ENOSYS;
+ GSList *list;
+ int err;
+
+ switch (type) {
+ case CONNMAN_SERVICE_TYPE_UNKNOWN:
+ case CONNMAN_SERVICE_TYPE_SYSTEM:
+ case CONNMAN_SERVICE_TYPE_ETHERNET:
+ case CONNMAN_SERVICE_TYPE_BLUETOOTH:
+ case CONNMAN_SERVICE_TYPE_CELLULAR:
+ case CONNMAN_SERVICE_TYPE_GPS:
+ case CONNMAN_SERVICE_TYPE_VPN:
+ case CONNMAN_SERVICE_TYPE_GADGET:
+ return -EOPNOTSUPP;
+ case CONNMAN_SERVICE_TYPE_WIFI:
+ case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
+ break;
+ }
+
+ for (list = device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+ enum connman_service_type service_type =
+ __connman_device_get_service_type(device);
+
+ if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) {
+ if (type == CONNMAN_SERVICE_TYPE_P2P) {
+ if (service_type != CONNMAN_SERVICE_TYPE_WIFI)
+ continue;
+ } else if (service_type != type)
+ continue;
+ }
+
+ if (ifname && g_strcmp0(device->interface, ifname) != 0)
+ continue;
+
+ err = device_specific_scan(type, device, scan_type, specific_scan_list);
+ if (err == 0 || err == -EINPROGRESS) {
+ success = true;
+ } else {
+ last_err = err;
+ DBG("device %p err %d", device, err);
+ }
+ }
+
+ if (success)
+ return 0;
+
+ return last_err;
+}
+
+int connman_device_request_device_scan(enum connman_service_type type,
+ const char * ifname, bool force_full_scan)
+{
+ bool success = false;
+ int last_err = -ENOSYS;
+ GSList *list;
+ int err;
+
+ switch (type) {
+ case CONNMAN_SERVICE_TYPE_UNKNOWN:
+ case CONNMAN_SERVICE_TYPE_SYSTEM:
+ case CONNMAN_SERVICE_TYPE_ETHERNET:
+ case CONNMAN_SERVICE_TYPE_BLUETOOTH:
+ case CONNMAN_SERVICE_TYPE_CELLULAR:
+ case CONNMAN_SERVICE_TYPE_GPS:
+ case CONNMAN_SERVICE_TYPE_VPN:
+ case CONNMAN_SERVICE_TYPE_GADGET:
+ return -EOPNOTSUPP;
+ case CONNMAN_SERVICE_TYPE_WIFI:
+ case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
+ break;
+ }
+
+ for (list = device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+
+ if (!device_has_service_type(device, type))
+ continue;
+
+ if (g_strcmp0(device->interface, ifname) != 0)
+ continue;
+
+ err = device_scan(type, device, force_full_scan);
+
+ if (err == 0 || err == -EINPROGRESS) {
+ success = true;
+ } else {
+ last_err = err;
+ DBG("device %p err %d", device, err);
+ }
+ break;
+ }
+
+ if (success)
+ return 0;
+
+ return last_err;
+}
+
+#if defined TIZEN_EXT_WIFI_MESH
+static int device_abort_scan(enum connman_service_type type,
+ struct connman_device *device)
+{
+ if (!device->driver || !device->driver->scan)
+ return -EOPNOTSUPP;
+
+ if (!device->powered)
+ return -ENOLINK;
+
+ return device->driver->abort_scan(type, device);
+}
+
+int __connman_device_abort_scan(enum connman_service_type type)
+{
+ GSList *list;
+ int err = -EINVAL;
+
+ if (type != CONNMAN_SERVICE_TYPE_MESH)
+ return -EINVAL;
+
+ for (list = device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+ enum connman_service_type service_type =
+ __connman_device_get_service_type(device);
+
+ if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) {
+ if (type == CONNMAN_SERVICE_TYPE_MESH)
+ if (service_type != CONNMAN_SERVICE_TYPE_WIFI)
+ continue;
+
+ if (!device->scanning) {
+ err = -EEXIST;
+ continue;
+ }
+
+ err = device_abort_scan(type, device);
+ }
+ }
+ return err;
+}
+
+static int device_mesh_specific_scan(enum connman_service_type type,
+ struct connman_device *device, const char *name,
+ unsigned int freq)
+{
+ if (!device->driver || !device->driver->mesh_specific_scan)
+ return -EOPNOTSUPP;
+
+ if (!device->powered)
+ return -ENOLINK;
+
+ return device->driver->mesh_specific_scan(type, device, name, freq, NULL);
+}
+
+int __connman_device_request_mesh_specific_scan(enum connman_service_type type,
+ const char *name,
+ unsigned int freq)
+{
+ bool success = false;
+ int last_err = -ENOSYS;
+ GSList *list;
+ int err;
+
+ if (type != CONNMAN_SERVICE_TYPE_MESH)
+ return -EINVAL;
+
+ for (list = device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+ enum connman_service_type service_type =
+ __connman_device_get_service_type(device);
+
+ if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) {
+ if (type == CONNMAN_SERVICE_TYPE_MESH)
+ if (service_type != CONNMAN_SERVICE_TYPE_WIFI)
+ continue;
+ }
+
+ err = device_mesh_specific_scan(type, device, name, freq);
+ if (err == 0 || err == -EALREADY || err == -EINPROGRESS) {
+ success = true;
+ } else {
+ last_err = err;
+ DBG("device %p err %d", device, err);
+ }
+ }
+
+ if (success)
+ return 0;
+
+ return last_err;
+}
+#endif /* TIZEN_EXT_WIFI_MESH */
+#endif
+
static int connman_device_request_scan(enum connman_service_type type,
bool force_full_scan)
{
return -EOPNOTSUPP;
case CONNMAN_SERVICE_TYPE_WIFI:
case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
break;
}
continue;
err = device_scan(type, device, force_full_scan);
+#if defined TIZEN_EXT
+ /* When Scan is already in progress then return Error so that
+ * wifi-manager can block the scan-done signal to be sent to
+ * application and start requested scan after scan already in progress
+ * is completed then notify to application about the scan event */
+ if (err == 0 || err == -EINPROGRESS) {
+#else
if (err == 0 || err == -EALREADY || err == -EINPROGRESS) {
+#endif
success = true;
} else {
last_err = err;
}
}
+#if defined TIZEN_EXT
+#define WIFI_MAC "/opt/etc/.mac.info"
+#define MAC_ADDR_LEN 18
+
+char *_get_wifi_addr(void)
+{
+ FILE *fp = NULL;
+ char* rv = 0;
+ char wifi_mac[MAC_ADDR_LEN + 1];
+ char *str;
+
+ fp = fopen(WIFI_MAC, "r");
+ if (!fp){
+ connman_error("[%s] not present", WIFI_MAC);
+ return NULL;
+ }
+
+ rv = fgets(wifi_mac, MAC_ADDR_LEN, fp);
+ if (!rv) {
+ connman_error("Failed to get wifi mac address");
+ fclose(fp);
+ return NULL;
+ }
+
+ str = g_try_malloc0(MAC_ADDR_LEN);
+ if (!str) {
+ connman_error("memory allocation failed");
+ fclose(fp);
+ return NULL;
+ }
+
+ snprintf(str, MAC_ADDR_LEN, "%c%c:%c%c:%c%c:%c%c:%c%c:%c%c",
+ g_ascii_tolower(wifi_mac[0]), g_ascii_tolower(wifi_mac[1]),
+ g_ascii_tolower(wifi_mac[3]), g_ascii_tolower(wifi_mac[4]),
+ g_ascii_tolower(wifi_mac[6]), g_ascii_tolower(wifi_mac[7]),
+ g_ascii_tolower(wifi_mac[9]), g_ascii_tolower(wifi_mac[10]),
+ g_ascii_tolower(wifi_mac[12]), g_ascii_tolower(wifi_mac[13]),
+ g_ascii_tolower(wifi_mac[15]), g_ascii_tolower(wifi_mac[16]));
+ fclose(fp);
+ return str;
+}
+
+char *_get_wifi_ident(void)
+{
+ FILE *fp = NULL;
+ char* rv = 0;
+ char wifi_mac[MAC_ADDR_LEN + 1];
+ char *str;
+
+ fp = fopen(WIFI_MAC, "r");
+ if (!fp){
+ connman_error("[%s] not present", WIFI_MAC);
+ return NULL;
+ }
+
+ rv = fgets(wifi_mac, MAC_ADDR_LEN, fp);
+ if (!rv) {
+ connman_error("Failed to get wifi mac address");
+ fclose(fp);
+ return NULL;
+ }
+
+ str = g_try_malloc0(MAC_ADDR_LEN);
+ if (!str) {
+ connman_error("memory allocation failed");
+ fclose(fp);
+ return NULL;
+ }
+
+ snprintf(str, MAC_ADDR_LEN, "%c%c%c%c%c%c%c%c%c%c%c%c",
+ g_ascii_tolower(wifi_mac[0]), g_ascii_tolower(wifi_mac[1]),
+ g_ascii_tolower(wifi_mac[3]), g_ascii_tolower(wifi_mac[4]),
+ g_ascii_tolower(wifi_mac[6]), g_ascii_tolower(wifi_mac[7]),
+ g_ascii_tolower(wifi_mac[9]), g_ascii_tolower(wifi_mac[10]),
+ g_ascii_tolower(wifi_mac[12]), g_ascii_tolower(wifi_mac[13]),
+ g_ascii_tolower(wifi_mac[15]), g_ascii_tolower(wifi_mac[16]));
+ fclose(fp);
+ return str;
+}
+#endif
+
+#if defined TIZEN_EXT
+char *index2ident(int index, const char *prefix)
+#else
static char *index2ident(int index, const char *prefix)
+#endif
{
struct ifreq ifr;
struct ether_addr eth;
return str;
}
+#if defined TIZEN_EXT
+char *index2addr(int index)
+#else
static char *index2addr(int index)
+#endif
{
struct ifreq ifr;
struct ether_addr eth;
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);
DBG("cleaning up %s index %d", interfaces[i], index);
+#if defined TIZEN_EXT
+ if (strcmp(interfaces[i], "wlan0") != 0)
+#endif
connman_inet_ifdown(index);
/*
{
DBG("");
+#if defined TIZEN_EXT
+ connection = connman_dbus_get_connection();
+#endif
+
if (device)
device_filter = g_strsplit(device, ",", -1);
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
static void dhcp_free(struct connman_dhcp *dhcp)
{
+#if defined TIZEN_EXT
+ DBG("dhcp_free [%p]", dhcp);
+#endif
g_strfreev(dhcp->nameservers);
g_strfreev(dhcp->timeservers);
g_free(dhcp->pac);
dhcp->pac = NULL;
g_free(dhcp);
+#if defined TIZEN_EXT
+ dhcp = NULL;
+#endif
}
static void ipv4ll_stop_client(struct connman_dhcp *dhcp)
{
+#if defined TIZEN_EXT
+ DBG("dhcp [%p] ipv4ll_client [%p]", dhcp, dhcp->ipv4ll_client);
+#endif
if (!dhcp->ipv4ll_client)
return;
}
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;
int index;
int err;
+#if defined TIZEN_EXT
+ DBG("dhcp %p", dhcp);
+#endif
+
if (dhcp->ipv4ll_client)
return -EALREADY;
if (error != G_DHCP_CLIENT_ERROR_NONE)
return -EINVAL;
+#if !defined TIZEN_EXT
if (getenv("CONNMAN_DHCP_DEBUG")) {
+#endif
dhcp->ipv4ll_debug_prefix = g_strdup_printf("IPv4LL index %d",
index);
g_dhcp_client_set_debug(ipv4ll_client, dhcp_debug,
dhcp->ipv4ll_debug_prefix);
+#if !defined TIZEN_EXT
}
+#endif
g_dhcp_client_set_id(ipv4ll_client);
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));
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);
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);
__connman_ipconfig_set_dhcp_address(dhcp->ipconfig, address);
DBG("last address %s", address);
+#if defined TIZEN_EXT
+ int dhcp_lease_duration = g_dhcp_client_get_dhcp_lease_duration(dhcp_client);
+#endif
+
option = g_dhcp_client_get_option(dhcp_client, G_DHCP_SUBNET);
if (option)
netmask = g_strdup(option->data);
__connman_ipconfig_set_method(dhcp->ipconfig,
CONNMAN_IPCONFIG_METHOD_DHCP);
+#if defined TIZEN_EXT
+ __connman_ipconfig_set_dhcp_lease_duration(dhcp->ipconfig, dhcp_lease_duration);
+#endif
+
/*
* Notify IPv4.Configuration's method moved back to DHCP.
*
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);
return g_dhcp_client_get_server_address(dhcp->dhcp_client);
}
+#if defined TIZEN_EXT_WIFI_MESH
+int __connman_mesh_dhcp_start(struct connman_ipconfig *ipconfig,
+ dhcp_cb callback, gpointer user_data)
+{
+ struct connman_dhcp *dhcp;
+ int err;
+
+ DBG("");
+
+ dhcp = g_hash_table_lookup(ipconfig_table, ipconfig);
+ if (!dhcp) {
+
+ dhcp = g_try_new0(struct connman_dhcp, 1);
+ if (!dhcp)
+ return -ENOMEM;
+
+ dhcp->ipconfig = ipconfig;
+ __connman_ipconfig_ref(ipconfig);
+
+ err = dhcp_initialize(dhcp);
+
+ if (err < 0) {
+ g_free(dhcp);
+ return err;
+ }
+
+ g_hash_table_insert(ipconfig_table, ipconfig, dhcp);
+ }
+
+ dhcp->callback = callback;
+ dhcp->user_data = user_data;
+ return g_dhcp_client_start(dhcp->dhcp_client, NULL);
+}
+#endif
+
int __connman_dhcp_start(struct connman_ipconfig *ipconfig,
struct connman_network *network, dhcp_cb callback,
gpointer user_data)
{
+#if !defined TIZEN_EXT
const char *last_addr = NULL;
+#endif
struct connman_dhcp *dhcp;
int err;
return -EINVAL;
}
+#if !defined TIZEN_EXT
last_addr = __connman_ipconfig_get_dhcp_address(ipconfig);
+#endif
dhcp = g_hash_table_lookup(ipconfig_table, ipconfig);
if (!dhcp) {
dhcp->callback = callback;
dhcp->user_data = user_data;
+#if defined TIZEN_EXT
+ DBG("Start DHCP with DHCPDISCOVER request");
+
+ return g_dhcp_client_start(dhcp->dhcp_client, NULL);
+#else
return g_dhcp_client_start(dhcp->dhcp_client, last_addr);
+#endif
}
void __connman_dhcp_stop(struct connman_ipconfig *ipconfig)
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);
if (!compare_string_arrays(nameservers, dhcp->nameservers)) {
if (dhcp->nameservers) {
for (i = 0; dhcp->nameservers[i]; i++)
+#if defined TIZEN_EXT
+ {
+ __connman_service_nameserver_remove(service,
+ dhcp->nameservers[i], false,
+ CONNMAN_IPCONFIG_TYPE_IPV6);
+#else
__connman_service_nameserver_remove(service,
dhcp->nameservers[i],
false);
+#endif
+#if defined TIZEN_EXT
+ }
+#endif
g_strfreev(dhcp->nameservers);
}
for (i = 0; dhcp->nameservers &&
dhcp->nameservers[i]; i++)
+#if defined TIZEN_EXT
+ {
+ __connman_service_nameserver_append(service,
+ dhcp->nameservers[i], false,
+ CONNMAN_IPCONFIG_TYPE_IPV6);
+#else
__connman_service_nameserver_append(service,
dhcp->nameservers[i],
false);
+#endif
+#if defined TIZEN_EXT
+ }
+#endif
} else
g_strfreev(nameservers);
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);
if (!compare_string_arrays(nameservers, dhcp->nameservers)) {
if (dhcp->nameservers) {
for (i = 0; dhcp->nameservers[i]; i++)
+#if defined TIZEN_EXT
+ {
+ __connman_service_nameserver_remove(service,
+ dhcp->nameservers[i],
+ false, CONNMAN_IPCONFIG_TYPE_IPV6);
+#else
__connman_service_nameserver_remove(service,
dhcp->nameservers[i],
false);
+#endif
+#if defined TIZEN_EXT
+ }
+#endif
g_strfreev(dhcp->nameservers);
}
for (i = 0; dhcp->nameservers &&
dhcp->nameservers[i]; i++)
+#if defined TIZEN_EXT
+ {
+ __connman_service_nameserver_append(service,
+ dhcp->nameservers[i],
+ false, CONNMAN_IPCONFIG_TYPE_IPV6);
+#else
__connman_service_nameserver_append(service,
dhcp->nameservers[i],
false);
+#endif
+#if defined TIZEN_EXT
+ }
+#endif
} else
g_strfreev(nameservers);
/* Is this prefix part of the subnet we are suppose to use? */
prefix_len = check_ipv6_addr_prefix(prefixes, address);
+#if defined TIZEN_EXT
+ char *gateway = g_strdup(__connman_ipconfig_get_gateway(ipconfig));
+#endif
__connman_ipconfig_address_remove(ipconfig);
__connman_ipconfig_set_local(ipconfig, address);
__connman_ipconfig_set_prefixlen(ipconfig, prefix_len);
DBG("new address %s/%d", address, prefix_len);
__connman_ipconfig_set_dhcp_address(ipconfig, address);
+#if defined TIZEN_EXT
+ DBG("Set gateway %s", gateway);
+ __connman_ipconfig_set_gateway(ipconfig, gateway);
+ g_free(gateway);
+#endif
__connman_service_save(
__connman_service_lookup_from_index(ifindex));
}
static int dhcpv6_solicitation(struct connman_dhcpv6 *dhcp)
{
struct connman_service *service;
+#if !defined TIZEN_EXT
struct connman_ipconfig *ipconfig_ipv6;
+#endif
GDHCPClient *dhcp_client;
GDHCPClientError error;
int index, ret;
return -EINVAL;
}
+#if !defined TIZEN_EXT
if (getenv("CONNMAN_DHCPV6_DEBUG"))
+#endif
g_dhcp_client_set_debug(dhcp_client, dhcpv6_debug, "DHCPv6");
service = connman_service_lookup_from_network(dhcp->network);
g_dhcpv6_client_set_oro(dhcp_client, 3, G_DHCPV6_DNS_SERVERS,
G_DHCPV6_DOMAIN_LIST, G_DHCPV6_SNTP_SERVERS);
+#if defined TIZEN_EXT
+ /**
+ When privacy extension is enabled then connman requests
+ OPTION_IA_TA (4) from DHCPv6 server. This option is used to request
+ temporary IPv6 address from DHCPv6 server but we found that DHCPv6
+ server never provided temporary IPv6 address and connman resend dhcpv6
+ requests. So always set OPTION_IA_NA in dhcpv6 request to get IPv6
+ address from DHCPv6 server.
+ */
+ dhcp->use_ta = FALSE;
+#else
ipconfig_ipv6 = __connman_service_get_ip6config(service);
dhcp->use_ta = __connman_ipconfig_ipv6_privacy_enabled(ipconfig_ipv6);
+#endif
g_dhcpv6_client_set_ia(dhcp_client, index,
dhcp->use_ta ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA,
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);
#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
* 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.
*/
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;
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));
}
}
+#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,
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;
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;
}
}
}
+#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)
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;
}
return FALSE;
}
+#if defined TIZEN_EXT
+static void recover_listener(GIOChannel *channel, struct listener_data *ifdata)
+{
+ int sk, index;
+
+ index = ifdata->index;
+
+ sk = g_io_channel_unix_get_fd(channel);
+ close(sk);
+
+ __connman_dnsproxy_remove_listener(index);
+
+ if (__connman_dnsproxy_add_listener(index) == 0)
+ DBG("listener %d successfully recovered", index);
+}
+#endif
+
static bool tcp_listener_event(GIOChannel *channel, GIOCondition condition,
struct listener_data *ifdata, int family,
guint *listener_watch)
condition, channel, ifdata, family);
if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+#if defined TIZEN_EXT
+ connman_error("Error %d with TCP listener channel", condition);
+
+ recover_listener(channel, ifdata);
+#else
if (*listener_watch > 0)
g_source_remove(*listener_watch);
*listener_watch = 0;
connman_error("Error with TCP listener channel");
+#endif
return false;
}
* The packet length bytes do not contain the total message length,
* that is the reason to -2 below.
*/
+#if defined TIZEN_EXT
+ if (msg_len > (unsigned int)(len - 2)) {
+#else
if (msg_len != (unsigned int)(len - 2)) {
+#endif
debug("client %d sent %d bytes but expecting %u pending %d",
client_sk, len, msg_len + 2, msg_len + 2 - len);
&ifdata->tcp6_listener_watch);
}
+#if defined TIZEN_EXT
+struct request_data * create_request(int sk, unsigned char *buf, size_t len,
+ const struct sockaddr *to, socklen_t tolen,
+ int protocol)
+{
+ struct request_data *req;
+ req = g_try_new0(struct request_data, 1);
+ if (!req)
+ return NULL;
+ memcpy(&req->sa, to, tolen);
+ req->sa_len = tolen;
+ req->client_sk = sk;
+ req->protocol = protocol;
+ req->request_len = len;
+ req->request = g_malloc(len);
+ memcpy(req->request, buf, len);
+ return req;
+
+}
+static gboolean send_response_timeout (gpointer user_data)
+{
+ struct request_data *req = user_data;
+
+ send_response(req->client_sk, req->request,(size_t) req->request_len, (const struct sockaddr *)&req->sa,
+ (socklen_t)req->sa_len, req->protocol);
+ g_free(req->request);
+ g_free(req);
+
+ return FALSE;
+
+}
+#endif
+
static bool udp_listener_event(GIOChannel *channel, GIOCondition condition,
struct listener_data *ifdata, int family,
guint *listener_watch)
int sk, err, len;
if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
+#if defined TIZEN_EXT
+ connman_error("Error %d with UDP listener channel", condition);
+
+ recover_listener(channel, ifdata);
+#else
connman_error("Error with UDP listener channel");
*listener_watch = 0;
+#endif
return false;
}
err = parse_request(buf, len, query, sizeof(query));
if (err < 0 || (g_slist_length(server_list) == 0)) {
+#if defined TIZEN_EXT
+ /** TEMP Fix
+ * Reason: In tizen6.0 same code working fine because it seems some delay in 6.0 platform
+ * where as in tizen6.5 this loop is continuously executing due to this unable to receive
+ * the response from telephony deamon and wpa_supplicant. To stop continuously execution
+ * of this code added 10ms delay.
+ */
+ req = create_request(sk, buf, len, client_addr,
+ *client_addr_len, IPPROTO_UDP);
+ if(!req)
+ return true;;
+ g_timeout_add(10, send_response_timeout, req);
+#else
send_response(sk, buf, len, client_addr,
*client_addr_len, IPPROTO_UDP);
+#endif
return true;
}
req->name = g_strdup(query);
req->request = g_malloc(len);
memcpy(req->request, buf, len);
+#if defined TIZEN_EXT
+ DBG("req %p dstid 0x%04x altid 0x%04x", req, req->dstid, req->altid);
+ req->timeout = g_timeout_add_seconds(30, request_timeout, req);
+#else
req->timeout = g_timeout_add_seconds(5, request_timeout, req);
+#endif
request_list = g_slist_append(request_list, req);
return true;
{
GIOChannel *channel;
const char *proto;
+#if !defined TIZEN_EXT
union {
struct sockaddr sa;
struct sockaddr_in6 sin6;
struct sockaddr_in sin;
} s;
socklen_t slen;
+#endif
int sk, type;
+#if !defined TIZEN_EXT
char *interface;
+#endif
+#if defined TIZEN_EXT
+ int option;
+ int sd_num = 0;
+ int rv;
+ int is_socket_inet = 0;
+#endif
debug("family %d protocol %d index %d", family, protocol, index);
default:
return NULL;
}
+#if defined TIZEN_EXT
+ sd_num = sd_listen_fds(0);
+ DBG("socket type(%s) systemd number of fds(%d)", proto, sd_num);
+ if(sd_num < 1){
+ DBG("fail to get the fd from systemd");
+ return NULL;
+ }
+ if(protocol == IPPROTO_TCP)
+ type = SOCK_STREAM;
+ else
+ type = SOCK_DGRAM;
+
+ for(sk = SD_LISTEN_FDS_START; sk < SD_LISTEN_FDS_START+sd_num; ++sk){
+ rv = sd_is_socket_inet(sk, family, type, -1, 53);
+ if(rv > 0){
+ DBG("socket fd (%d) is passed by systemd", sk);
+ is_socket_inet = 1;
+ break;
+ }
+ }
+
+ if (!is_socket_inet) {
+ DBG("socket fd is not matched what connman requests");
+ return NULL;
+ }
+#else
sk = socket(family, type, protocol);
if (sk < 0 && family == AF_INET6 && errno == EAFNOSUPPORT) {
connman_error("No IPv6 support");
close(sk);
return NULL;
}
+#endif
+#if defined TIZEN_EXT
+ /* When ConnMan crashed,
+ * probably DNS listener cannot bind existing address */
+ option = 1;
+ if (setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)) < 0) {
+ connman_error("Failed to set socket option SO_REUSEADDR");
+ close(sk);
+ return NULL;
+ }
+#endif
+#if !defined TIZEN_EXT
if (bind(sk, &s.sa, slen) < 0) {
connman_error("Failed to bind %s listener socket", proto);
close(sk);
return NULL;
}
+#endif
if (protocol == IPPROTO_TCP) {
+#if !defined TIZEN_EXT
if (listen(sk, 10) < 0) {
connman_error("Failed to listen on TCP socket %d/%s",
-errno, strerror(errno));
return NULL;
}
+#endif
fcntl(sk, F_SETFL, O_NONBLOCK);
}
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;
}
".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
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(ð, &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(ð, &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;
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;
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));
char cbuf[CMSG_SPACE(sizeof(*pinfo))];
struct iovec iov[2];
int fd, datalen, ret, iovlen = 1;
+#if defined TIZEN_EXT
+ char ebuf[256];
+#endif
DBG("");
msgh.msg_controllen = cmsg->cmsg_len;
ret = sendmsg(fd, &msgh, 0);
+#if defined TIZEN_EXT
+ DBG("sendmsg errno: %d/%s", errno, strerror_r(errno, ebuf, sizeof(ebuf)));
+#endif
close(fd);
return ret;
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;
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);
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;
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) {
ipconfig_set_p2p(index, ipconfig);
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
DBG("ipconfig %p index %d", ipconfig, index);
return 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);
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:
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)
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;
case CONNMAN_IPCONFIG_METHOD_MANUAL:
case CONNMAN_IPCONFIG_METHOD_DHCP:
append_addr = ipconfig->system;
+#if defined TIZEN_EXT
+ /* TIZEN enables get_properties before __connman_ipconfig_newaddr */
+ if (append_addr && append_addr->local == NULL)
+ append_addr = ipconfig->address;
+#endif
break;
}
if (append_addr->gateway)
connman_dbus_dict_append_basic(iter, "Gateway",
DBUS_TYPE_STRING, &append_addr->gateway);
+
+#if defined TIZEN_EXT
+ if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_DHCP) {
+ char *server_ip;
+ server_ip = __connman_dhcp_get_server_address(ipconfig);
+ if (server_ip) {
+ connman_dbus_dict_append_basic(iter, "DHCPServerIP",
+ DBUS_TYPE_STRING, &server_ip);
+ g_free(server_ip);
+ }
+ connman_dbus_dict_append_basic(iter, "DHCPLeaseDuration",
+ DBUS_TYPE_INT32, &ipconfig->dhcp_lease_duration);
+ }
+#endif
}
void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig,
case CONNMAN_IPCONFIG_METHOD_DHCP:
case CONNMAN_IPCONFIG_METHOD_AUTO:
append_addr = ipconfig->system;
+#if defined TIZEN_EXT
+ /* TIZEN enables get_properties before __connman_ipconfig_newaddr */
+ if (append_addr && append_addr->local == NULL)
+ append_addr = ipconfig->address;
+#endif
break;
}
case CONNMAN_IPCONFIG_METHOD_OFF:
ipconfig->method = method;
+#if defined TIZEN_EXT
+ if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6)
+ disable_ipv6(ipconfig);
+#endif
break;
ipconfig->method = method;
if (privacy_string)
ipconfig->ipv6_privacy_config = privacy;
+#if defined TIZEN_EXT
+ enable_ipv6(ipconfig);
+#endif
break;
case AF_INET6:
return g_hash_table_lookup(table_hash_ipv6, table_name);
}
-
+
return NULL;
}
case AF_INET6:
return g_hash_table_replace(table_hash_ipv6, table_name, table);
}
-
+
return false;
}
case AF_INET6:
return g_hash_table_remove(table_hash_ipv6, table_name);
}
-
+
return false;
}
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;
return true;
target = iptables_entry_get_target(e);
-
+
if (!target)
return false;
struct connman_iptables_entry *head;
struct xt_entry_target *target;
int builtin;
-
+
switch (table->type) {
case AF_INET:
case AF_INET6:
/* User defined chain */
target = iptables_entry_get_target(head);
-
+
if (!target)
continue;
if (is_fallthrough(modified_entry)) {
t = (struct xt_standard_target *)
iptables_entry_get_target(modified_entry);
-
+
if (!t)
return;
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;
}
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,
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);
struct connman_iptables *table = user_data;
struct connman_iptables_entry new_entry = { 0 };
u_int16_t next_offset;
-
+
new_entry.type = entry->type;
next_offset = iptables_entry_get_next_offset(entry);
default:
return -EINVAL;
}
-
+
return iptables_add_entry(table, &new_entry, NULL, builtin,
table->num_entries);
}
g_list_free(table->entries);
g_free(table->name);
-
+
if (table->type == AF_INET) {
g_free(table->info);
g_free(table->blob_entries);
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",
is_builtin = false;
is_user_defined = false;
-
+
DBG("target %s", target_name);
-
+
if (!table)
return NULL;
if (is_builtin || is_user_defined)
xt_t = xtables_find_target(get_standard_target(table->type),
XTF_LOAD_MUST_SUCCEED);
- else
+ else
xt_t = xtables_find_target(target_name, XTF_TRY_LOAD);
disable_jmp();
g_free(table->name);
table->name = g_strdup(table_name);
-
+
hash_table_replace(type, table->name, table);
return table;
if (invert)
ctx->ipv6->invflags |= IP6T_INV_DSTIP;
}
-
+
break;
case 'i':
/* In interface specification */
if (invert)
ctx->ip->invflags |= IPT_INV_VIA_IN;
}
-
+
if (ctx->type == AF_INET6) {
g_stpcpy(ctx->ipv6->iniface, optarg);
memset(ctx->ipv6->iniface_mask, 0xff, len + 1);
default:
return -1;
}
-
+
if (!err) {
current_type = type;
} else {
if(!find_chain_head(table, chain))
return -ENOENT; // Not Found
-
+
return 0; // Found
}
int err;
err = setup_xtables(type);
-
+
if (err < 0)
return err;
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);
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);
unsigned int cnt;
err = setup_xtables(type);
-
+
if (err < 0)
return err;
repl.r = iptables_blob(table);
if (!repl.r)
return -ENOMEM;
-
+
break;
case AF_INET6:
repl.r6 = ip6tables_blob(table);
for (list = table->entries, cnt = 0; list; list = list->next, cnt++) {
e = list->data;
if (e->counter_idx >= 0) {
-
+
switch (type) {
case AF_INET:
counters->counters[cnt] =
g_free(repl.r);
g_free(repl.r6);
-
+
reset_xtables();
return err;
int err;
err = setup_xtables(type);
-
+#if defined TIZEN_EXT
+ if (err < 0) {
+ g_free(cbd);
+ return err;
+ }
+#else
if (err < 0)
return err;
+#endif
table = get_table(type, table_name);
if (!table) {
iterate_chains_cb, cbd);
g_free(cbd);
-
+
reset_xtables();
return 0;
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);
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);
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);
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);
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);
#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
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,
.auto_connect_roaming_services = false,
.acd = false,
.use_gateways_as_timeservers = false,
+#if defined TIZEN_EXT
+ .cellular_interfaces = NULL,
+ .tizen_tv_extension = false,
+ .auto_ip = true,
+ .global_nameserver = NULL,
+ .supplicant_debug = false,
+ .def_wifi_ifname = DEFAULT_WIFI_INTERFACE,
+ .file_log = true,
+ .dlog_log = true,
+ .simple_log = true,
+ .wifi_roam_scan = false,
+ .wifi_roam = false,
+#endif
};
+#if defined TIZEN_EXT
+static struct {
+ /* BSSID */
+ char *ins_preferred_freq_bssid;
+ bool ins_last_connected_bssid;
+ bool ins_assoc_reject;
+ bool ins_signal_bssid;
+ unsigned int ins_preferred_freq_bssid_score;
+ unsigned int ins_last_connected_bssid_score;
+ unsigned int ins_assoc_reject_score;
+ /* SSID */
+ bool ins_last_user_selection;
+ unsigned int ins_last_user_selection_time;
+ bool ins_last_connected;
+ char *ins_preferred_freq;
+ char **ins_security_priority;
+ unsigned int ins_security_priority_count;
+ bool ins_signal;
+ bool ins_internet;
+ unsigned int ins_last_user_selection_score;
+ unsigned int ins_last_connected_score;
+ unsigned int ins_preferred_freq_score;
+ unsigned int ins_security_priority_score;
+ unsigned int ins_internet_score;
+ /* Common */
+ int ins_signal_level3_5ghz;
+ int ins_signal_level3_24ghz;
+} connman_ins_settings = {
+ /* BSSID */
+ .ins_preferred_freq_bssid = NULL,
+ .ins_last_connected_bssid = true,
+ .ins_assoc_reject = true,
+ .ins_signal_bssid = true,
+ .ins_preferred_freq_bssid_score = 20,
+ .ins_last_connected_bssid_score = 20,
+ .ins_assoc_reject_score = 10,
+ /* SSID */
+ .ins_last_user_selection = true,
+ .ins_last_user_selection_time = 480,
+ .ins_last_connected = true,
+ .ins_preferred_freq = NULL,
+ .ins_security_priority = NULL,
+ .ins_security_priority_count = 0,
+ .ins_signal = true,
+ .ins_internet = true,
+ .ins_last_user_selection_score = 30,
+ .ins_last_connected_score = 30,
+ .ins_preferred_freq_score = 60,
+ .ins_security_priority_score = 5,
+ .ins_internet_score = 30,
+ /* Common */
+ .ins_signal_level3_5ghz = -76,
+ .ins_signal_level3_24ghz = -74,
+};
+#endif
+
#define CONF_BG_SCAN "BackgroundScanning"
#define CONF_PREF_TIMESERVERS "FallbackTimeservers"
#define CONF_AUTO_CONNECT_TECHS "DefaultAutoConnectTechnologies"
#define CONF_AUTO_CONNECT_ROAMING_SERVICES "AutoConnectRoamingServices"
#define CONF_ACD "AddressConflictDetection"
#define CONF_USE_GATEWAYS_AS_TIMESERVERS "UseGatewaysAsTimeservers"
+#if defined TIZEN_EXT
+#define CONF_CELLULAR_INTERFACE "NetworkCellularInterfaceList"
+#define CONF_TIZEN_TV_EXT "TizenTVExtension"
+#define CONF_ENABLE_AUTO_IP "EnableAutoIp"
+#define CONF_GLOBAL_NAMESERVER "GlobalNameserver"
+#define CONF_CONNMAN_SUPPLICANT_DEBUG "ConnmanSupplicantDebug"
+#define CONF_CONNMAN_WIFI_DEF_IFNAME "DefaultWifiInterface"
+#define CONF_CONNMAN_FILE_LOG "FileLogging"
+#define CONF_CONNMAN_DLOG_LOG "DlogLogging"
+#define CONF_CONNMAN_SIMPLIFIED_LOG "SimplifiedLog"
+#define CONF_CONNMAN_WIFI_ROAM_SCAN "WifiRoamingScan"
+#define CONF_CONNMAN_WIFI_ROAM "WifiRoaming"
+#endif
+
+#if defined TIZEN_EXT
+/* BSSID */
+#define CONF_INS_PREFERRED_FREQ_BSSID "INSPreferredFreqBSSID"
+#define CONF_INS_PREFERRED_FREQ_BSSID_SCORE "INSPreferredFreqBSSIDScore"
+#define CONF_INS_LAST_CONNECTED_BSSID "INSLastConnectedBSSID"
+#define CONF_INS_LAST_CONNECTED_BSSID_SCORE "INSLastConnectedBSSIDScore"
+#define CONF_INS_ASSOC_REJECT "INSAssocReject"
+#define CONF_INS_ASSOC_REJECT_SCORE "INSAssocRejectScore"
+#define CONF_INS_SIGNAL_BSSID "INSSignalBSSID"
+/* SSID */
+#define CONF_INS_LAST_USER_SELECTION "INSLastUserSelection"
+#define CONF_INS_LAST_USER_SELECTION_TIME "INSLastUserSelectionTime"
+#define CONF_INS_LAST_USER_SELECTION_SCORE "INSLastUserSelectionScore"
+#define CONF_INS_LAST_CONNECTED "INSLastConnected"
+#define CONF_INS_LAST_CONNECTED_SCORE "INSLastConnectedScore"
+#define CONF_INS_PREFERRED_FREQ "INSPreferredFreq"
+#define CONF_INS_PREFERRED_FREQ_SCORE "INSPreferredFreqScore"
+#define CONF_INS_SECURITY_PRIORITY "INSSecurityPriority"
+#define CONF_INS_SECURITY_PRIORITY_COUNT "INSSecurityPriorityCount"
+#define CONF_INS_SECURITY_PRIORITY_SCORE "INSSecurityPriorityScore"
+#define CONF_INS_SIGNAL "INSSignal"
+#define CONF_INS_INTERNET "INSInternet"
+#define CONF_INS_INTERNET_SCORE "INSInternetScore"
+/* Common */
+#define CONF_INS_SIGNAL_LEVEL3_5GHZ "INSSignalLevel3_5GHz"
+#define CONF_INS_SIGNAL_LEVEL3_24GHZ "INSSignalLevel3_24GHz"
+#endif
static const char *supported_options[] = {
CONF_BG_SCAN,
CONF_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;
keys = g_key_file_get_groups(config, NULL);
for (j = 0; keys && keys[j]; j++) {
+#if defined TIZEN_EXT
+ if (g_strcmp0(keys[j], "General") != 0 &&
+ g_strcmp0(keys[j], "INS") != 0)
+#else
if (g_strcmp0(keys[j], "General") != 0)
+#endif
connman_warn("Unknown group %s in %s",
keys[j], MAINFILE);
}
}
g_strfreev(keys);
+
+#if defined TIZEN_EXT
+ keys = g_key_file_get_keys(config, "INS", NULL, NULL);
+
+ for (j = 0; keys && keys[j]; j++) {
+ bool found;
+ int i;
+
+ found = false;
+ for (i = 0; supported_ins_options[i]; i++) {
+ if (g_strcmp0(keys[j], supported_ins_options[i]) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found && !supported_ins_options[i])
+ connman_warn("Unknown option %s in %s",
+ keys[j], MAINFILE);
+ }
+
+ g_strfreev(keys);
+#endif
}
+#if defined TIZEN_EXT
+static void check_Tizen_INS_configuration(GKeyFile *config)
+{
+ GError *error = NULL;
+ char *ins_preferred_freq_bssid;
+ char *ins_preferred_freq;
+ char **ins_security_priority;
+ bool boolean;
+ int integer;
+ gsize len;
+
+ ins_preferred_freq_bssid = __connman_config_get_string(config, "INS",
+ CONF_INS_PREFERRED_FREQ_BSSID, &error);
+ if (!error)
+ connman_ins_settings.ins_preferred_freq_bssid = ins_preferred_freq_bssid;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_PREFERRED_FREQ_BSSID_SCORE, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_preferred_freq_bssid_score = integer;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "INS",
+ CONF_INS_LAST_CONNECTED_BSSID, &error);
+ if (!error)
+ connman_ins_settings.ins_last_connected_bssid = boolean;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_LAST_CONNECTED_BSSID_SCORE, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_last_connected_bssid_score = integer;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "INS",
+ CONF_INS_ASSOC_REJECT, &error);
+ if (!error)
+ connman_ins_settings.ins_assoc_reject = boolean;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_ASSOC_REJECT_SCORE, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_assoc_reject_score = integer;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "INS",
+ CONF_INS_SIGNAL_BSSID, &error);
+ if (!error)
+ connman_ins_settings.ins_signal_bssid = boolean;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "INS",
+ CONF_INS_LAST_USER_SELECTION, &error);
+ if (!error)
+ connman_ins_settings.ins_last_user_selection = boolean;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_LAST_USER_SELECTION_TIME, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_last_user_selection_time = integer;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_LAST_USER_SELECTION_SCORE, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_last_user_selection_score = integer;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "INS",
+ CONF_INS_LAST_CONNECTED, &error);
+ if (!error)
+ connman_ins_settings.ins_last_connected = boolean;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_LAST_CONNECTED_SCORE, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_last_connected_score = integer;
+
+ g_clear_error(&error);
+
+ ins_preferred_freq = __connman_config_get_string(config, "INS",
+ CONF_INS_PREFERRED_FREQ, &error);
+ if (!error)
+ connman_ins_settings.ins_preferred_freq = ins_preferred_freq;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_PREFERRED_FREQ_SCORE, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_preferred_freq_score = integer;
+
+ g_clear_error(&error);
+
+ ins_security_priority = g_key_file_get_string_list(config, "INS",
+ CONF_INS_SECURITY_PRIORITY, &len, &error);
+
+ if (error == NULL) {
+ connman_ins_settings.ins_security_priority = ins_security_priority;
+ connman_ins_settings.ins_security_priority_count = len;
+ }
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_SECURITY_PRIORITY_SCORE, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_security_priority_score = integer;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "INS",
+ CONF_INS_SIGNAL, &error);
+ if (!error)
+ connman_ins_settings.ins_signal = boolean;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "INS",
+ CONF_INS_INTERNET, &error);
+ if (!error)
+ connman_ins_settings.ins_internet = boolean;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_INTERNET_SCORE, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_internet_score = integer;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_SIGNAL_LEVEL3_5GHZ, &error);
+ if (!error)
+ connman_ins_settings.ins_signal_level3_5ghz = integer;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_SIGNAL_LEVEL3_24GHZ, &error);
+ if (!error)
+ connman_ins_settings.ins_signal_level3_24ghz = integer;
+
+ g_clear_error(&error);
+}
+
+static void check_Tizen_configuration(GKeyFile *config)
+{
+ GError *error = NULL;
+ char **cellular_interfaces;
+ char *global_nameserver;
+ char *default_wifi_ifname;
+ bool boolean;
+ gsize len;
+
+ cellular_interfaces = g_key_file_get_string_list(config, "General",
+ CONF_CELLULAR_INTERFACE, &len, &error);
+
+ if (error == NULL)
+ connman_settings.cellular_interfaces = cellular_interfaces;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "General",
+ CONF_TIZEN_TV_EXT, &error);
+ if (!error)
+ connman_settings.tizen_tv_extension = boolean;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "General",
+ CONF_ENABLE_AUTO_IP, &error);
+ if (!error)
+ connman_settings.auto_ip = boolean;
+
+ g_clear_error(&error);
+
+ global_nameserver = __connman_config_get_string(config, "General",
+ CONF_GLOBAL_NAMESERVER, &error);
+ if (!error)
+ connman_settings.global_nameserver = global_nameserver;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "General",
+ CONF_CONNMAN_SUPPLICANT_DEBUG, &error);
+ if (!error)
+ connman_settings.supplicant_debug = boolean;
+
+ g_clear_error(&error);
+
+ default_wifi_ifname = __connman_config_get_string(config, "General",
+ CONF_CONNMAN_WIFI_DEF_IFNAME, &error);
+ if (!error)
+ connman_settings.def_wifi_ifname = default_wifi_ifname;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "General",
+ CONF_CONNMAN_FILE_LOG, &error);
+ if (!error)
+ connman_settings.file_log = boolean;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "General",
+ CONF_CONNMAN_DLOG_LOG, &error);
+ if (!error)
+ connman_settings.dlog_log = boolean;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "General",
+ CONF_CONNMAN_SIMPLIFIED_LOG, &error);
+ if (!error)
+ connman_settings.simple_log = boolean;
+
+ boolean = __connman_config_get_bool(config, "General",
+ CONF_CONNMAN_WIFI_ROAM_SCAN, &error);
+ if (!error)
+ connman_settings.wifi_roam_scan = boolean;
+
+ boolean = __connman_config_get_bool(config, "General",
+ CONF_CONNMAN_WIFI_ROAM, &error);
+ if (!error)
+ connman_settings.wifi_roam = boolean;
+
+ g_clear_error(&error);
+
+ check_Tizen_INS_configuration(config);
+}
+
+static void set_nofile_inc(void)
+{
+ int err;
+ struct rlimit rlim;
+
+ rlim.rlim_cur = 8192;
+ rlim.rlim_max = 8192;
+
+ err = setrlimit(RLIMIT_NOFILE, &rlim);
+ if (err)
+ DBG("fail to increase FILENO err(%d)", err);
+
+ return;
+}
+#endif
+
static void parse_config(GKeyFile *config)
{
GError *error = NULL;
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",
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;
}
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;
}
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;
}
if (g_str_equal(key, CONF_ONLINE_CHECK_MAX_INTERVAL))
return connman_settings.online_check_max_interval;
+#if defined TIZEN_EXT
+ if (g_str_equal(key, CONF_INS_PREFERRED_FREQ_BSSID_SCORE))
+ return connman_ins_settings.ins_preferred_freq_bssid_score;
+
+ if (g_str_equal(key, CONF_INS_LAST_CONNECTED_BSSID_SCORE))
+ return connman_ins_settings.ins_last_connected_bssid_score;
+
+ if (g_str_equal(key, CONF_INS_ASSOC_REJECT_SCORE))
+ return connman_ins_settings.ins_assoc_reject_score;
+
+ if (g_str_equal(key, CONF_INS_LAST_USER_SELECTION_TIME))
+ return connman_ins_settings.ins_last_user_selection_time;
+
+ if (g_str_equal(key, CONF_INS_SECURITY_PRIORITY_COUNT))
+ return connman_ins_settings.ins_security_priority_count;
+
+ if (g_str_equal(key, CONF_INS_LAST_USER_SELECTION_SCORE))
+ return connman_ins_settings.ins_last_user_selection_score;
+
+ if (g_str_equal(key, CONF_INS_LAST_CONNECTED_SCORE))
+ return connman_ins_settings.ins_last_connected_score;
+
+ if (g_str_equal(key, CONF_INS_PREFERRED_FREQ_SCORE))
+ return connman_ins_settings.ins_preferred_freq_score;
+
+ if (g_str_equal(key, CONF_INS_SECURITY_PRIORITY_SCORE))
+ return connman_ins_settings.ins_security_priority_score;
+
+ if (g_str_equal(key, CONF_INS_INTERNET_SCORE))
+ return connman_ins_settings.ins_internet_score;
+#endif
return 0;
}
+#if defined TIZEN_EXT
+int connman_setting_get_int(const char *key)
+{
+ if (g_str_equal(key, CONF_INS_SIGNAL_LEVEL3_5GHZ))
+ return connman_ins_settings.ins_signal_level3_5ghz;
+
+ if (g_str_equal(key, CONF_INS_SIGNAL_LEVEL3_24GHZ))
+ return connman_ins_settings.ins_signal_level3_24ghz;
+
+ return 0;
+}
+#endif
+
char **connman_setting_get_string_list(const char *key)
{
if (g_str_equal(key, CONF_PREF_TIMESERVERS))
if (g_str_equal(key, CONF_TETHERING_TECHNOLOGIES))
return connman_settings.tethering_technologies;
+#if defined TIZEN_EXT
+ if (g_str_equal(key, CONF_CELLULAR_INTERFACE))
+ return connman_settings.cellular_interfaces;
+#endif
+
+#if defined TIZEN_EXT
+ if (g_str_equal(key, CONF_INS_SECURITY_PRIORITY))
+ return connman_ins_settings.ins_security_priority;
+#endif
+
return NULL;
}
__connman_dbus_init(conn);
+#if defined TIZEN_EXT
+ if (access(CONTAINER_FILE, F_OK) == 0) {
+ g_main_loop_run(main_loop);
+
+ g_source_remove(signal);
+ dbus_connection_unref(conn);
+ g_main_loop_unref(main_loop);
+
+ __connman_dbus_cleanup();
+ __connman_log_cleanup(option_backtrace);
+
+ return 0;
+ }
+#endif
+
if (!option_config)
config_init(CONFIGMAINFILE);
else
__connman_service_init();
__connman_peer_service_init();
__connman_peer_init();
+#if defined TIZEN_EXT_WIFI_MESH
+ __connman_mesh_init();
+#endif /* TIZEN_EXT_WIFI_MESH */
__connman_provider_init();
__connman_network_init();
__connman_config_init();
__connman_clock_init();
__connman_ipconfig_init();
+#if defined TIZEN_EXT
+ __connman_rtnl_init(GIO_SOCKET_RETRY_COUNT);
+#else /* TIZEN_EXT */
__connman_rtnl_init();
+#endif /* TIZEN_EXT */
__connman_task_init();
__connman_proxy_init();
__connman_detect_init();
__connman_dhcpv6_init();
__connman_wpad_init();
__connman_wispr_init();
+#if !defined TIZEN_EXT
__connman_rfkill_init();
__connman_machine_init();
+#endif
g_free(option_config);
g_free(option_device);
g_source_remove(signal);
+#if !defined TIZEN_EXT
__connman_machine_cleanup();
__connman_rfkill_cleanup();
+#endif
__connman_wispr_cleanup();
__connman_wpad_cleanup();
__connman_dhcpv6_cleanup();
__connman_firewall_cleanup();
__connman_peer_service_cleanup();
__connman_peer_cleanup();
+#if defined TIZEN_EXT_WIFI_MESH
+ __connman_mesh_cleanup();
+#endif /* TIZEN_EXT_WIFI_MESH */
__connman_ippool_cleanup();
__connman_device_cleanup();
__connman_network_cleanup();
g_strfreev(connman_settings.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);
# 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
# 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
# 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
# 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.
# 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
--- /dev/null
+[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
--- /dev/null
+[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
--- /dev/null
+[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
DBusMessageIter array, dict;
dbus_bool_t offlinemode;
const char *str;
+#if defined TIZEN_EXT
+ dbus_bool_t autoconnectmode;
+#endif
DBG("conn %p", conn);
connman_dbus_dict_append_basic(&dict, "SessionMode",
DBUS_TYPE_BOOLEAN,
&sessionmode);
+#if defined TIZEN_EXT
+ autoconnectmode = __connman_service_get_auto_connect_mode();
+ connman_dbus_dict_append_basic(&dict, "AutoConnectMode",
+ DBUS_TYPE_BOOLEAN,
+ &autoconnectmode);
+#endif
connman_dbus_dict_close(&array, &dict);
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);
{
DBusMessage *reply;
+#if !defined TIZEN_EXT
DBG("");
+#endif
reply = dbus_message_new_method_return(msg);
if (!reply)
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);
}
+#if defined TIZEN_EXT_WIFI_MESH
+static void append_mesh_peer_structs(DBusMessageIter *iter, void *user_data)
+{
+ __connman_mesh_peer_list_struct(iter);
+}
+
+static DBusMessage *get_mesh_peers(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return NULL;
+
+ __connman_dbus_append_objpath_dict_array(reply,
+ append_mesh_peer_structs, NULL);
+ return reply;
+}
+
+static DBusMessage *get_connected_mesh_peers(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter, array;
+
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING
+ DBUS_STRUCT_END_CHAR_AS_STRING, &array);
+
+ __connman_mesh_connected_peer_list_struct(&array);
+ dbus_message_iter_close_container(&iter, &array);
+ return reply;
+}
+
+static DBusMessage *get_disconnected_mesh_peers(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter, array;
+
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_STRUCT_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_ARRAY_AS_STRING
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING
+ DBUS_STRUCT_END_CHAR_AS_STRING, &array);
+
+ __connman_mesh_disconnected_peer_list_struct(&array);
+ dbus_message_iter_close_container(&iter, &array);
+ return reply;
+}
+
+static DBusMessage *mesh_add_peer(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ const char *addr;
+ int err;
+
+ dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr,
+ DBUS_TYPE_INVALID);
+
+ DBG("Address %s", addr);
+
+ err = __connman_mesh_change_peer_status(msg, addr, CONNMAN_MESH_PEER_ADD);
+ if (err < 0)
+ return __connman_error_failed(msg, -err);
+
+ return NULL;
+}
+
+static DBusMessage *mesh_remove_peer(DBusConnection *conn,
+ DBusMessage *msg, void *user_data)
+{
+ const char *addr;
+ int err;
+
+ dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &addr,
+ DBUS_TYPE_INVALID);
+
+ DBG("Address %s", addr);
+
+ err = __connman_mesh_change_peer_status(msg, addr,
+ CONNMAN_MESH_PEER_REMOVE);
+ if (err < 0)
+ return __connman_error_failed(msg, -err);
+
+ return NULL;
+}
+#endif
+
static const GDBusMethodTable manager_methods[] = {
{ GDBUS_METHOD("GetProperties",
NULL, GDBUS_ARGS({ "properties", "a{sv}" }),
{ GDBUS_METHOD("GetServices",
NULL, GDBUS_ARGS({ "services", "a(oa{sv})" }),
get_services) },
+#if defined TIZEN_EXT
+ { GDBUS_METHOD("GetInterfaces",
+ NULL, GDBUS_ARGS({ "interface_list", "as" }),
+ get_interfaces) },
+ { GDBUS_METHOD("GetDefaultService",
+ NULL, GDBUS_ARGS({ "service", "oa{sv}" }),
+ get_default_service) },
+ { GDBUS_METHOD("GetConnectedService",
+ GDBUS_ARGS({ "ifname", "s" }),
+ GDBUS_ARGS({ "service", "oa{sv}" }),
+ get_connected_service) },
+#endif
+#if defined TIZEN_EXT_INS
+ { GDBUS_METHOD("GetINS",
+ NULL, GDBUS_ARGS({ "services", "a(oa{sv})" }),
+ get_ins) },
+#endif
{ GDBUS_METHOD("GetPeers",
NULL, GDBUS_ARGS({ "peers", "a(oa{sv})" }),
get_peers) },
{ GDBUS_METHOD("UnregisterPeerService",
GDBUS_ARGS({ "specification", "a{sv}" }), NULL,
unregister_peer_service) },
+#if defined TIZEN_EXT_WIFI_MESH
+ { GDBUS_METHOD("GetMeshPeers",
+ NULL, GDBUS_ARGS({ "peers", "a(oa{sv})" }),
+ get_mesh_peers) },
+ { GDBUS_METHOD("GetConnectedMeshPeers",
+ NULL, GDBUS_ARGS({ "peers", "a(a{sv})" }),
+ get_connected_mesh_peers) },
+ { GDBUS_METHOD("GetDisconnectedMeshPeers",
+ NULL, GDBUS_ARGS({ "peers", "a(a{sv})" }),
+ get_disconnected_mesh_peers) },
+ { GDBUS_ASYNC_METHOD("MeshAddPeer", GDBUS_ARGS({ "address", "s" }), NULL,
+ mesh_add_peer) },
+ { GDBUS_ASYNC_METHOD("MeshRemovePeer", GDBUS_ARGS({ "address", "s" }), NULL,
+ mesh_remove_peer) },
+#endif
{ },
};
--- /dev/null
+/*
+ *
+ * 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);
+}
--- /dev/null
+/*
+ *
+ * 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);
+}
[D-BUS Service]
Name=net.connman
-Exec=@sbindir@/connmand -n
-User=root
+Exec=/bin/false
+User=network_fw
+Group=network_fw
SystemdService=connman.service
#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;
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)
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;
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;
ipconfig = __connman_service_get_ip4config(service);
__connman_ipconfig_enable(ipconfig);
+#if defined TIZEN_EXT
+ if (!service || !ipconfig)
+ return -EINVAL;
+#endif
if (!__connman_ipconfig_get_local(ipconfig))
__connman_service_read_ip4config(service);
if (err < 0)
goto err;
+#if defined TIZEN_EXT
+ err = __connman_ipconfig_gateway_add(ipconfig, service);
+#else
err = __connman_ipconfig_gateway_add(ipconfig);
+#endif
if (err < 0)
goto err;
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;
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;
check_dhcpv6, network);
return;
}
+#if defined TIZEN_EXT
+ DBG("RA message is not received from server in reply of RS.");
+#endif
connman_network_unref(network);
return;
}
*/
if (!network->connected) {
connman_network_unref(network);
+#if defined TIZEN_EXT
+ DBG("Network is not connected");
+#endif
return;
}
* We do stateful/stateless DHCPv6 if router advertisement says so.
*/
if (reply->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) {
+#if defined TIZEN_EXT
+ DBG("IPv6 ND_RA_FLAG_MANAGED");
+#endif
__connman_dhcpv6_start(network, prefixes, dhcpv6_callback);
} else {
if (reply->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)
+#if defined TIZEN_EXT
+ {
+ DBG("IPv6 ND_RA_FLAG_OTHER");
+#endif
__connman_dhcpv6_start_info(network,
dhcpv6_info_callback);
+#if defined TIZEN_EXT
+ }
+#endif
g_slist_free_full(prefixes, g_free);
network->connecting = false;
__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;
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
driver = NULL;
continue;
}
-
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
DBG("driver %p name %s", driver, driver->name);
if (driver->probe(network) == 0)
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);
return false;
}
+#if defined TIZEN_EXT
+void connman_network_set_connecting(struct connman_network *network)
+{
+ DBG("set network connecting true");
+ network->connecting = TRUE;
+ return;
+}
+#endif
+
bool connman_network_get_connecting(struct connman_network *network)
{
return network->connecting;
int connman_network_set_available(struct connman_network *network,
bool available)
{
+#if !defined TIZEN_EXT
DBG("network %p available %d", network, available);
+#endif
if (network->available == available)
return -EALREADY;
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
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)
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);
}
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)
{
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;
if (!network->device)
return -ENODEV;
+#if defined TIZEN_EXT
+ if (network->type != CONNMAN_NETWORK_TYPE_CELLULAR)
+#endif
__connman_device_disconnect(network->device);
network->connecting = true;
+#if defined TIZEN_EXT
+ DBG("ConnMan, Connect Request [%s]", network->name);
+#endif
+
err = network->driver->connect(network);
if (err < 0) {
- if (err == -EINPROGRESS)
+ if (err == -EINPROGRESS) {
+#if defined TIZEN_EXT
+ if (network->type != CONNMAN_NETWORK_TYPE_CELLULAR)
+#endif
connman_network_set_associating(network, true);
- else
+ } else
network->connecting = false;
return err;
}
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If EAP on Ethernet is ON, then network will be connected
+ * after EAP Success event is recieved, from plugin/ethernet.c
+ */
+ struct connman_service *service = connman_service_lookup_from_network(network);
+ if (service && __connman_service_get_use_eapol(service)) {
+ connman_network_set_associating(network, true);
+ return 0;
+ }
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
set_connected(network);
return err;
int __connman_network_disconnect(struct connman_network *network)
{
int err = 0;
-
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
DBG("network %p", network);
remove_ipv4ll_timeout(network);
network->connecting = false;
+#if defined TIZEN_EXT
+ DBG("ConnMan, Disconnect request");
+ struct connman_service *service = connman_service_lookup_from_network(network);
+ connman_service_set_disconnection_requested(service, true);
+#endif
if (network->driver->disconnect)
err = network->driver->disconnect(network);
return 0;
}
+#if defined TIZEN_EXT
+void __connman_network_set_auto_ipv6_gateway(char *gateway, void *user_data)
+{
+ DBG("");
+
+ struct connman_network *network = user_data;
+ struct connman_service *service;
+ struct connman_ipconfig *ipconfig = NULL;
+
+ service = connman_service_lookup_from_network(network);
+ if (service == NULL)
+ return;
+
+ ipconfig = __connman_service_get_ipconfig(service, AF_INET6);
+ if (ipconfig == NULL)
+ return;
+
+ __connman_ipconfig_set_gateway(ipconfig, gateway);
+
+ return;
+}
+#endif
+
int __connman_network_enable_ipconfig(struct connman_network *network,
struct connman_ipconfig *ipconfig)
{
int r = 0;
enum connman_ipconfig_type type;
enum connman_ipconfig_method method;
+#if defined TIZEN_EXT
+ struct connman_service *service;
+#endif
if (!network || !ipconfig)
return -EINVAL;
break;
case CONNMAN_IPCONFIG_METHOD_AUTO:
+#if defined TIZEN_EXT
+ service = connman_service_lookup_from_network(network);
+
+ if(network->type == CONNMAN_NETWORK_TYPE_CELLULAR)
+ __connman_service_ipconfig_indicate_state(service,
+ CONNMAN_SERVICE_STATE_CONFIGURATION,
+ CONNMAN_IPCONFIG_TYPE_IPV6);
+#endif
autoconf_ipv6_set(network);
break;
return 0;
}
+#if defined TIZEN_EXT
+/*
+ * Description: Network client requires additional wifi specific info
+ */
+int connman_network_set_bssid(struct connman_network *network,
+ const unsigned char *bssid)
+{
+ int i = 0;
+
+ if (bssid == NULL)
+ return -EINVAL;
+
+ if (network->connected)
+ return -EPERM;
+
+ if (!simplified_log)
+ DBG("network %p bssid %02x:%02x:%02x:%02x:%02x:%02x", network,
+ bssid[0], bssid[1], bssid[2],
+ bssid[3], bssid[4], bssid[5]);
+
+ for (;i < WIFI_BSSID_LEN_MAX;i++)
+ network->wifi.bssid[i] = bssid[i];
+
+ return 0;
+}
+
+unsigned char *connman_network_get_bssid(struct connman_network *network)
+{
+ return (unsigned char *)network->wifi.bssid;
+}
+
+int connman_network_set_transition_mode_bssid(struct connman_network *network,
+ const unsigned char *transition_mode_bssid)
+{
+ int i = 0;
+
+ if (transition_mode_bssid == NULL)
+ return -EINVAL;
+
+ for (;i < WIFI_BSSID_LEN_MAX;i++)
+ network->wifi.transition_mode_bssid[i] = transition_mode_bssid[i];
+
+ return 0;
+}
+
+unsigned char *connman_network_get_transition_mode_bssid(struct connman_network *network)
+{
+ return (unsigned char *)network->wifi.transition_mode_bssid;
+}
+
+bool connman_network_check_transition_mode(struct connman_network *network1, struct connman_network *network2)
+{
+
+ if (network1 == NULL || network2 == NULL)
+ return FALSE;
+
+ if (network1->wifi.owe_transition_mode == FALSE || network2->wifi.owe_transition_mode == FALSE)
+ return FALSE;
+
+ if ((memcmp(network1->wifi.bssid, network2->wifi.transition_mode_bssid, WIFI_BSSID_LEN_MAX) == 0)
+ && (memcmp(network1->wifi.transition_mode_bssid, network2->wifi.bssid, WIFI_BSSID_LEN_MAX) == 0))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+int connman_network_set_maxspeed(struct connman_network *network,
+ int maxspeed)
+{
+ network->wifi.maxspeed = maxspeed;
+ return 0;
+}
+
+int connman_network_get_maxspeed(struct connman_network *network)
+{
+ if (!network->driver)
+ return 0;
+
+ if (network->connected)
+ return network->wifi.maxspeed;
+
+ return 0;
+}
+
+int connman_network_set_sec_list(struct connman_network *network,
+ GSList *sec_list)
+{
+ g_slist_free(network->wifi.sec_list);
+ network->wifi.sec_list = sec_list;
+
+ return 0;
+}
+
+void *connman_network_get_sec_list(struct connman_network *network)
+{
+ return network->wifi.sec_list;
+}
+
+int connman_network_set_maxrate(struct connman_network *network,
+ unsigned int maxrate)
+{
+#if !defined TIZEN_EXT
+ DBG("network %p maxrate %d", network, maxrate);
+#endif
+
+ network->wifi.maxrate = maxrate;
+
+ return 0;
+}
+
+unsigned int connman_network_get_maxrate(struct connman_network *network)
+{
+ return network->wifi.maxrate;
+}
+
+int connman_network_set_enc_mode(struct connman_network *network,
+ const char *encryption_mode)
+{
+ if (encryption_mode == NULL)
+ return -EINVAL;
+
+ if (!simplified_log)
+ DBG("network %p encryption mode %s", network, encryption_mode);
+
+ g_strlcpy(network->wifi.encryption_mode, encryption_mode,
+ WIFI_ENCYPTION_MODE_LEN_MAX);
+
+ return 0;
+}
+
+const char *connman_network_get_enc_mode(struct connman_network *network)
+{
+ return (const char *)network->wifi.encryption_mode;
+}
+
+int connman_network_set_rsn_mode(struct connman_network *network,
+ bool rsn_mode)
+{
+ network->wifi.rsn_mode = rsn_mode;
+
+ return 0;
+}
+
+int connman_network_set_proxy(struct connman_network *network,
+ const char *proxies)
+{
+ struct connman_service *service;
+
+ DBG("network %p proxies %s", network, proxies);
+
+ service = connman_service_lookup_from_network(network);
+ if (service == NULL)
+ return -EINVAL;
+
+ __connman_service_set_proxy(service, proxies);
+
+ connman_service_set_proxy_method(service,
+ CONNMAN_SERVICE_PROXY_METHOD_MANUAL);
+
+ return 0;
+}
+
+int connman_network_set_keymgmt(struct connman_network *network,
+ unsigned int keymgmt)
+{
+ if (network == NULL)
+ return 0;
+
+ network->wifi.keymgmt = keymgmt;
+
+ return 0;
+}
+
+unsigned int connman_network_get_keymgmt(struct connman_network *network)
+{
+ if (network == NULL)
+ return 0;
+
+ return network->wifi.keymgmt;
+}
+
+int connman_network_set_disconnect_reason(struct connman_network *network,
+ int reason_code)
+{
+ if (network == NULL)
+ return 0;
+
+ network->wifi.disconnect_reason = reason_code;
+
+ return 0;
+}
+
+int connman_network_get_disconnect_reason(struct connman_network *network)
+{
+ if (network == NULL)
+ return 0;
+
+ return network->wifi.disconnect_reason;
+}
+int connman_network_get_assoc_status_code(struct connman_network *network)
+{
+ if (network == NULL)
+ return 0;
+
+ return network->wifi.assoc_status_code;
+}
+
+int connman_network_set_countrycode(struct connman_network *network,
+ const unsigned char *country_code)
+{
+ int i = 0;
+
+ if (country_code == NULL)
+ return -EINVAL;
+
+ if (!simplified_log)
+ DBG("network %p Country Code %02x:%02x",network,
+ country_code[0],country_code[1]);
+
+ for (; i < WIFI_COUNTRY_CODE_LEN; i++)
+ network->wifi.country_code[i] = country_code[i];
+
+ return 0;
+}
+
+unsigned char *connman_network_get_countrycode(struct connman_network *network)
+{
+ return (unsigned char *)network->wifi.country_code;
+}
+
+int connman_network_set_bssid_list(struct connman_network *network,
+ GSList *bssids)
+{
+ g_slist_free_full(network->wifi.bssid_list, g_free);
+ network->wifi.bssid_list = bssids;
+
+ return 0;
+}
+
+int connman_network_set_phy_mode(struct connman_network *network,
+ ieee80211_modes_e mode)
+{
+ if (!simplified_log)
+ DBG("network %p phy mode %d", network, mode);
+ network->wifi.phy_mode = mode;
+
+ return 0;
+}
+
+ieee80211_modes_e connman_network_get_phy_mode(struct connman_network *network)
+{
+ return network->wifi.phy_mode;
+}
+
+int connman_network_set_connection_mode(struct connman_network *network,
+ connection_mode_e mode)
+{
+ DBG("network %p connection mode %d", network, mode);
+ network->wifi.connection_mode = mode;
+
+ return 0;
+}
+
+connection_mode_e connman_network_get_connection_mode(struct connman_network *network)
+{
+ return network->wifi.connection_mode;
+}
+
+void *connman_network_get_bssid_list(struct connman_network *network)
+{
+ return network->wifi.bssid_list;
+}
+
+int connman_network_set_last_connected_bssid(struct connman_network *network,
+ const unsigned char *bssid)
+{
+ if (!bssid)
+ return -EINVAL;
+
+ if (!memcmp(bssid, invalid_bssid, WIFI_BSSID_LEN_MAX))
+ return -EINVAL;
+
+ memcpy(network->wifi.last_connected_bssid, bssid, WIFI_BSSID_LEN_MAX);
+
+ return 0;
+}
+
+unsigned char *connman_network_get_last_connected_bssid(struct connman_network *network)
+{
+ return (unsigned char *)network->wifi.last_connected_bssid;
+}
+
+void connman_network_set_assoc_reject_table(struct connman_network *network,
+ GHashTable *assoc_reject_table)
+{
+ if (!network)
+ return;
+
+ if (!assoc_reject_table)
+ return;
+
+ network->wifi.assoc_reject_table = assoc_reject_table;
+}
+
+GHashTable *connman_network_get_assoc_reject_table(struct connman_network *network)
+{
+ if (!network)
+ return NULL;
+
+ return network->wifi.assoc_reject_table;
+}
+
+__time_t connman_network_get_roam_scan_time(struct connman_network *network)
+{
+ return network->wifi.roam_scan_time;
+}
+
+void connman_network_set_roam_scan_time(struct connman_network *network,
+ __time_t roam_scan_time)
+{
+ network->wifi.roam_scan_time = roam_scan_time;
+}
+
+int connman_network_get_snr(struct connman_network *network)
+{
+ return network->wifi.snr;
+}
+
+void connman_network_set_snr(struct connman_network *network, int snr)
+{
+ network->wifi.snr = snr;
+}
+#endif
+
int connman_network_set_nameservers(struct connman_network *network,
const char *nameservers)
{
nameservers_array = g_strsplit(nameservers, " ", 0);
for (i = 0; nameservers_array[i]; i++) {
+#if defined TIZEN_EXT
+ __connman_service_nameserver_append(service,
+ nameservers_array[i], false,
+ CONNMAN_IPCONFIG_TYPE_ALL);
+#else
__connman_service_nameserver_append(service,
nameservers_array[i], false);
+#endif
}
g_strfreev(nameservers_array);
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);
uint8_t strength)
{
network->strength = strength;
+#if defined TIZEN_EXT
+ __connman_service_notify_strength_changed(network);
+#endif
return 0;
}
g_free(network->wifi.security);
network->wifi.security = g_strdup(value);
} else if (g_str_equal(key, "WiFi.Passphrase")) {
+#if defined TIZEN_EXT
+ DBG("ConnMan, %p key %s", network, key);
+#endif
g_free(network->wifi.passphrase);
network->wifi.passphrase = g_strdup(value);
} else if (g_str_equal(key, "WiFi.EAP")) {
} else if (g_str_equal(key, "WiFi.PinWPS")) {
g_free(network->wifi.pin_wps);
network->wifi.pin_wps = g_strdup(value);
+#if defined TIZEN_EXT
+ } else if (g_str_equal(key, "WiFi.Connector")) {
+ g_free(network->wifi.connector);
+ network->wifi.connector = g_strdup(value);
+ } else if (g_str_equal(key, "WiFi.CSignKey")) {
+ g_free(network->wifi.c_sign_key);
+ network->wifi.c_sign_key = g_strdup(value);
+ } else if (g_str_equal(key, "WiFi.NetAccessKey")) {
+ g_free(network->wifi.net_access_key);
+ network->wifi.net_access_key = g_strdup(value);
+ } else if (g_str_equal(key, "WiFi.RoamingCurBSSID")) {
+ g_free(network->wifi.roaming_cur_bssid);
+ network->wifi.roaming_cur_bssid = g_strdup(value);
+ } else if (g_str_equal(key, "WiFi.RoamingDstBSSID")) {
+ g_free(network->wifi.roaming_dst_bssid);
+ network->wifi.roaming_dst_bssid = g_strdup(value);
+#endif
} else {
return -EINVAL;
}
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;
}
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;
}
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
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;
}
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;
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;
}
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;
}
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");
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;
LOGTOD(msg->poll), offset, delay, tmx.freq / 65536);
nd->cb(true, nd->user_data);
+#endif
}
static gboolean received_data(GIOChannel *channel, GIOCondition condition,
}
__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);
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;
}
#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"
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);
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;
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;
return CONNMAN_SERVICE_TYPE_UNKNOWN;
}
+#if !defined TIZEN_EXT
static enum rfkill_type convert_service_type(enum connman_service_type type)
{
switch (type) {
return NUM_RFKILL_TYPES;
}
+#endif
static GIOStatus rfkill_process(GIOChannel *chan)
{
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;
close(fd);
return err;
+#endif
}
int __connman_rfkill_init(void)
#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)
return false;
}
+#if !defined TIZEN_EXT
static bool wext_interface(char *ifname)
{
struct iwreq wrq;
return true;
}
+#endif
+
+#if defined TIZEN_EXT
+static bool __connman_rtnl_is_cellular_device(const char *name)
+{
+ char **pattern;
+ char **cellular_interfaces;
+
+ cellular_interfaces =
+ connman_setting_get_string_list(
+ "NetworkCellularInterfaceList");
+ if (!cellular_interfaces)
+ return false;
+
+ for (pattern = cellular_interfaces; *pattern; pattern++) {
+ if (g_str_has_prefix(name, *pattern)) {
+ DBG("Cellular interface: %s", name);
+ return true;
+ }
+ }
+
+ return false;
+}
+#endif
static void read_uevent(struct interface_data *interface)
{
name = connman_inet_ifname(interface->index);
+#if defined TIZEN_EXT
+ if (__connman_rtnl_is_cellular_device(name)) {
+ interface->service_type = CONNMAN_SERVICE_TYPE_CELLULAR;
+ interface->device_type = CONNMAN_DEVICE_TYPE_CELLULAR;
+ g_free(name);
+ return;
+ }
+#endif
+
if (ether_blacklisted(name)) {
interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
interface->device_type = CONNMAN_DEVICE_TYPE_UNKNOWN;
if (found_devtype)
goto out;
+#if !defined TIZEN_EXT
+ /* TIZEN does not use old wext interface */
/* We haven't got a DEVTYPE, let's check if it's a wireless device */
if (wext_interface(name)) {
interface->service_type = CONNMAN_SERVICE_TYPE_WIFI;
connman_error("%s runs an unsupported 802.11 driver", name);
}
+#endif
out:
g_free(name);
if (!extract_link(msg, bytes, &address, &ifname, &mtu, &operstate, &stats))
return;
+#if defined TIZEN_EXT_WIFI_MESH
+ /* Do not accept Wi-Fi Mesh interface */
+ if (g_strrstr(ifname, "mesh") != NULL) {
+ DBG("Newlink event for Wi-Fi Mesh interface ignored");
+ return;
+ }
+
+ /* Do not accept Wi-Fi WLAN1 interface "dedicated for softAP */
+ if (!g_strcmp0(ifname, "wlan1")) {
+ DBG("Newlink event for Wi-Fi WLAN1 interface ignored");
+ return;
+ }
+#endif
+
+#if defined TIZEN_EXT
+ /* Do not accept Wi-Fi P2P interface */
+ if (g_strrstr(ifname, "p2p") != NULL) {
+ DBG("Newlink event for Wi-Fi P2P interface ignored");
+ return;
+ }
+#endif
+
snprintf(ident, 13, "%02x%02x%02x%02x%02x%02x",
address.ether_addr_octet[0],
address.ether_addr_octet[1],
return;
}
+#ifdef TIZEN_EXT
+ if (TIZEN_TV_EXT && g_strcmp0(ident, "eeeeeeeeeeee") == 0) {
+ DBG("Newlink event with Dummy MAC. Ignored!");
+ return;
+ }
+#endif
+
switch (type) {
case ARPHRD_ETHER:
case ARPHRD_LOOPBACK:
case ARPHDR_PHONET_PIPE:
case ARPHRD_PPP:
case ARPHRD_NONE:
+#if defined TIZEN_EXT
+/*
+ * Description: ARPHDR_RMNET for QC modem using QMI
+ */
+ case ARPHDR_RMNET:
+#endif
__connman_ipconfig_newlink(index, type, flags,
str, mtu, &stats);
break;
if (type == ARPHRD_ETHER)
read_uevent(interface);
+#if defined TIZEN_EXT
+ if (type == ARPHRD_PPP || type == ARPHDR_RMNET)
+ read_uevent(interface);
+
+ } else if (g_strcmp0(interface->ident, ident) != 0) {
+ /* If an original address is built-in physical device,
+ * it's hardly get an address at a initial creation
+ */
+ __connman_technology_remove_interface(interface->service_type,
+ interface->index, interface->ident);
+
+ g_free(interface->ident);
+ interface->ident = g_strdup(ident);
+
+ __connman_technology_add_interface(interface->service_type,
+ interface->index, interface->ident);
+
+ interface = NULL;
+#endif
} else if (type == ARPHRD_ETHER && interface->device_type == CONNMAN_DEVICE_TYPE_UNKNOWN)
read_uevent(interface);
else
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;
}
if (index < 0)
return;
+#if defined TIZEN_EXT
+ struct connman_service *service;
+ enum connman_service_state state;
+ enum connman_dnsconfig_method ipv6_dns_method;
+
+ service = __connman_service_lookup_from_index(index);
+ if (!service) {
+ DBG("Invalid service");
+ return;
+ }
+
+ DBG("service: %p index: %d\n", service, index);
+
+ if (connman_setting_get_bool("SingleConnectedTechnology") == TRUE) {
+ state = __connman_service_ipconfig_get_state(service, CONNMAN_IPCONFIG_TYPE_IPV6);
+ if (state != CONNMAN_SERVICE_STATE_ASSOCIATION &&
+ state != CONNMAN_SERVICE_STATE_CONFIGURATION &&
+ state != CONNMAN_SERVICE_STATE_READY &&
+ state != CONNMAN_SERVICE_STATE_ONLINE) {
+ DBG("Service state[%d] is not connecting/connected", state);
+ return;
+ }
+ }
+
+ ipv6_dns_method = connman_service_get_ipv6_dns_method(service);
+ if (ipv6_dns_method != CONNMAN_DNSCONFIG_METHOD_DHCP) {
+ DBG("IPv6 DNS method is not Auto ignore RA!!! [DNS method: %d]", ipv6_dns_method);
+ return;
+ }
+#endif
+
for (opt = (void *)&msg[1];
msglen > 0;
msglen -= opt->nd_opt_len * 8,
if (opt->nd_opt_type == 25) { /* ND_OPT_RDNSS */
char buf[40];
+#if defined TIZEN_EXT
+ struct connman_service *service;
+ service = __connman_service_lookup_from_index(index);
+ DBG("service: %p\n",service);
+#endif
servers = rtnl_nd_opt_rdnss(opt, &lifetime,
&nr_servers);
for (i = 0; i < nr_servers; i++) {
sizeof(buf)))
continue;
+#if defined TIZEN_EXT
+ __connman_service_nameserver_remove(service,
+ buf, false,
+ CONNMAN_IPCONFIG_TYPE_IPV6);
+ __connman_service_nameserver_append(service,
+ buf, false,
+ CONNMAN_IPCONFIG_TYPE_IPV6);
+#endif
connman_resolver_append_lifetime(index,
NULL, buf, lifetime);
}
ssize_t status;
int fd;
+#if defined TIZEN_EXT
+ if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR)) {
+ __connman_rtnl_init(GIO_SOCKET_RETRY_COUNT);
+ return FALSE;
+ }
+#else /* TIZEN_EXT */
if (cond & (G_IO_NVAL | G_IO_HUP | G_IO_ERR))
return FALSE;
+#endif /* TIZEN_EXT */
memset(buf, 0, sizeof(buf));
memset(&nladdr, 0, sizeof(nladdr));
if (errno == EINTR || errno == EAGAIN)
return TRUE;
+#if defined TIZEN_EXT
+ __connman_rtnl_init(GIO_SOCKET_RETRY_COUNT);
+#endif /* TIZEN_EXT */
return FALSE;
}
+#if defined TIZEN_EXT
+ if (status == 0) {
+ __connman_rtnl_init(GIO_SOCKET_RETRY_COUNT);
+ return FALSE;
+ }
+#else /* TIZEN_EXT */
if (status == 0)
return FALSE;
+#endif /* TIZEN_EXT */
if (nladdr.nl_pid != 0) { /* not sent by kernel, ignore */
DBG("Received msg from %u, ignoring it", nladdr.nl_pid);
return send_getlink();
}
+#if defined TIZEN_EXT
+int __connman_rtnl_init(int retry_count)
+#else /* TIZEN_EXT */
int __connman_rtnl_init(void)
+#endif /* TIZEN_EXT */
{
struct sockaddr_nl addr;
int sk;
+#if defined TIZEN_EXT
+ if (retry_count < 0)
+ return -1;
+
+ DBG("retry_count %d", retry_count);
+#else /* TIZEN_EXT */
DBG("");
+#endif /* TIZEN_EXT */
interface_list = g_hash_table_new_full(g_direct_hash, g_direct_equal,
NULL, free_interface);
sk = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_ROUTE);
if (sk < 0)
+#if defined TIZEN_EXT
+ return __connman_rtnl_init(retry_count - 1);
+#else /* TIZEN_EXT */
return -1;
+#endif /* TIZEN_EXT */
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
if (bind(sk, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
close(sk);
+#if defined TIZEN_EXT
+ return __connman_rtnl_init(retry_count - 1);
+#else /* TIZEN_EXT */
return -1;
+#endif /* TIZEN_EXT */
}
channel = g_io_channel_unix_new(sk);
#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
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;
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);
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;
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;
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;
}
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";
}
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:
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;
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,
return 0;
}
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+static void __connman_service_cleanup_8021x(struct connman_service *service)
+{
+ if (service == NULL)
+ return;
+
+ DBG("service %p ", service);
+
+ __connman_service_set_string(service, "EAP", NULL);
+ __connman_service_set_string(service, "Identity", NULL);
+ __connman_service_set_string(service, "Passphrase", NULL);
+ __connman_service_set_string(service, "AnonymousIdentity", NULL);
+ __connman_service_set_string(service, "CACertFile", NULL);
+ __connman_service_set_string(service, "ClientCertFile", NULL);
+ __connman_service_set_string(service, "PrivateKeyFile", NULL);
+ __connman_service_set_string(service, "PrivateKeyPassphrase", NULL);
+ __connman_service_set_string(service, "Phase1", NULL);
+ __connman_service_set_string(service, "Phase2", NULL);
+ __connman_service_set_string(service, "PacFile", NULL);
+}
+
+static int connman_service_set_eapol_property(struct connman_service *service,
+ DBusMessageIter *array)
+{
+ DBusMessageIter dict;
+ char *str = NULL;
+
+ __connman_service_cleanup_8021x(service);
+
+ if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(array, &dict);
+
+ while(dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter entry, value;
+ const char *key;
+ int type;
+
+ dbus_message_iter_recurse(&dict, &entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&entry, &key);
+ dbus_message_iter_next(&entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(&entry, &value);
+
+ type = dbus_message_iter_get_arg_type(&value);
+
+ if (g_str_equal(key, "UseEapol")) {
+ dbus_bool_t use_eapol;
+
+ if (type != DBUS_TYPE_BOOLEAN)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &use_eapol);
+ service->use_eapol = use_eapol;
+
+ } else if (g_str_equal(key, "EAP")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "EAP", str);
+
+ } else if (g_str_equal(key, "Identity")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "Identity", str);
+
+ } else if (g_str_equal(key, "AnonymousIdentity")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "AnonymousIdentity", str);
+
+ } else if (g_str_equal(key, "CACertFile")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "CACertFile", str);
+ } else if (g_str_equal(key, "ClientCertFile")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "ClientCertFile", str);
+ } else if (g_str_equal(key, "PrivateKeyFile")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "PrivateKeyFile", str);
+ } else if (g_str_equal(key, "PrivateKeyPassphrase")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "PrivateKeyPassphrase", str);
+ } else if (g_str_equal(key, "Phase2")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "Phase2", str);
+ } else if (g_str_equal(key, "Phase1")) {
+ int val;
+ char phase1[5] = {0,};
+
+ if (type != DBUS_TYPE_INT32)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &val);
+ sprintf(phase1, "%d", val);
+ __connman_service_set_string(service, "Phase1", phase1);
+ } else if (g_str_equal(key, "PacFile")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "PacFile", str);
+ }
+
+ dbus_message_iter_next(&dict);
+ }
+
+ return 0;
+}
+#endif
+
+#if defined TIZEN_EXT
+static void save_assoc_reject(gpointer key, gpointer value, gpointer user_data)
+{
+ struct assoc_reject_data *assoc_rd = value;
+ GString *assoc_reject_str = user_data;
+ GSList *list;
+ char *val_str;
+
+ if (g_slist_length(assoc_rd->reject_time_list) < 1)
+ return;
+
+ for (list = assoc_rd->reject_time_list; list; list = list->next) {
+ time_t assoc_reject_time = GPOINTER_TO_INT(list->data);
+
+ val_str = g_strdup_printf("%s_%ld", assoc_rd->bssid, assoc_reject_time);
+
+ if (assoc_reject_str->len > 0)
+ g_string_append_printf(assoc_reject_str, " %s", val_str);
+ else
+ g_string_append(assoc_reject_str, val_str);
+
+ g_free(val_str);
+ }
+}
+
+static void count_assoc_reject(gpointer key, gpointer value, gpointer user_data)
+{
+ struct assoc_reject_data *assoc_data = value;
+ int *assoc_reject_count = user_data;
+
+ if (assoc_data)
+ *assoc_reject_count += g_slist_length(assoc_data->reject_time_list);
+}
+
+static bool update_assoc_reject(struct connman_service *service)
+{
+ GHashTable *assoc_reject_table;
+ int assoc_reject_count;
+
+ if (!service->network)
+ return false;
+
+ assoc_reject_table = connman_network_get_assoc_reject_table(service->network);
+ if (assoc_reject_table) {
+ assoc_reject_count = 0;
+ g_hash_table_foreach(assoc_reject_table, count_assoc_reject, &assoc_reject_count);
+#if defined TIZEN_EXT_INS
+ DBG("assoc reject count [%d -> %d]",
+ service->assoc_reject_count, assoc_reject_count);
+#endif
+ if (service->assoc_reject_count != assoc_reject_count) {
+ service->assoc_reject_count = assoc_reject_count;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static int service_ext_load(struct connman_service *service)
+{
+ GKeyFile *keyfile;
+ GHashTable *reject_table;
+ char **reject_list;
+ gsize reject_len;
+ struct assoc_reject_data *reject_data;
+ char **bssid_time;
+ char *bssid;
+ time_t reject_time;
+ time_t curr_time;
+ time_t ref_time;
+ struct tm* ref_timeinfo;
+ int i;
+ int err = 0;
+
+ if (!simplified_log)
+ DBG("service %p", service);
+
+ if (!service->network)
+ return -EINVAL;
+
+ if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
+ return -EINVAL;
+
+ keyfile = connman_storage_load_service(service->identifier);
+ if (!keyfile)
+ return -EIO;
+
+ reject_table = connman_network_get_assoc_reject_table(service->network);
+
+ reject_list = g_key_file_get_string_list(keyfile,
+ service->identifier, "AssocReject", &reject_len, NULL);
+
+ if (!reject_list || reject_len == 0) {
+ g_strfreev(reject_list);
+ goto done;
+ }
+
+ /* Only events that occur within one hour are appened. */
+ curr_time = time(NULL);
+ ref_timeinfo = localtime(&curr_time);
+ ref_timeinfo->tm_hour -= 1;
+ ref_time = mktime(ref_timeinfo);
+
+ for (i = 0; reject_list[i]; i++) {
+ bssid_time = g_strsplit(reject_list[i], "_", 0);
+ if (!bssid_time) {
+ err = -ERANGE;
+ continue;
+ }
+
+ bssid = bssid_time[0];
+ reject_time = strtol(bssid_time[1], NULL, 10);
+
+ if (reject_time < ref_time) {
+ g_strfreev(bssid_time);
+ err = -ERANGE;
+ continue;
+ }
+
+ reject_data = g_hash_table_lookup(reject_table, bssid);
+ if (!reject_data) {
+ reject_data = g_try_new0(struct assoc_reject_data, 1);
+ if (!reject_data) {
+ g_strfreev(bssid_time);
+ err = -ERANGE;
+ continue;
+ }
+
+ reject_data->bssid = g_strdup(bssid);
+ g_hash_table_insert(reject_table, reject_data->bssid, reject_data);
+ }
+
+ reject_data->reject_time_list = g_slist_append(reject_data->reject_time_list,
+ GINT_TO_POINTER(reject_time));
+
+#if defined TIZEN_EXT_INS
+ DBG("assoc reject [%s_%ld]", bssid, reject_time);
+#endif
+
+ g_strfreev(bssid_time);
+ }
+
+ g_strfreev(reject_list);
+
+done:
+ g_key_file_free(keyfile);
+ return err;
+}
+
+static int service_ext_save(struct connman_service *service)
+{
+ GKeyFile *keyfile;
+ GHashTable *reject_table;
+ GString *reject_str;
+ char **reject_list;
+ guint reject_len;
+ int err = 0;
+
+ DBG("service %p", service);
+
+ if (!service->network)
+ return -EINVAL;
+
+ if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
+ return -EINVAL;
+
+ keyfile = g_key_file_new();
+ if (!keyfile)
+ return -EIO;
+
+ /* Last connected BSSID */
+ if (memcmp(service->last_connected_bssid, invalid_bssid, WIFI_BSSID_LEN_MAX)) {
+ char *identifier = service->identifier;
+ GString *bssid_str;
+ unsigned int i;
+
+ bssid_str = g_string_sized_new(MAC_ADDRESS_LENGTH);
+ if (!bssid_str) {
+ err = -ENOMEM;
+ goto next;
+ }
+
+ for (i = 0; i < WIFI_BSSID_LEN_MAX; i++) {
+ g_string_append_printf(bssid_str,
+ "%02x", service->last_connected_bssid[i]);
+ if (i < WIFI_BSSID_LEN_MAX - 1)
+ g_string_append(bssid_str, ":");
+ }
+
+ g_key_file_set_string(keyfile, identifier,
+ "LastConnectedBSSID", bssid_str->str);
+
+#if defined TIZEN_EXT_INS
+ DBG("last connected bssid[%s]", bssid_str->str);
+#endif
+
+ g_string_free(bssid_str, TRUE);
+ }
+
+next:
+
+ /* Assoc reject */
+ reject_table = connman_network_get_assoc_reject_table(service->network);
+ if (reject_table && g_hash_table_size(reject_table) > 0) {
+ reject_str = g_string_new(NULL);
+ if (!reject_str) {
+ err = -ENOMEM;
+ goto done;
+ }
+
+ g_hash_table_foreach(reject_table, save_assoc_reject, reject_str);
+
+ reject_list = g_strsplit_set(reject_str->str, " ", 0);
+ reject_len = g_strv_length(reject_list);
+
+ g_key_file_set_string_list(keyfile, service->identifier,
+ "AssocReject", (const gchar **)reject_list, reject_len);
+
+#if defined TIZEN_EXT_INS
+ DBG("assoc reject table [%d]", reject_len);
+#endif
+
+ g_strfreev(reject_list);
+ g_string_free(reject_str, TRUE);
+ } else {
+ g_key_file_remove_key(keyfile, service->identifier, "AssocReject", NULL);
+ }
+
+done:
+ __connman_storage_save_service(keyfile, service->identifier);
+
+ g_key_file_free(keyfile);
+ return err;
+}
+#endif
+
static int service_load(struct connman_service *service)
{
GKeyFile *keyfile;
bool autoconnect;
unsigned int ssid_len;
int err = 0;
-
+#if defined TIZEN_EXT
+ bool internet_connection;
+#endif
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ bool use_eapol;
+#endif
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
DBG("service %p", service);
keyfile = connman_storage_load_service(service->identifier);
case CONNMAN_SERVICE_TYPE_SYSTEM:
case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
break;
case CONNMAN_SERVICE_TYPE_VPN:
__connman_service_set_split_routing(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:
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;
}
service->nameservers_config = NULL;
}
+#ifdef TIZEN_EXT
+ char *dns_method;
+
+ dns_method = g_key_file_get_string(keyfile, service->identifier,
+ "Nameservers.IPv4method", NULL);
+ if (dns_method) {
+ service->dns_config_method_ipv4 = __connman_dnsconfig_string2method(dns_method);
+ g_free(dns_method);
+ }
+
+ dns_method = g_key_file_get_string(keyfile, service->identifier,
+ "Nameservers.IPv6method", NULL);
+ if (dns_method) {
+ service->dns_config_method_ipv6 = __connman_dnsconfig_string2method(dns_method);
+ g_free(dns_method);
+ }
+#endif
+
service->timeservers_config = g_key_file_get_string_list(keyfile,
service->identifier, "Timeservers", &length, NULL);
if (service->timeservers_config && length == 0) {
service->hidden_service = g_key_file_get_boolean(keyfile,
service->identifier, "Hidden", NULL);
+#if defined TIZEN_EXT
+ if ((service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+ service->security == CONNMAN_SERVICE_SECURITY_8021X)
+#if defined TIZEN_EXT_EAP_ON_ETHERNET
+ || (service->type == CONNMAN_SERVICE_TYPE_ETHERNET && service->use_eapol)
+#endif
+ ) {
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "EAP", NULL);
+ if (str != NULL) {
+ g_free(service->eap);
+ service->eap = str;
+ }
+
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "Phase2", NULL);
+ if (str != NULL) {
+ g_free(service->phase2);
+ service->phase2 = str;
+ }
+
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "Identity", NULL);
+ if (str != NULL) {
+ g_free(service->identity);
+ service->identity = str;
+ }
+
+#if defined TIZEN_EXT_EAP_ON_ETHERNET
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "AnonymousIdentity", NULL);
+ if (str != NULL) {
+ g_free(service->anonymous_identity);
+ service->anonymous_identity = str;
+ }
+#endif
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "CACertFile", NULL);
+ if (str != NULL) {
+ g_free(service->ca_cert_file);
+ service->ca_cert_file = str;
+ }
+
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "ClientCertFile", NULL);
+ if (str != NULL) {
+ g_free(service->client_cert_file);
+ service->client_cert_file = str;
+ }
+
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "PrivateKeyFile", NULL);
+ if (str != NULL) {
+ g_free(service->private_key_file);
+ service->private_key_file = str;
+ }
+
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "PrivateKeyPassphrase", NULL);
+ if (str != NULL) {
+ g_free(service->private_key_passphrase);
+ service->private_key_passphrase = str;
+ }
+
+#if defined TIZEN_EXT_EAP_ON_ETHERNET
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "Phase1", NULL);
+ if (str != NULL) {
+ g_free(service->phase1);
+ service->phase1 = str;
+ }
+
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "PacFile", NULL);
+ if (str != NULL) {
+ g_free(service->pac_file);
+ service->pac_file = str;
+ }
+#endif
+ }
+#endif
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+ service->security == CONNMAN_SERVICE_SECURITY_DPP) {
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "Connector", NULL);
+ if (str != NULL) {
+ g_free(service->connector);
+ service->connector = str;
+ }
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "CSignKey", NULL);
+ if (str != NULL) {
+ g_free(service->c_sign_key);
+ service->c_sign_key = str;
+ }
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "NetAccessKey", NULL);
+ if (str != NULL) {
+ g_free(service->net_access_key);
+ service->net_access_key = str;
+ }
+ }
+#endif
+
done:
g_key_file_free(keyfile);
case CONNMAN_SERVICE_TYPE_SYSTEM:
case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
break;
case CONNMAN_SERVICE_TYPE_VPN:
g_key_file_set_boolean(keyfile, service->identifier,
if (service->network) {
const unsigned char *ssid;
unsigned int ssid_len = 0;
+#if defined TIZEN_EXT
+ GHashTable *assoc_reject_table;
+#endif
ssid = connman_network_get_blob(service->network,
"WiFi.SSID", &ssid_len);
freq = connman_network_get_frequency(service->network);
g_key_file_set_integer(keyfile, service->identifier,
"Frequency", freq);
+
+#if defined TIZEN_EXT
+ /* Last connected BSSID */
+ if (memcmp(service->last_connected_bssid, invalid_bssid, WIFI_BSSID_LEN_MAX)) {
+ char *identifier = service->identifier;
+ GString *bssid_str;
+ unsigned int i;
+
+ bssid_str = g_string_sized_new(18);
+ if (!bssid_str) {
+ err = -ENOMEM;
+ goto done;
+ }
+
+ for (i = 0; i < WIFI_BSSID_LEN_MAX; i++) {
+ g_string_append_printf(bssid_str,
+ "%02x", service->last_connected_bssid[i]);
+ if (i < WIFI_BSSID_LEN_MAX - 1)
+ g_string_append(bssid_str, ":");
+ }
+
+ g_key_file_set_string(keyfile, identifier,
+ "LastConnectedBSSID", bssid_str->str);
+
+#if defined TIZEN_EXT_INS
+ DBG("last connected bssid[%s]", bssid_str->str);
+#endif
+
+ g_string_free(bssid_str, TRUE);
+ }
+
+ /* Assoc reject */
+ assoc_reject_table = connman_network_get_assoc_reject_table(service->network);
+ if (assoc_reject_table && g_hash_table_size(assoc_reject_table) > 0) {
+ GString *assoc_reject_str;
+ char **assoc_reject_list;
+ guint assoc_reject_len;
+
+ assoc_reject_str = g_string_new(NULL);
+ if (!assoc_reject_str) {
+ err = -ENOMEM;
+ goto done;
+ }
+
+ g_hash_table_foreach(assoc_reject_table, save_assoc_reject, assoc_reject_str);
+
+ assoc_reject_list = g_strsplit_set(assoc_reject_str->str, " ", 0);
+ assoc_reject_len = g_strv_length(assoc_reject_list);
+
+ g_key_file_set_string_list(keyfile, service->identifier,
+ "AssocReject", (const gchar **)assoc_reject_list, assoc_reject_len);
+
+#if defined TIZEN_EXT_INS
+ DBG("assoc reject table [%d]", assoc_reject_len);
+#endif
+
+ g_strfreev(assoc_reject_list);
+ g_string_free(assoc_reject_str, TRUE);
+ } else
+ g_key_file_remove_key(keyfile, service->identifier, "AssocReject", NULL);
+
+ /* Internet connection */
+ g_key_file_set_boolean(keyfile, service->identifier,
+ "InternetConnection", service->is_internet_connection);
+#if defined TIZEN_EXT_INS
+ DBG("internet connection [%s]", service->is_internet_connection ? "true" : "false");
+#endif
+#endif
}
/* fall through */
if (service->favorite)
g_key_file_set_boolean(keyfile, service->identifier,
"AutoConnect", service->autoconnect);
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ g_key_file_set_boolean(keyfile, service->identifier,
+ "UseEapol", service->use_eapol);
+#endif
break;
}
(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);
g_key_file_set_string(keyfile, service->identifier,
"Config.ident", service->config_entry);
+#if defined TIZEN_EXT
+ if ((service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+ service->security == CONNMAN_SERVICE_SECURITY_8021X)
+#if defined TIZEN_EXT_EAP_ON_ETHERNET
+ || (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
+#endif
+ ) {
+ if (service->eap != NULL && strlen(service->eap) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "EAP", service->eap);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "EAP", NULL);
+
+ if (service->phase2 != NULL && strlen(service->phase2) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "Phase2", service->phase2);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "Phase2", NULL);
+
+ if (service->identity != NULL && strlen(service->identity) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "Identity", service->identity);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "Identity", NULL);
+#if defined TIZEN_EXT_EAP_ON_ETHERNET
+ if (service->anonymous_identity != NULL && strlen(service->anonymous_identity) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "AnonymousIdentity", service->anonymous_identity);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "AnonymousIdentity", NULL);
+#endif
+
+ if (service->ca_cert_file != NULL && strlen(service->ca_cert_file) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "CACertFile", service->ca_cert_file);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "CACertFile", NULL);
+
+ if (service->client_cert_file != NULL && strlen(service->client_cert_file) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "ClientCertFile", service->client_cert_file);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "ClientCertFile", NULL);
+
+ if (service->private_key_file != NULL && strlen(service->private_key_file) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "PrivateKeyFile", service->private_key_file);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "PrivateKeyFile", NULL);
+
+ if (service->private_key_passphrase != NULL && strlen(service->private_key_passphrase) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "PrivateKeyPassphrase", service->private_key_passphrase);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "PrivateKeyPassphrase", NULL);
+#if defined TIZEN_EXT_EAP_ON_ETHERNET
+ if (service->phase1 != NULL && strlen(service->phase1) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "Phase1", service->phase1);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "Phase1", NULL);
+ if (service->pac_file != NULL && strlen(service->pac_file) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "PacFile", service->pac_file);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "PacFile", NULL);
+#endif
+ }
+
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+ service->security == CONNMAN_SERVICE_SECURITY_DPP) {
+ if (service->connector != NULL && strlen(service->connector) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "Connector", service->connector);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "Connector", NULL);
+
+ if (service->c_sign_key != NULL && strlen(service->c_sign_key) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "CSignKey", service->c_sign_key);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "CSignKey", NULL);
+
+ if (service->net_access_key != NULL && strlen(service->net_access_key) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "NetAccessKey", service->net_access_key);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "NetAccessKey", NULL);
+ }
+#endif
+
done:
__connman_storage_save_service(keyfile, service->identifier);
return err;
}
+#if defined TIZEN_EXT
+static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+ GTimeVal *aval = (GTimeVal *)a;
+ GTimeVal *bval = (GTimeVal *)b;
+
+ /* Note that the sort order is ascending */
+ if (aval->tv_sec > bval->tv_sec)
+ return 1;
+
+ if (aval->tv_sec < bval->tv_sec)
+ return -1;
+
+ return 0;
+}
+
+static void free_entry(gpointer data)
+{
+ struct saved_profiles *entry = data;
+ g_free(entry->profile_name);
+ g_free(entry);
+}
+
+static void __connman_manage_saved_profiles()
+{
+ GKeyFile *keyfile;
+ gchar **services = NULL;
+ GTimeVal modified;
+ int i, num_profiles = 0;
+ GSequenceIter *iter;
+ GSequence *profile_list;
+ struct saved_profiles *entry;
+
+ profile_list = g_sequence_new(free_entry);
+ if (!profile_list)
+ return;
+
+ services = connman_storage_get_services();
+
+ /* Check the count of saved profiles */
+ for (i = 0; services && services[i]; i++) {
+ if (strncmp(services[i], "wifi_", 5) != 0)
+ continue;
+
+ keyfile = connman_storage_load_service(services[i]);
+ if (!keyfile)
+ continue;
+
+ gchar *str = g_key_file_get_string(keyfile,
+ services[i], "Modified", NULL);
+ if (!str) {
+ g_key_file_free(keyfile);
+ continue;
+ }
+
+ g_time_val_from_iso8601(str, &modified);
+ g_free(str);
+
+ entry = g_try_new(struct saved_profiles, 1);
+ if (!entry) {
+ g_sequence_free(profile_list);
+ g_key_file_free(keyfile);
+ g_strfreev(services);
+ return;
+ }
+
+ entry->modified = modified;
+ entry->profile_name = g_strdup(services[i]);
+
+ g_sequence_insert_sorted(profile_list, entry,
+ sort_entry, NULL);
+
+ num_profiles++;
+ }
+ DBG("number of profiles: %d", num_profiles);
+
+ if (num_profiles > MAX_WIFI_PROFILES) {
+ iter = g_sequence_get_begin_iter(profile_list);
+
+ entry = g_sequence_get(iter);
+
+ if (__connman_storage_remove_service(entry->profile_name) == false)
+ DBG("Failed to remove service profile: %s", entry->profile_name);
+ }
+
+ g_sequence_free(profile_list);
+ g_strfreev(services);
+}
+#endif
+
void __connman_service_save(struct connman_service *service)
{
if (!service)
return;
service_save(service);
+#if defined TIZEN_EXT
+ /*
+ * Description: Manage the wireless profiles saved in connman.
+ * If the number of saved profiles is more than 200, remove the
+ * profile that is not updated for longer duration.
+ */
+ __connman_manage_saved_profiles();
+#endif
}
static enum connman_service_state combine_state(
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);
if (service->nameservers_config) {
while (service->nameservers_config[i]) {
+#if defined TIZEN_EXT
+ DBG("type %d add service->nameservers_config[%d]:%s",type,
+ i, service->nameservers_config[i]);
+ if(strncmp(service->nameservers_config[i], "::", 2) == 0) {
+ DBG("Invalid nameserver");
+ i++;
+ continue;
+ }
+
+ switch(type) {
+ case CONNMAN_IPCONFIG_TYPE_IPV4:
+ if (connman_inet_check_ipaddress(
+ service->nameservers_config[i]) == AF_INET &&
+ service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL) {
+ nameserver_add(service, type,
+ service->nameservers_config[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_IPV6:
+ if (connman_inet_check_ipaddress(
+ service->nameservers_config[i]) == AF_INET6 &&
+ service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL) {
+ nameserver_add(service, type,
+ service->nameservers_config[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_ALL:
+ if (connman_inet_check_ipaddress(
+ service->nameservers_config[i]) == AF_INET &&
+ service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL) {
+ nameserver_add(service, type,
+ service->nameservers_config[i]);
+ }
+ if (connman_inet_check_ipaddress(
+ service->nameservers_config[i]) == AF_INET6 &&
+ service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL) {
+ nameserver_add(service, type,
+ service->nameservers_config[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
+ DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing");
+ break;
+ default:
+ DBG("default case do nothing");
+ break;
+ }
+#else
nameserver_add(service, type,
service->nameservers_config[i]);
+#endif
i++;
}
} else if (service->nameservers) {
while (service->nameservers[i]) {
+#if defined TIZEN_EXT
+ DBG("type %d service->nameservers[%d]: %s",type,
+ i, service->nameservers[i]);
+
+ switch(type) {
+ case CONNMAN_IPCONFIG_TYPE_IPV4:
+ if (connman_inet_check_ipaddress(
+ service->nameservers[i]) == AF_INET &&
+ service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP) {
+ nameserver_add(service, type,
+ service->nameservers[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_IPV6:
+ if (connman_inet_check_ipaddress(
+ service->nameservers[i]) == AF_INET6 &&
+ service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP) {
+ nameserver_add(service, type,
+ service->nameservers[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_ALL:
+ if (connman_inet_check_ipaddress(
+ service->nameservers[i]) == AF_INET &&
+ service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP) {
+ nameserver_add(service, type,
+ service->nameservers[i]);
+ }
+ if (connman_inet_check_ipaddress(
+ service->nameservers[i]) == AF_INET6 &&
+ service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP) {
+ nameserver_add(service, type,
+ service->nameservers[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
+ DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing");
+ break;
+ default:
+ DBG("default case do nothing");
+ break;
+ }
+#else
nameserver_add(service, type,
service->nameservers[i]);
+#endif
i++;
}
}
if (!i)
__connman_resolver_append_fallback_nameservers();
+#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;
if (index < 0)
return -ENXIO;
+#if defined TIZEN_EXT
+ DBG("Resolver remove nameserver: %s", nameserver);
+#endif
ret = connman_resolver_remove(index, NULL, nameserver);
if (ret >= 0)
nameservers_changed(service);
static int nameserver_remove_all(struct connman_service *service,
enum connman_ipconfig_type type)
{
+#if defined TIZEN_EXT
+ /**
+ * Skip this function if there is any connected profiles
+ * that use same interface
+ */
+ if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
+ __connman_service_get_connected_count_of_iface(service) > 0)
+ return 0;
+#endif
int index, i = 0;
index = __connman_service_get_index(service);
while (service->nameservers_config && service->nameservers_config[i]) {
+#if defined TIZEN_EXT
+ DBG("type %d Remove service->nameservers_config[%d]: %s",
+ type, i, service->nameservers_config[i]);
+ switch(type) {
+ case CONNMAN_IPCONFIG_TYPE_IPV4:
+ if (connman_inet_check_ipaddress(
+ service->nameservers_config[i]) == AF_INET &&
+ (service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP ||
+ service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL)) {
+ nameserver_remove(service, type,
+ service->nameservers_config[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_IPV6:
+ if (connman_inet_check_ipaddress(
+ service->nameservers_config[i]) == AF_INET6 &&
+ (service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP ||
+ service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL)) {
+ nameserver_remove(service, type,
+ service->nameservers_config[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_ALL:
+ if (connman_inet_check_ipaddress(
+ service->nameservers_config[i]) == AF_INET &&
+ (service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP ||
+ service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL)) {
+ nameserver_remove(service, type,
+ service->nameservers_config[i]);
+ }
+ if (connman_inet_check_ipaddress(
+ service->nameservers_config[i]) == AF_INET6 &&
+ (service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP ||
+ service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL)) {
+ nameserver_remove(service, type,
+ service->nameservers_config[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
+ DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing");
+ break;
+ default:
+ DBG("default case do nothing");
+ break;
+ }
+#else
nameserver_remove(service, type,
service->nameservers_config[i]);
+#endif
i++;
}
i = 0;
while (service->nameservers && service->nameservers[i]) {
+#if defined TIZEN_EXT
+ DBG("type %d Remove service->nameservers[%d]: %s",type, i,
+ service->nameservers[i]);
+ switch(type) {
+ case CONNMAN_IPCONFIG_TYPE_IPV4:
+ if (connman_inet_check_ipaddress(
+ service->nameservers[i]) == AF_INET &&
+ (service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL ||
+ service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP)) {
+ nameserver_remove(service, type,
+ service->nameservers[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_IPV6:
+ if (connman_inet_check_ipaddress(
+ service->nameservers[i]) == AF_INET6 &&
+ (service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL ||
+ service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP)) {
+ nameserver_remove(service, type,
+ service->nameservers[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_ALL:
+ if (connman_inet_check_ipaddress(
+ service->nameservers[i]) == AF_INET &&
+ (service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL ||
+ service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP)) {
+ nameserver_remove(service, type,
+ service->nameservers[i]);
+ }
+ if (connman_inet_check_ipaddress(
+ service->nameservers[i]) == AF_INET6 &&
+ (service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL ||
+ service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP)) {
+ nameserver_remove(service, type,
+ service->nameservers[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
+ DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing");
+ break;
+ default:
+ DBG("default case do nothing");
+ break;
+ }
+#else
nameserver_remove(service, type, service->nameservers[i]);
+#endif
i++;
}
+#if defined TIZEN_EXT
+ const char *global_dns = connman_setting_get_string("GlobalNameserver");
+ if (global_dns)
+ nameserver_remove(service, type, global_dns);
+#endif
searchdomain_remove_all(service);
return 0;
* inserted to resolver via netlink message (see rtnl.c:rtnl_newnduseropt()
* for details) and not through service.c
*/
+#if defined TIZEN_EXT
+int __connman_service_nameserver_append(struct connman_service *service,
+ const char *nameserver, bool is_auto,
+ enum connman_ipconfig_type type)
+#else
int __connman_service_nameserver_append(struct connman_service *service,
const char *nameserver, bool is_auto)
+#endif
{
char **nameservers;
int len, i;
if (nameservers) {
for (i = 0; nameservers[i]; i++) {
+#if defined TIZEN_EXT
+ DBG("nameservers[%d] %s, nameserver %s", i, nameservers[i], nameserver);
+#endif
if (g_strcmp0(nameservers[i], nameserver) == 0)
return -EEXIST;
}
nameservers[len] = g_strdup(nameserver);
nameservers[len + 1] = NULL;
+#ifdef TIZEN_EXT
+ if(type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
+ service->dns_config_method_ipv4 == CONNMAN_DNSCONFIG_METHOD_UNKNOWN)
+ service->dns_config_method_ipv4 = CONNMAN_DNSCONFIG_METHOD_DHCP;
+
+ if(type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
+ service->dns_config_method_ipv6 == CONNMAN_DNSCONFIG_METHOD_UNKNOWN)
+ service->dns_config_method_ipv6 = CONNMAN_DNSCONFIG_METHOD_DHCP;
+#endif
+
if (is_auto) {
service->nameservers_auto = nameservers;
} else {
return 0;
}
+#if defined TIZEN_EXT
+int __connman_service_nameserver_remove(struct connman_service *service,
+ const char *nameserver, bool is_auto,
+ enum connman_ipconfig_type type)
+#else
int __connman_service_nameserver_remove(struct connman_service *service,
const char *nameserver, bool is_auto)
+#endif
{
char **servers, **nameservers;
bool found = false;
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;
g_timer_reset(service->stats_roaming.timer);
}
+#if defined TIZEN_EXT
+static gboolean __connman_service_is_internet_profile(
+ struct connman_service *cellular)
+{
+ const char internet_suffix[] = "_1";
+
+ DBG("Service path: %s", cellular->path);
+
+ if (g_str_has_suffix(cellular->path, internet_suffix) == TRUE)
+ return TRUE;
+
+ return FALSE;
+}
+
+struct connman_service *connman_service_get_default_connection(void)
+{
+ GList *list;
+ struct connman_service *service;
+ struct connman_service *default_service = NULL;
+
+ for (list = service_list; list; list = list->next) {
+ service = list->data;
+
+ DBG("service: %p %s %s %s", service, service->name,
+ state2string(service->state),
+ __connman_service_type2string(service->type));
+
+#if defined TIZEN_MAINTAIN_ONLINE
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+ service->state == CONNMAN_SERVICE_STATE_ONLINE) {
+#else
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+ is_connected(service->state) == TRUE) {
+#endif
+ return service;
+ } else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
+ __connman_service_is_internet_profile(service) == TRUE) {
+ if (default_service == NULL)
+ default_service = service;
+ else if (is_connected(service->state) == TRUE &&
+ is_connected(default_service->state) == FALSE)
+ default_service = service;
+ } else if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET &&
+ is_connected(service->state) == TRUE) {
+ if (default_service == NULL)
+ default_service = service;
+ } else if (service->type == CONNMAN_SERVICE_TYPE_BLUETOOTH &&
+ is_connected(service->state) == TRUE) {
+ if (default_service == NULL)
+ default_service = service;
+ }
+ }
+
+ return default_service;
+}
+
+struct connman_service *connman_service_get_connected_service(const char *ifname)
+{
+ GList *list;
+ const char *svc_ifname;
+ struct connman_service *service;
+
+ if (!ifname)
+ return NULL;
+
+ for (list = service_list; list; list = list->next) {
+ service = list->data;
+
+ if (!is_connected(service->state))
+ continue;
+
+ svc_ifname = connman_device_get_string(
+ connman_network_get_device(service->network), "Interface");
+
+ if (svc_ifname && g_strcmp0(svc_ifname, ifname) == 0)
+ return service;
+ }
+
+ return NULL;
+}
+#endif
+
struct connman_service *connman_service_get_default(void)
{
+#if defined TIZEN_MAINTAIN_ONLINE
+ return connman_service_get_default_connection();
+#else
struct connman_service *service;
if (!service_list)
return NULL;
return service;
+#endif
}
bool __connman_service_index_is_default(int index)
static void default_changed(void)
{
+#if defined TIZEN_EXT
+ struct connman_service *service = connman_service_get_default_connection();
+#else
struct connman_service *service = connman_service_get_default();
+#endif
if (service == current_default)
return;
current_default ? current_default->identifier : "");
DBG("new default %p %s", service, service ? service->identifier : "");
+#if defined TIZEN_EXT
+ current_default = service;
+
+ __connman_service_timeserver_changed(service, NULL);
+#else
__connman_service_timeserver_changed(current_default, NULL);
current_default = service;
+#endif
if (service) {
if (service->hostname &&
__connman_notifier_default_changed(service);
}
+#if defined TIZEN_EXT
+static void append_struct(gpointer value, gpointer user_data);
+
+static void emit_state_changed_with_properties(struct connman_service *service)
+{
+ DBusMessage *signal;
+ DBusMessageIter iter;
+
+ if (!service)
+ return;
+
+ signal = dbus_message_new_signal(service->path, CONNMAN_SERVICE_INTERFACE,
+ "StateChangedProperties");
+ if (!signal)
+ return;
+
+ dbus_message_iter_init_append(signal, &iter);
+ append_struct(service, &iter);
+
+ g_dbus_send_message(connection, signal);
+
+ return;
+}
+#endif
+
static void state_changed(struct connman_service *service)
{
const char *str;
if (!str)
return;
+#if !defined TIZEN_EXT
if (!allow_property_changed(service))
return;
+#else
+ DBG(" %s, %s", str, service->path);
+#endif
connman_dbus_property_changed_basic(service->path,
CONNMAN_SERVICE_INTERFACE, "State",
DBUS_TYPE_STRING, &str);
+
+#if defined TIZEN_EXT
+ emit_state_changed_with_properties(service);
+#endif
+}
+
+#if defined TIZEN_EXT
+static void connect_reason_changed(struct connman_service *service)
+{
+#if defined TIZEN_EXT_INS
+ struct connman_device *device;
+#endif
+ if (!service->path)
+ return;
+
+ if (!allow_property_changed(service))
+ return;
+
+#if defined TIZEN_EXT_INS
+ if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
+ device = connman_network_get_device(service->network);
+ if (device) {
+ bool need_save = false;
+
+ need_save |= connman_device_set_last_user_selection_ident(device, service->identifier);
+ need_save |= connman_device_set_last_user_selection_time(device, time(NULL));
+
+ DBG("last user selection ident[%s] time[%ld]",
+ connman_device_get_last_user_selection_ident(device),
+ connman_device_get_last_user_selection_time(device));
+
+ if (need_save)
+ connman_device_save_last_user_selection(device);
+ }
+ }
+#endif
+
+ connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE,
+ "ConnectReason",
+ DBUS_TYPE_INT32,
+ &service->connect_reason);
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
+#if defined TIZEN_EXT
+static void disconnection_requested_changed(struct connman_service *service)
+{
+ dbus_bool_t disconnection_requested;
+
+ if (!service->path)
+ return;
+
+ if (!allow_property_changed(service))
+ return;
+
+ disconnection_requested = service->disconnection_requested;
+ connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE,
+ "DisconnectionRequested",
+ DBUS_TYPE_BOOLEAN,
+ &disconnection_requested);
+}
+
+void connman_service_set_disconnection_requested(struct connman_service *service,
+ bool disconnection_requested)
+{
+ if (service == NULL)
+ return;
+
+ service->disconnection_requested = disconnection_requested;
+ disconnection_requested_changed(service);
}
+#endif
static void strength_changed(struct connman_service *service)
{
DBUS_TYPE_BYTE, &service->strength);
}
+#if defined TIZEN_EXT
+static bool update_last_connected_bssid(struct connman_service *service)
+{
+ const unsigned char *last_connected_bssid;
+
+ if (!service->network)
+ return false;
+
+ last_connected_bssid = connman_network_get_last_connected_bssid(service->network);
+ if (memcmp(last_connected_bssid, invalid_bssid, WIFI_BSSID_LEN_MAX) == 0)
+ return false;
+
+ if (memcmp(last_connected_bssid, service->last_connected_bssid, WIFI_BSSID_LEN_MAX) != 0) {
+ memcpy(service->last_connected_bssid, last_connected_bssid, WIFI_BSSID_LEN_MAX);
+ return true;
+ }
+
+ return false;
+}
+#endif
+
static void favorite_changed(struct connman_service *service)
{
dbus_bool_t favorite;
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:
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;
}
}
+#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,
{
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)
return ret;
}
+#if defined TIZEN_EXT
+static void append_security_list(DBusMessageIter *iter, void *user_data)
+{
+ GSList *sec_list = (GSList *)user_data;
+ const char *sec_str;
+
+ if (sec_list) {
+ GSList *list;
+ for (list = sec_list; list; list = list->next) {
+ sec_str = (const char *)list->data;
+
+ dbus_message_iter_append_basic(iter,
+ DBUS_TYPE_STRING, &sec_str);
+ }
+ }
+}
+
+static void append_wifi_ext_info(DBusMessageIter *dict,
+ struct connman_network *network)
+{
+ char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
+ char *bssid_str = bssid_buff;
+ const void *ssid;
+ unsigned int ssid_len;
+ unsigned char *bssid;
+ unsigned int maxrate;
+ int maxspeed;
+ unsigned int keymgmt;
+ uint16_t frequency;
+ const char *enc_mode;
+ const char *str;
+ gboolean passpoint;
+ gboolean pmf_required;
+ char country_code_buff[WIFI_COUNTRY_CODE_LEN + 1] = {0,};
+ char *country_code_str = country_code_buff;
+ unsigned char *country_code;
+ uint16_t connection_mode;
+ GSList *sec_list = NULL;
+
+ ssid = connman_network_get_blob(network, "WiFi.SSID", &ssid_len);
+ bssid = connman_network_get_bssid(network);
+ maxrate = connman_network_get_maxrate(network);
+ maxspeed = connman_network_get_maxspeed(network);
+ frequency = connman_network_get_frequency(network);
+ enc_mode = connman_network_get_enc_mode(network);
+ passpoint = connman_network_get_bool(network, "WiFi.HS20AP");
+ keymgmt = connman_network_get_keymgmt(network);
+ pmf_required = connman_network_get_bool(network, "WiFi.PMFRequired");
+ country_code = connman_network_get_countrycode(network);
+ connection_mode = connman_network_get_connection_mode(network);
+ sec_list = (GSList *)connman_network_get_sec_list(network);
+
+ snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid));
+
+ snprintf(country_code_str, (WIFI_COUNTRY_CODE_LEN + 1), "%c%c",
+ country_code[0], country_code[1]);
+
+ connman_dbus_dict_append_array(dict, "SecurityList",
+ DBUS_TYPE_STRING,
+ append_security_list, sec_list);
+
+ connman_dbus_dict_append_fixed_array(dict, "SSID",
+ DBUS_TYPE_BYTE, &ssid, ssid_len);
+ connman_dbus_dict_append_basic(dict, "BSSID",
+ DBUS_TYPE_STRING, &bssid_str);
+ connman_dbus_dict_append_basic(dict, "MaxRate",
+ DBUS_TYPE_UINT32, &maxrate);
+ connman_dbus_dict_append_basic(dict, "MaxSpeed",
+ DBUS_TYPE_INT32, &maxspeed);
+ connman_dbus_dict_append_basic(dict, "Frequency",
+ DBUS_TYPE_UINT16, &frequency);
+ connman_dbus_dict_append_basic(dict, "EncryptionMode",
+ DBUS_TYPE_STRING, &enc_mode);
+ connman_dbus_dict_append_basic(dict, "Passpoint",
+ DBUS_TYPE_BOOLEAN, &passpoint);
+ connman_dbus_dict_append_basic(dict, "Keymgmt",
+ DBUS_TYPE_UINT32, &keymgmt);
+ connman_dbus_dict_append_basic(dict, "PmfReq",
+ DBUS_TYPE_BOOLEAN, &pmf_required);
+ connman_dbus_dict_append_basic(dict, "Country", DBUS_TYPE_STRING,
+ &country_code_str);
+ connman_dbus_dict_append_basic(dict, "ConnMode",
+ DBUS_TYPE_UINT16, &connection_mode);
+
+ str = connman_network_get_string(network, "WiFi.Security");
+ if (str != NULL && g_str_equal(str, "ieee8021x") == TRUE) {
+ str = connman_network_get_string(network, "WiFi.EAP");
+ if (str != NULL)
+ connman_dbus_dict_append_basic(dict, "EAP",
+ DBUS_TYPE_STRING, &str);
+
+ str = connman_network_get_string(network, "WiFi.Phase2");
+ if (str != NULL)
+ connman_dbus_dict_append_basic(dict, "Phase2",
+ DBUS_TYPE_STRING, &str);
+
+ str = connman_network_get_string(network, "WiFi.Identity");
+ if (str != NULL)
+ connman_dbus_dict_append_basic(dict, "Identity",
+ DBUS_TYPE_STRING, &str);
+
+ str = connman_network_get_string(network, "WiFi.CACertFile");
+ if (str != NULL)
+ connman_dbus_dict_append_basic(dict, "CACertFile",
+ DBUS_TYPE_STRING, &str);
+
+ str = connman_network_get_string(network,
+ "WiFi.ClientCertFile");
+ if (str != NULL)
+ connman_dbus_dict_append_basic(dict, "ClientCertFile",
+ DBUS_TYPE_STRING, &str);
+
+ str = connman_network_get_string(network,
+ "WiFi.PrivateKeyFile");
+ if (str != NULL)
+ connman_dbus_dict_append_basic(dict, "PrivateKeyFile",
+ DBUS_TYPE_STRING, &str);
+ }
+}
+
+static void append_bssid_info(DBusMessageIter *iter, void *user_data)
+{
+ GSList *bssid_list = NULL;
+ struct connman_network *network = user_data;
+ struct connman_bssids *bssids;
+ char bssid_buf[MAC_ADDRESS_LENGTH] = {0,};
+ char *bssid_str = bssid_buf;
+
+ bssid_list = (GSList *)connman_network_get_bssid_list(network);
+ if(bssid_list) {
+ GSList *list;
+ for (list = bssid_list; list; list = list->next) {
+ bssids = (struct connman_bssids *)list->data;
+ g_snprintf(bssid_buf, MAC_ADDRESS_LENGTH, MACSTR, MAC2STR(bssids->bssid));
+
+ connman_dbus_dict_append_basic(iter, "BSSID",
+ DBUS_TYPE_STRING, &bssid_str);
+
+ connman_dbus_dict_append_basic(iter, "Strength",
+ DBUS_TYPE_UINT16, &bssids->strength);
+
+ connman_dbus_dict_append_basic(iter, "Frequency",
+ DBUS_TYPE_UINT16, &bssids->frequency);
+ }
+ }
+}
+#endif
+
static void append_properties(DBusMessageIter *dict, dbus_bool_t limited,
struct connman_service *service)
{
const char *str;
GSList *list;
+#if defined TIZEN_EXT
+ unsigned int frequency = 0U;
+ unsigned char *wifi_vsie;
+ unsigned int wifi_vsie_len;
+ GSList *vsie_list = NULL;
+
+ if (service->network) {
+ frequency = connman_network_get_frequency(service->network);
+ connman_dbus_dict_append_basic(dict, "Frequency",
+ DBUS_TYPE_UINT16, &frequency);
+ vsie_list = (GSList *)connman_network_get_vsie_list(service->network);
+ }
+
+ if (vsie_list) {
+ GSList *list;
+ for (list = vsie_list; list; list = list->next) {
+ wifi_vsie = (unsigned char *)list->data;
+ wifi_vsie_len = wifi_vsie[1] + 2;
+
+ connman_dbus_dict_append_fixed_array(dict, "Vsie", DBUS_TYPE_BYTE,
+ &wifi_vsie, wifi_vsie_len);
+ }
+ }
+#endif
+
str = __connman_service_type2string(service->type);
if (str)
connman_dbus_dict_append_basic(dict, "Type",
connman_dbus_dict_append_basic(dict, "State",
DBUS_TYPE_STRING, &str);
+#ifdef TIZEN_EXT
+ str = state2string(service->state_ipv6);
+ if (str != NULL)
+ connman_dbus_dict_append_basic(dict, "StateIPv6",
+ DBUS_TYPE_STRING, &str);
+#endif
+
str = error2string(service->error);
if (str)
connman_dbus_dict_append_basic(dict, "Error",
case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_VPN:
case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
break;
case CONNMAN_SERVICE_TYPE_CELLULAR:
val = service->roaming;
append_ethernet, service);
break;
case CONNMAN_SERVICE_TYPE_WIFI:
+#if defined TIZEN_EXT
+ if (service->network != NULL) {
+ append_wifi_ext_info(dict, service->network);
+ connman_dbus_dict_append_dict(dict, "BSSID.List",
+ append_bssid_info, service->network);
+ }
+
+ connman_dbus_dict_append_dict(dict, "Ethernet",
+ append_ethernet, service);
+
+ service->disconnect_reason = connman_network_get_disconnect_reason(service->network);
+ connman_dbus_dict_append_basic(dict, "DisconnectReason",
+ DBUS_TYPE_INT32, &service->disconnect_reason);
+
+ connman_dbus_dict_append_basic(dict, "AssocStatusCode",
+ DBUS_TYPE_INT32, &service->assoc_status_code);
+
+ val = service->hidden_service;
+ connman_dbus_dict_append_basic(dict, "Hidden",
+ DBUS_TYPE_BOOLEAN, &val);
+
+ break;
+#endif
case CONNMAN_SERVICE_TYPE_ETHERNET:
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ connman_dbus_dict_append_dict(dict, "EapOverEthernet",
+ append_eap_over_ethernet, service);
+ /* fall through */
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
case CONNMAN_SERVICE_TYPE_BLUETOOTH:
case CONNMAN_SERVICE_TYPE_GADGET:
connman_dbus_dict_append_dict(dict, "Ethernet",
connman_network_append_acddbus(dict, service->network);
}
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+static void append_ins_bssid_info(DBusMessageIter *iter, void *user_data)
+{
+ GSList *bssid_list = NULL;
+ struct connman_network *network = user_data;
+ struct connman_bssids *bssids;
+ char bssid_buf[MAC_ADDRESS_LENGTH] = {0,};
+ char *bssid_str = bssid_buf;
+
+ bssid_list = (GSList *)connman_network_get_bssid_list(network);
+ if(bssid_list) {
+ GSList *list;
+ for (list = bssid_list; list; list = list->next) {
+ bssids = (struct connman_bssids *)list->data;
+ g_snprintf(bssid_buf, MAC_ADDRESS_LENGTH, MACSTR, MAC2STR(bssids->bssid));
+
+ connman_dbus_dict_append_basic(iter, "BSSID",
+ DBUS_TYPE_STRING, &bssid_str);
+
+ connman_dbus_dict_append_basic(iter, "ScoreINS",
+ DBUS_TYPE_INT32, &bssids->ins_score);
+
+ connman_dbus_dict_append_basic(iter, "ScoreLastConnected",
+ DBUS_TYPE_INT32, &bssids->score_last_connected_bssid);
+
+ connman_dbus_dict_append_basic(iter, "ScoreAssocReject",
+ DBUS_TYPE_INT32, &bssids->score_assoc_reject);
+
+ connman_dbus_dict_append_basic(iter, "Frequency",
+ DBUS_TYPE_UINT16, &bssids->frequency);
+
+ connman_dbus_dict_append_basic(iter, "ScoreFrequency",
+ DBUS_TYPE_INT32, &bssids->score_frequency);
+
+ connman_dbus_dict_append_basic(iter, "Strength",
+ DBUS_TYPE_UINT16, &bssids->strength);
+
+ connman_dbus_dict_append_basic(iter, "ScoreStrength",
+ DBUS_TYPE_INT32, &bssids->score_strength);
+ }
+ }
+}
+
+static void append_ins_properties(DBusMessageIter *dict,
+ struct connman_service *service)
+{
+ const char *str;
+ unsigned int frequency = 0U;
+
+ if (service->name)
+ connman_dbus_dict_append_basic(dict, "Name",
+ DBUS_TYPE_STRING, &service->name);
+
+ connman_dbus_dict_append_basic(dict, "ScoreINS",
+ DBUS_TYPE_INT32, &service->ins_score);
+
+ connman_dbus_dict_append_basic(dict, "ScoreLastUserSelection",
+ DBUS_TYPE_INT32, &service->score_last_user_selection);
+
+ connman_dbus_dict_append_basic(dict, "ScoreLastConnected",
+ DBUS_TYPE_INT32, &service->score_last_connected);
+
+ str = security2string(service->security);
+ if (str)
+ connman_dbus_dict_append_basic(dict, "Security",
+ DBUS_TYPE_STRING, &str);
+
+ connman_dbus_dict_append_basic(dict, "ScoreSecurityPriority",
+ DBUS_TYPE_INT32, &service->score_security_priority);
+
+ connman_dbus_dict_append_basic(dict, "Strength",
+ DBUS_TYPE_BYTE, &service->strength);
+
+ connman_dbus_dict_append_basic(dict, "ScoreStrength",
+ DBUS_TYPE_INT32, &service->score_strength);
+
+ connman_dbus_dict_append_basic(dict, "ScoreInternetConnection",
+ DBUS_TYPE_INT32, &service->score_internet_connection);
+
+ if (service->network) {
+ frequency = connman_network_get_frequency(service->network);
+ connman_dbus_dict_append_basic(dict, "Frequency",
+ DBUS_TYPE_UINT16, &frequency);
+
+ connman_dbus_dict_append_basic(dict, "ScoreFrequency",
+ DBUS_TYPE_INT32, &service->score_frequency);
+
+ connman_dbus_dict_append_dict(dict, "BSSID.List",
+ append_ins_bssid_info, service->network);
+ }
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
static void append_struct_service(DBusMessageIter *iter,
connman_dbus_append_cb_t function,
struct connman_service *service)
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);
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)
{
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)
{
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)
{
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)
{
case CONNMAN_SERVICE_SECURITY_UNKNOWN:
case CONNMAN_SERVICE_SECURITY_NONE:
case CONNMAN_SERVICE_SECURITY_WPA:
+#if !defined TIZEN_EXT
case CONNMAN_SERVICE_SECURITY_RSN:
+#endif
DBG("service security '%s' (%d) not handled",
security2string(security), security);
return -EOPNOTSUPP;
case CONNMAN_SERVICE_SECURITY_PSK:
+#if defined TIZEN_EXT
+ case CONNMAN_SERVICE_SECURITY_RSN:
+ /* TO CHECK: We need to check the key length supported by SAE */
+ case CONNMAN_SERVICE_SECURITY_SAE:
+#endif
/* A raw key is always 64 bytes length,
* its content is in hex representation.
* A PSK key must be between [8..63].
break;
case CONNMAN_SERVICE_SECURITY_8021X:
+#if defined TIZEN_EXT
+ case CONNMAN_SERVICE_SECURITY_OWE:
+ case CONNMAN_SERVICE_SECURITY_DPP:
+#endif
break;
}
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)
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)
{
GString *str;
int index;
const char *gw;
+#if defined TIZEN_EXT
+ enum connman_ipconfig_type ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
+ DBG("%s", name);
+#endif
if (__connman_provider_is_immutable(service->provider) ||
service->immutable)
gw = __connman_ipconfig_get_gateway_from_index(index,
CONNMAN_IPCONFIG_TYPE_ALL);
+#if !defined TIZEN_EXT
if (gw && strlen(gw))
__connman_service_nameserver_del_routes(service,
CONNMAN_IPCONFIG_TYPE_ALL);
+#endif
dbus_message_iter_recurse(&value, &entry);
+#if defined TIZEN_EXT
+ /* IPv4/IPv6 Last DNS config method */
+ int last_dns_ipv4 = service->dns_config_method_ipv4;
+ int last_dns_ipv6 = service->dns_config_method_ipv6;
+ DBG("Last DNS Config Method IPv4: %d IPv6: %d", last_dns_ipv4, last_dns_ipv6);
+#endif
+
while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
const char *val;
dbus_message_iter_get_basic(&entry, &val);
dbus_message_iter_next(&entry);
+#ifdef TIZEN_EXT
+ /* First unpack the DNS Config Method */
+ DBG("DNS Config Method: %s", val);
+ if((g_strcmp0(val, "ipv4.manual") == 0)) {
+ service->dns_config_method_ipv4 =
+ CONNMAN_DNSCONFIG_METHOD_MANUAL;
+
+ if(last_dns_ipv4 != CONNMAN_DNSCONFIG_METHOD_MANUAL) {
+ if(ip_type == CONNMAN_IPCONFIG_TYPE_UNKNOWN)
+ ip_type = CONNMAN_IPCONFIG_TYPE_IPV4;
+ else
+ ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
+ }
+ continue;
+ } else if(g_strcmp0(val, "ipv4.dhcp") == 0) {
+ service->dns_config_method_ipv4 =
+ CONNMAN_DNSCONFIG_METHOD_DHCP;
+ if(last_dns_ipv4 == CONNMAN_DNSCONFIG_METHOD_MANUAL)
+ ip_type = CONNMAN_IPCONFIG_TYPE_IPV4;
+
+ continue;
+ } else if(g_strcmp0(val, "ipv6.manual") == 0) {
+ service->dns_config_method_ipv6 =
+ CONNMAN_DNSCONFIG_METHOD_MANUAL;
+ if(last_dns_ipv6 != CONNMAN_DNSCONFIG_METHOD_MANUAL) {
+ if(ip_type == CONNMAN_IPCONFIG_TYPE_UNKNOWN)
+ ip_type = CONNMAN_IPCONFIG_TYPE_IPV6;
+ else
+ ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
+ }
+ continue;
+ } else if(g_strcmp0(val, "ipv6.dhcp") == 0) {
+ service->dns_config_method_ipv6 =
+ CONNMAN_DNSCONFIG_METHOD_DHCP;
+ if(last_dns_ipv6 == CONNMAN_DNSCONFIG_METHOD_MANUAL)
+ ip_type = CONNMAN_IPCONFIG_TYPE_IPV6;
+ continue;
+ }
+#endif
if (!val[0])
continue;
g_string_append(str, val);
}
+#if defined TIZEN_EXT
+ if (service->dns_config_method_ipv4 == CONNMAN_DNSCONFIG_METHOD_DHCP &&
+ service->dns_config_method_ipv6 == CONNMAN_DNSCONFIG_METHOD_DHCP) {
+ DBG("Both IPv4 and IPv6 DNS Method DHCP");
+ ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
+ }
+ if (gw && strlen(gw))
+ __connman_service_nameserver_del_routes(service,
+ ip_type);
+
+ DBG("%s ip_type: %d nameserver remove all", name, ip_type);
+ nameserver_remove_all(service, ip_type);
+#else
nameserver_remove_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
+#endif
g_strfreev(service->nameservers_config);
if (str->len > 0) {
if (gw && strlen(gw))
__connman_service_nameserver_add_routes(service, gw);
+#if defined TIZEN_EXT
+ DBG("%s ip_type: %d nameserver add all", name, ip_type);
+ nameserver_add_all(service, ip_type);
+#else
nameserver_add_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
+#endif
dns_configuration_changed(service);
if (__connman_service_is_connected_state(service,
}
service_save(service);
+#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);
if (!service->path)
return;
+#if !defined TIZEN_EXT
if (!allow_property_changed(service))
return;
+#endif
str = error2string(service->error);
case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_VPN:
case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
break;
}
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);
}
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;
}
}
always_connect[always_connected_techs[i]] = 1;
}
+#if !defined TIZEN_EXT
static bool autoconnect_no_session_active(struct connman_service *service)
{
/*
return false;
}
+#endif
static bool autoconnect_already_connecting(struct connman_service *service,
bool autoconnecting)
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);
if (service->pending ||
is_connecting(service->state) ||
is_connected(service->state)) {
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
+ int index = connman_network_get_index(service->network);
+ wifi_ignore = g_slist_prepend(wifi_ignore, GINT_TO_POINTER(index));
+
+ autoconnecting = true;
+ continue;
+ }
+#else
if (autoconnect_no_session_active(service))
return true;
-
+#endif
ignore[service->type] = true;
autoconnecting = true;
if (preferred)
continue;
+#if defined TIZEN_EXT
+ DBG("Service is not favorite, autoconnecting %d",
+ autoconnecting);
+ g_slist_free(wifi_ignore);
+#endif
return autoconnecting;
}
+#if defined TIZEN_EXT
+ DBG("service %p identifier %s roaming %d ignore %d "
+ "ipconfig_usable %d autoconnect %d state %d",
+ service,
+ service->identifier, service->roaming,
+ service->ignore, is_ipconfig_usable(service),
+ service->autoconnect, service->state);
+#endif
if (is_ignore(service) || service->state !=
CONNMAN_SERVICE_STATE_IDLE)
continue;
-
+#if defined TIZEN_EXT
+ if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
+#endif
if (autoconnect_already_connecting(service, autoconnecting)) {
DBG("service %p type %s has no users", service,
__connman_service_type2string(service->type));
DBG("service %p %s %s", service, service->name,
(preferred) ? "preferred" : reason2string(reason));
+#if defined TIZEN_EXT
+ __connman_service_connect(service, reason);
+#else
if (__connman_service_connect(service, reason) == 0)
service_indicate_state(service);
if (autoconnect_no_session_active(service))
return true;
-
+#endif
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
+ int index = connman_network_get_index(service->network);
+ wifi_ignore = g_slist_prepend(wifi_ignore, GINT_TO_POINTER(index));
+ autoconnecting = true;
+ }
+#endif
ignore[service->type] = true;
}
-
+#if defined TIZEN_EXT
+ g_slist_free(wifi_ignore);
+#endif
return autoconnecting;
}
return FALSE;
}
+#if defined TIZEN_EXT
+bool __connman_service_get_auto_connect_mode(void)
+{
+ return auto_connect_mode;
+}
+
+void __connman_service_set_auto_connect_mode(bool enable)
+{
+ DBG("set auto_connect_mode = %d", enable);
+
+ if (auto_connect_mode != enable)
+ auto_connect_mode = enable;
+}
+#endif
+
void __connman_service_auto_connect(enum connman_service_connect_reason reason)
{
DBG("");
if (autoconnect_id != 0)
return;
+#if defined TIZEN_EXT
+ if (auto_connect_mode == FALSE) {
+ DBG("Currently, not auto connection mode");
+ return;
+ }
+#endif
+
if (!__connman_session_policy_autoconnect(reason))
return;
+#if defined TIZEN_EXT
+ /* Adding Timeout of 500ms before trying to auto connect.
+ * This is done because of below scenario
+ * 1. Device is connected to AP1
+ * 2. WPS Connection request is initiated for AP2
+ * 3. Immediately WPS Connection is Cancelled
+ * When WPS Connection Connection is initiated for AP2 then
+ * sometimes there is a scenario where connman gets in ASSOCIATED
+ * state with AP1 due to autoconnect and subsequently the connection
+ * initiated by AP1 fails and connman service for AP1 comes in
+ * FAILURE state due to this when connection with AP2 is cancelled
+ * then autoconnect with AP1 doesn't works because its autoconnection
+ * is ignored as its last state was FAILURE rather than IDLE */
+ autoconnect_id = g_timeout_add(500, run_auto_connect,
+#else
autoconnect_id = g_idle_add(run_auto_connect,
+#endif
GUINT_TO_POINTER(reason));
}
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;
}
if (err == -EINPROGRESS)
return __connman_error_operation_timeout(msg);
+#endif
service->ignore = false;
DBG("service %p", service);
+#if defined TIZEN_EXT
+ /*
+ * Description: TIZEN implements system global connection management.
+ */
+ if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
+ if (connman_service_user_pdn_connection_unref_and_test(service) != TRUE)
+ return __connman_error_failed(msg, EISCONN);
+
+ if (is_connected(service->state) == TRUE &&
+ service == connman_service_get_default_connection())
+ return __connman_error_failed(msg, EISCONN);
+ }
+#endif
+
service->ignore = true;
err = __connman_service_disconnect(service);
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
+#if defined TIZEN_EXT
+static void __connman_service_cleanup_network_8021x(struct connman_service *service)
+{
+ if (service == NULL)
+ return;
+
+ DBG("service %p ", service);
+
+ connman_network_set_string(service->network, "WiFi.EAP", NULL);
+ connman_network_set_string(service->network, "WiFi.Identity", NULL);
+ connman_network_set_string(service->network, "WiFi.CACertFile", NULL);
+ connman_network_set_string(service->network, "WiFi.ClientCertFile", NULL);
+ connman_network_set_string(service->network, "WiFi.PrivateKeyFile", NULL);
+ connman_network_set_string(service->network, "WiFi.PrivateKeyPassphrase", NULL);
+ connman_network_set_string(service->network, "WiFi.Phase2", NULL);
+ connman_network_set_string(service->network, "WiFi.AnonymousIdentity", NULL);
+}
+static void __connman_service_cleanup_network_dpp(struct connman_service *service)
+{
+ if (service == NULL)
+ return;
+
+ DBG("service %p ", service);
+
+ connman_network_set_string(service->network, "WiFi.Connector", NULL);
+ connman_network_set_string(service->network, "WiFi.CSignKey", NULL);
+ connman_network_set_string(service->network, "WiFi.NetAccessKey", NULL);
+}
+#endif
+
bool __connman_service_remove(struct connman_service *service)
{
if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET ||
__connman_provider_is_immutable(service->provider))
return false;
+#if !defined TIZEN_EXT
if (!service->favorite && !is_idle(service->state))
return false;
+#endif
__connman_service_disconnect(service);
g_free(service->eap);
service->eap = NULL;
+#if defined TIZEN_EXT
+ g_free(service->ca_cert_file);
+ service->ca_cert_file = NULL;
+
+ g_free(service->client_cert_file);
+ service->client_cert_file = NULL;
+
+ g_free(service->private_key_file);
+ service->private_key_file = NULL;
+
+ g_free(service->private_key_passphrase);
+ service->private_key_passphrase = NULL;
+
+ g_free(service->phase2);
+ service->phase2 = NULL;
+
+ __connman_service_cleanup_network_8021x(service);
+
+ __connman_ipconfig_set_method(service->ipconfig_ipv4, CONNMAN_IPCONFIG_METHOD_DHCP);
+ __connman_ipconfig_set_method(service->ipconfig_ipv6, CONNMAN_IPCONFIG_METHOD_AUTO);
+ connman_service_set_proxy(service, NULL, false);
+
+ __connman_service_nameserver_clear(service);
+
+ g_strfreev(service->nameservers_config);
+ service->nameservers_config = NULL;
+
+ g_free(service->connector);
+ service->connector = NULL;
+
+ g_free(service->c_sign_key);
+ service->c_sign_key = NULL;
+
+ g_free(service->net_access_key);
+ service->net_access_key = NULL;
+
+ __connman_service_cleanup_network_dpp(service);
+#endif
+
service->error = CONNMAN_SERVICE_ERROR_UNKNOWN;
__connman_service_set_favorite(service, false);
__connman_ipconfig_ipv6_reset_privacy(service->ipconfig_ipv6);
+#if defined TIZEN_EXT
+ /* Reset IP Method and DNS Method to DHCP */
+ __connman_ipconfig_set_method(service->ipconfig_ipv4,
+ CONNMAN_IPCONFIG_METHOD_DHCP);
+ service->dns_config_method_ipv4 = CONNMAN_DNSCONFIG_METHOD_DHCP;
+ g_strfreev(service->nameservers_config);
+ service->nameservers_config = NULL;
+#endif
+
+#if defined TIZEN_EXT
+ __connman_storage_remove_service(service->identifier);
+#else
service_save(service);
+#endif
return true;
}
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);
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);
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;
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
{ },
};
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);
static void service_initialize(struct connman_service *service)
{
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
DBG("service %p", service);
service->refcount = 1;
service->wps = false;
service->wps_advertizing = false;
+#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 */
}
/**
g_hash_table_remove(service_hash, service->identifier);
}
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+static int calculate_score_last_user_selection(struct connman_service *service)
+{
+ int score = 0;
+ struct connman_device *device;
+ const char *last_user_selection_ident;
+ time_t last_user_selection_time;
+ unsigned int frequency;
+ time_t curr_time;
+ time_t ref_time;
+ struct tm* ref_timeinfo;
+
+ device = connman_network_get_device(service->network);
+ if (!device)
+ return 0;
+
+ last_user_selection_time = connman_device_get_last_user_selection_time(device);
+ last_user_selection_ident = connman_device_get_last_user_selection_ident(device);
+ frequency = connman_network_get_frequency(service->network);
+
+ if (ins_settings.last_user_selection) {
+ if (g_strcmp0(last_user_selection_ident, service->identifier) == 0 &&
+ (((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
+ frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
+ service->strength >= ins_settings.signal_level3_24ghz) ||
+ ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
+ frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
+ service->strength >= ins_settings.signal_level3_5ghz))) {
+
+ /* Only events that occur within 8 hours are counted. */
+ curr_time = time(NULL);
+ ref_timeinfo = localtime(&curr_time);
+ ref_timeinfo->tm_hour -= 8;
+ ref_time = mktime(ref_timeinfo);
+
+ if (last_user_selection_time > ref_time) {
+ int time_diff = (curr_time - last_user_selection_time) / 60;
+ int denominator = ins_settings.last_user_selection_time - time_diff;
+ int numerator = ins_settings.last_user_selection_time /
+ ins_settings.last_user_selection_score;
+ int last_user_score = denominator / numerator;
+
+ score += (last_user_score > ins_settings.last_user_selection_score ?
+ ins_settings.last_user_selection_score : last_user_score);
+ }
+ }
+ }
+
+ return score;
+}
+
+static int calculate_score_last_connected(struct connman_service *service)
+{
+ int score = 0;
+ struct connman_device *device;
+ const char *last_connected_ident;
+ unsigned int frequency;
+
+ device = connman_network_get_device(service->network);
+ if (!device)
+ return 0;
+
+ last_connected_ident = connman_device_get_last_connected_ident(device);
+ frequency = connman_network_get_frequency(service->network);
+
+ if (ins_settings.last_connected) {
+ if (g_strcmp0(last_connected_ident, service->identifier) == 0 &&
+ (((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
+ frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
+ service->strength >= ins_settings.signal_level3_24ghz) ||
+ ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
+ frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
+ service->strength >= ins_settings.signal_level3_5ghz))) {
+ score += ins_settings.last_connected_score;
+ }
+ }
+
+ return score;
+}
+
+static int calculate_score_frequency(struct connman_service *service)
+{
+ int score = 0;
+ unsigned int frequency;
+
+ frequency = connman_network_get_frequency(service->network);
+
+ switch (ins_settings.preferred_freq) {
+ case CONNMAN_INS_PREFERRED_FREQ_24GHZ:
+ if ((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
+ frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
+ (service->strength >= ins_settings.signal_level3_24ghz))
+ score += ins_settings.preferred_freq_score;
+
+ break;
+ case CONNMAN_INS_PREFERRED_FREQ_5GHZ:
+ if ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
+ frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
+ (service->strength >= ins_settings.signal_level3_5ghz))
+ score += ins_settings.preferred_freq_score;
+
+ break;
+ default:
+ break;
+ }
+
+ return score;
+}
+
+static int calculate_score_security_priority(struct connman_service *service)
+{
+ int score = 0;
+
+ if (ins_settings.security_priority_count)
+ score += ins_settings.security_priority[service->security];
+
+ return score;
+}
+
+static int calculate_score_internet_connection(struct connman_service *service)
+{
+ int score = 0;
+
+ if (ins_settings.internet) {
+ if (service->is_internet_connection)
+ score += ins_settings.internet_score;
+ }
+
+ return score;
+}
+
+static int calculate_score_strength(struct connman_service *service)
+{
+ int score = 0;
+
+ if (ins_settings.signal)
+ score += (((service->strength > 60) ? 60 : service->strength) - 35);
+
+ return score;
+}
+
+static int calculate_score(struct connman_service *service)
+{
+ int score_last_user_selection;
+ int score_last_connected;
+ int score_frequency;
+ int score_security_priority;
+ int score_internet_connection;
+ int score_strength;
+ int score = 0;
+
+ if (service->type != CONNMAN_SERVICE_TYPE_WIFI) {
+ score += calculate_score_internet_connection(service);
+ service->ins_score = score;
+ return score;
+ }
+
+ score_last_user_selection = calculate_score_last_user_selection(service);
+ score_last_connected = calculate_score_last_connected(service);
+ score_frequency = calculate_score_frequency(service);
+ score_security_priority = calculate_score_security_priority(service);
+ score_internet_connection = calculate_score_internet_connection(service);
+ score_strength = calculate_score_strength(service);
+
+ score = score_last_user_selection + score_last_connected +
+ score_frequency + score_security_priority +
+ score_internet_connection + score_strength;
+
+ service->score_last_user_selection = score_last_user_selection;
+ service->score_last_connected = score_last_connected;
+ service->score_frequency = score_frequency;
+ service->score_security_priority = score_security_priority;
+ service->score_internet_connection = score_internet_connection;
+ service->score_strength = score_strength;
+
+ service->ins_score = score;
+ return score;
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
static gint service_compare(gconstpointer a, gconstpointer b);
static gint service_compare_vpn(struct connman_service *a,
struct connman_service *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;
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();
}
}
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
bool favorite,
bool delay_ordering)
{
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
+ return -EIO;
+#endif
if (service->hidden)
return -EOPNOTSUPP;
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,
/* 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();
tech_array = connman_setting_get_uint_list("PreferredTechnologies");
if (tech_array) {
- for (i = 0; tech_array[i] != 0; i += 1) {
- if (default_service->type == tech_array[i])
- return -EALREADY;
+ for (i = 0; tech_array[i] != 0; i += 1) {
+ if (default_service->type == tech_array[i])
+ return -EALREADY;
+
+ if (new_service->type == tech_array[i]) {
+ switch_default_service(default_service,
+ new_service);
+ __connman_connection_update_gateway();
+ return 0;
+ }
+ }
+ }
+
+ return -EALREADY;
+}
+
+#if defined TIZEN_EXT
+static gboolean __connman_service_can_drop(struct connman_service *service)
+{
+ if (is_connected(service->state) == TRUE || is_connecting(service->state) == TRUE) {
+ if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR)
+ return TRUE;
+ else if (connman_service_is_no_ref_user_pdn_connection(service) == TRUE)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static struct connman_device *default_connecting_device = NULL;
+
+static void __connman_service_disconnect_default(struct connman_service *service)
+{
+ struct connman_device *default_device = NULL;
+ struct connman_network *network = __connman_service_get_network(service);
+
+ if (!network)
+ return;
+
+ if (default_connecting_device == NULL)
+ return;
+
+ default_device = connman_network_get_device(network);
+
+ DBG("Disconnecting service %p %s", service, service->path);
+ DBG("Disconnecting device %p %p %s",
+ default_connecting_device,
+ default_device,
+ connman_device_get_string(default_device, "Name"));
+
+ if (default_connecting_device == default_device)
+ default_connecting_device = NULL;
+}
+
+#if defined TIZEN_MAINTAIN_ONLINE
+static void __connman_service_connect_default(struct connman_service *current,
+ enum connman_service_state old_state)
+#else
+static void __connman_service_connect_default(struct connman_service *current)
+#endif
+{
+ int err;
+ GList *list;
+ bool default_internet;
+ struct connman_service *service;
+ struct connman_service *default_service = NULL;
+ struct connman_device *default_device = NULL;
+
+ if (current->type == CONNMAN_SERVICE_TYPE_CELLULAR) {
+ switch (current->state) {
+ case CONNMAN_SERVICE_STATE_UNKNOWN:
+ case CONNMAN_SERVICE_STATE_ASSOCIATION:
+ case CONNMAN_SERVICE_STATE_CONFIGURATION:
+ return;
+ default:
+ break;
+ }
+
+ if (default_connecting_device &&
+ __connman_service_is_internet_profile(current) == TRUE) {
+ if (current->network == NULL)
+ return;
+
+ default_device = connman_network_get_device(current->network);
+ if (default_connecting_device == default_device) {
+ DBG("Cellular service[%s] %p %s",
+ state2string(current->state), current, current->path);
+ DBG("Cellular device %p %p %s",
+ default_connecting_device, default_device,
+ connman_device_get_string(default_device, "Name"));
+
+ default_connecting_device = NULL;
+ }
+ }
+
+ return;
+#if defined TIZEN_MAINTAIN_ONLINE
+ } else if (current->state == CONNMAN_SERVICE_STATE_READY &&
+ old_state == CONNMAN_SERVICE_STATE_ONLINE) {
+ DBG("Device is downgraded: online --> ready");
+#endif
+ } else if (is_connected(current->state) == TRUE || is_connecting(current->state) == TRUE)
+ return;
+
+ /* Always-on: keep default cellular connection as possible */
+ for (list = service_list; list; list = list->next) {
+ service = list->data;
+
+ if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
+ __connman_service_is_internet_profile(service) != TRUE ||
+ service->network == NULL) {
+ continue;
+ }
+
+ default_internet =
+ connman_network_get_bool(service->network, "DefaultInternet");
+
+ DBG("service: %p %s %s %s (default: %d)", service, service->name,
+ __connman_service_type2string(service->type),
+ state2string(service->state), default_internet);
+
+ if (default_internet) {
+ default_service = service;
+ if (is_connected(default_service->state) == TRUE ||
+ is_connecting(default_service->state) == TRUE)
+ return;
- if (new_service->type == tech_array[i]) {
- switch_default_service(default_service,
- new_service);
- __connman_connection_update_gateway();
- return 0;
+ default_device = connman_network_get_device(default_service->network);
+ if (default_connecting_device == default_device) {
+ DBG("Device is connecting (%p)", default_connecting_device);
+ return;
}
+
+ default_connecting_device = default_device;
+ default_service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_USER;
+
+ err = __connman_network_connect(default_service->network);
+ DBG("Connecting default service %p %s [%d]",
+ default_service, default_service->path, err);
+ DBG("Connecting device %p %s", default_connecting_device,
+ connman_device_get_string(default_connecting_device, "Name"));
+ if (err < 0 && err != -EINPROGRESS) {
+ default_connecting_device = NULL;
+ } else
+ break;
}
}
-
- return -EALREADY;
}
+#endif
static void single_connected_tech(struct connman_service *allowed)
{
DBG("keeping %p %s", allowed, allowed->path);
+#if defined TIZEN_EXT
+ if (!allowed || allowed->type == CONNMAN_SERVICE_TYPE_CELLULAR)
+ return;
+#endif
+
for (iter = service_list; iter; iter = iter->next) {
service = iter->data;
+#if defined TIZEN_EXT
+ if (service != allowed && service->type != allowed->type &&
+ __connman_service_can_drop(service) == TRUE)
+#else
if (!is_connected(service->state))
break;
if (service == allowed)
continue;
+#endif
services = g_slist_prepend(services, service);
}
service = list->data;
DBG("disconnecting %p %s", service, service->path);
+#if defined TIZEN_EXT
+ __connman_service_disconnect_default(service);
+#endif
__connman_service_disconnect(service);
}
g_slist_free(services);
}
+#if defined TIZEN_EXT
+static void set_priority_connected_service(void)
+{
+ struct connman_service *service;
+ GList *list;
+
+ for (list = service_list; list; list = list->next) {
+ service = list->data;
+
+ if (is_connected(service->state) == FALSE)
+ service->order = 5;
+ else
+#if defined TIZEN_MAINTAIN_ONLINE
+ {
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+ service->state == CONNMAN_SERVICE_STATE_ONLINE)
+ service->order = 6;
+ else if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
+ service->order = 6;
+ else
+ service->order = 5;
+ }
+#else
+ service->order = 6;
+#endif
+ }
+}
+#endif
+
static const char *get_dbus_sender(struct connman_service *service)
{
if (!service->pending)
searchdomain_remove_all(service);
service->state = new_state;
+#if defined TIZEN_EXT
+ if (!is_connected(old_state) && is_connected(new_state))
+ connman_device_send_connected_signal(
+ connman_network_get_device(service->network), true);
+ else if (is_connected(old_state) && !is_connected(new_state))
+ connman_device_send_connected_signal(
+ connman_network_get_device(service->network), false);
+#endif
state_changed(service);
if (!is_connected(old_state) && is_connected(new_state))
__connman_ipconfig_disable_ipv6(
service->ipconfig_ipv6);
+#if !defined TIZEN_MAINTAIN_ONLINE
if (connman_setting_get_bool("SingleConnectedTechnology"))
single_connected_tech(service);
else if (service->type != CONNMAN_SERVICE_TYPE_VPN)
vpn_auto_connect();
+#else
+ if (service->type != CONNMAN_SERVICE_TYPE_VPN)
+ vpn_auto_connect();
+#endif
+
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
+ set_priority_connected_service();
+#endif
break;
case CONNMAN_SERVICE_STATE_ONLINE:
+#if defined TIZEN_MAINTAIN_ONLINE
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
+ set_priority_connected_service();
+#endif
+
+ if (connman_setting_get_bool("SingleConnectedTechnology"))
+ single_connected_tech(service);
+#endif
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
+ connman_service_set_internet_connection(service, true);
+#endif
break;
case CONNMAN_SERVICE_STATE_DISCONNECT:
__connman_wpad_stop(service);
+#if defined TIZEN_EXT
+ /**
+ * Skip the functions if there is any connected profiles
+ * that use same interface
+ */
+ if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
+ __connman_service_get_connected_count_of_iface(
+ service) <= 0) {
+#endif
domain_changed(service);
proxy_changed(service);
+#if defined TIZEN_EXT
+ }
+#endif
/*
* Previous services which are connected and which states
break;
case CONNMAN_SERVICE_STATE_FAILURE:
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI)
+ service->order = 5;
+ __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+#endif
if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
connman_agent_report_error(service, service->path,
error2string(service->error),
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:
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);
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
{
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;
}
connman_warn("ipconfig state %d ipconfig method %d",
new_state, method);
+#if defined TIZEN_EXT
+ if (old_state != CONNMAN_SERVICE_STATE_READY &&
+ old_state != CONNMAN_SERVICE_STATE_ONLINE)
+#endif
new_state = CONNMAN_SERVICE_STATE_IDLE;
break;
if (old_state == new_state)
return -EALREADY;
+#if defined TIZEN_EXT
+ __sync_synchronize();
+ if (service->user_pdn_connection_refcount > 0 &&
+ service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
+ if (new_state == CONNMAN_SERVICE_STATE_FAILURE ||
+ new_state == CONNMAN_SERVICE_STATE_DISCONNECT ||
+ new_state == CONNMAN_SERVICE_STATE_IDLE) {
+ service->user_pdn_connection_refcount = 0;
+ __sync_synchronize();
+ }
+#endif
+
DBG("service %p (%s) old state %d (%s) new state %d (%s) type %d (%s)",
service, service ? service->identifier : NULL,
old_state, state2string(old_state),
case CONNMAN_SERVICE_STATE_CONFIGURATION:
break;
case CONNMAN_SERVICE_STATE_READY:
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
+ __connman_service_is_internet_profile(service) != TRUE) {
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
+ service_rp_filter(service, TRUE);
+
+ break;
+ }
+#endif
+ if (connman_setting_get_bool("EnableOnlineCheck"))
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
+#if !defined TIZEN_EXT
+ check_proxy_setup(service);
+#endif
+#if defined TIZEN_MAINTAIN_ONLINE
+/* if (old_state == CONNMAN_SERVICE_STATE_ONLINE) */
+ check_proxy_setup(service);
+#endif
+ } else {
+ __connman_service_wispr_start(service, type);
+ }
+ else
+ connman_info("Online check disabled. "
+ "Default service remains in READY state.");
if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
service_rp_filter(service, true);
set_mdns(service, service->mdns_config);
__connman_timeserver_sync(service);
+#if defined TIZEN_EXT
+ int ret = service_indicate_state(service);
+ /*Sent the Ready changed signal again in case IPv4 IP set
+ after IPv6 IP set*/
+
+ if(ret == -EALREADY && type == CONNMAN_IPCONFIG_TYPE_IPV4
+ && new_state == CONNMAN_SERVICE_STATE_READY) {
+ DBG("Notify IPv4 state new/old %d/%d", new_state,old_state);
+ state_changed(service);
+ }
+
+ return ret;
+#endif
return service_indicate_state(service);
}
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;
if (service->hidden)
return -EPERM;
+#if defined TIZEN_EXT
+ GList *list;
+ int index;
+
+ index = __connman_service_get_index(service);
+
+ for (list = service_list; list; list = list->next) {
+ struct connman_service *temp = list->data;
+
+ if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
+ break;
+
+ if (!is_connecting(temp->state) && !is_connected(temp->state))
+ break;
+
+ if (service == temp)
+ continue;
+
+ if (service->type != temp->type)
+ continue;
+
+ if (__connman_service_get_index(temp) == index &&
+ __connman_service_disconnect(temp) == -EINPROGRESS)
+ return -EINPROGRESS;
+ }
+#endif
+
switch (service->type) {
case CONNMAN_SERVICE_TYPE_UNKNOWN:
case CONNMAN_SERVICE_TYPE_SYSTEM:
case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
return -EINVAL;
case CONNMAN_SERVICE_TYPE_ETHERNET:
case CONNMAN_SERVICE_TYPE_GADGET:
switch (service->security) {
case CONNMAN_SERVICE_SECURITY_UNKNOWN:
case CONNMAN_SERVICE_SECURITY_NONE:
+#if defined TIZEN_EXT
+ case CONNMAN_SERVICE_SECURITY_OWE:
+#endif
break;
case CONNMAN_SERVICE_SECURITY_WEP:
case CONNMAN_SERVICE_SECURITY_PSK:
case CONNMAN_SERVICE_SECURITY_WPA:
case CONNMAN_SERVICE_SECURITY_RSN:
+#if defined TIZEN_EXT
+ case CONNMAN_SERVICE_SECURITY_SAE:
+#endif
if (service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
return -ENOKEY;
}
break;
+#if defined TIZEN_EXT
+ case CONNMAN_SERVICE_SECURITY_DPP:
+ if (has_valid_configuration_object(service) &&
+ !service->network)
+ return -EINVAL;
+ break;
+#endif
case CONNMAN_SERVICE_SECURITY_8021X:
if (!service->eap) {
connman_warn("EAP type has not been found. "
return -EINVAL;
}
+#if defined TIZEN_EXT
+ /*
+ * never request credentials if using EAP-TLS, EAP-SIM
+ * or EAP-AKA (EAP-TLS, EAP-SIM and EAP-AKA networks
+ * need to be fully provisioned)
+ */
+ DBG("service eap: %s", service->eap);
+ if (g_str_equal(service->eap, "tls") ||
+ g_str_equal(service->eap, "sim") ||
+ g_str_equal(service->eap, "aka") ||
+ g_str_equal(service->eap, "aka'") ||
+ g_str_equal(service->eap, "pwd") ||
+ g_str_equal(service->eap, "fast"))
+ break;
+#else
/*
* never request credentials if using EAP-TLS
* (EAP-TLS networks need to be fully provisioned)
if (g_str_equal(service->eap, "tls"))
break;
+#endif
/*
* Return -ENOKEY if either identity or passphrase is
* missing. Agent provided credentials can be used as
case CONNMAN_SERVICE_SECURITY_PSK:
case CONNMAN_SERVICE_SECURITY_WPA:
case CONNMAN_SERVICE_SECURITY_RSN:
+#if defined TIZEN_EXT
+ case CONNMAN_SERVICE_SECURITY_SAE:
+ case CONNMAN_SERVICE_SECURITY_OWE:
+ break;
+ case CONNMAN_SERVICE_SECURITY_DPP:
+ prepare_dpp(service);
+#endif
break;
case CONNMAN_SERVICE_SECURITY_8021X:
prepare_8021x(service);
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:
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;
__connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv6,
NULL);
+#if defined TIZEN_EXT
+ /**
+ * Skip the functions If there is any connected profiles
+ * that use same interface
+ */
+ if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR ||
+ __connman_service_get_connected_count_of_iface(service) <= 0) {
+#endif
__connman_ipconfig_address_remove(service->ipconfig_ipv4);
settings_changed(service, service->ipconfig_ipv4);
__connman_ipconfig_disable(service->ipconfig_ipv4);
__connman_ipconfig_disable(service->ipconfig_ipv6);
+#if defined TIZEN_EXT
+ }
+#endif
return err;
}
+int __connman_service_disconnect_all(void)
+{
+ struct connman_service *service;
+ GSList *services = NULL, *list;
+ GList *iter;
+
+ DBG("");
+
+ for (iter = service_list; iter; iter = iter->next) {
+ service = iter->data;
+
+ if (!is_connected(service->state))
+ break;
+
+ services = g_slist_prepend(services, service);
+ }
+
+ for (list = services; list; list = list->next) {
+ struct connman_service *service = list->data;
+
+ service->ignore = true;
+
+ __connman_service_disconnect(service);
+ }
+
+ g_slist_free(services);
+
+ return 0;
+}
+
/**
* lookup_by_identifier:
* @identifier: service identifier
service = connman_service_create();
if (!service)
return NULL;
-
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
DBG("service %p", service);
service->identifier = g_strdup(identifier);
static int service_register(struct connman_service *service)
{
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
DBG("service %p", service);
if (service->path)
DBG("path %s", service->path);
+#if defined TIZEN_EXT
+ int ret;
+ service_load(service);
+ ret = service_ext_load(service);
+ if (ret == -ERANGE)
+ service_ext_save(service);
+ ret = __connman_config_provision_service(service);
+ if (ret < 0 && !simplified_log)
+ DBG("Failed to provision service");
+#else
+ if (__connman_config_provision_service(service) < 0)
+ service_load(service);
+#endif
+
g_dbus_register_interface(connection, service->path,
CONNMAN_SERVICE_INTERFACE,
service_methods, service_signals,
struct connman_service *service = __connman_ipconfig_get_data(ipconfig);
enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN;
enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
+#if defined TIZEN_EXT
+ int err;
+#endif
DBG("%s ip bound", ifname);
if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
method == CONNMAN_IPCONFIG_METHOD_AUTO)
+#if defined TIZEN_EXT
+ {
+ err = __connman_ipconfig_gateway_add(ipconfig, service);
+
+ if(err < 0)
+ DBG("Failed to add gateway");
+ }
+#else
__connman_service_ipconfig_indicate_state(service,
CONNMAN_SERVICE_STATE_READY,
CONNMAN_IPCONFIG_TYPE_IPV6);
+#endif
settings_changed(service, ipconfig);
address_updated(service, type);
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)
{
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:
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
}
/**
return service;
}
+#if defined TIZEN_EXT
+void __connman_service_notify_strength_changed(struct connman_network *network)
+{
+ struct connman_service *service;
+ uint8_t strength = 0;
+
+ service = connman_service_lookup_from_network(network);
+ if (!service)
+ return;
+
+ if (!service->network)
+ return;
+
+ strength = connman_network_get_strength(service->network);
+ if (strength == service->strength)
+ return;
+
+ service->strength = strength;
+ if (!simplified_log)
+ DBG("Strength %d", strength);
+ strength_changed(service);
+ service_list_sort();
+}
+#endif
+
void __connman_service_update_from_network(struct connman_network *network)
{
bool need_sort = false;
bool roaming;
const char *name;
bool stats_enable;
+#if defined TIZEN_EXT
+ bool need_save = false;
+#endif
service = connman_service_lookup_from_network(network);
if (!service)
if (!service->network)
return;
+#if defined TIZEN_EXT
+ if (service->storage_reload) {
+ service_load(service);
+ __connman_service_set_storage_reload(service, false);
+ }
+#endif
+
name = connman_network_get_string(service->network, "Name");
if (g_strcmp0(service->name, name) != 0) {
g_free(service->name);
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();
}
.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;
remove_unprovisioned_services();
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+ ins_setting_init();
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
return 0;
}
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 "";
}
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 ||
#include <unistd.h>
#include <sys/stat.h>
#include <dirent.h>
+#include <stdio.h>
#include <connman/storage.h>
#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)
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;
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;
#include <errno.h>
#include <string.h>
+#if defined TIZEN_EXT
+#include <stdio.h>
+#include <stdlib.h>
+#include <net/if.h>
+#endif
#include <gdbus.h>
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;
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;
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;
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);
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;
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;
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);
return offlinemode;
}
+#if defined TIZEN_EXT
+static void append_devices(DBusMessageIter *iter, void *user_data)
+{
+ GSList *list;
+ dbus_bool_t val;
+ struct connman_technology *technology = user_data;
+
+ for (list = technology->device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+
+ const char *str = connman_device_get_string(device, "Interface");
+ struct connman_network *network = connman_device_get_default_network(device);
+ struct connman_service *service = connman_service_lookup_from_network(network);
+
+ connman_dbus_dict_append_basic(iter, "Ifname",
+ DBUS_TYPE_STRING, &str);
+
+ val = connman_device_get_powered(device);
+ connman_dbus_dict_append_basic(iter, "Powered",
+ DBUS_TYPE_BOOLEAN, &val);
+
+ if (__connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV4) ||
+ __connman_service_is_connected_state(service, CONNMAN_IPCONFIG_TYPE_IPV6))
+ val = TRUE;
+ else
+ val = FALSE;
+
+ connman_dbus_dict_append_basic(iter, "Connected",
+ DBUS_TYPE_BOOLEAN, &val);
+
+ str = connman_device_get_string(device, "Address");
+ connman_dbus_dict_append_basic(iter, "MAC.Address",
+ DBUS_TYPE_STRING, &str);
+ }
+}
+
+void __connman_technology_append_interfaces(DBusMessageIter *array,
+ enum connman_service_type type, const char *ifname)
+{
+ GSList *list;
+ struct connman_technology *technology = NULL;
+
+ for (list = technology_list; list; list = list->next) {
+ struct connman_technology *local_tech = list->data;
+
+ if (local_tech->type != type)
+ continue;
+
+ technology = local_tech;
+ break;
+ }
+
+ if (!technology)
+ return;
+
+ for (list = technology->device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+ const char *str = connman_device_get_string(device, "Interface");
+
+ if (g_strcmp0(ifname, str) == 0)
+ continue;
+
+ dbus_message_iter_append_basic(array,
+ DBUS_TYPE_STRING, &str);
+ }
+}
+#endif
+
static void append_properties(DBusMessageIter *iter,
struct connman_technology *technology)
{
DBUS_TYPE_STRING,
&technology->tethering_passphrase);
+#if defined TIZEN_EXT
+ connman_dbus_dict_append_basic(&dict, "MacPolicy",
+ DBUS_TYPE_UINT32,
+ &(technology->mac_policy));
+
+ connman_dbus_dict_append_basic(&dict, "PreassocMacPolicy",
+ DBUS_TYPE_UINT32,
+ &(technology->preassoc_mac_policy));
+
+ connman_dbus_dict_append_basic(&dict, "RandomMacLifetime",
+ DBUS_TYPE_UINT32,
+ &(technology->random_mac_lifetime));
+
+ if (technology->type == CONNMAN_SERVICE_TYPE_WIFI)
+ connman_dbus_dict_append_dict(&dict, "Device.List",
+ append_devices, technology);
+ if (technology->regdom)
+ connman_dbus_dict_append_basic(&dict, "CountryCode",
+ DBUS_TYPE_STRING,
+ &technology->regdom);
+#endif
connman_dbus_dict_close(iter, &dict);
}
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;
__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);
return reply;
}
+#if defined TIZEN_EXT
+int set_connman_bssid(enum bssid_type mode, char *bssid, const char *ifname)
+{
+ static int bssid_len;
+ static const char *def_ifname = "default";
+ static GSList *bssid_list = NULL;
+ GSList *list;
+ const char *local_ifname = ifname;
+ bool found = false;
+ struct connman_bssid_pending *bssid_info;
+
+ DBG("mode: %d, ifname: %s", mode, ifname);
+
+ if (!ifname)
+ local_ifname = def_ifname;
+
+ for (list = bssid_list; list; list = list->next) {
+ bssid_info = list->data;
+
+ if (g_strcmp0(bssid_info->ifname, local_ifname) == 0) {
+ found = true;
+ break;
+ }
+ }
+
+ if (mode == CHECK_BSSID) {
+ if (found)
+ return 6;
+
+ return 0;
+ }
+
+ if (mode == GET_BSSID && bssid) {
+ if (found) {
+ memcpy(bssid, bssid_info->bssid, 6);
+ return 6;
+ }
+ return 0;
+ }
+
+ if (mode == RESET_BSSID) {
+ if (found) {
+ bssid_list = g_slist_remove(bssid_list, bssid_info);
+ g_free(bssid_info->ifname);
+ g_free(bssid_info);
+ }
+ return 0;
+ }
+
+ if (mode != SET_BSSID || !bssid) {
+ DBG("Invalid parameter");
+ return 0;
+ }
+
+ if (found) {
+ bssid_list = g_slist_remove(bssid_list, bssid_info);
+ g_free(bssid_info->ifname);
+ g_free(bssid_info);
+ }
+
+ bssid_info = g_try_malloc0(sizeof(struct connman_bssid_pending));
+ if (!bssid_info) {
+ DBG("Failed to allocate memory");
+ return 0;
+ }
+
+ unsigned char *bssid_data = bssid_info->bssid;
+
+ bssid_len = sscanf(bssid, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
+ &bssid_data[0], &bssid_data[1], &bssid_data[2],
+ &bssid_data[3], &bssid_data[4], &bssid_data[5]);
+ if (bssid_len != 6) {
+ DBG("Incorrect BSSID format. bssid_len = %d", bssid_len);
+ g_free(bssid_info);
+ return 0;
+ }
+
+ DBG("SET BSSID len: %d, BSSID: %02x:%02x:%02x:%02x:%02x:%02x ifname: %s",
+ bssid_len,
+ bssid_data[0], bssid_data[1], bssid_data[2],
+ bssid_data[3], bssid_data[4], bssid_data[5],
+ ifname);
+
+ bssid_info->ifname = g_strdup(ifname);
+ bssid_list = g_slist_prepend(bssid_list, bssid_info);
+
+ return bssid_len;
+}
+
+void connman_technology_mac_policy_notify(struct connman_technology *technology,
+ unsigned int policy)
+{
+ DBG("Mac polict set to %u", policy);
+
+ technology->mac_policy = policy;
+ technology_save(technology);
+}
+
+void __connman_technology_notify_mac_policy_by_device(struct connman_device *device,
+ int result, unsigned int policy)
+{
+ struct connman_technology *technology;
+ enum connman_service_type type;
+
+ type = __connman_device_get_service_type(device);
+ technology = technology_find(type);
+
+ if (!technology)
+ return;
+
+ connman_technology_mac_policy_notify(technology, policy);
+}
+
+static DBusMessage *set_mac_policy(struct connman_technology *technology,
+ DBusMessage *msg, unsigned int policy)
+{
+ DBusMessage *reply = NULL;
+ int err = 0;
+ unsigned int last_policy = technology->mac_policy;
+
+ if (technology->rfkill_driven && technology->hardblocked) {
+ err = -EACCES;
+ goto make_reply;
+ }
+
+ for (GSList *list = technology->device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+
+ err = connman_device_set_mac_policy(device, policy);
+ if (err < 0)
+ break;
+ }
+
+make_reply:
+ if (err < 0) {
+ if (err != -EACCES && err != -EOPNOTSUPP) {
+ for (GSList *list = technology->device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+
+ connman_device_set_mac_policy(device, last_policy);
+ }
+ }
+
+ reply = __connman_error_failed(msg, -err);
+ } else {
+ reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ }
+
+ return reply;
+}
+
+void connman_technology_preassoc_mac_policy_notify(struct connman_technology *technology,
+ unsigned int policy)
+{
+ DBG("Preassoc mac polict set to %u", policy);
+
+ technology->preassoc_mac_policy = policy;
+ technology_save(technology);
+}
+
+void __connman_technology_notify_preassoc_mac_policy_by_device(struct connman_device *device,
+ int result, unsigned int policy)
+{
+ struct connman_technology *technology;
+ enum connman_service_type type;
+
+ type = __connman_device_get_service_type(device);
+ technology = technology_find(type);
+
+ if (!technology)
+ return;
+
+ connman_technology_preassoc_mac_policy_notify(technology, policy);
+}
+
+static DBusMessage *set_preassoc_mac_policy(struct connman_technology *technology,
+ DBusMessage *msg, unsigned int policy)
+{
+ DBusMessage *reply = NULL;
+ int err = 0;
+ unsigned int last_policy = technology->preassoc_mac_policy;
+
+ if (technology->rfkill_driven && technology->hardblocked) {
+ err = -EACCES;
+ goto make_reply;
+ }
+
+ for (GSList *list = technology->device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+
+ err = connman_device_set_preassoc_mac_policy(device, policy);
+ if (err < 0)
+ break;
+ }
+
+make_reply:
+ if (err < 0) {
+ if (err != -EACCES && err != -EOPNOTSUPP) {
+ for (GSList *list = technology->device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+
+ connman_device_set_preassoc_mac_policy(device, last_policy);
+ }
+ }
+
+ reply = __connman_error_failed(msg, -err);
+ } else {
+ reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ }
+
+ return reply;
+}
+
+void connman_technology_random_mac_lifetime_notify(struct connman_technology *technology,
+ unsigned int lifetime)
+{
+ DBG("Random mac lifetime set to %u", lifetime);
+
+ technology->random_mac_lifetime = lifetime;
+ technology_save(technology);
+}
+
+void __connman_technology_notify_random_mac_lifetime_by_device(struct connman_device *device,
+ int result, unsigned int lifetime)
+{
+ struct connman_technology *technology;
+ enum connman_service_type type;
+
+ type = __connman_device_get_service_type(device);
+ technology = technology_find(type);
+
+ if (!technology)
+ return;
+
+ connman_technology_random_mac_lifetime_notify(technology, lifetime);
+}
+
+static DBusMessage *set_random_mac_lifetime(struct connman_technology *technology,
+ DBusMessage *msg, unsigned int lifetime)
+{
+ DBusMessage *reply = NULL;
+ int err = 0;
+ unsigned int last_lifetime = technology->random_mac_lifetime;
+
+ if (technology->rfkill_driven && technology->hardblocked) {
+ err = -EACCES;
+ goto make_reply;
+ }
+
+ for (GSList *list = technology->device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+
+ err = connman_device_set_random_mac_lifetime(device, lifetime);
+ }
+
+make_reply:
+ if (err < 0) {
+ if (err != -EACCES && err != -EOPNOTSUPP) {
+ for (GSList *list = technology->device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+
+ connman_device_set_random_mac_lifetime(device, last_lifetime);
+ }
+ }
+
+ reply = __connman_error_failed(msg, -err);
+ } else {
+ reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ }
+
+ return reply;
+}
+#endif
+
static DBusMessage *set_property(DBusConnection *conn,
DBusMessage *msg, void *data)
{
dbus_message_iter_get_basic(&value, &enable);
return set_powered(technology, msg, enable);
- } else
- return __connman_error_invalid_property(msg);
+#if defined TIZEN_EXT
+ } else if (g_str_equal(name, "SetBSSID")) {
+ char *key;
- return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
-}
+ if (type != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value, &key);
+ DBG("BSSID %s", key);
+ set_connman_bssid(SET_BSSID, key, NULL);
+ } else if (g_str_equal(name, "MacPolicy")) {
+ dbus_uint32_t mac_policy;
+
+ if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
+ return __connman_error_not_supported(msg);
+
+ if (type != DBUS_TYPE_UINT32)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value, &mac_policy);
+
+ if (mac_policy <= 2)
+ return set_mac_policy(technology, msg, mac_policy);
+ else
+ return __connman_error_invalid_arguments(msg);
+
+ } else if (g_str_equal(name, "PreassocMacPolicy")) {
+ dbus_uint32_t preassoc_mac_policy;
+
+ if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
+ return __connman_error_not_supported(msg);
+
+ if (type != DBUS_TYPE_UINT32)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value, &preassoc_mac_policy);
+
+ if (preassoc_mac_policy <= 2)
+ return set_preassoc_mac_policy(technology, msg, preassoc_mac_policy);
+ else
+ return __connman_error_invalid_arguments(msg);
+
+ } else if (g_str_equal(name, "RandomMacLifetime")) {
+ dbus_uint32_t random_mac_lifetime;
+
+ if (technology->type != CONNMAN_SERVICE_TYPE_WIFI)
+ return __connman_error_not_supported(msg);
+
+ if (type != DBUS_TYPE_UINT32)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value, &random_mac_lifetime);
+
+ if (random_mac_lifetime > 0)
+ return set_random_mac_lifetime(technology, msg, random_mac_lifetime);
+ else
+ return __connman_error_invalid_arguments(msg);
+
+ } else if (g_str_equal(name, "CountryCode")) {
+ const char *str;
+
+ dbus_message_iter_get_basic(&value, &str);
+ DBG("country code %s", str);
+ connman_technology_set_regdom(str);
+#endif
+ } else
+ return __connman_error_invalid_property(msg);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
static void reply_scan_pending(struct connman_technology *technology, int err)
{
DBG("technology %p err %d", technology, err);
while (technology->scan_pending) {
+#if defined TIZEN_EXT
+ struct connman_scan_pending *pending_data = technology->scan_pending->data;
+ DBusMessage *msg = pending_data->msg;
+#else
DBusMessage *msg = technology->scan_pending->data;
+#endif
+ DBG("reply to %s", dbus_message_get_sender(msg));
+
+ if (err == 0)
+ reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ else
+ reply = __connman_error_failed(msg, -err);
+ g_dbus_send_message(connection, reply);
+ dbus_message_unref(msg);
+
+ technology->scan_pending =
+ g_slist_delete_link(technology->scan_pending,
+ technology->scan_pending);
+#if defined TIZEN_EXT
+ g_free(pending_data->ifname);
+ g_free(pending_data);
+#endif
+ }
+}
+
+#if defined TIZEN_EXT
+dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val)
+{
+ DBG("key %s", key);
+ DBusMessage *signal;
+ DBusMessageIter iter;
+ dbus_bool_t result = FALSE;
+
+ signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
+ CONNMAN_MANAGER_INTERFACE, "ScanChanged");
+ if (!signal)
+ return result;
+
+ dbus_message_iter_init_append(signal, &iter);
+ if (key)
+ connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val);
+ else
+ connman_dbus_property_append_basic(&iter, "", DBUS_TYPE_BOOLEAN, val);
+
+ result = dbus_connection_send(connection, signal, NULL);
+ dbus_message_unref(signal);
+
+ DBG("Successfuly sent signal");
+
+ return result;
+}
+
+void __connman_technology_notify_scan_done(const char *ifname, int val)
+{
+ DBG("");
+ DBusMessage *signal;
+ DBusMessageIter iter;
+
+ signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
+ CONNMAN_MANAGER_INTERFACE, "ScanDone");
+ if (!signal)
+ return;
+
+ dbus_message_iter_init_append(signal, &iter);
+ if (ifname)
+ connman_dbus_property_append_basic(&iter, ifname,
+ DBUS_TYPE_INT32, &val);
+ else
+ connman_dbus_property_append_basic(&iter, "",
+ DBUS_TYPE_INT32, &val);
+
+ dbus_connection_send(connection, signal, NULL);
+ dbus_message_unref(signal);
+
+ DBG("Successfuly sent ScanDone signal");
+}
+
+static void reply_scan_pending_device(
+ struct connman_technology *technology, const char *ifname, int count)
+{
+ DBusMessage *reply;
+ GSList *list;
+ dbus_bool_t status = 0;
+ connman_scan_type_e scan_type = CONNMAN_SCAN_TYPE_UNKNOWN;
+
+ DBG("technology %p ifname %s count %d", technology, ifname, count);
+
+ list = technology->scan_pending;
+
+ while (list) {
+ struct connman_scan_pending *pending_data = list->data;
+ DBusMessage *msg = pending_data->msg;
+ list = list->next;
+
+ if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
+ scan_type = pending_data->scan_type;
+
+ if (count != 0 && g_strcmp0(pending_data->ifname, ifname) != 0)
+ continue;
+
+ scan_type = pending_data->scan_type;
DBG("reply to %s", dbus_message_get_sender(msg));
+ reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+
+ g_dbus_send_message(connection, reply);
+ dbus_message_unref(msg);
+
+ technology->scan_pending =
+ g_slist_remove(technology->scan_pending, pending_data);
+
+ g_free(pending_data->ifname);
+ g_free(pending_data);
+ }
+
+ if (scan_type == CONNMAN_SCAN_TYPE_UNKNOWN)
+ scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
+
+ __connman_technology_notify_scan_changed(ifname, &status);
+ __connman_technology_notify_scan_done(ifname, scan_type);
+}
+
+static void __connman_technology_notify_device_detected(
+ struct connman_technology *technology, const char *ifname, bool val)
+{
+ DBG("");
+ DBusMessage *signal;
+ DBusMessageIter iter;
+ dbus_bool_t detected = val;
+
+ if (!ifname)
+ return;
+
+ signal = dbus_message_new_signal(technology->path,
+ CONNMAN_TECHNOLOGY_INTERFACE, "DeviceDetected");
+ if (!signal)
+ return;
+
+ dbus_message_iter_init_append(signal, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_BOOLEAN, &detected);
+
+ dbus_connection_send(connection, signal, NULL);
+ dbus_message_unref(signal);
+
+ DBG("Successfuly sent DeviceDetected signal");
+}
+
+void __connman_technology_notify_roaming_state(const char *ifname,
+ const char *state, const char *cur_bssid, const char *dst_bssid)
+{
+ DBG("");
+ DBusMessage *signal;
+ DBusMessageIter array, dict;
+
+ signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH,
+ CONNMAN_MANAGER_INTERFACE, "RoamingStateChanged");
+ if (!signal)
+ return;
+
+ dbus_message_iter_init_append(signal, &array);
+
+ connman_dbus_dict_open(&array, &dict);
+
+ if (ifname)
+ connman_dbus_dict_append_basic(&dict, "Interface",
+ DBUS_TYPE_STRING, &ifname);
+ if (state)
+ connman_dbus_dict_append_basic(&dict, "State",
+ DBUS_TYPE_STRING, &state);
+ if (cur_bssid)
+ connman_dbus_dict_append_basic(&dict, "ConnectedBSSID",
+ DBUS_TYPE_STRING, &cur_bssid);
+ if (dst_bssid)
+ connman_dbus_dict_append_basic(&dict, "TargetBSSID",
+ DBUS_TYPE_STRING, &dst_bssid);
+
+ connman_dbus_dict_close(&array, &dict);
+
+ dbus_connection_send(connection, signal, NULL);
+ dbus_message_unref(signal);
+
+ DBG("Successfully sent Roaming State Changed signal");
+}
+#endif
+
+void __connman_technology_scan_started(struct connman_device *device)
+{
+ DBG("device %p", device);
+#if defined TIZEN_EXT
+ dbus_bool_t status = 1;
+ const char *ifname = connman_device_get_string(device, "Interface");
+
+ __connman_technology_notify_scan_changed(ifname, &status);
+#endif
+}
+
+void __connman_technology_scan_stopped(struct connman_device *device,
+ enum connman_service_type type)
+{
+ int count = 0;
+ struct connman_technology *technology;
+ GSList *list;
+
+ technology = technology_find(type);
+
+ DBG("technology %p device %p", technology, device);
+
+ if (!technology)
+ return;
+
+ for (list = technology->device_list; list; list = list->next) {
+ struct connman_device *other_device = list->data;
+
+ if (device == other_device)
+ continue;
+
+ if (connman_device_get_scanning(other_device, type))
+ count += 1;
+ }
+
+#if defined TIZEN_EXT
+ const char *ifname = connman_device_get_string(device, "Interface");
+ reply_scan_pending_device(technology, ifname, count);
+
+ return;
+#else
+ if (count == 0)
+ reply_scan_pending(technology, 0);
+#endif
+}
+
+void __connman_technology_notify_regdom_by_device(struct connman_device *device,
+ int result, const char *alpha2)
+{
+ bool regdom_set = false;
+ struct connman_technology *technology;
+ enum connman_service_type type;
+ GSList *tech_drivers;
+
+ type = __connman_device_get_service_type(device);
+ technology = technology_find(type);
+
+ if (!technology)
+ return;
+
+ if (result < 0) {
+
+ for (tech_drivers = technology->driver_list;
+ tech_drivers;
+ tech_drivers = g_slist_next(tech_drivers)) {
+ struct connman_technology_driver *driver =
+ tech_drivers->data;
+
+ if (driver->set_regdom) {
+ driver->set_regdom(technology, alpha2);
+ regdom_set = true;
+ }
+
+ }
+
+ if (!regdom_set)
+ alpha2 = NULL;
+ }
+
+ connman_technology_regdom_notify(technology, alpha2);
+}
+
+static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
+{
+ struct connman_technology *technology = data;
+ int err;
+
+ DBG("technology %p request from %s", technology,
+ dbus_message_get_sender(msg));
+
+ if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
+ !technology->enabled)
+ return __connman_error_permission_denied(msg);
+
+#if !defined TIZEN_EXT
+ dbus_message_ref(msg);
+ technology->scan_pending =
+ g_slist_prepend(technology->scan_pending, msg);
+#endif
+
+ err = __connman_device_request_scan_full(technology->type);
+ if (err < 0)
+#if defined TIZEN_EXT
+ return __connman_error_failed(msg, -err);
+#else
+ reply_scan_pending(technology, err);
+#endif
+
+#if defined TIZEN_EXT
+ struct connman_scan_pending *pending_data =
+ g_try_malloc0(sizeof(struct connman_scan_pending));
+ if (!pending_data)
+ return __connman_error_failed(msg, ENOMEM);
+
+ pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
+ DBG("scan_type %d", pending_data->scan_type);
+
+ pending_data->msg = dbus_message_ref(msg);
+
+ technology->scan_pending =
+ g_slist_prepend(technology->scan_pending, pending_data);
+#endif
+ return NULL;
+}
+
+#if defined TIZEN_EXT
+static DBusMessage *scan_device(DBusConnection *conn, DBusMessage *msg, void *data)
+{
+ struct connman_technology *technology = data;
+ DBusMessageIter iter;
+ const char *ifname;
+ int err;
+
+ DBG("technology %p request from %s", technology,
+ dbus_message_get_sender(msg));
+
+ if (!dbus_message_iter_init(msg, &iter))
+ return __connman_error_invalid_arguments(msg);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&iter, &ifname);
+ DBG("Interface name %s", ifname);
+
+ if (!ifname || strlen(ifname) == 0)
+ return __connman_error_invalid_arguments(msg);
+
+ err = connman_device_request_device_scan(technology->type, ifname, true);
+ if (err < 0)
+ return __connman_error_failed(msg, -err);
+
+ struct connman_scan_pending *pending_data =
+ g_try_malloc0(sizeof(struct connman_scan_pending));
+ if (!pending_data)
+ return __connman_error_failed(msg, ENOMEM);
+
+ pending_data->ifname = g_strdup(ifname);
+ if (pending_data->ifname == NULL) {
+ g_free(pending_data);
+ return __connman_error_failed(msg, ENOMEM);
+ }
+
+ pending_data->scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL;
+ DBG("scan_type %d", pending_data->scan_type);
+
+ pending_data->msg = dbus_message_ref(msg);
+
+ technology->scan_pending =
+ g_slist_prepend(technology->scan_pending, pending_data);
+
+ return NULL;
+}
+
+static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data)
+{
+ struct connman_technology *technology = data;
+ GSList *specific_scan_list = NULL;
+ int scan_type = 0;
+ const char *name = NULL;
+ const char *freq = NULL;
+ const char *ifname = NULL;
+ DBusMessageIter iter, dict;
+ int err;
+
+ DBG("technology %p request from %s", technology,
+ dbus_message_get_sender(msg));
+
+ if (!dbus_message_iter_init(msg, &iter))
+ return __connman_error_invalid_arguments(msg);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_recurse(&iter, &dict);
+ while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter entry, value2;
+ const char *key;
+ int type;
+
+ dbus_message_iter_recurse(&dict, &entry);
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
+ g_slist_free_full(specific_scan_list, g_free);
+ return __connman_error_invalid_arguments(msg);
+ }
+
+ dbus_message_iter_get_basic(&entry, &key);
+ dbus_message_iter_next(&entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
+ g_slist_free_full(specific_scan_list, g_free);
+ return __connman_error_invalid_arguments(msg);
+ }
+
+ dbus_message_iter_recurse(&entry, &value2);
+ type = dbus_message_iter_get_arg_type(&value2);
+ if (g_str_equal(key, "Ifname") && type == DBUS_TYPE_STRING) {
+
+ dbus_message_iter_get_basic(&value2, &ifname);
+ DBG("ifname %s", ifname);
+ } else if (g_str_equal(key, "SSID")) {
+ if (type != DBUS_TYPE_STRING) {
+ g_slist_free_full(specific_scan_list, g_free);
+ return __connman_error_invalid_arguments(msg);
+ }
+
+ scan_type = CONNMAN_MULTI_SCAN_SSID; /* SSID based scan */
+ dbus_message_iter_get_basic(&value2, &name);
+ DBG("name %s", name);
+ specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name));
+ } else if (g_str_equal(key, "Frequency")) {
+ if (type != DBUS_TYPE_STRING) {
+ g_slist_free_full(specific_scan_list, g_free);
+ return __connman_error_invalid_arguments(msg);
+ }
+
+ scan_type = CONNMAN_MULTI_SCAN_FREQ; /* Frequency based scan */
+ dbus_message_iter_get_basic(&value2, &freq);
+ DBG("freq %s", freq);
+ specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(atoi(freq)));
+ } else if (g_str_equal(key, "SSID_Mixed")) {
+ if (type != DBUS_TYPE_STRING) {
+ g_slist_free_full(specific_scan_list, g_free);
+ return __connman_error_invalid_arguments(msg);
+ }
+
+ scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
+ dbus_message_iter_get_basic(&value2, &name);
+
+ connman_multi_scan_ap_s *ap =
+ (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
+ if (ap) {
+ g_strlcpy(ap->str, name, strlen(name) + 1);
+ ap->flag = true;
+ specific_scan_list = g_slist_append(specific_scan_list, ap);
+ } else
+ DBG("Failed to allocate memory");
+
+ } else if (g_str_equal(key, "Frequency_Mixed")) {
+ if (type != DBUS_TYPE_STRING) {
+ g_slist_free_full(specific_scan_list, g_free);
+ return __connman_error_invalid_arguments(msg);
+ }
+
+ scan_type = CONNMAN_MULTI_SCAN_SSID_FREQ; /* SSID & Frequency mixed scan */
+ dbus_message_iter_get_basic(&value2, &freq);
+
+ connman_multi_scan_ap_s *ap =
+ (connman_multi_scan_ap_s*)g_try_malloc0(sizeof(connman_multi_scan_ap_s));
+ if (ap) {
+ g_strlcpy(ap->str, freq, strlen(freq) + 1);
+ ap->flag = false;
+ specific_scan_list = g_slist_append(specific_scan_list, ap);
+ } else
+ DBG("Failed to allocate memory");
+ }
+ dbus_message_iter_next(&dict);
+ }
+
+ err = __connman_device_request_specific_scan(technology->type, ifname, scan_type, specific_scan_list);
+ if (err < 0)
+ return __connman_error_failed(msg, -err);
+
+ guint list_size = g_slist_length(specific_scan_list);
+
+ if (scan_type == CONNMAN_MULTI_SCAN_SSID ||
+ scan_type == CONNMAN_MULTI_SCAN_SSID_FREQ)
+ g_slist_free_full(specific_scan_list, g_free);
+
+ struct connman_scan_pending *pending_data =
+ g_try_malloc0(sizeof(struct connman_scan_pending));
+ if (!pending_data)
+ return __connman_error_failed(msg, ENOMEM);
+
+ if (ifname) {
+ pending_data->ifname = g_strdup(ifname);
+ if (pending_data->ifname == NULL) {
+ g_free(pending_data);
+ return __connman_error_failed(msg, ENOMEM);
+ }
+ }
+
+ if (list_size == 1)
+ pending_data->scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP;
+ else
+ pending_data->scan_type = CONNMAN_SCAN_TYPE_MULTI_AP;
+ DBG("list_size %u scan_type %d", list_size, pending_data->scan_type);
+
+ pending_data->msg = dbus_message_ref(msg);
+
+ technology->scan_pending =
+ g_slist_prepend(technology->scan_pending, pending_data);
+
+ return NULL;
+}
+
+static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, void *data)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter, dict;
+ GSList *list;
+ struct connman_technology *technology = data;
+ dbus_bool_t supported = false;
+ const char *ifname = NULL;
+
+ DBG("technology %p", technology);
+
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+ connman_dbus_dict_open(&iter, &dict);
+
+ for (list = technology->device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+
+ supported = connman_device_get_wifi_5ghz_supported(device);
+ ifname = connman_device_get_string(device, "Interface");
+
+ DBG("ifname %s supported : %d", ifname, supported);
+ connman_dbus_dict_append_basic(&dict, ifname,
+ DBUS_TYPE_BOOLEAN,
+ &supported);
+ }
+
+ connman_dbus_dict_close(&iter, &dict);
+
+ return reply;
+}
+
+static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter, dict;
+ GSList *list;
+ struct connman_technology *technology = data;
+ dbus_bool_t scanning = false;
+ const char *ifname = NULL;
+
+ DBG("technology %p", technology);
+
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+ connman_dbus_dict_open(&iter, &dict);
+
+ for (list = technology->device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+
+ scanning = connman_device_get_scanning(device, technology->type);
+ ifname = connman_device_get_string(device, "Interface");
+
+ DBG("ifname %s scanning : %d", ifname, scanning);
+ connman_dbus_dict_append_basic(&dict, ifname,
+ DBUS_TYPE_BOOLEAN,
+ &scanning);
+ }
+
+ connman_dbus_dict_close(&iter, &dict);
+
+ return reply;
+}
+
+static DBusMessage *get_max_scan_ssid(DBusConnection *conn, DBusMessage *msg, void *data)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter, dict;
+ GSList *list;
+ struct connman_technology *technology = data;
+ dbus_int32_t max_scan_ssids = 0;
+ const char *ifname = NULL;
+
+ DBG("technology %p", technology);
+
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+ connman_dbus_dict_open(&iter, &dict);
+
+ for (list = technology->device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+
+ max_scan_ssids = connman_device_get_max_scan_ssids(device);
+ ifname = connman_device_get_string(device, "Interface");
+
+ DBG("ifname %s max_scan_ssids : %d", ifname, max_scan_ssids);
+ connman_dbus_dict_append_basic(&dict, ifname,
+ DBUS_TYPE_INT32,
+ &max_scan_ssids);
+ }
+
+ connman_dbus_dict_close(&iter, &dict);
+
+ return reply;
+}
+
+static int technology_enable_device(struct connman_technology *technology,
+ bool enable_device, const char *ifname, struct connman_device **device_out)
+{
+ int err = 0;
+ GSList *list;
+
+ for (list = technology->device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+ const char *str = connman_device_get_string(device, "Interface");
+
+ if (g_strcmp0(str, ifname) != 0)
+ continue;
+
+ if (enable_device)
+ err = __connman_device_enable(device);
+ else
+ err = __connman_device_disable(device);
+
+ *device_out = device;
+ return err;
+ }
+
+ return -ENXIO;
+}
+
+static DBusMessage *technology_set_device_powered(struct connman_technology *technology,
+ DBusMessage *msg, bool powered, const char *ifname)
+{
+ DBusMessage *reply = NULL;
+ struct connman_device *device = NULL;
+ int err = 0;
+
+ err = technology_enable_device(technology, powered, ifname, &device);
+
+ if (err == -EINPROGRESS) {
+ if (device)
+ connman_device_set_pending_reply(device, msg);
+ return reply;
+ } else if (err == -EALREADY) {
+ if (powered)
+ reply = __connman_error_already_enabled(msg);
+ else
+ reply = __connman_error_already_disabled(msg);
+ } else if (err < 0)
+ reply = __connman_error_failed(msg, -err);
+ else
+ reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+
+ return reply;
+}
+
+static DBusMessage *set_device_power(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ struct connman_technology *technology = data;
+ DBusMessageIter iter;
+ const char *name;
+ int len;
+ dbus_bool_t enable;
+
+ DBG("conn %p", conn);
+
+ if (!dbus_message_iter_init(msg, &iter))
+ return __connman_error_invalid_arguments(msg);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&iter, &name);
+ dbus_message_iter_next(&iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
+ return __connman_error_invalid_arguments(msg);
+
+ DBG("interface name %s", name);
+
+ len = strlen(name);
+
+ if (len + 1 > IFNAMSIZ)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&iter, &enable);
+ DBG("powered %s", enable ? "TRUE" : "FALSE");
+
+ return technology_set_device_powered(technology, msg, enable, name);
+}
+
+static DBusMessage *set_bssid(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ DBusMessageIter iter;
+ char *name, *bssid;
+ int len;
+
+ DBG("conn %p", conn);
+
+ if (!dbus_message_iter_init(msg, &iter))
+ return __connman_error_invalid_arguments(msg);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&iter, &name);
+ dbus_message_iter_next(&iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&iter, &bssid);
+
+ DBG("interface name %s bssid %s", name, bssid);
+
+ len = strlen(name);
+
+ if (len + 1 > IFNAMSIZ)
+ return __connman_error_invalid_arguments(msg);
+
+ set_connman_bssid(SET_BSSID, bssid, name);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+}
+static struct connman_technology *technology_get(enum connman_service_type type);
+
+void technology_save_device(struct connman_device *device)
+{
+ struct connman_technology *technology;
+ enum connman_service_type type;
+
+ type = __connman_device_get_service_type(device);
+
+ if (type != CONNMAN_SERVICE_TYPE_WIFI)
+ return;
+
+ technology = technology_get(type);
+ if (!technology)
+ return;
+
+ if (!g_slist_find(technology->device_list, device))
+ return;
+
+ GKeyFile *keyfile;
+ gchar *identifier;
+ const char *name = get_name(technology->type);
+
+ DBG("technology %p type %d name %s", technology, technology->type,
+ name);
+ if (!name)
+ return;
+
+ keyfile = __connman_storage_load_global();
+ if (!keyfile)
+ keyfile = g_key_file_new();
+
+ identifier = g_strdup_printf("%s", name);
+ if (!identifier)
+ goto done;
+
+ GSList *list = NULL;
+ gchar **ifname_list = NULL;
+ guint dev_count = g_slist_length(technology->device_list);
+
+ if (dev_count >= 1) {
+ GString *ifname_str = g_string_new(NULL);
+
+ if (ifname_str) {
+ for (list = technology->device_list; list; list = list->next) {
+ struct connman_device *device = list->data;
+
+ if (connman_device_get_powered(device)) {
+ const char *ifname = connman_device_get_string(device, "Interface");
+
+ if (ifname_str->len > 0)
+ g_string_append_printf(ifname_str, " %s", ifname);
+ else
+ g_string_append(ifname_str, ifname);
+ }
+ }
+
+ if (ifname_str->len > 0) {
+ ifname_list = g_strsplit_set(ifname_str->str, " ", 0);
+ dev_count = g_strv_length(ifname_list);
+ g_key_file_set_string_list(keyfile, identifier, "Enable.Devices",
+ (const gchar **) ifname_list, dev_count);
+
+ technology->enable_persistent = true;
+ } else {
+ g_key_file_remove_key(keyfile, identifier, "Enable.Devices", NULL);
+ technology->enable_persistent = false;
+ }
+
+ g_strfreev(ifname_list);
+ g_string_free(ifname_str, TRUE);
+ }
+ }
+
+ g_key_file_set_boolean(keyfile, identifier, "Enable",
+ technology->enable_persistent);
+
+ g_key_file_set_boolean(keyfile, identifier, "Tethering",
+ technology->tethering_persistent);
+
+ if (technology->tethering_ident)
+ g_key_file_set_string(keyfile, identifier,
+ "Tethering.Identifier",
+ technology->tethering_ident);
+
+ if (technology->tethering_passphrase)
+ g_key_file_set_string(keyfile, identifier,
+ "Tethering.Passphrase",
+ technology->tethering_passphrase);
+
+done:
+ g_free(identifier);
- if (err == 0)
- reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
- else
- reply = __connman_error_failed(msg, -err);
- g_dbus_send_message(connection, reply);
- dbus_message_unref(msg);
+ __connman_storage_save_global(keyfile);
- technology->scan_pending =
- g_slist_delete_link(technology->scan_pending,
- technology->scan_pending);
- }
+ g_key_file_free(keyfile);
}
+#endif
-void __connman_technology_scan_started(struct connman_device *device)
+#if defined TIZEN_EXT_WIFI_MESH
+bool __connman_technology_get_connected(enum connman_service_type type)
{
- DBG("device %p", device);
+ struct connman_technology *technology;
+
+ technology = technology_find(type);
+
+ if (!technology)
+ return false;
+
+ return technology->connected;
}
-void __connman_technology_scan_stopped(struct connman_device *device,
- enum connman_service_type type)
+void __connman_technology_mesh_interface_create_finished(
+ enum connman_service_type type, bool success,
+ const char *error)
{
- int count = 0;
+ DBusMessage *reply;
struct connman_technology *technology;
- GSList *list;
-
+ DBusMessage *msg;
technology = technology_find(type);
- DBG("technology %p device %p", technology, device);
+ DBG("technology %p success %d", technology, success);
if (!technology)
return;
- for (list = technology->device_list; list; list = list->next) {
- struct connman_device *other_device = list->data;
-
- if (device == other_device)
- continue;
-
- if (connman_device_get_scanning(other_device, type))
- count += 1;
+ msg = technology->mesh_dbus_msg;
+ if (!msg) {
+ DBG("No pending dbus message");
+ return;
}
- if (count == 0)
- reply_scan_pending(technology, 0);
+ if (success) {
+ reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ __connman_device_request_scan(technology->type);
+ } else
+ reply = g_dbus_create_error(msg, CONNMAN_ERROR_INTERFACE
+ ".MeshInterfaceAddFailed", "%s", error);
+ g_dbus_send_message(connection, reply);
+ dbus_message_unref(msg);
+ technology->mesh_dbus_msg = NULL;
}
-void __connman_technology_notify_regdom_by_device(struct connman_device *device,
- int result, const char *alpha2)
+void __connman_technology_mesh_interface_remove_finished(
+ enum connman_service_type type, bool success)
{
- bool regdom_set = false;
+ DBusMessage *reply;
struct connman_technology *technology;
- enum connman_service_type type;
- GSList *tech_drivers;
-
- type = __connman_device_get_service_type(device);
+ DBusMessage *msg;
technology = technology_find(type);
- if (!technology)
+ DBG("technology %p success %d", technology, success);
+
+ if (!technology || !technology->mesh_dbus_msg)
return;
- if (result < 0) {
+ msg = technology->mesh_dbus_msg;
+ if (!msg) {
+ DBG("No pending dbus message");
+ return;
+ }
- for (tech_drivers = technology->driver_list;
- tech_drivers;
- tech_drivers = g_slist_next(tech_drivers)) {
- struct connman_technology_driver *driver =
- tech_drivers->data;
+ if (success)
+ reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ else
+ reply = __connman_error_failed(msg, EINVAL);
+ g_dbus_send_message(connection, reply);
+ dbus_message_unref(msg);
+ technology->mesh_dbus_msg = NULL;
+}
- if (driver->set_regdom) {
- driver->set_regdom(technology, alpha2);
- regdom_set = true;
- }
+void __connman_technology_notify_abort_scan(enum connman_service_type type,
+ int result)
+{
+ DBusMessage *reply;
+ struct connman_technology *technology;
+ DBusMessage *msg;
+ technology = technology_find(type);
- }
+ DBG("technology %p result %d", technology, result);
- if (!regdom_set)
- alpha2 = NULL;
+ if (!technology || !technology->mesh_dbus_msg)
+ return;
+
+ msg = technology->mesh_dbus_msg;
+ if (!msg) {
+ DBG("No pending dbus message");
+ return;
}
- connman_technology_regdom_notify(technology, alpha2);
+ if (result < 0)
+ reply = __connman_error_scan_abort_failed(msg);
+ else
+ reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+
+ g_dbus_send_message(connection, reply);
+ dbus_message_unref(msg);
+ technology->mesh_dbus_msg = NULL;
}
-static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data)
+static DBusMessage *mesh_commands(DBusConnection *conn,
+ DBusMessage *msg, void *data)
{
struct connman_technology *technology = data;
+ DBusMessageIter iter, value, dict;
+ const char *cmd = NULL, *ifname = NULL, *parent_ifname = NULL;
int err;
- DBG("technology %p request from %s", technology,
- dbus_message_get_sender(msg));
+ DBG("conn %p", conn);
- if (technology->type == CONNMAN_SERVICE_TYPE_P2P &&
- !technology->enabled)
- return __connman_error_permission_denied(msg);
+ if (technology->type != CONNMAN_SERVICE_TYPE_MESH)
+ return __connman_error_invalid_arguments(msg);
- dbus_message_ref(msg);
- technology->scan_pending =
- g_slist_prepend(technology->scan_pending, msg);
+ if (!dbus_message_iter_init(msg, &iter))
+ return __connman_error_invalid_arguments(msg);
- err = __connman_device_request_scan_full(technology->type);
- if (err < 0)
- reply_scan_pending(technology, err);
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&iter, &cmd);
+ dbus_message_iter_next(&iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_recurse(&iter, &value);
+
+ if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_ARRAY)
+ return __connman_error_invalid_arguments(msg);
+
+ DBG("Mesh Command %s", cmd);
+ if (g_str_equal(cmd, "MeshInterfaceAdd")) {
+ dbus_message_iter_recurse(&value, &dict);
+ const char *bridge_ifname = NULL;
+ while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter entry, value2;
+ const char *key;
+ int type;
+
+ dbus_message_iter_recurse(&dict, &entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&entry, &key);
+ dbus_message_iter_next(&entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_recurse(&entry, &value2);
+
+ type = dbus_message_iter_get_arg_type(&value2);
+
+ if (g_str_equal(key, "Ifname")) {
+ if (type != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value2, &ifname);
+ } else if (g_str_equal(key, "ParentIfname")) {
+ if (type != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value2, &parent_ifname);
+ } else if (g_str_equal(key, "BridgeIfname")) {
+ if (type != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value2, &bridge_ifname);
+ }
+ dbus_message_iter_next(&dict);
+ }
+ DBG("Mesh Ifname %s parent %s bridge %s", ifname, parent_ifname,
+ bridge_ifname ? bridge_ifname : "NULL");
+ err = __connman_mesh_add_virtual_interface(ifname, parent_ifname,
+ bridge_ifname);
+
+ if (err != 0) {
+ DBG("Failed to add virtual mesh interface");
+ return __connman_error_failed(msg, -err);
+ }
+
+ DBG("Successfully added virtual mesh interface");
+
+ dbus_message_ref(msg);
+ technology->mesh_dbus_msg = msg;
+
+ } else if (g_str_equal(cmd, "MeshInterfaceRemove")) {
+ dbus_message_iter_recurse(&value, &dict);
+ while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter entry, value2;
+ const char *key;
+ int type;
+
+ dbus_message_iter_recurse(&dict, &entry);
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&entry, &key);
+ dbus_message_iter_next(&entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_recurse(&entry, &value2);
+
+ type = dbus_message_iter_get_arg_type(&value2);
+
+ if (g_str_equal(key, "Ifname")) {
+ if (type != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value2, &ifname);
+ }
+ dbus_message_iter_next(&dict);
+ }
+ DBG("Mesh Ifname %s", ifname);
+ err = __connman_mesh_remove_virtual_interface(ifname);
+
+ if (err != 0) {
+ DBG("Failed to remove virtual mesh interface");
+ return __connman_error_failed(msg, -err);
+ }
+
+ DBG("Successfully removed virtual mesh interface");
+
+ dbus_message_ref(msg);
+ technology->mesh_dbus_msg = msg;
+
+ } else if (g_str_equal(cmd, "MeshCreateNetwork")) {
+ struct connman_mesh *connman_mesh;
+ const char *name = NULL;
+ const char *sec_type = NULL;
+ const char *mesh_ifname = NULL;
+ char *identifier, *group, *address;
+ unsigned int freq = 0;
+ unsigned int ieee80211w = 0;
+ GString *str;
+ int i;
+ dbus_message_iter_recurse(&value, &dict);
+ while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter entry, value2;
+ const char *key;
+ int type;
+
+ dbus_message_iter_recurse(&dict, &entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&entry, &key);
+ dbus_message_iter_next(&entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_recurse(&entry, &value2);
+
+ type = dbus_message_iter_get_arg_type(&value2);
+
+ if (g_str_equal(key, "Name")) {
+ if (type != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value2, &name);
+ } else if (g_str_equal(key, "Frequency")) {
+ if (type != DBUS_TYPE_UINT16)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value2, &freq);
+ } else if (g_str_equal(key, "Security")) {
+ if (type != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value2, &sec_type);
+ } else if (g_str_equal(key, "Pmf")) {
+ if (type != DBUS_TYPE_UINT16)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value2, &ieee80211w);
+ }
+ dbus_message_iter_next(&dict);
+ }
+
+ if (name == NULL || sec_type == NULL || freq == 0)
+ return __connman_error_invalid_arguments(msg);
+
+ DBG("Name %s Frequency %d Security type %s Pmf %u",
+ name, freq, sec_type, ieee80211w);
+
+ if (g_strcmp0(sec_type, "none") != 0 &&
+ g_strcmp0(sec_type, "sae") != 0) {
+ DBG("Unsupported security");
+ return __connman_error_invalid_arguments(msg);
+ }
+
+ mesh_ifname = connman_mesh_get_interface_name();
+
+ if (!connman_mesh_is_interface_created()) {
+ DBG("Mesh interface doesn't exists");
+ return __connman_error_invalid_command(msg);
+ }
+
+ str = g_string_sized_new((strlen(name) * 2) + 24);
+
+ for (i = 0; name[i]; i++)
+ g_string_append_printf(str, "%02x", name[i]);
+
+ g_string_append_printf(str, "_mesh");
+
+ if (g_strcmp0(sec_type, "none") == 0)
+ g_string_append_printf(str, "_none");
+ else if (g_strcmp0(sec_type, "sae") == 0)
+ g_string_append_printf(str, "_sae");
+
+ group = g_string_free(str, FALSE);
+
+ identifier = connman_inet_ifaddr(mesh_ifname);
+ address = connman_inet_ifname2addr(mesh_ifname);
+
+ connman_mesh = connman_mesh_create(identifier, group);
+ connman_mesh_set_name(connman_mesh, name);
+ connman_mesh_set_address(connman_mesh, address);
+ connman_mesh_set_security(connman_mesh, sec_type);
+ connman_mesh_set_frequency(connman_mesh, freq);
+ connman_mesh_set_index(connman_mesh, connman_inet_ifindex(mesh_ifname));
+ connman_mesh_set_peer_type(connman_mesh,
+ CONNMAN_MESH_PEER_TYPE_CREATED);
+ connman_mesh_set_ieee80211w(connman_mesh, ieee80211w);
+
+ connman_mesh_register(connman_mesh);
+ g_free(group);
+ g_free(identifier);
+ g_free(address);
+ DBG("Successfully Created Mesh Network");
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+
+ } else if (g_str_equal(cmd, "AbortScan")) {
+ DBG("Abort Scan method");
+ err = __connman_device_abort_scan(technology->type);
+ if (err != 0) {
+ DBG("Failed to abort scan");
+ return __connman_error_failed(msg, -err);
+ }
+
+ DBG("Successfully requested to abort scan");
+ dbus_message_ref(msg);
+ technology->mesh_dbus_msg = msg;
+
+ } else if (g_str_equal(cmd, "MeshSpecificScan")) {
+ const char *name = NULL;
+ unsigned int freq = 0;
+ dbus_message_iter_recurse(&value, &dict);
+ while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter entry, value2;
+ const char *key;
+ int type;
+
+ dbus_message_iter_recurse(&dict, &entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&entry, &key);
+ dbus_message_iter_next(&entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_recurse(&entry, &value2);
+
+ type = dbus_message_iter_get_arg_type(&value2);
+
+ if (g_str_equal(key, "Name")) {
+ if (type != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value2, &name);
+ } else if (g_str_equal(key, "Frequency")) {
+ if (type != DBUS_TYPE_UINT16)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value2, &freq);
+ }
+ dbus_message_iter_next(&dict);
+ }
+
+ DBG("MeshID %s Frequency %d sender %s", name, freq,
+ dbus_message_get_sender(msg));
+
+ struct connman_scan_pending *pending_data =
+ g_try_malloc0(sizeof(struct connman_scan_pending));
+ if (!pending_data)
+ return __connman_error_failed(msg, ENOMEM);
+
+ pending_data->msg = dbus_message_ref(msg);
+
+ technology->scan_pending =
+ g_slist_prepend(technology->scan_pending, pending_data);
+
+ err = __connman_device_request_mesh_specific_scan(technology->type,
+ name, freq);
+ if (err < 0)
+ reply_scan_pending(technology, err);
+ else
+ DBG("Successfully requested to scan specific Mesh Network");
+
+ } else if (g_str_equal(cmd, "SetMeshGate")) {
+ unsigned int hwmp_rootmode = 0;
+ bool gate_announce = false;
+ unsigned int stp = 0;
+ int err;
+ dbus_message_iter_recurse(&value, &dict);
+ while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter entry, value2;
+ const char *key;
+ int type;
+
+ dbus_message_iter_recurse(&dict, &entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&entry, &key);
+ dbus_message_iter_next(&entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_recurse(&entry, &value2);
+
+ type = dbus_message_iter_get_arg_type(&value2);
+
+ if (g_str_equal(key, "GateAnnounce")) {
+ if (type != DBUS_TYPE_BOOLEAN)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value2, &gate_announce);
+ } else if (g_str_equal(key, "HWMPRootMode")) {
+ if (type != DBUS_TYPE_UINT16)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value2, &hwmp_rootmode);
+ } else if (g_str_equal(key, "STP")) {
+ if (type != DBUS_TYPE_UINT16)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value2, &stp);
+ }
+ dbus_message_iter_next(&dict);
+ }
+
+ DBG("GateAnnounce %d HWMPRootMode %d STP %d sender %s",
+ gate_announce, hwmp_rootmode, stp, dbus_message_get_sender(msg));
+
+ err = __connman_mesh_set_stp_gate_announce(gate_announce,
+ hwmp_rootmode,
+ stp);
+
+ if (err < 0)
+ return __connman_error_failed(msg, -err);
+
+ return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
+ } else
+ return __connman_error_invalid_command(msg);
return NULL;
}
+#endif
static const GDBusMethodTable technology_methods[] = {
{ GDBUS_DEPRECATED_METHOD("GetProperties",
GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
NULL, set_property) },
{ GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) },
+#if defined TIZEN_EXT
+ { GDBUS_ASYNC_METHOD("ScanDevice", GDBUS_ARGS({ "interface_name", "s" }),
+ NULL, scan_device) },
+ { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }),
+ NULL, specific_scan) },
+ { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }),
+ get_scan_state) },
+ { GDBUS_METHOD("Get5GhzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }),
+ get_5ghz_supported) },
+ { GDBUS_METHOD("GetMaxScanSsid", NULL, GDBUS_ARGS({ "maxscanssid", "a{sv}" }),
+ get_max_scan_ssid) },
+ { GDBUS_ASYNC_METHOD("SetDevicePower",
+ GDBUS_ARGS({ "ifname", "s" }, { "value", "b" }),
+ NULL, set_device_power) },
+ { GDBUS_ASYNC_METHOD("SetBSSID",
+ GDBUS_ARGS({ "ifname", "s" }, { "bssid", "s" }),
+ NULL, set_bssid) },
+#endif
+#if defined TIZEN_EXT_WIFI_MESH
+ { GDBUS_ASYNC_METHOD("MeshCommands",
+ GDBUS_ARGS({ "name", "s" }, { "value", "v" }),
+ NULL, mesh_commands) },
+#endif
{ },
};
static const GDBusSignalTable technology_signals[] = {
{ GDBUS_SIGNAL("PropertyChanged",
GDBUS_ARGS({ "name", "s" }, { "value", "v" })) },
+#if defined TIZEN_EXT
+ { GDBUS_SIGNAL("DeviceChanged",
+ GDBUS_ARGS({ "device_property", "a{sv}" })) },
+ { GDBUS_SIGNAL("DeviceDetected",
+ GDBUS_ARGS({ "ifname", "s" }, { "detected", "b" })) },
+#endif
{ },
};
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);
technology = technology_find(type);
if (technology) {
+#if defined TIZEN_EXT_WIFI_MESH
+ if (type != CONNMAN_SERVICE_TYPE_P2P &&
+ type != CONNMAN_SERVICE_TYPE_MESH)
+#else
if (type != CONNMAN_SERVICE_TYPE_P2P)
+#endif
__sync_fetch_and_add(&technology->refcount, 1);
return technology;
}
technology->path = g_strdup_printf("%s/technology/%s",
CONNMAN_PATH, str);
+#if defined TIZEN_EXT_WIFI_MESH
+ if (type == CONNMAN_SERVICE_TYPE_MESH) {
+ struct connman_technology *wifi;
+
+ wifi = technology_find(CONNMAN_SERVICE_TYPE_WIFI);
+ if (wifi)
+ technology->enabled = wifi->enabled;
+ }
+#endif
+
technology_load(technology);
technology_list = g_slist_prepend(technology_list, technology);
technology->driver_list = tech_drivers;
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;
}
if (technology)
technology_put(technology);
}
+#if defined TIZEN_EXT_WIFI_MESH
+ if (driver->type == CONNMAN_SERVICE_TYPE_MESH) {
+ technology = technology_find(CONNMAN_SERVICE_TYPE_MESH);
+ if (technology)
+ technology_put(technology);
+ }
+#endif
}
void __connman_technology_add_interface(enum connman_service_type type,
case CONNMAN_SERVICE_TYPE_VPN:
case CONNMAN_SERVICE_TYPE_GADGET:
case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
break;
}
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;
}
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
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;
}
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);
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);
}
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;
return err;
}
+#if defined TIZEN_EXT_WIFI_MESH
+static gboolean __add_ethernet_to_bridge(gpointer data)
+{
+ DBG("");
+ __connman_mesh_add_ethernet_to_bridge();
+ return FALSE;
+}
+#endif
+
void __connman_technology_set_connected(enum connman_service_type type,
bool connected)
{
technology->connected = connected;
+#if defined TIZEN_EXT_WIFI_MESH
+ if (technology->type == CONNMAN_SERVICE_TYPE_ETHERNET && connected)
+ g_idle_add(__add_ethernet_to_bridge, NULL);
+#endif
+
val = connected;
connman_dbus_property_changed_basic(technology->path,
CONNMAN_TECHNOLOGY_INTERFACE, "Connected",
g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill);
done:
+#if defined TIZEN_EXT
+ /* Fix Svace Issue [WGID: 1348]. */
+ g_free(rfkill);
+#endif
technology = technology_get(type);
/* If there is no driver for this type, ignore it. */
if (!technology)
technology->rfkill_driven = true;
+#if !defined TIZEN_EXT
/* If hardblocked, there is no need to handle softblocked state */
if (technology_apply_rfkill_change(technology,
softblock, hardblock, true))
return 0;
+#endif
if (global_offlinemode)
return 0;
{
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) {
__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;
}
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,
const char *str = NULL;
guint16 status;
gsize length;
+#if defined TIZEN_MAINTAIN_ONLINE
+ static int retried = 0;
+#endif
DBG("");
wp_context->status_url, wp_context);
break;
case 200:
+#if defined TIZEN_MAINTAIN_ONLINE
+ retried = 0;
+#endif
if (wp_context->wispr_msg.message_type >= 0)
break;
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,
case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_VPN:
case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
return -EOPNOTSUPP;
}
goto done;
}
+#if !defined TIZEN_EXT
if (getenv("CONNMAN_WEB_DEBUG"))
+#endif
g_web_set_debug(wp_context->web, web_debug, "WEB");
if (wp_context->type == CONNMAN_IPCONFIG_TYPE_IPV4) {
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;
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++)
[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
{ 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.
[D-BUS Service]
Name=net.connman.vpn
-Exec=@sbindir@/connman-vpnd -n
-User=root
+Exec=/bin/false
SystemdService=connman-vpn.service
--- /dev/null
+/*
+ *
+ * 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)
--- /dev/null
+/*
+ *
+ * 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 */
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 */
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
--- /dev/null
+/*
+ *
+ * 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;
+}
--- /dev/null
+/*
+ *
+ * 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 */
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);
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);
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,
#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;
char *endpoint_fqdn;
char *port;
int reresolve_id;
+#if defined TIZEN_EXT
+ int allowed_ip_route_id;
+#endif /* TIZEN_EXT */
};
struct sockaddr_u {
int i;
curaip = NULL;
+#if defined TIZEN_EXT
+ /**
+ * Note: At API level we donot check Wireguard specific configurations,
+ * User can provide any space separated string for IP.
+ * Ideally it should be using "10.0.0.2/32, 10.0.0.3/32"
+ * However there can be cases like "10.0.0.2/32,10.0.0.3/32"
+ *
+ * So we need to parse the allowed_ips configuration properly.
+ */
+ tokens = g_strsplit(allowed_ips, ",", -1);
+#else
tokens = g_strsplit(allowed_ips, ", ", -1);
+#endif
for (i = 0; tokens[i]; i++) {
+#if defined TIZEN_EXT
+ int len = strlen(tokens[i]);
+ char *ptr = tokens[i];
+ int j = -1;
+
+ //skip forward spaces
+ while (++j < len && ptr[j] == ' ')
+ ;// Do Nothing
+
+ if (!ptr[j])
+ continue;
+
+ toks = g_strsplit(ptr + j, "/", -1);
+ if (g_strv_length(toks) != 2) {
+ DBG("Ignore AllowedIPs value [%s]", ptr + j);
+ g_strfreev(toks);
+ continue;
+ }
+
+ DBG("Parsed AllowedIPs [%s]", ptr + j);
+#else
+
toks = g_strsplit(tokens[i], "/", -1);
if (g_strv_length(toks) != 2) {
DBG("Ignore AllowedIPs value %s", tokens[i]);
g_strfreev(toks);
continue;
}
+#endif
allowedip = g_malloc0(sizeof(*allowedip));
allowedip->family = AF_INET6;
memcpy(&allowedip->ip6, buf, sizeof(allowedip->ip6));
} else {
+#if defined TIZEN_EXT
+ DBG("Ignore AllowedIPs value [%s]", ptr + j);
+#else
DBG("Ignore AllowedIPs value %s", tokens[i]);
+#endif
g_free(allowedip);
g_strfreev(toks);
continue;
curaip->next_allowedip = allowedip;
curaip = allowedip;
+#if defined TIZEN_EXT
+ g_strfreev(toks);
+#endif
}
peer->last_allowedip = curaip;
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;
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,
if (!info)
return;
+#if defined TIZEN_EXT
+ if (info->allowed_ip_route_id > 0)
+ g_source_remove(info->allowed_ip_route_id);
+#endif /* TIZEN_EXT */
+
if (info->reresolve_id > 0)
g_source_remove(info->reresolve_id);
g_free(info);
}
+#if defined TIZEN_EXT
+static int wg_save(struct vpn_provider *provider, GKeyFile *keyfile)
+{
+ const char *option;
+
+ DBG("");
+
+ /*
+ * The client/own device listen port.
+ */
+ option = vpn_provider_get_string(provider, "WireGuard.ListenPort");
+ if (option)
+ g_key_file_set_string(keyfile,
+ vpn_provider_get_save_group(provider),
+ "WireGuard.ListenPort",
+ option);
+
+ /*
+ * comma separated DNS.
+ */
+ option = vpn_provider_get_string(provider, "WireGuard.DNS");
+ if (option)
+ g_key_file_set_string(keyfile,
+ vpn_provider_get_save_group(provider),
+ "WireGuard.DNS",
+ option);
+
+ /*
+ * The client private key.
+ */
+ option = vpn_provider_get_string(provider, "WireGuard.PrivateKey");
+ if (option)
+ g_key_file_set_string(keyfile,
+ vpn_provider_get_save_group(provider),
+ "WireGuard.PrivateKey",
+ option);
+
+ /*
+ * The server public key.
+ */
+ option = vpn_provider_get_string(provider, "WireGuard.PublicKey");
+ if (option)
+ g_key_file_set_string(keyfile,
+ vpn_provider_get_save_group(provider),
+ "WireGuard.PublicKey",
+ option);
+
+ /*
+ * The preshared key.
+ */
+ option = vpn_provider_get_string(provider, "WireGuard.PresharedKey");
+ if (option)
+ g_key_file_set_string(keyfile,
+ vpn_provider_get_save_group(provider),
+ "WireGuard.PresharedKey",
+ option);
+
+ /*
+ * Subnets accessed via VPN tunnel, 0.0.0.0/0 routes all traffic.
+ */
+ option = vpn_provider_get_string(provider, "WireGuard.AllowedIPs");
+ if (option)
+ g_key_file_set_string(keyfile,
+ vpn_provider_get_save_group(provider),
+ "WireGuard.AllowedIPs",
+ option);
+
+ /*
+ * The time in seconds to emit periodic keep alive message.
+ */
+ option = vpn_provider_get_string(provider, "WireGuard.PersistentKeepalive");
+ if (option)
+ g_key_file_set_string(keyfile,
+ vpn_provider_get_save_group(provider),
+ "WireGuard.PersistentKeepalive",
+ option);
+
+ /*
+ * The server listen port, default: 51820
+ */
+ option = vpn_provider_get_string(provider, "WireGuard.EndpointPort");
+ if (option)
+ g_key_file_set_string(keyfile,
+ vpn_provider_get_save_group(provider),
+ "WireGuard.EndpointPort",
+ option);
+
+ /*
+ * Save Address: The internal IP of the client node
+ */
+ option = vpn_provider_get_string(provider, "WireGuard.Address");
+ if (option)
+ g_key_file_set_string(keyfile,
+ vpn_provider_get_save_group(provider),
+ "WireGuard.Address",
+ option);
+
+ return 0;
+}
+#endif
+
static struct vpn_driver vpn_driver = {
.flags = VPN_FLAG_NO_TUN | VPN_FLAG_NO_DAEMON,
.connect = wg_connect,
.disconnect = wg_disconnect,
+#if defined TIZEN_EXT
+ .save = wg_save,
+#endif
};
static int wg_init(void)
struct vpn_config *config, enum what action)
{
struct vpn_config_provider *config_provider;
+#if !defined TIZEN_EXT
const char *ident, *host, *domain;
+#else
+ const char *ident, *host, *domain, *name;
+#endif
int err;
/* Strip off "provider_" prefix */
host = get_string(config_provider, "Host");
domain = get_string(config_provider, "Domain");
+#if !defined TIZEN_EXT
if (host) {
char *id = __vpn_provider_create_identifier(host, domain);
+#else
+ name = get_string(config_provider, "Name");
+ if (host && name) {
+ char *id = __vpn_provider_create_identifier(host, domain, name);
+#endif
struct vpn_provider *provider;
provider = __vpn_provider_lookup(id);
DBG("provider identifier %s", id);
} else {
+#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;
}
<!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>
<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>
g_strfreev(providers);
}
+#if !defined TIZEN_EXT
char *__vpn_provider_create_identifier(const char *host, const char *domain)
{
char *ident;
return ident;
}
+#else
+char *__vpn_provider_create_identifier(const char *host, const char *domain, const char *name)
+{
+ char *ident;
+
+ if (domain)
+ ident = g_strdup_printf("%s_%s_%s", host, domain, name);
+ else
+ ident = g_strdup_printf("%s_%s", host, name);
+ if (!ident)
+ return NULL;
+
+ provider_dbus_ident(ident);
+
+ return ident;
+}
+#endif
int __vpn_provider_create(DBusMessage *msg)
{
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);
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);
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;
void *vpn_provider_get_plugin_data(struct vpn_provider *provider)
{
+#if defined TIZEN_EXT
+ if (!provider)
+ return NULL;
+#endif
return provider->plugin_data;
}
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,