Matt Vogt <matthew.vogt@jollamobile.com>
David Llewellyn-Jones <david.llewellyn-jones@jolla.com>
David Weidenkopf <David.Weidenkopf@Arthrex.com>
+ Maxime Roussin-Bélanger <maxime.roussinbelanger@gmail.com>
+ Holesch, Simon (GED-SDD1) <Simon.Holesch@bshg.com>
+ Christoph Steiger <c.steiger@lemonage.de>
+ Markus Held <mjh42@gmx.de>
+ Sergey Matyukevich <geomatsi@gmail.com>
+ Pieter Cardoen <P.Cardoen@TELEVIC.com>
+ Emmanuel Vautrin <emmanuel.vautrin@cpexterne.org>
+ Boleslaw Tokarski <boleslaw.tokarski@jolla.com>
+ Gabriel FORTE <gforte@wyplay.com>
+ Colin Wee <cwee@tesla.com>
+ Valery Kashcheev <v.kascheev@omp.ru>
+ Alyssa Ross <hi@alyssa.is>
include/inotify.h include/peer.h include/machine.h \
include/acd.h include/tethering.h
+if TIZEN_EXT_WIFI_MESH
+include_HEADERS += include/mesh.h include/mesh-netlink.h
+endif
+
nodist_include_HEADERS = include/version.h
noinst_HEADERS = include/rtnl.h include/task.h \
- include/dbus.h include/option.h \
+ include/dbus.h \
include/provider.h include/vpn-dbus.h \
include/utsname.h include/timeserver.h include/proxy.h \
include/technology.h include/setting.h \
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-agent.h \
++ vpn/vpn-agent.c vpn/vpn-util.c vpn/vpn-agent.h \
+ vpn/vpn-config.c vpn/vpn-settings.c src/acd.c
+
+if TIZEN_EXT_WIFI_MESH
+vpn_connman_vpnd_SOURCES += src/mesh.c src/mesh-netlink.c
+endif
vpn_connman_vpnd_LDADD = gdbus/libgdbus-internal.la $(builtin_vpn_libadd) \
- @GLIB_LIBS@ @DBUS_LIBS@ @GNUTLS_LIBS@ \
+ @DLOG_LIBS@ @GLIB_LIBS@ @DBUS_LIBS@ @GNUTLS_LIBS@ \
+ @LIBSYSTEMD_LIBS@ @XTABLES_LIBS@ \
-lresolv -ldl
+if TIZEN_EXT_WIFI_MESH
+vpn_connman_vpnd_LDADD += @LIBNL_LIBS@ @LIBNL_GENL_LIBS@
+endif
+
vpn_connman_vpnd_LDFLAGS = -Wl,--export-dynamic \
-Wl,--version-script=$(srcdir)/vpn/vpn.ver
endif
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
if OPENCONNECT_BUILTIN
builtin_vpn_modules += openconnect
builtin_vpn_sources += vpn/plugins/openconnect.c
- builtin_vpn_cflags += -DOPENCONNECT=\"@OPENCONNECT@\"
+ builtin_vpn_cflags += -DOPENCONNECT=\"@OPENCONNECT@\" \
+ @LIBOPENCONNECT_CFLAGS@
+ builtin_vpn_libadd += @LIBOPENCONNECT_LIBS@
else
vpn_plugin_LTLIBRARIES += vpn/plugins/openconnect.la
vpn_plugin_objects += $(plugins_openconnect_la_OBJECTS)
vpn_plugins_openconnect_la_CFLAGS = $(plugin_cflags) \
-DOPENCONNECT=\"@OPENCONNECT@\" \
-DVPN_STATEDIR=\""$(vpn_statedir)"\" \
- -DSCRIPTDIR=\""$(build_scriptdir)"\"
+ -DSCRIPTDIR=\""$(build_scriptdir)"\" \
+ @LIBOPENCONNECT_CFLAGS@
vpn_plugins_openconnect_la_LDFLAGS = $(plugin_ldflags)
+ vpn_plugins_openconnect_la_LIBADD = @LIBOPENCONNECT_LIBS@
endif
endif
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
===========
Mailing list:
- connman@connman.net
+ connman@lists.linux.dev
- For additional information about the project visit ConnMan web site:
- https://01.org/connman
- http://www.connman.net
+ If you would like to subscribe to receive mail in your inbox, just
+ send a (empty) message from your email account to
- You can report bugs at https://01.org/jira/browse/CM
+ connman+subscribe@lists.linux.dev
+
+ Mailing list archive:
+ https://lore.kernel.org/connman
AC_PREREQ(2.60)
- AC_INIT(connman, 1.38)
+ AC_INIT(connman, 1.40)
AC_CONFIG_MACRO_DIR([m4])
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
OPENCONNECT="${path_openconnect}"
AC_SUBST(OPENCONNECT)
fi
+ PKG_CHECK_MODULES(LIBOPENCONNECT, openconnect >= 8, [],
+ AC_MSG_ERROR(openconnect >= 8 is required))
fi
AM_CONDITIONAL(OPENCONNECT, test "${enable_openconnect}" != "no")
AM_CONDITIONAL(OPENCONNECT_BUILTIN, test "${enable_openconnect}" = "builtin")
[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)
This list of servers is used when TimeUpdates is set
to auto.
+
+ boolean TimeserverSynced [readonly] [experimental]
+
+ This value indicates if the current system time
+ is synced via NTP servers.
+
+ True when TimeUpdates is set to auto and Time value
+ results from the system time synchronization with a NTP
+ server. Otherwise False.
configured externally via a configuration file.
The only valid operation are Connect(), Disconnect()
- and GetProperties()
+ and GetProperties()
+
+ boolean SplitRouting
+
+ This value reflects the split routing setting on
+ connmand side. By default, this value is omitted and
+ defaults to false. The value needs to be explicitly
+ set to true for VPN to be split routed.
int Index [readonly]
return NULL;
}
- #if defined TIZEN_EXT
- #define SENDER_PREFIX ",sender='%s'"
- #define PATH_PREFIX ",path='%s'"
- #define IFACE_PREFIX ",interface='%s'"
- #define MEMBER_PREFIX ",member='%s'"
- #define ARG0_PREFIX ",arg0='%s'"
-
- static gboolean check_rule_length(int remains, const char *prefix, const char *data)
- {
- if (!prefix || !data)
- return FALSE;
-
- return strlen(prefix) - 2 + strlen(data) < remains;
- }
-
- static void format_rule(struct filter_data *data, char *rule, size_t size)
+ static char *format_rule(struct filter_data *data)
{
+ char *rule, *tmp;
const char *sender;
- int offset;
- offset = snprintf(rule, size, "type='signal'");
+ rule = g_strdup("type='signal'");
sender = data->name ? : data->owner;
- if (sender &&
- check_rule_length(size - offset, SENDER_PREFIX, sender))
- offset += snprintf(rule + offset, size - offset,
- SENDER_PREFIX, sender);
- if (data->path &&
- check_rule_length(size - offset, PATH_PREFIX, data->path))
- offset += snprintf(rule + offset, size - offset,
- PATH_PREFIX, data->path);
- if (data->interface &&
- check_rule_length(size - offset, IFACE_PREFIX, data->interface))
- offset += snprintf(rule + offset, size - offset,
- IFACE_PREFIX, data->interface);
- if (data->member &&
- check_rule_length(size - offset, MEMBER_PREFIX, data->member))
- offset += snprintf(rule + offset, size - offset,
- MEMBER_PREFIX, data->member);
- if (data->argument &&
- check_rule_length(size - offset, ARG0_PREFIX, data->argument))
- snprintf(rule + offset, size - offset,
- ARG0_PREFIX, data->argument);
- }
- #else
- static void format_rule(struct filter_data *data, char *rule, size_t size)
- {
- const char *sender;
- int offset;
+ if (sender) {
+ tmp = rule;
+ rule = g_strdup_printf("%s,sender='%s'", rule, sender);
+ g_free(tmp);
+ }
- offset = snprintf(rule, size, "type='signal'");
- sender = data->name ? : data->owner;
+ if (data->path) {
+ tmp = rule;
+ rule = g_strdup_printf("%s,path='%s'", rule, data->path);
+ g_free(tmp);
+ }
- if (sender)
- offset += snprintf(rule + offset, size - offset,
- ",sender='%s'", sender);
- if (data->path)
- offset += snprintf(rule + offset, size - offset,
- ",path='%s'", data->path);
- if (data->interface)
- offset += snprintf(rule + offset, size - offset,
- ",interface='%s'", data->interface);
- if (data->member)
- offset += snprintf(rule + offset, size - offset,
- ",member='%s'", data->member);
- if (data->argument)
- snprintf(rule + offset, size - offset,
- ",arg0='%s'", data->argument);
+ if (data->interface){
+ tmp = rule;
+ rule = g_strdup_printf("%s,interface='%s'", rule,
+ data->interface);
+ g_free(tmp);
+ }
+
+ if (data->member) {
+ tmp = rule;
+ rule = g_strdup_printf("%s,member='%s'", rule, data->member);
+ g_free(tmp);
+ }
+
+ if (data->argument) {
+ tmp = rule;
+ rule = g_strdup_printf("%s,arg0='%s'", rule, data->argument);
+ g_free(tmp);
+ }
+
+ return rule;
}
- #endif
static gboolean add_match(struct filter_data *data,
DBusHandleMessageFunction filter)
{
DBusError err;
- char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
+ char *rule;
- format_rule(data, rule, sizeof(rule));
+ rule = format_rule(data);
dbus_error_init(&err);
dbus_bus_add_match(data->connection, rule, &err);
error("Adding match rule \"%s\" failed: %s", rule,
err.message);
dbus_error_free(&err);
+ g_free(rule);
return FALSE;
}
data->handle_func = filter;
data->registered = TRUE;
+ g_free(rule);
return TRUE;
}
static gboolean remove_match(struct filter_data *data)
{
DBusError err;
- char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH];
+ char *rule;
- format_rule(data, rule, sizeof(rule));
+ rule = format_rule(data);
dbus_error_init(&err);
error("Removing owner match rule for %s failed: %s",
rule, err.message);
dbus_error_free(&err);
+ g_free(rule);
return FALSE;
}
+ g_free(rule);
return TRUE;
}
#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);
{
GDHCPClient *dhcp_client = user_data;
struct sockaddr_in dst_addr = { 0 };
- struct dhcp_packet packet;
+ struct dhcp_packet packet = { 0 };
struct dhcpv6_packet *packet6 = NULL;
uint8_t *message_type = NULL, *client_id = NULL, *option,
*server_id = NULL;
if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) {
dhcp_client->listener_watch = 0;
+#if defined TIZEN_EXT
+ /* re-register event listener when socket failed */
+ int retry_count = 0;
+ int ret = -1;
+ while (retry_count++ < GIO_SOCKET_RETRY_COUNT && ret < 0)
+ ret = switch_listening_mode(dhcp_client,
+ dhcp_client->type);
+#endif /* defined TIZEN_EXT */
return FALSE;
}
dhcp_client->lease_seconds = get_lease(&packet, pkt_len);
+#if defined TIZEN_EXT
+ dhcp_client->dhcp_lease_seconds = dhcp_client->lease_seconds;
+#endif
+
get_request(dhcp_client, &packet, pkt_len);
switch_listening_mode(dhcp_client, L_NONE);
remove_timeouts(dhcp_client);
+#if defined TIZEN_EXT
+ if (dhcp_client->init_reboot) {
+ g_dhcp_client_set_address_known(dhcp_client, FALSE);
+ dhcp_client->timeout = g_idle_add_full(
+ G_PRIORITY_HIGH,
+ restart_dhcp_timeout,
+ dhcp_client,
+ NULL);
+
+ break;
+ }
+#endif
dhcp_client->timeout = g_timeout_add_seconds_full(
G_PRIORITY_HIGH, 3,
restart_dhcp_timeout,
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
#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 */
{ }
};
regdom->callback(result, regdom->alpha2,
(void *) regdom->user_data);
- dbus_free(regdom);
+ g_free(regdom);
}
static void country_params(DBusMessageIter *iter, void *user_data)
g_free(data->ifname);
g_free(data->driver);
g_free(data->bridge);
+#if defined TIZEN_EXT_WIFI_MESH
+ g_free(data->parent_ifname);
+#endif
dbus_free(data);
}
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);
SUPPLICANT_DBG("");
if (error) {
- g_message("error %s", error);
+ g_warning("error %s", error);
err = -EIO;
goto done;
}
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
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);
int connman_inet_set_ipv6_address(int index,
struct connman_ipaddress *ipaddress);
int connman_inet_clear_ipv6_address(int index,
- const char *address, int prefix_len);
+ struct connman_ipaddress *ipaddress);
int connman_inet_add_ipv6_network_route(int index, const char *host,
const char *gateway, unsigned char prefix_len);
int connman_inet_add_ipv6_host_route(int index, const char *host,
int connman_inet_check_ipaddress(const char *host);
bool connman_inet_check_hostname(const char *ptr, size_t len);
bool connman_inet_is_ipv6_supported();
+ bool connman_inet_is_default_route(int family, const char *host,
+ const char *gateway, const char *netmask);
+
+ int connman_inet_get_route_addresses(int index, char **network, char **netmask,
+ char **destination);
+ int connman_inet_ipv6_get_route_addresses(int index, char **network,
+ char **netmask,
+ char **destination);
+#if defined TIZEN_EXT_WIFI_MESH
+char *connman_inet_ifaddr(const char *name);
+char *connman_inet_ifname2addr(const char *name);
+#endif
+
#ifdef __cplusplus
}
#endif
#ifndef __CONNMAN_IPADDRESS_H
#define __CONNMAN_IPADDRESS_H
+ #include <stdbool.h>
+
#ifdef __cplusplus
extern "C" {
#endif
unsigned char connman_ipaddress_calc_netmask_len(const char *netmask);
struct connman_ipaddress *connman_ipaddress_alloc(int family);
+ void connman_ipaddress_set_p2p(struct connman_ipaddress *ipaddress,
+ bool value);
void connman_ipaddress_free(struct connman_ipaddress *ipaddress);
int connman_ipaddress_set_ipv4(struct connman_ipaddress *ipaddress,
const char *address, const char *netmask,
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,
int connman_network_set_wifi_channel(struct connman_network *network,
uint16_t channel);
uint16_t connman_network_get_wifi_channel(struct connman_network *network);
+ int connman_network_set_autoconnect(struct connman_network *network,
+ bool autoconnect);
int connman_network_set_string(struct connman_network *network,
const char *key, const char *value);
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);
void (*remove) (struct connman_network *network);
int (*connect) (struct connman_network *network);
int (*disconnect) (struct connman_network *network);
+ int (*set_autoconnect) (struct connman_network *network,
+ bool autoconnect);
+#if defined TIZEN_EXT
+ int (*merge) (struct connman_network *network);
+#endif
};
int connman_network_driver_register(struct connman_network_driver *driver);
char * const *nameservers);
void connman_provider_set_autoconnect(struct connman_provider *provider,
bool flag);
+ bool connman_provider_is_split_routing(struct connman_provider *provider);
+ int connman_provider_set_split_routing(struct connman_provider *provider,
+ bool split_routing);
+ int connman_provider_get_family(struct connman_provider *provider);
const char *connman_provider_get_driver_name(struct connman_provider *provider);
const char *connman_provider_get_save_group(struct connman_provider *provider);
#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 {
CONNMAN_SERVICE_CONNECT_REASON_AUTO = 1,
CONNMAN_SERVICE_CONNECT_REASON_USER = 2,
CONNMAN_SERVICE_CONNECT_REASON_SESSION = 3,
+ CONNMAN_SERVICE_CONNECT_REASON_NATIVE = 4,
};
struct connman_service;
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);
- unsigned int connman_setting_get_uint(const char *key);
+#if defined TIZEN_EXT
+int connman_setting_get_int(const char *key);
+#endif
+ unsigned int connman_setting_get_uint(const char *key);
+ char *connman_setting_get_string(const char *key);
char **connman_setting_get_string_list(const char *key);
unsigned int *connman_setting_get_uint_list(const char *key);
--- /dev/null
- Version: 1.38
- Release: 14
+%bcond_with connman_openconnect
+%bcond_without connman_wireguard
+%bcond_without connman_openvpn
+%bcond_without connman_ipsec
+%bcond_without connman_vpnd
+
+Name: connman
++Version: 1.40
++Release: 1
+License: GPL-2.0+
+Summary: Connection Manager
+Url: http://connman.net
+Group: Network & Connectivity/Connection Management
+Source0: %{name}-%{version}.tar.gz
+BuildRequires: systemd-devel
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(dbus-1)
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(gio-2.0)
+BuildRequires: pkgconfig(libiptc)
+BuildRequires: pkgconfig(xtables)
+BuildRequires: pkgconfig(libsmack)
+BuildRequires: pkgconfig(libnl-3.0)
+BuildRequires: pkgconfig(libnl-genl-3.0)
+BuildRequires: pkgconfig(libsystemd)
+%if %{with connman_openconnect}
+BuildRequires: openconnect
+%endif
+%if %{with connman_openvpn}
+BuildRequires: openvpn
+%endif
+%if %{with connman_ipsec}
+BuildRequires: strongswan
+%endif
+BuildRequires: readline-devel
+#%systemd_requires
+Requires: iptables
+Requires: systemd
+Requires(post): systemd
+Requires(preun): systemd
+Requires(postun): systemd
+Requires: security-config
+Provides: %{name}-profile_common = %{version}-%{release}
+Provides: %{name}-profile_mobile = %{version}-%{release}
+Provides: %{name}-profile_wearable = %{version}-%{release}
+Provides: %{name}-profile_robot = %{version}-%{release}
+
+%description
+Connection Manager provides a daemon for managing Internet connections
+within embedded devices running the Linux operating system.
+
+%if %{with connman_openconnect}
+%package plugin-openconnect
+Summary: Openconnect Support for Connman
+Requires: %{name} = %{version}
+Requires: openconnect
+
+%description plugin-openconnect
+Openconnect Support for Connman.
+%endif
+
+%if %{with connman_openvpn}
+%package plugin-openvpn
+Summary: Openvpn Support for Connman
+Requires: %{name} = %{version}
+Requires: openvpn
+
+%description plugin-openvpn
+OpenVPN support for Connman.
+%endif
+
+%if %{with connman_ipsec}
+%package plugin-ipsec
+Summary: IPsec Support for Connman
+Requires: %{name} = %{version}
+Requires: strongswan
+
+%description plugin-ipsec
+OpenVPN support for Connman.
+%endif
+
+%if %{with connman_vpnd}
+%package connman-vpnd
+Summary: VPN Support for Connman
+#BuildRequires: %{name} = %{version}
+Requires: %{name} = %{version}
+
+%description connman-vpnd
+Provides VPN support for Connman
+%endif
+
+%if %{with connman_wireguard}
+%package plugin-wireguard
+Summary: Wireguard Support for Connman
+BuildRequires: pkgconfig(libmnl)
+Requires: %{name} = %{version}
+
+%description plugin-wireguard
+Wireguard Support for Connman.
+%endif
+
+%package test
+Summary: Test Scripts for Connection Manager
+Group: Development/Tools
+Requires: %{name} = %{version}
+Requires: dbus-python
+Requires: pygobject
+Requires: python-xml
+
+%description test
+Scripts for testing Connman and its functionality
+
+%package devel
+Summary: Development files for connman
+Group: Development/Tools
+Requires: %{name} = %{version}
+
+%description devel
+Header files and development files for connman.
+
+%package extension-tv
+Summary: Connman service script for TV profile
+Requires: %{name} = %{version}-%{release}
+Provides: %{name}-profile_tv = %{version}-%{release}
+Conflicts: %{name}-extension-ivi
+Conflicts: %{name}-extension-disable-eth
+%description extension-tv
+Supplies Tizen TV profile systemd service scripts instead of the default one.
+This overwrites service script of %{name}.
+
+%package extension-ivi
+Summary: Connman configuration for IVI profile
+Requires: %{name} = %{version}-%{release}
+Provides: %{name}-profile_ivi = %{version}-%{release}
+Conflicts: %{name}-extension-tv
+Conflicts: %{name}-extension-disable-eth
+%description extension-ivi
+Supplies Tizen IVI profile configuration instead of the default one.
+This overwrites conf file of %{name}.
+
+%package extension-disable-eth
+Summary: Connman configuration for testing which requires the ethernet to be disabled
+Requires: %{name} = %{version}-%{release}
+Conflicts: %{name}-extension-tv
+Conflicts: %{name}-extension-ivi
+%description extension-disable-eth
+Connman without ethernet support
+This overwrites conf file of %{name}.
+
+%package profile_robot
+Summary: connman extension for robot profile
+Requires: %{name} = %{version}-%{release}
+%description profile_robot
+connman extension for Tizen robot profile
+
+%prep
+%setup -q
+
+
+%build
+%if %{with connman_vpnd}
+VPN_CFLAGS+=" -DTIZEN_EXT -lsmack -Werror"
+%endif
+
+chmod +x bootstrap
+./bootstrap
+%configure \
+ --sysconfdir=/etc \
+ --enable-client \
+ --enable-tizen-ext \
+ --disable-tizen-ext-ins \
+ --enable-tizen-ext-eap-on-ethernet \
+ --enable-pacrunner \
+ --enable-wifi=builtin \
+%if %{with connman_openconnect}
+ --enable-openconnect \
+%endif
+%if %{with connman_openvpn}
+ --enable-openvpn \
+%endif
+%if %{with connman_ipsec}
+ --enable-ipsec \
+%endif
+%if %{without connman_wireguard}
+ --disable-wireguard \
+%endif
+%if 0%{?enable_connman_features}
+ %connman_features \
+%endif
+ --disable-ofono \
+ --enable-telephony=builtin \
+ --enable-test \
+ --enable-loopback \
+ --enable-ethernet \
+ --with-systemdunitdir=%{_unitdir} \
+ --enable-pie \
+ --disable-wispr \
+ --disable-backtrace \
+ --disable-tools
+
+make %{?_smp_mflags}
+
+%install
+%make_install
+
+#Systemd service file
+mkdir -p %{buildroot}%{_unitdir}
+
+cp src/connman_tv.service %{buildroot}%{_unitdir}/connman.service.tv
+cp src/connman.service %{buildroot}%{_unitdir}/connman.service
+cp vpn/connman-vpn.service %{buildroot}%{_unitdir}/connman-vpn.service
+
+mkdir -p %{buildroot}%{_unitdir}/multi-user.target.wants
+ln -s ../connman.service %{buildroot}%{_unitdir}/multi-user.target.wants/connman.service
+
+#Systemd socket file for DNS proxy
+cp src/connman.socket %{buildroot}%{_unitdir}/connman.socket
+mkdir -p %{buildroot}%{_unitdir}/sockets.target.wants
+ln -s ../connman.socket %{buildroot}%{_unitdir}/sockets.target.wants/connman.socket
+
+mkdir -p %{buildroot}/%{_localstatedir}/lib/connman
+cp resources/var/lib/connman/settings %{buildroot}/%{_localstatedir}/lib/connman/settings
+mkdir -p %{buildroot}%{_datadir}/dbus-1/system-services
+cp resources/usr/share/dbus-1/system-services/net.connman.service %{buildroot}%{_datadir}/dbus-1/system-services/net.connman.service
+mkdir -p %{buildroot}/etc/connman
+
+cp src/main_ivi.conf %{buildroot}/etc/connman/main.conf.ivi
+cp src/main_tv.conf %{buildroot}/etc/connman/main.conf.tv
+cp src/main_disable_eth.conf %{buildroot}/etc/connman/main.conf.disable.eth
+cp src/main.conf %{buildroot}/etc/connman/main.conf
+
+rm %{buildroot}%{_sysconfdir}/dbus-1/system.d/*.conf
+mkdir -p %{buildroot}%{_sysconfdir}/dbus-1/system.d/
+cp src/connman.conf %{buildroot}%{_sysconfdir}/dbus-1/system.d/
+cp src/connman-robot.conf %{buildroot}%{_sysconfdir}/dbus-1/system.d/
+
+%if %{with connman_vpnd}
+cp vpn/vpn-dbus.conf %{buildroot}%{_sysconfdir}/dbus-1/system.d/connman-vpn-dbus.conf
+%endif
+
+%post
+#chsmack -a 'System' /%{_localstatedir}/lib/connman
+#chsmack -a 'System' /%{_localstatedir}/lib/connman/settings
+
+%preun
+
+%postun
+systemctl daemon-reload
+
+%docs_package
+
+%files
+%manifest connman.manifest
+%attr(500,network_fw,network_fw) %{_bindir}/connmand
+%attr(500,network_fw,network_fw) %{_bindir}/connmanctl
+%attr(600,network_fw,network_fw) /%{_localstatedir}/lib/connman/settings
+%attr(644,root,root) %{_datadir}/dbus-1/system-services/net.connman.service
+%attr(644,root,root) %{_sysconfdir}/dbus-1/system.d/*
+%exclude %{_sysconfdir}/dbus-1/system.d/connman-robot.conf
+%attr(644,network_fw,network_fw) %{_sysconfdir}/connman/main.conf
+%attr(644,root,root) %{_sysconfdir}/dbus-1/system.d/*.conf
+%attr(644,root,root) %{_unitdir}/connman.service
+%attr(644,root,root) %{_unitdir}/multi-user.target.wants/connman.service
+%attr(644,root,root) %{_unitdir}/connman.socket
+%attr(644,root,root) %{_unitdir}/sockets.target.wants/connman.socket
+%license COPYING
+
+%files test
+%manifest connman.manifest
+%{_libdir}/%{name}/test/*
+
+%files devel
+%manifest connman.manifest
+%{_includedir}/*
+%{_libdir}/pkgconfig/*.pc
+
+%if %{with connman_openconnect}
+%files plugin-openconnect
+%manifest %{name}.manifest
+%{_libdir}/connman/plugins-vpn/openconnect.so
+%{_libdir}/connman/scripts/openconnect-script
+%license COPYING
+%endif
+
+%if %{with connman_openvpn}
+%files plugin-openvpn
+%manifest %{name}.manifest
+%{_libdir}/%{name}/plugins-vpn/openvpn.so
+%{_libdir}/%{name}/scripts/openvpn-script
+%license COPYING
+%endif
+
+%if %{with connman_ipsec}
+%files plugin-ipsec
+%manifest %{name}.manifest
+%{_libdir}/%{name}/plugins-vpn/ipsec.so
+%{_libdir}/%{name}/scripts/ipsec-script
+%license COPYING
+%endif
+
+%if %{with connman_vpnd}
+%files connman-vpnd
+%manifest %{name}.manifest
+%{_bindir}/connman-vpnd
+%dir %{_libdir}/%{name}
+%dir %{_libdir}/%{name}/scripts
+%dir %{_libdir}/%{name}/plugins-vpn
+%attr(644,root,root) %config %{_sysconfdir}/dbus-1/system.d/connman-vpn-dbus.conf
+%{_datadir}/dbus-1/system-services/net.connman.vpn.service
+%license COPYING
+%attr(644,root,root) %{_unitdir}/connman-vpn.service
+%endif
+
+%if %{with connman_wireguard}
+%files plugin-wireguard
+%manifest %{name}.manifest
+%{_libdir}/%{name}/plugins-vpn/wireguard.so
+%license COPYING
+%endif
+
+%post extension-tv
+mv -f %{_unitdir}/connman.service.tv %{_unitdir}/connman.service
+mv -f %{_sysconfdir}/connman/main.conf.tv %{_sysconfdir}/connman/main.conf
+
+%files extension-tv
+%attr(644,network_fw,network_fw) %{_sysconfdir}/connman/main.conf.tv
+%license COPYING
+%attr(644,root,root) %{_unitdir}/connman.service.tv
+
+%post extension-ivi
+mv -f %{_sysconfdir}/connman/main.conf.ivi %{_sysconfdir}/connman/main.conf
+
+%files extension-ivi
+%attr(644,network_fw,network_fw) %{_sysconfdir}/connman/main.conf.ivi
+%license COPYING
+
+%post extension-disable-eth
+mv -f %{_sysconfdir}/connman/main.conf.disable.eth %{_sysconfdir}/connman/main.conf
+
+%files extension-disable-eth
+%attr(644,network_fw,network_fw) %{_sysconfdir}/connman/main.conf.disable.eth
+%license COPYING
+
+%post profile_robot
+mv %{_sysconfdir}/dbus-1/system.d/connman-robot.conf %{_sysconfdir}/dbus-1/system.d/connman.conf
+
+%files profile_robot
+%manifest %{name}.manifest
+%attr(644,root,root) %{_sysconfdir}/dbus-1/system.d/connman-robot.conf
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);
const char *method;
bool result;
- DBG("path %s bridge %s", path, bridge);
-
if (!bridge) {
g_free(tethering);
return false;
return false;
}
+ DBG("path %s bridge %s", path, bridge);
+
tethering->technology = technology;
tethering->bridge = g_strdup(bridge);
tethering->enable = enabled;
if (index < 0)
goto out;
- info->address = connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
+ info->address = connman_ipaddress_alloc(AF_INET);
if (!info->address)
goto out;
#include <connman/rtnl.h>
#include <connman/log.h>
#include <connman/setting.h>
- #include <connman/option.h>
+#if defined TIZEN_EXT_WIFI_MESH
+#include <connman/mesh.h>
+#endif
+
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+#include <gsupplicant/gsupplicant.h>
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
static bool eth_tethering = false;
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 */
};
return -errno;
vifr.cmd = GET_VLAN_VID_CMD;
- stpncpy(vifr.device1, ifname, sizeof(vifr.device1));
+ stpncpy(vifr.device1, ifname, sizeof(vifr.device1) - 1);
if(ioctl(sk, SIOCSIFVLAN, &vifr) >= 0)
vid = vifr.u.VID;
return -errno;
memset(&ifr, 0, sizeof(ifr));
- stpncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ stpncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name) - 1);
/* check if it is a vlan and get physical interface name*/
vifr.cmd = GET_VLAN_REALDEV_NAME_CMD;
- stpncpy(vifr.device1, ifname, sizeof(vifr.device1));
+ stpncpy(vifr.device1, ifname, sizeof(vifr.device1) - 1);
- if(ioctl(sk, SIOCSIFVLAN, &vifr) >= 0)
- stpncpy(ifr.ifr_name, vifr.u.device2, sizeof(ifr.ifr_name));
+ if(ioctl(sk, SIOCSIFVLAN, &vifr) >= 0) {
+ stpncpy(ifr.ifr_name, vifr.u.device2, sizeof(ifr.ifr_name) - 1);
+ ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
+ }
/* get driver info */
drvinfocmd.cmd = ETHTOOL_GDRVINFO;
DBG("network %p", network);
}
- DBusMessageIter args;
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+#define NETCONFIG_SERVICE "net.netconfig"
+#define NETCONFIG_ETHERNET_INTERFACE NETCONFIG_SERVICE ".ethernet"
+#define NETCONFIG_ETHERNET_PATH "/net/netconfig/ethernet"
+
+struct eapol_method_call_data {
+ DBusConnection *connection;
+ struct connman_network *network;
+};
+
+static struct eapol_method_call_data enable_eapol_data;
+
+void handle_eap_signal(GSupplicantInterface *interface, bool status)
+{
+ DBG("captured EAP signal");
+
+ if (!enable_eapol_data.network)
+ return;
+
+ if (g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+
+ if (!connman_network_check_validity(enable_eapol_data.network))
+ return;
+
+ DBG("network is valid");
+
+ g_supplicant_unregister_eap_callback();
+
+ if (!status) {
+ // Should we mark service as non favorite or make autoconnect as false?
+
+ struct ethernet_data *ethernet = g_supplicant_interface_get_data(interface);
+ if (ethernet && ethernet->interface) {
+ g_supplicant_interface_remove(ethernet->interface, NULL, NULL);
+ ethernet->interface = NULL;
+ }
+
+ connman_network_set_error(enable_eapol_data.network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
+ enable_eapol_data.network = NULL;
+ return;
+ }
+
+ connman_network_set_connected(enable_eapol_data.network, status);
+ enable_eapol_data.network = NULL;
+}
+
+static void interface_create_callback(int result,
+ GSupplicantInterface *interface, void *user_data)
+{
+ struct ethernet_data *ethernet = user_data;
+
+ if (result < 0 || !interface || !ethernet)
+ return;
+
+ DBG("result %d ifname %s, ethernet %p", result,
+ g_supplicant_interface_get_ifname(interface),
+ ethernet);
+
+ ethernet->interface = interface;
+ g_supplicant_interface_set_data(interface, ethernet);
+}
+
+static int eapol_interface_create(void)
+{
+ struct connman_network *network = enable_eapol_data.network;
+ struct connman_service *service = connman_service_lookup_from_network(network);
+
+ if (!service) {
+ DBG("service not found");
+ return -1;
+ }
+
+ struct connman_device *device = connman_network_get_device(network);
+ struct ethernet_data *ethernet = connman_device_get_data(device);
+ const char *driver = "wired";
+ int index = connman_network_get_index(network);
+ char *ifname = connman_inet_ifname(index);;
+ char *config_file = NULL;
+
+ g_supplicant_register_eap_callback(handle_eap_signal);
+
+ if (asprintf(&config_file, "/var/lib/connman/%s-eapol.conf", ifname) < 0) {
+ g_free(ifname);
+ return -ENOMEM;
+ }
+
+ DBG("config_file %s", config_file);
+
+ g_supplicant_replace_config_file(ifname, config_file);
+ free(config_file);
+
+ /*
+ * TODO: RemoveInterface if already present because
+ * already created interface will not start EAP handshake.
+ */
+ return g_supplicant_interface_create(ifname, driver, NULL,
+ 0, 0, 60, interface_create_callback, ethernet);
+}
+
+static void enable_eapol_reply(DBusPendingCall *call, void *user_data)
+{
+ DBusMessage *reply;
+ DBusError error;
+
+ DBG("");
+
+ reply = dbus_pending_call_steal_reply(call);
+
+ dbus_error_init(&error);
+ if (dbus_set_error_from_message(&error, reply)) {
+ DBG("enable_eapol_request() %s %s", error.name, error.message);
+ dbus_error_free(&error);
+ dbus_message_unref(reply);
+ dbus_pending_call_unref(call);
+ dbus_connection_unref(enable_eapol_data.connection);
+
+ enable_eapol_data.connection = NULL;
+ return;
+ }
+
+ if (eapol_interface_create() < 0)
+ DBG("Failed to create eapol interface");
+}
+
+static int eth_network_enable_eapol(struct connman_service *service, struct connman_network *network)
+{
+ DBusMessage *msg = NULL;
+ DBusPendingCall *call;
+
+ DBusConnection *connection = connman_dbus_get_connection();
+ if (!connection) {
+ DBG("dbus connection does not exist");
+ return -EINVAL;
+ }
+
+ msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_ETHERNET_PATH,
+ NETCONFIG_ETHERNET_INTERFACE, "EnableEap");
+ if (!msg) {
+ dbus_connection_unref(connection);
+ return -EINVAL;
+ }
+
+ const char *path = __connman_service_get_path(service);
+ dbus_bool_t enable = true;
+
+ dbus_message_append_args(msg, DBUS_TYPE_STRING, &path,
+ DBUS_TYPE_INVALID);
+ dbus_message_append_args(msg, DBUS_TYPE_BOOLEAN, &enable,
+ DBUS_TYPE_INVALID);
+
+ if (!dbus_connection_send_with_reply(connection, msg,
+ &call, DBUS_TIMEOUT_USE_DEFAULT)) {
+ dbus_message_unref(msg);
+ dbus_connection_unref(connection);
+ return -EIO;
+ }
+
+ if (!call) {
+ dbus_message_unref(msg);
+ dbus_connection_unref(connection);
+ return -EIO;
+ }
+
+ enable_eapol_data.connection = connection;
+ enable_eapol_data.network = network;
+
+ dbus_pending_call_set_notify(call, enable_eapol_reply, NULL, NULL);
+ dbus_message_unref(msg);
+
+ return 0;
+}
+
+static int eth_network_connect(struct connman_network *network)
+{
+ DBG("network %p", network);
+
+ int err = 0;
+ struct connman_service *service = connman_service_lookup_from_network(network);
+
+ if (service && __connman_service_get_use_eapol(service)) {
+ /** Enable eapol on device reboot **/
+ if (__connman_service_get_connect_reason(service) != CONNMAN_SERVICE_CONNECT_REASON_USER) {
+ err = eth_network_enable_eapol(service, network);
+ if (err < 0) {
+ DBG("Failed to enable eapol");
+ return err;
+ }
+ } else {
+ err = eapol_interface_create();
+ if (err < 0) {
+ DBG("Failed to create eapol interface");
+ return err;
+ }
+
+ return 0;
+ }
+ }
+
+ connman_network_set_connected(network, true);
+
+ return 0;
+}
+
+static int eth_network_disconnect(struct connman_network *network)
+{
+ DBG("network %p", network);
+
+ struct connman_service *service = connman_service_lookup_from_network(network);
+
+ if (service && __connman_service_get_use_eapol(service)) {
+ struct connman_device *device = connman_network_get_device(network);
+ struct ethernet_data *ethernet = connman_device_get_data(device);
+
+ enable_eapol_data.network = NULL;
+ g_supplicant_unregister_eap_callback();
+ if (ethernet && ethernet->interface) {
+ g_supplicant_interface_remove(ethernet->interface, NULL, NULL);
+ ethernet->interface = NULL;
+ }
+ connman_network_set_associating(network, false);
+ connman_network_set_connected(network, false);
+
+ return 0;
+ }
+
+ connman_network_set_connected(network, false);
+
+ return 0;
+}
+
+#else /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
static int eth_network_connect(struct connman_network *network)
{
DBG("network %p", network);
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);
struct iwd_device *iwdd;
struct connman_network *network;
+ /* service's autoconnect */
+ bool autoconnect;
};
struct iwd_known_network {
char *last_connected_time;
bool auto_connect;
int auto_connect_id;
+
+ /* service's autoconnect */
+ bool autoconnect;
};
struct iwd_station {
if (!strcmp(dbus_error, "net.connman.iwd.Failed"))
connman_network_set_error(iwdn->network,
CONNMAN_NETWORK_ERROR_INVALID_KEY);
- else
+ else if (!iwdn->autoconnect)
connman_network_set_error(iwdn->network,
CONNMAN_NETWORK_ERROR_CONNECT_FAIL);
return;
return -EINPROGRESS;
}
+ struct auto_connect_cb_data {
+ char *path;
+ bool auto_connect;
+ };
+
+ static void auto_connect_cb_free(struct auto_connect_cb_data *cbd)
+ {
+ g_free(cbd->path);
+ g_free(cbd);
+ }
+
+ static void auto_connect_cb(const DBusError *error, void *user_data)
+ {
+ struct auto_connect_cb_data *cbd = user_data;
+ struct iwd_known_network *iwdkn;
+
+ iwdkn = g_hash_table_lookup(known_networks, cbd->path);
+ if (!iwdkn)
+ goto out;
+
+ if (dbus_error_is_set(error))
+ connman_warn("WiFi known network %s property auto connect %s",
+ cbd->path, error->message);
+
+ /* property is updated via watch known_network_property_change() */
+ out:
+ auto_connect_cb_free(cbd);
+ }
+
+ static int set_auto_connect(struct iwd_known_network *iwdkn, bool auto_connect)
+ {
+ dbus_bool_t dbus_auto_connect = auto_connect;
+ struct auto_connect_cb_data *cbd;
+
+ if (proxy_get_bool(iwdkn->proxy, "AutoConnect") == auto_connect)
+ return -EALREADY;
+
+ cbd = g_new(struct auto_connect_cb_data, 1);
+ cbd->path = g_strdup(iwdkn->path);
+ cbd->auto_connect = auto_connect;
+
+ if (!g_dbus_proxy_set_property_basic(iwdkn->proxy, "AutoConnect",
+ DBUS_TYPE_BOOLEAN,
+ &dbus_auto_connect,
+ auto_connect_cb, cbd, NULL)) {
+ auto_connect_cb_free(cbd);
+ return -EIO;
+ }
+
+ return -EINPROGRESS;
+ }
+
+ static gboolean disable_auto_connect_cb(gpointer data)
+ {
+ char *path = data;
+ struct iwd_known_network *iwdkn;
+
+ iwdkn = g_hash_table_lookup(known_networks, path);
+ if (!iwdkn)
+ return FALSE;
+
+ if (set_auto_connect(iwdkn, false) != -EINPROGRESS)
+ connman_warn("Failed to disable auto connect");
+
+ iwdkn->auto_connect_id = 0;
+ return FALSE;
+ }
+
+ static int disable_auto_connect(struct iwd_known_network *iwdkn)
+ {
+ if (iwdkn->auto_connect_id)
+ return -EBUSY;
+
+ iwdkn->auto_connect_id = g_timeout_add_full(G_PRIORITY_DEFAULT,
+ 0,
+ disable_auto_connect_cb,
+ g_strdup(iwdkn->path),
+ g_free);
+ return 0;
+ }
+
+ static gboolean enable_auto_connect_cb(gpointer data)
+ {
+ char *path = data;
+ struct iwd_known_network *iwdkn;
+
+ iwdkn = g_hash_table_lookup(known_networks, path);
+ if (!iwdkn)
+ return FALSE;
+
+ if (set_auto_connect(iwdkn, true) != -EINPROGRESS)
+ connman_warn("Failed to enable auto connect");
+
+ iwdkn->auto_connect_id = 0;
+ return FALSE;
+ }
+
+ static int enable_auto_connect(struct iwd_known_network *iwdkn)
+ {
+ if (iwdkn->auto_connect_id)
+ return -EBUSY;
+
+ iwdkn->auto_connect_id = g_timeout_add_full(G_PRIORITY_DEFAULT,
+ 0,
+ enable_auto_connect_cb,
+ g_strdup(iwdkn->path),
+ g_free);
+ return 0;
+ }
+
+ static int update_auto_connect(struct iwd_known_network *iwdkn)
+ {
+ DBG("auto_connect %d autoconnect %d", iwdkn->auto_connect, iwdkn->autoconnect);
+
+ if (iwdkn->auto_connect == iwdkn->autoconnect)
+ return -EALREADY;
+
+ if (iwdkn->autoconnect)
+ return enable_auto_connect(iwdkn);
+ return disable_auto_connect(iwdkn);
+ }
+
+ static int cm_network_set_autoconnect(struct connman_network *network,
+ bool autoconnect)
+ {
+ struct iwd_network *iwdn = connman_network_get_data(network);
+ struct iwd_known_network *iwdkn;
+
+ DBG("autoconnect %d", autoconnect);
+
+ iwdn->autoconnect = autoconnect;
+
+ if (!iwdn->known_network)
+ return -ENOENT;
+
+ iwdkn = g_hash_table_lookup(known_networks, iwdn->known_network);
+ if (!iwdkn)
+ return -ENOENT;
+
+ iwdkn->autoconnect = autoconnect;
+
+ return update_auto_connect(iwdkn);
+ }
+
static struct connman_network_driver network_driver = {
- .name = "iwd",
- .type = CONNMAN_NETWORK_TYPE_WIFI,
- .probe = cm_network_probe,
- .connect = cm_network_connect,
- .disconnect = cm_network_disconnect,
+ .name = "iwd",
+ .type = CONNMAN_NETWORK_TYPE_WIFI,
+ .probe = cm_network_probe,
+ .connect = cm_network_connect,
+ .disconnect = cm_network_disconnect,
+ .set_autoconnect = cm_network_set_autoconnect,
};
static int cm_device_probe(struct connman_device *device)
{
struct tech_cb_data *cbd = user_data;
struct iwd_device *iwdd;
- struct iwd_ap *iwdap;
+ struct iwd_ap *iwdap = NULL;
DBG("");
if (!g_dbus_proxy_method_call(iwdap->proxy, "Stop",
NULL, tech_ap_stop_cb, cbd, NULL)) {
- connman_warn("iwd ap %s could not start AccessPoint mode: %s",
+ connman_warn("iwd ap %s could not stop AccessPoint mode: %s",
cbd->path, error->message);
goto out;
}
DBusMessageIter *iter, void *user_data)
{
struct iwd_network *iwdn;
+ struct iwd_known_network *iwdkn;
const char *path;
path = g_dbus_proxy_get_path(proxy);
update_network_connected(iwdn);
else
update_network_disconnected(iwdn);
+ } else if (!strcmp(name, "KnownNetwork")) {
+ g_free(iwdn->known_network);
+ iwdn->known_network =
+ g_strdup(proxy_get_string(proxy, "KnownNetwork"));
+ if (!iwdn->known_network)
+ return;
+
+ iwdkn = g_hash_table_lookup(known_networks,
+ iwdn->known_network);
+ if (iwdkn)
+ update_auto_connect(iwdkn);
}
}
connman_network_set_strength(iwdn->network,
calculate_strength(signal_strength));
+ connman_network_set_available(iwdn->network, true);
connman_network_update(iwdn->network);
}
static void ordered_networks_cb(DBusMessage *message, void *user_data)
{
DBusMessageIter array, entry;
+ struct iwd_device *iwdd;
+ char *path = user_data;
DBG("");
dbus_message_iter_next(&entry);
}
+
+ iwdd = g_hash_table_lookup(devices, path);
+ if (iwdd)
+ connman_device_set_scanning(iwdd->device,
+ CONNMAN_SERVICE_TYPE_WIFI, false);
}
static void update_signal_strength(struct iwd_station *iwds)
if (!g_dbus_proxy_method_call(iwds->proxy,
"GetOrderedNetworks",
NULL, ordered_networks_cb,
- NULL, NULL))
+ g_strdup(iwds->path), g_free))
DBG("GetOrderedNetworks() failed");
}
DBusMessageIter *iter, void *user_data)
{
struct iwd_station *iwds;
+ struct iwd_device *iwdd;
const char *path;
path = g_dbus_proxy_get_path(proxy);
dbus_message_iter_get_basic(iter, &scanning);
iwds->scanning = scanning;
- if (!iwds->scanning)
+ if (iwds->scanning) {
+ iwdd = g_hash_table_lookup(devices, path);
+ if (iwdd)
+ connman_device_set_scanning(iwdd->device,
+ CONNMAN_SERVICE_TYPE_WIFI, true);
+ } else {
update_signal_strength(iwds);
+ }
+
DBG("%s scanning %d", path, iwds->scanning);
}
add_network(path, iwdn);
}
+struct auto_connect_cb_data {
+ char *path;
+ bool auto_connect;
+};
+
+static void auto_connect_cb_free(struct auto_connect_cb_data *cbd)
+{
+ g_free(cbd->path);
+ g_free(cbd);
+}
+
+static void auto_connect_cb(const DBusError *error, void *user_data)
+{
+ struct auto_connect_cb_data *cbd = user_data;
+ struct iwd_known_network *iwdkn;
+
+ iwdkn = g_hash_table_lookup(known_networks, cbd->path);
+ if (!iwdkn)
+ goto out;
+
+ if (dbus_error_is_set(error))
+ connman_warn("WiFi known network %s property auto connect %s",
+ cbd->path, error->message);
+
+ /* property is updated via watch known_network_property_change() */
+out:
+ auto_connect_cb_free(cbd);
+}
+
+static int set_auto_connect(struct iwd_known_network *iwdkn, bool auto_connect)
+{
+ dbus_bool_t dbus_auto_connect = auto_connect;
+ struct auto_connect_cb_data *cbd;
+
+ if (proxy_get_bool(iwdkn->proxy, "AutoConnect") == auto_connect)
+ return -EALREADY;
+
+ cbd = g_new(struct auto_connect_cb_data, 1);
+ cbd->path = g_strdup(iwdkn->path);
+ cbd->auto_connect = auto_connect;
+
+ if (!g_dbus_proxy_set_property_basic(iwdkn->proxy, "AutoConnect",
+ DBUS_TYPE_BOOLEAN,
+ &dbus_auto_connect,
+ auto_connect_cb, cbd, NULL)) {
+ auto_connect_cb_free(cbd);
+ return -EIO;
+ }
+
+ return -EINPROGRESS;
+}
+
+static gboolean disable_auto_connect_cb(gpointer data)
+{
+ char *path = data;
+ struct iwd_known_network *iwdkn;
+
+ iwdkn = g_hash_table_lookup(known_networks, path);
+ if (!iwdkn)
+ return FALSE;
+
+ if (set_auto_connect(iwdkn, false) != -EINPROGRESS)
+ connman_warn("Failed to disable auto connect");
+
+ iwdkn->auto_connect_id = 0;
+ return FALSE;
+}
+
+static void disable_auto_connect(struct iwd_known_network *iwdkn)
+{
+ if (iwdkn->auto_connect_id)
+ return;
+
+ iwdkn->auto_connect_id = g_timeout_add_full(G_PRIORITY_DEFAULT,
+ 0,
+ disable_auto_connect_cb,
+ g_strdup(iwdkn->path),
+ g_free);
+}
+
static void known_network_property_change(GDBusProxy *proxy, const char *name,
DBusMessageIter *iter, void *user_data)
{
DBG("%p auto_connect %d", path, iwdkn->auto_connect);
- if (iwdkn->auto_connect)
- disable_auto_connect(iwdkn);
+ update_auto_connect(iwdkn);
+ }
+ }
+
+ static void init_auto_connect(struct iwd_known_network *iwdkn)
+ {
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init(&iter, networks);
+
+ while (g_hash_table_iter_next(&iter, &key, &value)) {
+ struct iwd_network *iwdn = value;
+ struct iwd_known_network *kn;
+
+ if (!iwdn->known_network)
+ continue;
+
+ kn = g_hash_table_lookup(known_networks, iwdn->known_network);
+ if (iwdkn != kn)
+ continue;
+
+ iwdkn->autoconnect = iwdn->autoconnect;
+ update_auto_connect(iwdkn);
+ return;
}
}
iwdkn->name, iwdkn->type, iwdkn->hidden,
iwdkn->last_connected_time, iwdkn->auto_connect);
+ init_auto_connect(iwdkn);
+
g_dbus_proxy_set_property_watch(iwdkn->proxy,
known_network_property_change, NULL);
-
- if (iwdkn->auto_connect)
- disable_auto_connect(iwdkn);
}
static void create_station(GDBusProxy *proxy)
#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];
- static void create_hostname(void)
- {
- const char *name = "localhost";
-
- if (sethostname(name, strlen(name)) < 0)
- connman_error("Failed to set hostname to %s", name);
-
- strncpy(system_hostname, name, HOST_NAME_MAX);
- }
-
+#if defined TIZEN_EXT
+static void _create_hostname(void)
+{
+ FILE *fp = NULL;
+#define WIFI_MAC "/opt/etc/.mac.info"
+
+ memset(system_hostname, 0, sizeof(system_hostname));
+
+ char* rv = 0;
+ gchar* dev_id = "TIZEN";
+ char wifi_mac[HOST_NAME_MAX + 1];
+
+ fp = fopen(WIFI_MAC, "r");
+ if(!fp){
+ connman_error("Failed to get current hostname");
+ strncpy(system_hostname, dev_id, strlen(dev_id));
+ return;
+ }
+
+ rv = fgets(wifi_mac, HOST_NAME_MAX, fp);
+ if(!rv){
+ connman_error("Failed to get current hostname");
+ strncpy(system_hostname, dev_id, strlen(dev_id));
+ fclose(fp);
+ return;
+ }
+
+ dev_id = g_base64_encode((const guchar *)wifi_mac, strlen(wifi_mac));
+ g_sprintf(system_hostname, "TIZEN-%s", dev_id);
+ g_free(dev_id);
+ fclose(fp);
+}
++#else
+ static void create_hostname(void)
+ {
+ const char *name = "localhost";
+
+ if (sethostname(name, strlen(name)) < 0)
+ connman_error("Failed to set hostname to %s", name);
+
+ strncpy(system_hostname, name, HOST_NAME_MAX);
+ }
+
+#endif
+
static int setup_hostname(void)
{
char name[HOST_NAME_MAX + 1];
connman_error("Failed to get current hostname");
return -EIO;
}
+
+#if defined TIZEN_EXT
+ if (strlen(system_hostname) > 0 &&
+ strcmp(system_hostname, "(none)") != 0 &&
+ strcmp(system_hostname, "localhost") != 0)
+ connman_info("System hostname is %s", system_hostname);
+ else
+ _create_hostname();
+#else
if (strlen(system_hostname) > 0 &&
strcmp(system_hostname, "(none)") != 0)
connman_info("System hostname is %s", system_hostname);
else
create_hostname();
+#endif
memset(name, 0, sizeof(name));
DBusMessage *reply;
if (!dbus_pending_call_get_completed(pending))
- return;
+ goto out;
register_call = NULL;
if (context->ipv4_method != CONNMAN_IPCONFIG_METHOD_FIXED)
goto out;
- context->ipv4_address = connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4);
+ context->ipv4_address = connman_ipaddress_alloc(AF_INET);
if (!context->ipv4_address) {
context->index = -1;
goto out;
context->ipv6_method = CONNMAN_IPCONFIG_METHOD_AUTO;
context->ipv6_address =
- connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6);
+ connman_ipaddress_alloc(AF_INET6);
if (!context->ipv6_address)
goto out;
char *domain;
char **nameservers;
bool immutable;
+ bool default_route_set;
GHashTable *server_routes;
GHashTable *user_routes;
GResolv *resolv;
guint resolv_id;
+ guint remove_resolv_id;
};
static int set_string(struct connman_provider *provider,
return data->host_ip[0];
} else if (g_str_equal(key, "VPN.Domain"))
return data->domain;
+ else if (g_str_equal(key, "Transport"))
+ return data->service_ident;
return g_hash_table_lookup(data->setting_strings, key);
}
static void cancel_host_resolv(struct connection_data *data)
{
- if (data->resolv_id != 0)
+
+ if (data->remove_resolv_id)
+ g_source_remove(data->remove_resolv_id);
+
+ if (data->resolv && data->resolv_id)
g_resolv_cancel_lookup(data->resolv, data->resolv_id);
data->resolv_id = 0;
+ data->remove_resolv_id = 0;
g_resolv_unref(data->resolv);
data->resolv = NULL;
* We cannot unref the resolver here as resolv struct is manipulated
* by gresolv.c after we return from this callback.
*/
- g_idle_add(remove_resolv, data);
+ data->remove_resolv_id = g_idle_add(remove_resolv, data);
data->resolv_id = 0;
}
static void set_provider_state(struct connection_data *data)
{
enum connman_provider_state state = CONNMAN_PROVIDER_STATE_UNKNOWN;
+ bool connected;
int err = 0;
DBG("provider %p new state %s", data->provider, data->state);
- if (!provider_is_connected(data)) {
- g_free(data->service_ident);
- data->service_ident = NULL;
- }
+ connected = provider_is_connected(data);
if (g_str_equal(data->state, "ready")) {
state = CONNMAN_PROVIDER_STATE_READY;
}
connman_provider_set_state(data->provider, state);
- return;
+ goto free;
set:
if (data->cb_data)
free_config_cb_data(data->cb_data);
data->cb_data = NULL;
+
+ free:
+ if (!connected) {
+ g_free(data->service_ident);
+ data->service_ident = NULL;
+ }
}
static int create_provider(struct connection_data *data, void *user_data)
}
connman_ipaddress_set_peer(data->ip, peer);
+ connman_ipaddress_set_p2p(data->ip, true);
return 0;
}
struct connection_data *data = user_data;
struct config_create_data *cb_data = data->cb_data;
- if (!dbus_pending_call_get_completed(call))
- return;
+ DBG("");
+
+ if (!dbus_pending_call_get_completed(call)) {
+ connman_warn("vpn connect reply pending call incomplete");
+ goto out;
+ }
if (call != data->call) {
connman_error("invalid call %p to VPN connect_reply data %p "
DBUS_DICT_ENTRY_END_CHAR_AS_STRING
DBUS_STRUCT_END_CHAR_AS_STRING;
- if (!dbus_pending_call_get_completed(call))
- return;
-
DBG("");
+ if (!dbus_pending_call_get_completed(call)) {
+ connman_warn("get connections reply pending call incomplete");
+ goto out;
+ }
+
reply = dbus_pending_call_steal_reply(call);
+ if (!reply)
+ goto out;
dbus_error_init(&error);
done:
dbus_message_unref(reply);
+ out:
dbus_pending_call_unref(call);
}
DBusMessage *reply;
DBusError error;
- if (!dbus_pending_call_get_completed(call))
- return;
-
DBG("");
+ if (!dbus_pending_call_get_completed(call)) {
+ connman_warn("remove connection reply pending call incomplete");
+ goto out;
+ }
+
reply = dbus_pending_call_steal_reply(call);
+ if (!reply)
+ goto out;
dbus_error_init(&error);
dbus_message_unref(reply);
+ out:
dbus_pending_call_unref(call);
}
dbus_pending_call_set_notify(data->disconnect_call, disconnect_reply,
data, NULL);
- g_free(data->service_ident);
- data->service_ident = NULL;
+ data->default_route_set = false;
connman_provider_set_state(data->provider,
CONNMAN_PROVIDER_STATE_DISCONNECT);
+
+ g_free(data->service_ident);
+ data->service_ident = NULL;
+
return -EINPROGRESS;
}
struct connection_data *data;
struct config_create_data *cb_data = user_data;
- if (!dbus_pending_call_get_completed(call))
- return;
-
DBG("user %p", cb_data);
+ if (!dbus_pending_call_get_completed(call)) {
+ connman_warn("configuration create reply pending call incomplete");
+ goto out;
+ }
+
reply = dbus_pending_call_steal_reply(call);
+ if (!reply)
+ goto out;
dbus_error_init(&error);
done:
dbus_message_unref(reply);
+ out:
dbus_pending_call_unref(call);
}
return;
}
+ DBG("set route provider %p %s/%s/%s", data->provider,
+ route->network, route->gateway,
+ route->netmask);
+
+ /* Do not add default route for split routed VPNs.*/
+ if (connman_provider_is_split_routing(data->provider) &&
+ connman_inet_is_default_route(route->family,
+ route->network, route->gateway,
+ route->netmask))
+ return;
+
if (route->family == AF_INET6) {
unsigned char prefix_len = atoi(route->netmask);
route->gateway,
route->netmask);
}
+
+ if (connman_inet_is_default_route(route->family, route->network,
+ route->gateway, route->netmask))
+ data->default_route_set = true;
+ }
+
+ static int save_route(GHashTable *routes, int family, const char *network,
+ const char *netmask, const char *gateway);
+
+ static int add_network_route(struct connection_data *data)
+ {
+ struct vpn_route rt = { 0, };
+ int err;
+
+ if (!data)
+ return -EINVAL;
+
+ rt.family = connman_provider_get_family(data->provider);
+ switch (rt.family) {
+ case PF_INET:
+ err = connman_inet_get_route_addresses(data->index,
+ &rt.network, &rt.netmask, &rt.gateway);
+ break;
+ case PF_INET6:
+ err = connman_inet_ipv6_get_route_addresses(data->index,
+ &rt.network, &rt.netmask, &rt.gateway);
+ break;
+ default:
+ connman_error("invalid protocol family %d", rt.family);
+ return -EINVAL;
+ }
+
+ DBG("network %s gateway %s netmask %s for provider %p",
+ rt.network, rt.gateway, rt.netmask,
+ data->provider);
+
+ if (err) {
+ connman_error("cannot get network/gateway/netmask for %p",
+ data->provider);
+ goto out;
+ }
+
+ err = save_route(data->server_routes, rt.family, rt.network, rt.netmask,
+ rt.gateway);
+ if (err) {
+ connman_warn("failed to add network route for provider"
+ "%p", data->provider);
+ goto out;
+ }
+
+ set_route(data, &rt);
+
+ out:
+ g_free(rt.network);
+ g_free(rt.netmask);
+ g_free(rt.gateway);
+
+ return 0;
+ }
+
+ static bool is_valid_route_table(struct connman_provider *provider,
+ GHashTable *table)
+ {
+ GHashTableIter iter;
+ gpointer value, key;
+ struct vpn_route *route;
+ size_t table_size;
+
+ if (!table)
+ return false;
+
+ table_size = g_hash_table_size(table);
+
+ /* Non-split routed may have only the default route */
+ if (table_size > 0 && !connman_provider_is_split_routing(provider))
+ return true;
+
+ /* Split routed has more than the default route */
+ if (table_size > 1)
+ return true;
+
+ /*
+ * Only one route for split routed VPN, which should not be the
+ * default route.
+ */
+ g_hash_table_iter_init(&iter, table);
+ if (!g_hash_table_iter_next(&iter, &key, &value)) /* First and only */
+ return false;
+
+ route = value;
+ if (!route)
+ return false;
+
+ DBG("check route %d %s/%s/%s", route->family, route->network,
+ route->gateway, route->netmask);
+
+ if (!connman_inet_is_default_route(route->family, route->network,
+ route->gateway, route->netmask))
+ return true;
+
+ return false;
+ }
+
+ static bool check_routes(struct connman_provider *provider)
+ {
+ struct connection_data *data;;
+
+ DBG("provider %p", provider);
+
+ data = connman_provider_get_data(provider);
+ if (!data)
+ return false;
+
+ if (is_valid_route_table(provider, data->user_routes))
+ return true;
+
+ if (is_valid_route_table(provider, data->server_routes))
+ return true;
+
+ return false;
}
static int set_routes(struct connman_provider *provider,
set_route(data, value);
}
- return 0;
- }
-
- static bool check_routes(struct connman_provider *provider)
- {
- struct connection_data *data;
-
- DBG("provider %p", provider);
+ /* If non-split routed VPN does not have a default route, add it */
+ if (!connman_provider_is_split_routing(provider) &&
+ !data->default_route_set) {
+ int family = connman_provider_get_family(provider);
+ const char *ipaddr_any = family == AF_INET6 ?
+ "::" : "0.0.0.0";
+ struct vpn_route def_route = {family, (char*) ipaddr_any,
+ (char*) ipaddr_any, NULL};
- data = connman_provider_get_data(provider);
- if (!data)
- return false;
-
- if (data->user_routes &&
- g_hash_table_size(data->user_routes) > 0)
- return true;
+ set_route(data, &def_route);
+ }
- if (data->server_routes &&
- g_hash_table_size(data->server_routes) > 0)
- return true;
+ /* Split routed VPN must have at least one route to the network */
+ if (connman_provider_is_split_routing(provider) &&
+ !check_routes(provider)) {
+ int err = add_network_route(data);
+ if (err) {
+ connman_warn("cannot add network route provider %p",
+ provider);
+ return err;
+ }
+ }
- return false;
+ return 0;
}
static struct connman_provider_driver provider_driver = {
route->gateway = g_strdup(gateway);
g_hash_table_replace(routes, key, route);
- } else
+ } else {
g_free(key);
+ return -EALREADY;
+ }
return 0;
}
+ static void change_provider_split_routing(struct connman_provider *provider,
+ bool split_routing)
+ {
+ struct connection_data *data;
+ int err;
+
+ if (!provider)
+ return;
+
+ if (connman_provider_is_split_routing(provider) == split_routing)
+ return;
+
+ data = connman_provider_get_data(provider);
+ if (split_routing && data && provider_is_connected(data) &&
+ !check_routes(provider)) {
+ err = add_network_route(data);
+ if (err) {
+ connman_warn("cannot add network route provider %p",
+ provider);
+ return;
+ }
+ }
+
+ err = connman_provider_set_split_routing(provider, split_routing);
+ switch (err) {
+ case 0:
+ /* fall through */
+ case -EALREADY:
+ break;
+ case -EINVAL:
+ /* fall through */
+ case -EOPNOTSUPP:
+ connman_warn("cannot change split routing %d", err);
+ default:
+ break;
+ }
+ }
+
static int read_route_dict(GHashTable *routes, DBusMessageIter *dicts)
{
DBusMessageIter dict;
g_free(data->domain);
data->domain = g_strdup(str);
connman_provider_set_domain(data->provider, data->domain);
+ } else if (g_str_equal(key, "SplitRouting")) {
+ dbus_bool_t split_routing;
+ dbus_message_iter_get_basic(&value, &split_routing);
+ change_provider_split_routing(data->provider, split_routing);
}
if (ip_set && err == 0) {
if (!vpn_is_valid_transport(service)) {
connman_provider_disconnect(data->provider);
}
+
+ /* VPN moved to be split routed, default route is not set */
+ if (connman_provider_is_split_routing(data->provider))
+ data->default_route_set = false;
}
}
#include <connman/service.h>
#include <connman/peer.h>
#include <connman/log.h>
- #include <connman/option.h>
#include <connman/storage.h>
#include <include/setting.h>
#include <connman/provision.h>
#define BGSCAN_DEFAULT "simple:30:-65:300"
#define AUTOSCAN_EXPONENTIAL "exponential:3:300"
#define AUTOSCAN_SINGLE "single:3"
+ #define SCAN_MAX_DURATION 10
#define P2P_FIND_TIMEOUT 30
#define P2P_CONNECTION_TIMEOUT 100
#define P2P_LISTEN_PERIOD 500
#define P2P_LISTEN_INTERVAL 2000
+ #define ASSOC_STATUS_AUTH_TIMEOUT 16
#define ASSOC_STATUS_NO_CLIENT 17
+#if defined TIZEN_EXT
+#define LOAD_SHAPING_MAX_RETRIES 7
+#else
#define LOAD_SHAPING_MAX_RETRIES 3
+#endif
+
+#if defined TIZEN_EXT
+#define WIFI_EAP_FAST_PAC_FILE "/var/lib/wifi/wifi.pac" /* path of Pac file for EAP-FAST */
+
+ /* Wi-Fi Signal Strength (for 2.4G (dB))
+ * Excellent : ~ -63
+ * Good : -64 ~ -74
+ * Weak : -75 ~ -82
+ * Very weak : -83 ~ -88
+ * No signal : -89 ~
+ *
+ * Wi-Fi Signal Strength (for 5G (dB))
+ * Excellent : ~ -67
+ * Good : -68 ~ -76
+ * Weak : -77 ~ -82
+ * Very weak : -83 ~ -88
+ * No signal : -89 ~
+ */
+#define RSSI_LEVEL_2_5G -77
+#define RSSI_LEVEL_2_24G -75
+#define RSSI_LEVEL_3_5G -68
+#define RSSI_LEVEL_3_24G -64
+#define WIFI_BSSID_STR_LEN 18
+#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
+#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
+#define ROAM_SCAN_INTERVAL 60 /* 60 seconds */
+#endif
static struct connman_technology *wifi_technology = NULL;
static struct connman_technology *p2p_technology = NULL;
bool p2p_connecting;
bool p2p_device;
int servicing;
+#if defined TIZEN_EXT
+ int assoc_retry_count;
+ struct connman_network *scan_pending_network;
+ bool allow_full_scan;
+ unsigned int automaxspeed_timeout;
+ GSupplicantScanParams *hidden_scan_params;
+ unsigned int mac_policy;
+ unsigned int preassoc_mac_policy;
+ unsigned int mac_lifetime;
+#endif
int disconnect_code;
int assoc_code;
+#if defined TIZEN_EXT_WIFI_MESH
+ bool mesh_interface;
+ struct wifi_mesh_info *mesh_info;
+#endif
};
-
+ struct disconnect_data {
+ struct wifi_data *wifi;
+ struct connman_network *network;
+ };
+
+#if defined TIZEN_EXT
+#include "connman.h"
+#include "dbus.h"
+
+#define TIZEN_ASSOC_RETRY_COUNT 4
+
+static gboolean wifi_first_scan = false;
+static gboolean found_with_first_scan = false;
+static gboolean is_wifi_notifier_registered = false;
+static GHashTable *failed_bssids = NULL;
+static unsigned char buff_bssid[WIFI_BSSID_LEN_MAX] = { 0, };
+#endif
+
static GList *iface_list = NULL;
static GList *pending_wifi_device = NULL;
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;
- params->service = g_memdup(spec, spec_length);
++ if (spec_length > 0) {
++ params->service = g_malloc(spec_length);
++ memcpy(params->service, spec, spec_length);
++ }
+ } else if (query_length > 0 && spec_length > 0) {
- params->query = g_memdup(query, query_length);
++ params->query = g_malloc(query_length);
++ memcpy(params->query, query, query_length);
+ params->query_length = query_length;
+
- params->response = g_memdup(spec, spec_length);
++ params->response = g_malloc(spec_length);
++ memcpy(params->response, spec, spec_length);
+ params->response_length = spec_length;
+ } else {
- params->wfd_ies = g_memdup(spec, spec_length);
++ if (spec_length > 0) {
++ params->wfd_ies = g_malloc(spec_length);
++ memcpy(params->wfd_ies, spec, spec_length);
++ }
+ params->wfd_ies_length = spec_length;
+ }
+
+ return params;
+}
+
+static void free_peer_service_params(GSupplicantP2PServiceParams *params)
+{
+ if (!params)
+ return;
+
+ g_free(params->service);
+ g_free(params->query);
+ g_free(params->response);
+ g_free(params->wfd_ies);
+
+ g_free(params);
+}
+
+static int peer_register_wfd_service(const unsigned char *specification,
+ int specification_length,
+ peer_service_registration_cb_t callback,
+ void *user_data)
+{
+ struct peer_service_registration *reg_data = NULL;
+ static GSupplicantP2PServiceParams *params;
+ int ret;
+
+ DBG("");
+
+ if (wfd_service_registered)
+ return -EBUSY;
+
+ params = fill_in_peer_service_params(specification,
+ specification_length, NULL, 0, 0);
+ if (!params)
+ return -ENOMEM;
+
+ reg_data = g_try_malloc0(sizeof(*reg_data));
+ if (!reg_data) {
+ ret = -ENOMEM;
+ goto error;
+ }
+
+ reg_data->callback = callback;
+ reg_data->user_data = user_data;
+
+ ret = g_supplicant_set_widi_ies(params,
+ register_wfd_service_cb, reg_data);
+ if (ret < 0 && ret != -EINPROGRESS)
+ goto error;
+
+ wfd_service_registered = true;
+
+ return ret;
+error:
+ free_peer_service_params(params);
+ g_free(reg_data);
+
+ return ret;
+}
+
+static void register_peer_service_cb(int result,
+ GSupplicantInterface *iface, void *user_data)
+{
+ struct wifi_data *wifi = g_supplicant_interface_get_data(iface);
+ struct peer_service_registration *reg_data = user_data;
+
+#if defined TIZEN_EXT
+ if (!wifi)
return;
- if (flags & IFF_LOWER_UP) {
+#endif
+
+ DBG("");
+
+ if (result == 0)
+ apply_p2p_listen_on_iface(wifi, NULL);
+
+ if (reg_data->callback)
+ reg_data->callback(result, reg_data->user_data);
+
+ g_free(reg_data);
+}
+
+static int peer_register_service(const unsigned char *specification,
+ int specification_length,
+ const unsigned char *query,
+ int query_length, int version,
+ peer_service_registration_cb_t callback,
+ void *user_data)
+{
+ struct peer_service_registration *reg_data;
+ GSupplicantP2PServiceParams *params;
+ bool found = false;
+ int ret, ret_f;
+ GList *list;
+
+ DBG("");
+
+ if (specification && !version && !query &&
+ is_service_wfd(specification, specification_length)) {
+ return peer_register_wfd_service(specification,
+ specification_length, callback, user_data);
+ }
+
+ reg_data = g_try_malloc0(sizeof(*reg_data));
+ if (!reg_data)
+ return -ENOMEM;
+
+ reg_data->callback = callback;
+ reg_data->user_data = user_data;
+
+ ret_f = -EOPNOTSUPP;
+
+ for (list = iface_list; list; list = list->next) {
+ struct wifi_data *wifi = list->data;
+ GSupplicantInterface *iface = wifi->interface;
+
+ if (!g_supplicant_interface_has_p2p(iface))
+ continue;
+
+ params = fill_in_peer_service_params(specification,
+ specification_length, query,
+ query_length, version);
+ if (!params)
+ continue;
+
+ if (!found) {
+ ret_f = g_supplicant_interface_p2p_add_service(iface,
+ register_peer_service_cb, params, reg_data);
+ if (ret_f == 0 || ret_f == -EINPROGRESS)
+ found = true;
+ ret = ret_f;
+ } else
+ ret = g_supplicant_interface_p2p_add_service(iface,
+ register_peer_service_cb, params, NULL);
+ if (ret != 0 && ret != -EINPROGRESS)
+ free_peer_service_params(params);
+ }
+
+ if (ret_f != 0 && ret_f != -EINPROGRESS)
+ g_free(reg_data);
+
+ return ret_f;
+}
+
+static int peer_unregister_wfd_service(void)
+{
+ GSupplicantP2PServiceParams *params;
+ GList *list;
+
+ if (!wfd_service_registered)
+ return -EALREADY;
+
+ params = fill_in_peer_service_params(NULL, 0, NULL, 0, 0);
+ if (!params)
+ return -ENOMEM;
+
+ wfd_service_registered = false;
+
+ g_supplicant_set_widi_ies(params, NULL, NULL);
+
+ for (list = iface_list; list; list = list->next) {
+ struct wifi_data *wifi = list->data;
+
+ if (!g_supplicant_interface_has_p2p(wifi->interface))
+ continue;
+
+ wifi->servicing--;
+ if (!wifi->servicing || wifi->servicing < 0) {
+ g_supplicant_interface_p2p_listen(wifi->interface,
+ 0, 0);
+ wifi->servicing = 0;
+ }
+ }
+
+ return 0;
+}
+
+static int peer_unregister_service(const unsigned char *specification,
+ int specification_length,
+ const unsigned char *query,
+ int query_length, int version)
+{
+ GSupplicantP2PServiceParams *params;
+ bool wfd = false;
+ GList *list;
+ int ret;
+
+ if (specification && !version && !query &&
+ is_service_wfd(specification, specification_length)) {
+ ret = peer_unregister_wfd_service();
+ if (ret != 0 && ret != -EINPROGRESS)
+ return ret;
+ wfd = true;
+ }
+
+ for (list = iface_list; list; list = list->next) {
+ struct wifi_data *wifi = list->data;
+ GSupplicantInterface *iface = wifi->interface;
+
+ if (wfd)
+ goto stop_listening;
+
+ if (!g_supplicant_interface_has_p2p(iface))
+ continue;
+
+ params = fill_in_peer_service_params(specification,
+ specification_length, query,
+ query_length, version);
+ if (!params)
+ continue;
+
+ ret = g_supplicant_interface_p2p_del_service(iface, params);
+ if (ret != 0 && ret != -EINPROGRESS)
+ free_peer_service_params(params);
+stop_listening:
+ wifi->servicing--;
+ if (!wifi->servicing || wifi->servicing < 0) {
+ g_supplicant_interface_p2p_listen(iface, 0, 0);
+ wifi->servicing = 0;
+ }
+ }
+
+ return 0;
+}
+
+static struct connman_peer_driver peer_driver = {
+ .connect = peer_connect,
+ .disconnect = peer_disconnect,
+ .register_service = peer_register_service,
+ .unregister_service = peer_unregister_service,
+};
+
+static void handle_tethering(struct wifi_data *wifi)
+{
+ if (!wifi->tethering)
+ return;
+
+ if (!wifi->bridge)
+ return;
+
+ if (wifi->bridged)
+ return;
+
+ DBG("index %d bridge %s", wifi->index, wifi->bridge);
+
+ if (connman_inet_add_to_bridge(wifi->index, wifi->bridge) < 0)
+ return;
+
+ wifi->bridged = true;
+}
+
+static void wifi_newlink(unsigned flags, unsigned change, void *user_data)
+{
+ struct connman_device *device = user_data;
+ struct wifi_data *wifi = connman_device_get_data(device);
+
+ if (!wifi)
+ return;
+
+ DBG("index %d flags %d change %d", wifi->index, flags, change);
+
+ if ((wifi->flags & IFF_UP) != (flags & IFF_UP)) {
+ if (flags & IFF_UP)
+ DBG("interface up");
+ else
+ DBG("interface down");
+ }
+
+ if ((wifi->flags & IFF_LOWER_UP) != (flags & IFF_LOWER_UP)) {
-
- handle_tethering(wifi);
- } else
++ if (flags & IFF_LOWER_UP)
+ DBG("carrier on");
++ else
+ DBG("carrier off");
+ }
+
++ if (flags & IFF_LOWER_UP)
++ handle_tethering(wifi);
++
+ wifi->flags = flags;
+}
+
+static int wifi_probe(struct connman_device *device)
+{
+ struct wifi_data *wifi;
+
+ DBG("device %p", device);
+
+ wifi = g_try_new0(struct wifi_data, 1);
+ if (!wifi)
+ return -ENOMEM;
+
+ wifi->state = G_SUPPLICANT_STATE_INACTIVE;
+ wifi->ap_supported = WIFI_AP_UNKNOWN;
+ wifi->tethering_param = NULL;
+
+ connman_device_set_data(device, wifi);
+ wifi->device = connman_device_ref(device);
+
+ wifi->index = connman_device_get_index(device);
+ wifi->flags = 0;
+
+ wifi->watch = connman_rtnl_add_newlink_watch(wifi->index,
+ wifi_newlink, device);
+ if (is_p2p_connecting())
+ add_pending_wifi_device(wifi);
+ else
+ iface_list = g_list_append(iface_list, wifi);
+
+ return 0;
+}
+
+static void remove_networks(struct connman_device *device,
+ struct wifi_data *wifi)
+{
+ GSList *list;
+
+ for (list = wifi->networks; list; list = list->next) {
+ struct connman_network *network = list->data;
+
+ connman_device_remove_network(device, network);
+ connman_network_unref(network);
+ }
+
+ g_slist_free(wifi->networks);
+ wifi->networks = NULL;
+}
+
+static void remove_peers(struct wifi_data *wifi)
+{
+ GSList *list;
+
+ for (list = wifi->peers; list; list = list->next) {
+ struct connman_peer *peer = list->data;
+
+ connman_peer_unregister(peer);
+ connman_peer_unref(peer);
+ }
+
+ g_slist_free(wifi->peers);
+ wifi->peers = NULL;
+}
+
+static void reset_autoscan(struct connman_device *device)
+{
+ struct wifi_data *wifi = connman_device_get_data(device);
+ struct autoscan_params *autoscan;
+
+ DBG("");
+
+ if (!wifi || !wifi->autoscan)
+ return;
+
+ autoscan = wifi->autoscan;
+
+ autoscan->interval = 0;
+
+ if (autoscan->timeout == 0)
+ return;
+
+ g_source_remove(autoscan->timeout);
+ autoscan->timeout = 0;
+
+ connman_device_unref(device);
+}
+
+static void stop_autoscan(struct connman_device *device)
+{
+ const struct wifi_data *wifi = connman_device_get_data(device);
+
+ if (!wifi || !wifi->autoscan)
+ return;
+
+ reset_autoscan(device);
+
+ connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false);
+}
+
+static void check_p2p_technology(void)
+{
+ bool p2p_exists = false;
+ GList *list;
+
+ for (list = iface_list; list; list = list->next) {
+ struct wifi_data *w = list->data;
+
+ if (w->interface &&
+ g_supplicant_interface_has_p2p(w->interface))
+ p2p_exists = true;
+ }
+
+ if (!p2p_exists) {
+ connman_technology_driver_unregister(&p2p_tech_driver);
+ connman_peer_driver_unregister(&peer_driver);
+ }
+}
+
+struct last_connected {
+ GTimeVal modified;
+ gchar *ssid;
+ int freq;
+};
+
+static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+ GTimeVal *aval = (GTimeVal *)a;
+ GTimeVal *bval = (GTimeVal *)b;
+
+ /* Note that the sort order is descending */
+ if (aval->tv_sec < bval->tv_sec)
+ return 1;
+
+ if (aval->tv_sec > bval->tv_sec)
+ return -1;
+
+ return 0;
+}
+
+static void free_entry(gpointer data)
+{
+ struct last_connected *entry = data;
+
+ g_free(entry->ssid);
+ g_free(entry);
+}
+
+static void wifi_remove(struct connman_device *device)
+{
+ struct wifi_data *wifi = connman_device_get_data(device);
+
+ DBG("device %p wifi %p", device, wifi);
+
+ if (!wifi)
+ return;
+
+ stop_autoscan(device);
+
+ if (wifi->p2p_device)
+ p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
+ else
+ iface_list = g_list_remove(iface_list, wifi);
+
+ check_p2p_technology();
+#if defined TIZEN_EXT_WIFI_MESH
+ check_mesh_technology();
+#endif
+
+ remove_pending_wifi_device(wifi);
+
+ if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
+ g_source_remove(wifi->p2p_find_timeout);
+ connman_device_unref(wifi->device);
+ }
+
+ if (wifi->p2p_connection_timeout)
+ g_source_remove(wifi->p2p_connection_timeout);
+
+#if defined TIZEN_EXT
+ if (wifi->automaxspeed_timeout != 0) {
+ g_source_remove(wifi->automaxspeed_timeout);
+ wifi->automaxspeed_timeout = 0;
+ }
+#endif
+
+ remove_networks(device, wifi);
+ remove_peers(wifi);
+
+ connman_device_set_powered(device, false);
+ connman_device_set_data(device, NULL);
+ connman_device_unref(wifi->device);
+ connman_rtnl_remove_watch(wifi->watch);
+
+ g_supplicant_interface_set_data(wifi->interface, NULL);
+
+ g_supplicant_interface_cancel(wifi->interface);
+
+ if (wifi->scan_params)
+ g_supplicant_free_scan_params(wifi->scan_params);
+#if defined TIZEN_EXT
+ if (wifi->hidden_scan_params) {
+ while (wifi->hidden_scan_params->ssids) {
+ struct scan_ssid *ssid;
+ ssid = wifi->hidden_scan_params->ssids->data;
+ wifi->hidden_scan_params->ssids = g_slist_remove(wifi->hidden_scan_params->ssids, ssid);
+ }
+ g_supplicant_free_scan_params(wifi->hidden_scan_params);
+ }
+#endif
+
+ g_free(wifi->autoscan);
+ g_free(wifi->identifier);
+ g_free(wifi);
+}
+
+static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
+{
+ GSList *iter;
+
+ for (iter = list; iter; iter = g_slist_next(iter)) {
+ struct scan_ssid *scan_ssid = iter->data;
+
+ if (ssid_len == scan_ssid->ssid_len &&
+ memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
+ return true;
+ }
+
+ return false;
+}
+
+static int add_scan_param(gchar *hex_ssid, char *raw_ssid, int ssid_len,
+ int freq, GSupplicantScanParams *scan_data,
+ int driver_max_scan_ssids, char *ssid_name)
+{
+ unsigned int i;
+ struct scan_ssid *scan_ssid;
+
+ if ((driver_max_scan_ssids == 0 ||
+ driver_max_scan_ssids > scan_data->num_ssids) &&
+ (hex_ssid || raw_ssid)) {
+ gchar *ssid;
+ unsigned int j = 0, hex;
+
+ if (hex_ssid) {
+ size_t hex_ssid_len = strlen(hex_ssid);
+
+ ssid = g_try_malloc0(hex_ssid_len / 2);
+ if (!ssid)
+ return -ENOMEM;
+
+ for (i = 0; i < hex_ssid_len; i += 2) {
+ sscanf(hex_ssid + i, "%02x", &hex);
+ ssid[j++] = hex;
+ }
+ } else {
+ ssid = raw_ssid;
+ j = ssid_len;
+ }
+
+ /*
+ * If we have already added hidden AP to the list,
+ * then do not do it again. This might happen if you have
+ * used or are using multiple wifi cards, so in that case
+ * you might have multiple service files for same AP.
+ */
+ if (is_duplicate(scan_data->ssids, ssid, j)) {
+ if (hex_ssid)
+ g_free(ssid);
+ return 0;
+ }
+
+ scan_ssid = g_try_new(struct scan_ssid, 1);
+ if (!scan_ssid) {
+ if (hex_ssid)
+ g_free(ssid);
+ return -ENOMEM;
+ }
+
+ memcpy(scan_ssid->ssid, ssid, j);
+ scan_ssid->ssid_len = j;
+ scan_data->ssids = g_slist_prepend(scan_data->ssids,
+ scan_ssid);
+
+ scan_data->num_ssids++;
+
+ DBG("SSID %s added to scanned list of %d entries", ssid_name,
+ scan_data->num_ssids);
+
+ if (hex_ssid)
+ g_free(ssid);
+ } else
+ return -EINVAL;
+
+ scan_data->ssids = g_slist_reverse(scan_data->ssids);
+
+ if (!scan_data->freqs) {
+ scan_data->freqs = g_try_malloc0(sizeof(uint16_t));
+ if (!scan_data->freqs) {
+ g_slist_free_full(scan_data->ssids, g_free);
+ return -ENOMEM;
+ }
+
+ scan_data->num_freqs = 1;
+ scan_data->freqs[0] = freq;
+ } else {
+ bool duplicate = false;
+
+ /* Don't add duplicate entries */
+ for (i = 0; i < scan_data->num_freqs; i++) {
+ if (scan_data->freqs[i] == freq) {
+ duplicate = true;
+ break;
+ }
+ }
+
+ if (!duplicate) {
+ scan_data->num_freqs++;
+ scan_data->freqs = g_try_realloc(scan_data->freqs,
+ sizeof(uint16_t) * scan_data->num_freqs);
+ if (!scan_data->freqs) {
+ g_slist_free_full(scan_data->ssids, g_free);
+ return -ENOMEM;
+ }
+ scan_data->freqs[scan_data->num_freqs - 1] = freq;
+ }
+ }
+
+ return 1;
+}
+
+static int get_hidden_connections(GSupplicantScanParams *scan_data)
+{
+ struct connman_config_entry **entries;
+ GKeyFile *keyfile;
+#if defined TIZEN_EXT
+ gchar **services = NULL;
+#else
+ gchar **services;
+#endif /* defined TIZEN_EXT */
+ char *ssid, *name;
+ int i, ret;
+ bool value;
+ int num_ssids = 0, add_param_failed = 0;
+#if defined TIZEN_EXT
+ GSequenceIter *iter;
+ GSequence *latest_list;
+ struct last_connected *entry;
+ GTimeVal modified;
+
+ latest_list = g_sequence_new(free_entry);
+ if (!latest_list)
+ goto out;
+#endif
+ services = connman_storage_get_services();
+ for (i = 0; services && services[i]; i++) {
+ if (strncmp(services[i], "wifi_", 5) != 0)
+ continue;
+
+ keyfile = connman_storage_load_service(services[i]);
+ if (!keyfile)
+ continue;
+
+ value = g_key_file_get_boolean(keyfile,
+ services[i], "Hidden", NULL);
+ if (!value) {
+ g_key_file_free(keyfile);
+ continue;
+ }
+
+ value = g_key_file_get_boolean(keyfile,
+ services[i], "Favorite", NULL);
+ if (!value) {
+ g_key_file_free(keyfile);
+ continue;
+ }
+
+#if defined TIZEN_EXT
+ value = g_key_file_get_boolean(keyfile,
+ services[i], "AutoConnect", NULL);
+ if (!value) {
+ g_key_file_free(keyfile);
+ continue;
+ }
+
+ gchar *str = g_key_file_get_string(keyfile,
+ services[i], "Modified", NULL);
+ if (!str) {
+ g_key_file_free(keyfile);
+ continue;
+ }
+ g_time_val_from_iso8601(str, &modified);
+ g_free(str);
+#endif
+
+ ssid = g_key_file_get_string(keyfile,
+ services[i], "SSID", NULL);
+
+ name = g_key_file_get_string(keyfile, services[i], "Name",
+ NULL);
+
+#if defined TIZEN_EXT
+ entry = g_try_new(struct last_connected, 1);
+ if (!entry) {
+ g_sequence_free(latest_list);
+ g_free(ssid);
+ g_free(name);
+ g_key_file_free(keyfile);
+ goto out;
+ }
+
+ entry->modified = modified;
+ entry->ssid = ssid;
+
+ g_sequence_insert_sorted(latest_list, entry,
+ sort_entry, NULL);
+#else
+ ret = add_scan_param(ssid, NULL, 0, 0, scan_data, 0, name);
+ if (ret < 0)
+ add_param_failed++;
+ else if (ret > 0)
+ num_ssids++;
+
+ g_free(ssid);
+#endif
+ g_free(name);
+ g_key_file_free(keyfile);
+ }
+
+#if defined TIZEN_EXT
+ gint length = g_sequence_get_length(latest_list);
+ iter = g_sequence_get_begin_iter(latest_list);
+
+ for (i = 0; i < length; i++) {
+ entry = g_sequence_get(iter);
+
+ ret = add_scan_param(entry->ssid, NULL, 0, 0, scan_data, 0, entry->ssid);
+ if (ret < 0)
+ add_param_failed++;
+ else if (ret > 0)
+ num_ssids++;
+
+ iter = g_sequence_iter_next(iter);
+ }
+
+ g_sequence_free(latest_list);
+out:
+#endif
+ /*
+ * Check if there are any hidden AP that needs to be provisioned.
+ */
+ entries = connman_config_get_entries("wifi");
+ for (i = 0; entries && entries[i]; i++) {
+ int len;
+
+ if (!entries[i]->hidden)
+ continue;
+
+ if (!entries[i]->ssid) {
+ ssid = entries[i]->name;
+ len = strlen(ssid);
+ } else {
+ ssid = entries[i]->ssid;
+ len = entries[i]->ssid_len;
+ }
+
+ if (!ssid)
+ continue;
+
+ ret = add_scan_param(NULL, ssid, len, 0, scan_data, 0, ssid);
+ if (ret < 0)
+ add_param_failed++;
+ else if (ret > 0)
+ num_ssids++;
+ }
- stop_autoscan(device);
+ connman_config_free_entries(entries);
- if (wifi->p2p_device)
- p2p_iface_list = g_list_remove(p2p_iface_list, wifi);
- else
- iface_list = g_list_remove(iface_list, wifi);
+ if (add_param_failed > 0)
+ DBG("Unable to scan %d out of %d SSIDs",
+ add_param_failed, num_ssids);
- check_p2p_technology();
+ g_strfreev(services);
- remove_pending_wifi_device(wifi);
+ return num_ssids;
+}
- if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
- g_source_remove(wifi->p2p_find_timeout);
- connman_device_unref(wifi->device);
+static int get_hidden_connections_params(struct wifi_data *wifi,
+ GSupplicantScanParams *scan_params)
+{
+ int driver_max_ssids, i;
+ GSupplicantScanParams *orig_params;
+
+ /*
+ * Scan hidden networks so that we can autoconnect to them.
+ * We will assume 1 as a default number of ssid to scan.
+ */
+ driver_max_ssids = g_supplicant_interface_get_max_scan_ssids(
+ wifi->interface);
+ if (driver_max_ssids == 0)
+ driver_max_ssids = 1;
+
+ DBG("max ssids %d", driver_max_ssids);
+
+#if defined TIZEN_EXT
+ if (!wifi->hidden_scan_params) {
+ wifi->hidden_scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
+ if (!wifi->hidden_scan_params)
+ return 0;
+
+ if (get_hidden_connections(wifi->hidden_scan_params) == 0) {
+ g_supplicant_free_scan_params(wifi->hidden_scan_params);
+ wifi->hidden_scan_params = NULL;
+
+ return 0;
+ }
}
- if (wifi->p2p_connection_timeout)
- g_source_remove(wifi->p2p_connection_timeout);
+ orig_params = wifi->hidden_scan_params;
+#else
+ if (!wifi->scan_params) {
+ wifi->scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
+ if (!wifi->scan_params)
+ return 0;
- remove_networks(device, wifi);
- remove_peers(wifi);
+ if (get_hidden_connections(wifi->scan_params) == 0) {
+ g_supplicant_free_scan_params(wifi->scan_params);
+ wifi->scan_params = NULL;
- connman_device_set_powered(device, false);
- connman_device_set_data(device, NULL);
- connman_device_unref(wifi->device);
- connman_rtnl_remove_watch(wifi->watch);
+ return 0;
+ }
+ }
- g_supplicant_interface_set_data(wifi->interface, NULL);
+ orig_params = wifi->scan_params;
+#endif
- g_supplicant_interface_cancel(wifi->interface);
+ /* Let's transfer driver_max_ssids params */
+ for (i = 0; i < driver_max_ssids; i++) {
+ struct scan_ssid *ssid;
- if (wifi->scan_params)
- g_supplicant_free_scan_params(wifi->scan_params);
+#if defined TIZEN_EXT
+ if (!wifi->hidden_scan_params->ssids)
+#else
+ if (!wifi->scan_params->ssids)
+#endif
+ break;
- g_free(wifi->autoscan);
- g_free(wifi->identifier);
- g_free(wifi);
+ ssid = orig_params->ssids->data;
+ orig_params->ssids = g_slist_remove(orig_params->ssids, ssid);
+ scan_params->ssids = g_slist_prepend(scan_params->ssids, ssid);
+ }
+
+ if (i > 0) {
+ scan_params->num_ssids = i;
+ scan_params->ssids = g_slist_reverse(scan_params->ssids);
+
- scan_params->freqs = g_memdup(orig_params->freqs,
- sizeof(uint16_t) * orig_params->num_freqs);
- if (!scan_params->freqs)
++ if (orig_params->num_freqs <= 0)
+ goto err;
+
++ scan_params->freqs =
++ g_malloc(sizeof(uint16_t) * orig_params->num_freqs);
++ memcpy(scan_params->freqs, orig_params->freqs,
++ sizeof(uint16_t) *orig_params->num_freqs);
++
+ scan_params->num_freqs = orig_params->num_freqs;
+
+ } else
+ goto err;
+
+ orig_params->num_ssids -= scan_params->num_ssids;
+
+ return scan_params->num_ssids;
+
+err:
+ g_slist_free_full(scan_params->ssids, g_free);
+#if defined TIZEN_EXT
+ g_supplicant_free_scan_params(wifi->hidden_scan_params);
+ wifi->hidden_scan_params = NULL;
+#else
+ g_supplicant_free_scan_params(wifi->scan_params);
+ wifi->scan_params = NULL;
+#endif
+
+ return 0;
}
-static bool is_duplicate(GSList *list, gchar *ssid, int ssid_len)
+static int throw_wifi_scan(struct connman_device *device,
+ GSupplicantInterfaceCallback callback)
{
- GSList *iter;
+ struct wifi_data *wifi = connman_device_get_data(device);
+ int ret;
- for (iter = list; iter; iter = g_slist_next(iter)) {
- struct scan_ssid *scan_ssid = iter->data;
+ if (!wifi)
+ return -ENODEV;
- if (ssid_len == scan_ssid->ssid_len &&
- memcmp(ssid, scan_ssid->ssid, ssid_len) == 0)
- return true;
+ DBG("device %p %p", device, wifi->interface);
+
+ if (wifi->tethering)
+ return -EBUSY;
+
+#if defined TIZEN_EXT
+ if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)
+ && !wifi->allow_full_scan)
+#else
+ if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI))
+#endif
+ return -EALREADY;
+
+ connman_device_ref(device);
+
+ ret = g_supplicant_interface_scan(wifi->interface, NULL,
+ callback, device);
+ if (ret == 0) {
+ connman_device_set_scanning(device,
+ CONNMAN_SERVICE_TYPE_WIFI, true);
+ } else
+ connman_device_unref(device);
+
+ return ret;
+}
+
+static void hidden_free(struct hidden_params *hidden)
+{
+ if (!hidden)
+ return;
+
+ if (hidden->scan_params)
+ g_supplicant_free_scan_params(hidden->scan_params);
+ g_free(hidden->identity);
+ g_free(hidden->passphrase);
+ g_free(hidden->security);
+ g_free(hidden);
+}
+
+#if defined TIZEN_EXT
+static void service_state_changed(struct connman_service *service,
+ enum connman_service_state state);
+
+static int network_connect(struct connman_network *network);
+
+static struct connman_notifier notifier = {
+ .name = "wifi",
+ .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
+ .service_state_changed = service_state_changed,
+};
+
+static void service_state_changed(struct connman_service *service,
+ enum connman_service_state state)
+{
+ enum connman_service_type type;
+
+ type = connman_service_get_type(service);
+ if (type != CONNMAN_SERVICE_TYPE_WIFI)
+ return;
+
+ DBG("service %p state %d", service, state);
+
+ switch (state) {
+ case CONNMAN_SERVICE_STATE_READY:
+ case CONNMAN_SERVICE_STATE_ONLINE:
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ connman_notifier_unregister(¬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);
+
- if (scanning) {
- connman_device_set_scanning(device,
- CONNMAN_SERVICE_TYPE_WIFI, false);
++ /*
++ * Set the BSS expiration age to match the long scanning
++ * interval to avoid the loss of unconnected networks between
++ * two scans.
++ */
++ bgscan_range_max = strrchr(BGSCAN_DEFAULT, ':');
++ if (!bgscan_range_max || strlen(bgscan_range_max) < 1)
++ return;
+
++ value = strtol(bgscan_range_max + 1, NULL, 10);
++ if (value <= 0 || errno == ERANGE)
++ return;
++
++ if (g_supplicant_interface_set_bss_expiration_age(interface,
++ value + SCAN_MAX_DURATION) < 0) {
++ connman_warn("Failed to set bss expiration age");
+ }
+}
- if (result != -ENOLINK)
- start_autoscan(device);
+static int wifi_enable(struct connman_device *device)
+{
+ struct wifi_data *wifi = connman_device_get_data(device);
+ int index;
+ char *interface;
- const char *driver = connman_option_get_string("wifi");
++ const char *driver = connman_setting_get_string("wifi");
+ int ret;
- /*
- * If we are here then we were scanning; however, if we are
- * also mid-flight disabling the interface, then wifi_disable
- * has already cleared the device scanning state and
- * unreferenced the device, obviating the need to do it here.
- */
+ DBG("device %p %p", device, wifi);
- if (scanning)
- connman_device_unref(device);
+ index = connman_device_get_index(device);
+ if (!wifi || index < 0)
+ return -ENODEV;
+
+ if (is_p2p_connecting())
+ return -EINPROGRESS;
+
+ interface = connman_inet_ifname(index);
+ ret = g_supplicant_interface_create(interface, driver, NULL,
+#ifdef TIZEN_EXT
+ connman_device_get_mac_policy(device),
+ connman_device_get_preassoc_mac_policy(device),
+ connman_device_get_random_mac_lifetime(device),
+#endif /* TIZEN_EXT */
+ interface_create_callback,
+ wifi);
+ g_free(interface);
+
+ if (ret < 0)
+ return ret;
+
+ return -EINPROGRESS;
}
-static void scan_callback_hidden(int result,
- GSupplicantInterface *interface, void *user_data)
+static int wifi_disable(struct connman_device *device)
{
- struct connman_device *device = user_data;
struct wifi_data *wifi = connman_device_get_data(device);
- GSupplicantScanParams *scan_params;
int ret;
- DBG("result %d wifi %p", result, wifi);
+ DBG("device %p wifi %p", device, wifi);
if (!wifi)
- goto out;
+ return -ENODEV;
- /* User is trying to connect to a hidden AP */
- if (wifi->hidden && wifi->postpone_hidden)
- goto out;
+ wifi->connected = false;
+ wifi->disconnecting = false;
- scan_params = g_try_malloc0(sizeof(GSupplicantScanParams));
- if (!scan_params)
- goto out;
+ if (wifi->pending_network)
+ wifi->pending_network = NULL;
- if (get_hidden_connections_params(wifi, scan_params) > 0) {
- ret = g_supplicant_interface_scan(wifi->interface,
- scan_params,
- scan_callback_hidden,
- device);
- if (ret == 0)
- return;
- }
+#if !defined TIZEN_EXT
+ stop_autoscan(device);
+#endif
- g_supplicant_free_scan_params(scan_params);
+ if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_P2P)) {
+ g_source_remove(wifi->p2p_find_timeout);
+ wifi->p2p_find_timeout = 0;
+ connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_P2P, false);
+ connman_device_unref(wifi->device);
+ }
-out:
- scan_callback(result, interface, user_data);
-}
+#if defined TIZEN_EXT
+ if (wifi->automaxspeed_timeout != 0) {
+ g_source_remove(wifi->automaxspeed_timeout);
+ wifi->automaxspeed_timeout = 0;
+ }
+#endif
-static gboolean autoscan_timeout(gpointer data)
-{
- struct connman_device *device = data;
- struct wifi_data *wifi = connman_device_get_data(device);
- struct autoscan_params *autoscan;
- int interval;
+ /* In case of a user scan, device is still referenced */
+ if (connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_WIFI)) {
+ connman_device_set_scanning(device,
+ CONNMAN_SERVICE_TYPE_WIFI, false);
+ connman_device_unref(wifi->device);
+ }
- if (!wifi)
- return FALSE;
+#if defined TIZEN_EXT
+ stop_autoscan(device);
+#endif
- autoscan = wifi->autoscan;
+ remove_networks(device, wifi);
+ remove_peers(wifi);
- if (autoscan->interval <= 0) {
- interval = autoscan->base;
- goto set_interval;
- } else
- interval = autoscan->interval * autoscan->base;
+#if defined TIZEN_EXT
+ wifi->scan_pending_network = NULL;
- if (interval > autoscan->limit)
- interval = autoscan->limit;
+ if (is_wifi_notifier_registered == true) {
+ connman_notifier_unregister(¬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);
static void disconnect_callback(int result, GSupplicantInterface *interface,
void *user_data)
{
- struct wifi_data *wifi = dd->wifi;
+ struct disconnect_data *dd = user_data;
+ struct connman_network *network = dd->network;
- struct connman_network *network = user_data;
+#if defined TIZEN_EXT
+ GList *list;
+ struct wifi_data *wifi;
+
++ g_free(dd);
+ DBG("network %p result %d", network, result);
+
+ for (list = iface_list; list; list = list->next) {
+ wifi = list->data;
+
+ if (wifi->network == NULL && wifi->disconnecting == true)
+ wifi->disconnecting = false;
+
+ if (wifi->network == network)
+ goto found;
+ }
+
+ /* wifi_data may be invalid because wifi is already disabled */
+ return;
- struct wifi_data *wifi = user_data;
+found:
+#else
++ struct wifi_data *wifi = dd->wifi;
+ g_free(dd);
+#endif
- DBG("result %d supplicant interface %p wifi %p",
- result, interface, wifi);
+ DBG("result %d supplicant interface %p wifi %p networks: current %p "
+ "pending %p disconnected %p", result, interface, wifi,
+ wifi->network, wifi->pending_network, network);
if (result == -ECONNABORTED) {
DBG("wifi interface no longer available");
return;
}
- if (wifi->network && wifi->network != wifi->pending_network)
+#if defined TIZEN_EXT
+ if (wifi->network &&
+ (wifi->network != wifi->pending_network ||
+ connman_network_get_bool(wifi->network, "WiFi.Roaming")))
+#else
- connman_network_set_connected(wifi->network, false);
- wifi->network = NULL;
+ if (g_slist_find(wifi->networks, network))
+#endif
+ connman_network_set_connected(network, false);
wifi->disconnecting = false;
+
+ if (network != wifi->network) {
+ if (network == wifi->pending_network)
+ wifi->pending_network = NULL;
+ DBG("current wifi network has changed since disconnection");
+ return;
+ }
+
+ wifi->network = NULL;
+
wifi->connected = false;
if (wifi->pending_network) {
static int network_disconnect(struct connman_network *network)
{
struct connman_device *device = connman_network_get_device(network);
+ struct disconnect_data *dd;
struct wifi_data *wifi;
int err;
+#if defined TIZEN_EXT
+ struct connman_service *service;
+#endif
DBG("network %p", network);
if (!wifi || !wifi->interface)
return -ENODEV;
+#if defined TIZEN_EXT
+ if (connman_network_get_associating(network) == true) {
+ connman_network_clear_associating(network);
+ connman_network_set_bool(network, "WiFi.UseWPS", false);
+ } else {
+ service = connman_service_lookup_from_network(network);
+
+ if (service != NULL &&
+ (__connman_service_is_connected_state(service,
+ CONNMAN_IPCONFIG_TYPE_IPV4) == false &&
+ __connman_service_is_connected_state(service,
+ CONNMAN_IPCONFIG_TYPE_IPV6) == false) &&
+ (connman_service_get_favorite(service) == false))
+ __connman_service_set_passphrase(service, NULL);
+ }
+
+ if (wifi->pending_network == network)
+ wifi->pending_network = NULL;
+
+ if (wifi->scan_pending_network == network)
+ wifi->scan_pending_network = NULL;
+
+#endif
connman_network_set_associating(network, false);
if (wifi->disconnecting)
wifi->disconnecting = true;
- #if defined TIZEN_EXT
- err = g_supplicant_interface_disconnect(wifi->interface,
- disconnect_callback, network);
- #else
- err = g_supplicant_interface_disconnect(wifi->interface,
- disconnect_callback, wifi);
- #endif
+ dd = g_malloc0(sizeof(*dd));
+ dd->wifi = wifi;
+ dd->network = network;
- if (err < 0)
+ err = g_supplicant_interface_disconnect(wifi->interface,
+ disconnect_callback, dd);
+ if (err < 0) {
wifi->disconnecting = false;
+ g_free(dd);
+ }
return err;
}
+#if defined TIZEN_EXT
+static void set_connection_mode(struct connman_network *network,
+ int linkspeed)
+{
+ ieee80211_modes_e phy_mode;
+ connection_mode_e conn_mode;
+
+ phy_mode = connman_network_get_phy_mode(network);
+ switch (phy_mode) {
+ case IEEE80211_MODE_B:
+ if (linkspeed > 0 && linkspeed <= 11)
+ conn_mode = CONNECTION_MODE_IEEE80211B;
+ else
+ conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
+
+ break;
+ case IEEE80211_MODE_BG:
+ if (linkspeed > 0 && linkspeed <= 11)
+ conn_mode = CONNECTION_MODE_IEEE80211B;
+ else if (linkspeed > 11 && linkspeed <= 54)
+ conn_mode = CONNECTION_MODE_IEEE80211G;
+ else
+ conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
+
+ break;
+ case IEEE80211_MODE_BGN:
+ if (linkspeed > 0 && linkspeed <= 11)
+ conn_mode = CONNECTION_MODE_IEEE80211B;
+ else if (linkspeed > 11 && linkspeed <= 54)
+ conn_mode = CONNECTION_MODE_IEEE80211G;
+ else if (linkspeed > 54 && linkspeed <= 450)
+ conn_mode = CONNECTION_MODE_IEEE80211N;
+ else
+ conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
+
+ break;
+ case IEEE80211_MODE_A:
+ if (linkspeed > 0 && linkspeed <= 54)
+ conn_mode = CONNECTION_MODE_IEEE80211A;
+ else
+ conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
+
+ break;
+ case IEEE80211_MODE_AN:
+ if (linkspeed > 0 && linkspeed <= 54)
+ conn_mode = CONNECTION_MODE_IEEE80211A;
+ else if (linkspeed > 54 && linkspeed <= 450)
+ conn_mode = CONNECTION_MODE_IEEE80211N;
+ else
+ conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
+
+ break;
+ case IEEE80211_MODE_ANAC:
+ if (linkspeed > 0 && linkspeed <= 54)
+ conn_mode = CONNECTION_MODE_IEEE80211A;
+ else if (linkspeed > 54 && linkspeed <= 450)
+ conn_mode = CONNECTION_MODE_IEEE80211N;
+ else if (linkspeed > 450 && linkspeed <= 1300)
+ conn_mode = CONNECTION_MODE_IEEE80211AC;
+ else
+ conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
+
+ break;
+ default:
+ conn_mode = CONNECTION_MODE_IEEE80211_UNKNOWN;
+ break;
+ }
+
+ DBG("connection mode(%d)", conn_mode);
+ connman_network_set_connection_mode(network, conn_mode);
+}
+
+static void signalpoll_callback(int result, int maxspeed, int strength,
+ int snr, void *user_data)
+{
+ char bssid_buff[WIFI_BSSID_STR_LEN] = {0,};
+ char *bssid_str = bssid_buff;
+ unsigned char *bssid;
+ struct timespec curr_time = {0};
+ __time_t roam_scan_time;
+ const char *interface = NULL;
+ struct connman_device *device;
+ struct connman_network *network = user_data;
+ uint16_t freq = connman_network_get_frequency(network);
+
+ if (result != 0) {
+ DBG("Failed to get maxspeed from signalpoll !");
+ connman_network_unref(network);
+ return;
+ }
+
+ strength += 120;
+ if (strength > 100)
+ strength = 100;
+
+ DBG("freq = %u, maxspeed = %d, strength = %d, snr = %d", freq, maxspeed, strength, snr);
+
+ connman_network_set_strength(network, (uint8_t)strength);
+ connman_network_set_snr(network, snr);
+ connman_network_set_maxspeed(network, maxspeed);
+ set_connection_mode(network, maxspeed);
+
+ clock_gettime(CLOCK_MONOTONIC, &curr_time);
+ roam_scan_time = connman_network_get_roam_scan_time(network);
+ if (curr_time.tv_sec <= roam_scan_time + ROAM_SCAN_INTERVAL)
+ goto done;
+
+ if (need_bss_transition(freq, snr, strength)) {
+ device = connman_network_get_device(network);
+ if (!device)
+ goto done;
+
+ interface = connman_device_get_string(device, "Interface");
+ bssid = connman_network_get_bssid(network);
+ snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid));
+ __connman_technology_notify_roaming_state(interface, "required", bssid_str, NULL);
+
+ if (connman_setting_get_bool("WifiRoamingScan") == false)
+ goto done;
+
+ throw_wifi_scan(device, scan_callback);
+ connman_network_set_roam_scan_time(network, curr_time.tv_sec);
+ }
+
+done:
+ connman_network_unref(network);
+}
+
+static int network_signalpoll(struct wifi_data *wifi)
+{
+ GSupplicantInterface *interface;
+ struct connman_network *network;
+
+ if (!wifi || !wifi->network)
+ return -ENODEV;
+
+ wifi->network = connman_network_ref(wifi->network);
+
+ interface = wifi->interface;
+ network = wifi->network;
+
+ DBG("network %p", network);
+
+ return g_supplicant_interface_signalpoll(interface, signalpoll_callback, network);
+}
+
+static gboolean autosignalpoll_timeout(gpointer data)
+{
+ struct wifi_data *wifi = data;
+
+ if (!wifi || !wifi->automaxspeed_timeout) {
+ DBG("automaxspeed_timeout is found to be zero. i.e. currently in disconnected state. !!");
+ return FALSE;
+ }
+
+ int ret = network_signalpoll(wifi);
+ if (ret < 0) {
+ DBG("Fail to get max speed !!");
+ wifi->automaxspeed_timeout = 0;
+
+ if (wifi->network)
+ connman_network_unref(wifi->network);
+
+ return FALSE;
+ }
+
+ return TRUE;
+}
+#endif
+
static struct connman_network_driver network_driver = {
.name = "wifi",
.type = CONNMAN_NETWORK_TYPE_WIFI,
{
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)
if (wps) {
const unsigned char *ssid, *wps_ssid;
unsigned int ssid_len, wps_ssid_len;
+ struct disconnect_data *dd;
const char *wps_key;
/* Checking if we got associated with requested
if (!wps_ssid || wps_ssid_len != ssid_len ||
memcmp(ssid, wps_ssid, ssid_len) != 0) {
+ dd = g_malloc0(sizeof(*dd));
+ dd->wifi = wifi;
+ dd->network = network;
+
connman_network_set_associating(network, false);
- #if defined TIZEN_EXT
g_supplicant_interface_disconnect(wifi->interface,
- disconnect_callback, wifi->network);
-
+ disconnect_callback, dd);
++#if defined TIZEN_EXT
+ connman_network_set_bool(network, "WiFi.UseWPS", false);
+ connman_network_set_string(network, "WiFi.PinWPS", NULL);
- #else
- g_supplicant_interface_disconnect(wifi->interface,
- disconnect_callback, wifi);
+#endif
return false;
}
wps_key = g_supplicant_interface_get_wps_key(interface);
+#if defined TIZEN_EXT
+ /* Check the passphrase and encrypt it
+ */
+ int ret;
+ gchar *passphrase = g_strdup(wps_key);
+
+ connman_network_set_string(network, "WiFi.PinWPS", NULL);
+
+ if (check_passphrase_ext(network, passphrase) < 0) {
+ DBG("[WPS] Invalid passphrase");
+ g_free(passphrase);
+ return true;
+ }
+
+ ret = send_encryption_request(passphrase, network);
+
+ g_free(passphrase);
+
+ if (!ret)
+ DBG("[WPS] Encryption request succeeded");
+ else
+ DBG("[WPS] Encryption request failed %d", ret);
+
+#else
connman_network_set_string(network, "WiFi.Passphrase",
wps_key);
connman_network_set_string(network, "WiFi.PinWPS", NULL);
+#endif
}
return true;
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_network *network,
struct wifi_data *wifi)
{
- #if defined TIZEN_EXT
- const char *security;
struct connman_service *service;
- struct connman_service *service;
-
- if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
++#if defined TIZEN_EXT
++ const char *security;
+ if (wifi->connected)
+ return false;
+
+ security = connman_network_get_string(network, "WiFi.Security");
+
+ if (security && g_str_equal(security, "ieee8021x") == true &&
+ wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
+ wifi->retries = 0;
+ connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
+
+ return false;
+ }
+
+ if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE)
+ return false;
+#else
+ if ((wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE) &&
+ !((wifi->state == G_SUPPLICANT_STATE_ASSOCIATING) &&
+ (wifi->assoc_code == ASSOC_STATUS_AUTH_TIMEOUT)))
return false;
if (wifi->connected)
return false;
+#endif
service = connman_service_lookup_from_network(network);
if (!service)
return false;
}
+#if defined TIZEN_EXT
+static bool handle_wifi_assoc_retry(struct connman_network *network,
+ struct wifi_data *wifi)
+{
+ const char *security;
+
+ if (!wifi->network || wifi->connected || wifi->disconnecting ||
+ connman_network_get_connecting(network) != true) {
+ wifi->assoc_retry_count = 0;
+ return false;
+ }
+
+ if (wifi->state != G_SUPPLICANT_STATE_AUTHENTICATING &&
+ wifi->state != G_SUPPLICANT_STATE_ASSOCIATING &&
+ wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) {
+ wifi->assoc_retry_count = 0;
+ return false;
+ }
+
+ security = connman_network_get_string(network, "WiFi.Security");
+ if (security && g_str_equal(security, "ieee8021x") == true &&
+ wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) {
+ wifi->assoc_retry_count = 0;
+ return false;
+ }
+
+ if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) {
+ wifi->assoc_retry_count = 0;
+
+ /* Honestly it's not an invalid-key error,
+ * however QA team recommends that the invalid-key error
+ * might be better to display for user experience.
+ */
+ switch (wifi->state) {
+ case G_SUPPLICANT_STATE_AUTHENTICATING:
+ connman_network_set_error(network, CONNMAN_NETWORK_ERROR_AUTHENTICATE_FAIL);
+ break;
+ case G_SUPPLICANT_STATE_ASSOCIATED:
+ connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY);
+ break;
+ default:
+ connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL);
+ break;
+ }
+
+ return false;
+ }
+
+ return true;
+}
+#endif
+
static void interface_state(GSupplicantInterface *interface)
{
struct connman_network *network;
struct connman_device *device;
struct wifi_data *wifi;
GSupplicantState state = g_supplicant_interface_get_state(interface);
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Note: If supplicant interface's driver is wired then skip it,
+ * because it meanti only for ethernet not Wi-Fi.
+ */
+ if (!g_strcmp0("wired", g_supplicant_interface_get_driver(interface)))
+ return;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
bool wps;
bool old_connected;
switch (state) {
case G_SUPPLICANT_STATE_SCANNING:
+#if defined TIZEN_EXT
+ if (wifi->automaxspeed_timeout != 0) {
+ g_source_remove(wifi->automaxspeed_timeout);
+ wifi->automaxspeed_timeout = 0;
+ DBG("Remove signalpoll timer!!");
+ }
+#endif
if (wifi->connected)
connman_network_set_connected(network, false);
case G_SUPPLICANT_STATE_AUTHENTICATING:
case G_SUPPLICANT_STATE_ASSOCIATING:
+#if defined TIZEN_EXT
+ reset_autoscan(device);
+#else
stop_autoscan(device);
+#endif
if (!wifi->connected)
connman_network_set_associating(network, true);
break;
case G_SUPPLICANT_STATE_COMPLETED:
+#if defined TIZEN_EXT
+ /* though it should be already reset: */
+ reset_autoscan(device);
+
+ wifi->assoc_retry_count = 0;
+
+ wifi->scan_pending_network = NULL;
+
+ /* should be cleared scanning flag */
+ bool scanning = connman_device_get_scanning(device,
+ CONNMAN_SERVICE_TYPE_WIFI);
+ if (scanning){
+ connman_device_set_scanning(device,
+ CONNMAN_SERVICE_TYPE_WIFI, false);
+ connman_device_unref(device);
+ }
+
+ if (!wifi->automaxspeed_timeout) {
+ DBG("Going to start signalpoll timer!!");
+ int ret = network_signalpoll(wifi);
+ if (ret < 0)
+ DBG("Fail to get max speed !!");
+ else
+ wifi->automaxspeed_timeout = g_timeout_add_seconds(10, autosignalpoll_timeout, wifi);
+ }
+
+ g_hash_table_remove_all(failed_bssids);
+#else
/* though it should be already stopped: */
stop_autoscan(device);
+#endif
if (!handle_wps_completion(interface, network, device, wifi))
break;
break;
case G_SUPPLICANT_STATE_DISCONNECTED:
+#if defined TIZEN_EXT
+ connman_network_set_strength(network, 0);
+ connman_network_set_maxspeed(network, 0);
+
+ if (wifi->automaxspeed_timeout != 0) {
+ g_source_remove(wifi->automaxspeed_timeout);
+ wifi->automaxspeed_timeout = 0;
+ DBG("Remove signalpoll timer!!");
+ }
+#endif
/*
* If we're in one of the idle modes, we have
* not started association yet and thus setting
if (is_idle(wifi))
break;
+#if defined TIZEN_EXT
+ if (handle_assoc_status_code(interface, wifi)) {
+ const char *group = connman_network_get_group(network);
+ GSupplicantNetwork *supplicant_network;
+ GSList *bssid_list = NULL;
+ guint bssid_length = 0;
+
+ if (group) {
+ supplicant_network = g_supplicant_interface_get_network(interface, group);
+
+ connman_network_set_assoc_reject_table(network,
+ g_supplicant_network_get_assoc_reject_table(supplicant_network));
+
+ g_supplicant_network_update_assoc_reject(interface, supplicant_network);
+ }
+
+ bssid_list = (GSList *)connman_network_get_bssid_list(network);
+ if (bssid_list)
+ bssid_length = g_slist_length(bssid_list);
+
+ if (bssid_length > 1 && bssid_length > g_hash_table_size(failed_bssids)) {
+ network_connect(network);
+ break;
+ }
+
+ wifi->load_shaping_retries = 0;
+ }
+
+ g_hash_table_remove_all(failed_bssids);
+#else
if (handle_assoc_status_code(interface, wifi))
break;
+#endif
/* If previous state was 4way-handshake, then
* it's either: psk was incorrect and thus we retry
/* See table 8-36 Reason codes in IEEE Std 802.11 */
switch (wifi->disconnect_code) {
-
++#if defined TIZEN_EXT
+ case 1: /* Unspecified reason */
+ /* Let's assume it's because we got blocked */
++#endif
case 6: /* Class 2 frame received from nonauthenticated STA */
connman_network_set_error(network,
CONNMAN_NETWORK_ERROR_BLOCKED);
break;
}
+#if defined TIZEN_EXT
+ /* Some of Wi-Fi networks are not comply Wi-Fi specification.
+ * Retry association until its retry count is expired */
+ if (handle_wifi_assoc_retry(network, wifi) == true) {
+ throw_wifi_scan(wifi->device, scan_callback);
+ wifi->scan_pending_network = wifi->network;
+ break;
+ }
+
+ if(wifi->disconnect_code > 0){
+ DBG("Set disconnect reason code(%d)", wifi->disconnect_code);
+ connman_network_set_disconnect_reason(network, wifi->disconnect_code);
+ }
+#endif
+
if (network != wifi->pending_network) {
connman_network_set_connected(network, false);
connman_network_set_associating(network, false);
break;
case G_SUPPLICANT_STATE_INACTIVE:
+#if defined TIZEN_EXT
+ if (handle_wps_completion(interface, network, device, wifi) == false)
+ break;
+#endif
connman_network_set_associating(network, false);
start_autoscan(device);
{
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;
void *user_data)
{
struct wifi_tethering_info *info = user_data;
- const char *driver = connman_option_get_string("wifi");
+ const char *driver = connman_setting_get_string("wifi");
DBG("ifname %s result %d ", info->ifname, result);
info->wifi->interface = NULL;
g_supplicant_interface_create(info->ifname, driver, info->wifi->bridge,
+#ifdef TIZEN_EXT
+ 0, 0, 60,
+#endif /* TIZEN_EXT */
ap_create_callback,
info);
}
return g_supplicant_set_country(alpha2, regdom_callback, NULL);
}
- string = connman_option_get_string("INSPreferredFreqBSSID");
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+static void supp_ins_init(void)
+{
+ const char *string;
+ GSupplicantINSPreferredFreq preferred_freq;
+
++ string = connman_setting_get_string("INSPreferredFreqBSSID");
+ if (g_strcmp0(string, "5GHz") == 0)
+ preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_5GHZ;
+ else if (g_strcmp0(string, "2.4GHz") == 0)
+ preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_24GHZ;
+ else
+ preferred_freq = G_SUPPLICANT_INS_PREFERRED_FREQ_UNKNOWN;
+
+ g_supplicant_set_ins_settings(preferred_freq,
+ connman_setting_get_bool("INSLastConnectedBSSID"),
+ connman_setting_get_bool("INSAssocReject"),
+ connman_setting_get_bool("INSSignalBSSID"),
+ connman_setting_get_uint("INSPreferredFreqBSSIDScore"),
+ connman_setting_get_uint("INSLastConnectedBSSIDScore"),
+ connman_setting_get_uint("INSAssocRejectScore"),
+ connman_setting_get_int("INSSignalLevel3_5GHz"),
+ connman_setting_get_int("INSSignalLevel3_24GHz")
+ );
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
static struct connman_technology_driver tech_driver = {
.name = "wifi",
.type = CONNMAN_SERVICE_TYPE_WIFI,
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,
err = __connman_inet_modify_address(RTM_NEWADDR,
NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
- ip_address, NULL, prefix_len, broadcast);
+ ip_address, NULL, prefix_len, broadcast,
+ false);
if (err < 0)
return err;
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)
{
{
DBusMessage *reply;
DBusMessageIter array, dict;
+ dbus_bool_t is_synced;
struct timeval tv;
const char *str;
+#if defined TIZEN_EXT
+ dbus_bool_t val = time_updated;
+#endif
DBG("conn %p", conn);
connman_dbus_dict_open(&array, &dict);
+#if defined TIZEN_EXT
+ connman_dbus_dict_append_basic(&dict, "TimeUpdated",
+ DBUS_TYPE_BOOLEAN,
+ &val);
+#endif
+
if (gettimeofday(&tv, NULL) == 0) {
dbus_uint64_t val = tv.tv_sec;
connman_dbus_dict_append_array(&dict, "Timeservers",
DBUS_TYPE_STRING, append_timeservers, NULL);
+ is_synced = __connman_timeserver_is_synced();
+ connman_dbus_dict_append_basic(&dict, "TimeserverSynced",
+ DBUS_TYPE_BOOLEAN, &is_synced);
+
connman_dbus_dict_close(&array, &dict);
return reply;
type = dbus_message_iter_get_arg_type(&value);
if (g_str_equal(name, "Time")) {
+#if defined TIZEN_EXT
+ /* Tizen updates time (ntp) by system service */
+
+ return __connman_error_permission_denied(msg);
+#else
struct timeval tv;
dbus_uint64_t newval;
if (settimeofday(&tv, NULL) < 0)
return __connman_error_invalid_arguments(msg);
+ __connman_timeserver_set_synced(false);
connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH,
CONNMAN_CLOCK_INTERFACE, "Time",
DBUS_TYPE_UINT64, &newval);
+#endif
} else if (g_str_equal(name, "TimeUpdates")) {
const char *strval;
enum time_updates newval;
connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH,
CONNMAN_CLOCK_INTERFACE, "TimeUpdates",
DBUS_TYPE_STRING, &strval);
+
+ if (newval == TIME_UPDATES_AUTO) {
+ struct connman_service *service;
+
+ service = connman_service_get_default();
+ __connman_timeserver_conf_update(service);
+ }
} else if (g_str_equal(name, "Timezone")) {
const char *strval;
connman_dbus_property_changed_array(CONNMAN_MANAGER_PATH,
CONNMAN_CLOCK_INTERFACE, "Timeservers",
DBUS_TYPE_STRING, append_timeservers, NULL);
+ } else if (g_str_equal(name, "TimeserverSynced")) {
+ return __connman_error_permission_denied(msg);
} else
return __connman_error_invalid_property(msg);
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("");
}
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.
return -1;
}
+ int __connman_connection_get_vpn_phy_index(int vpn_index)
+ {
+ GHashTableIter iter;
+ gpointer value, key;
+
+ g_hash_table_iter_init(&iter, gateway_hash);
+
+ while (g_hash_table_iter_next(&iter, &key, &value)) {
+ struct gateway_data *data = value;
+
+ if (data->index != vpn_index)
+ continue;
+
+ if (data->ipv4_gateway)
+ return data->ipv4_gateway->vpn_phy_index;
+
+ if (data->ipv6_gateway)
+ return data->ipv6_gateway->vpn_phy_index;
+ }
+
+ return -1;
+ }
+
int __connman_connection_init(void)
{
int err;
#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);
#include <connman/backtrace.h>
- #include <connman/option.h>
-
#include <connman/setting.h>
#include <connman/plugin.h>
const char *address,
const char *peer,
unsigned char prefixlen,
- const char *broadcast);
+ const char *broadcast,
+ bool is_p2p);
int __connman_inet_get_interface_address(int index, int family, void *address);
int __connman_inet_get_interface_ll_address(int index, int family, void *address);
int __connman_inet_get_interface_mac_address(int index, uint8_t *mac_address);
__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);
char *peer;
char *broadcast;
char *gateway;
+ bool is_p2p; /* P2P connection or VPN, broadcast is excluded. */
};
struct connman_ipconfig_ops {
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,
GSList *__connman_timeserver_add_list(GSList *server_list,
const char *timeserver);
GSList *__connman_timeserver_get_all(struct connman_service *service);
- int __connman_timeserver_sync(struct connman_service *service);
+ void __connman_timeserver_sync(struct connman_service *service);
+ void __connman_timeserver_conf_update(struct connman_service *service);
+
+ bool __connman_timeserver_is_synced(void);
+ void __connman_timeserver_set_synced(bool status);
enum __connman_dhcpv6_status {
CONNMAN_DHCPV6_STATUS_FAIL = 0,
CONNMAN_DHCPV6_STATUS_RESTART = 2,
};
+#if defined TIZEN_EXT
+void set_dhcp_discover_timeout(int timeout_value);
+void set_dhcp_discover_retry_count(int retry_count);
+#endif
+
typedef void (* dhcpv6_cb) (struct connman_network *network,
enum __connman_dhcpv6_status status, gpointer data);
void __connman_connection_gateway_remove(struct connman_service *service,
enum connman_ipconfig_type type);
int __connman_connection_get_vpn_index(int phy_index);
+ int __connman_connection_get_vpn_phy_index(int vpn_index);
bool __connman_connection_update_gateway(void);
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);
const char *__connman_network_get_group(struct connman_network *network);
const char *__connman_network_get_ident(struct connman_network *network);
bool __connman_network_get_weakness(struct connman_network *network);
+ bool __connman_network_native_autoconnect(struct connman_network *network);
int __connman_config_init();
void __connman_config_cleanup(void);
bool __connman_provider_is_immutable(struct connman_provider *provider);
int __connman_provider_create_and_connect(DBusMessage *msg);
const char * __connman_provider_get_ident(struct connman_provider *provider);
+ const char * __connman_provider_get_transport_ident(
+ struct connman_provider *provider);
int __connman_provider_indicate_state(struct connman_provider *provider,
enum connman_provider_state state);
int __connman_provider_indicate_error(struct connman_provider *provider,
int __connman_service_init(void);
void __connman_service_cleanup(void);
+ int __connman_service_move(struct connman_service *service,
+ struct connman_service *target, bool before);
int __connman_service_load_modifiable(struct connman_service *service);
void __connman_service_list_struct(DBusMessageIter *iter);
+#if defined TIZEN_EXT_INS
+void __connman_ins_list_struct(DBusMessageIter *iter);
+#endif
+
+#if defined TIZEN_EXT
+int connman_service_get_ipv6_dns_method(struct connman_service *service);
+enum connman_dnsconfig_method {
+ CONNMAN_DNSCONFIG_METHOD_UNKNOWN = 0,
+ CONNMAN_DNSCONFIG_METHOD_MANUAL = 1,
+ CONNMAN_DNSCONFIG_METHOD_DHCP = 2,
+};
+#endif
int __connman_service_compare(const struct connman_service *a,
const struct connman_service *b);
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,
void __connman_service_set_string(struct connman_service *service,
const char *key, const char *value);
- int __connman_service_online_check_failed(struct connman_service *service,
- enum connman_ipconfig_type type);
+ void __connman_service_online_check(struct connman_service *service,
+ enum connman_ipconfig_type type,
+ bool success);
int __connman_service_ipconfig_indicate_state(struct connman_service *service,
enum connman_service_state new_state,
enum connman_ipconfig_type type);
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_connect(struct connman_service *service,
enum connman_service_connect_reason reason);
int __connman_service_disconnect(struct connman_service *service);
- int __connman_service_disconnect_all(void);
void __connman_service_set_active_session(bool enable, GSList *list);
void __connman_service_auto_connect(enum connman_service_connect_reason reason);
+
+#if defined TIZEN_EXT
+bool __connman_service_get_auto_connect_mode(void);
+void __connman_service_set_auto_connect_mode(bool enable);
+#endif
+
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+int __connman_service_get_use_eapol(struct connman_service *service);
+int __connman_service_get_connect_reason(struct connman_service *service);
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
bool __connman_service_remove(struct connman_service *service);
bool __connman_service_is_provider_pending(struct connman_service *service);
void __connman_service_set_provider_pending(struct connman_service *service,
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);
+ void __connman_service_set_split_routing(struct connman_service *service,
+ bool split_routing);
+ void __connman_service_split_routing_changed(struct connman_service *service);
int __connman_service_get_index(struct connman_service *service);
void __connman_service_set_hidden(struct connman_service *service);
void __connman_service_set_hostname(struct connman_service *service,
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 */
dbus_message_iter_init_append(signal, &iter);
connman_dbus_property_append_basic(&iter, key, type, val);
- g_dbus_send_message(connection, signal);
-
- return TRUE;
+ return g_dbus_send_message(connection, signal);
}
dbus_bool_t connman_dbus_property_changed_dict(const char *path,
dbus_message_iter_init_append(signal, &iter);
connman_dbus_property_append_dict(&iter, key, function, user_data);
- g_dbus_send_message(connection, signal);
-
- return TRUE;
+ return g_dbus_send_message(connection, signal);
}
dbus_bool_t connman_dbus_property_changed_array(const char *path,
connman_dbus_property_append_array(&iter, key, type,
function, user_data);
- g_dbus_send_message(connection, signal);
-
- return TRUE;
+ return g_dbus_send_message(connection, signal);
}
dbus_bool_t connman_dbus_setting_changed_basic(const char *owner,
connman_dbus_dict_close(&array, &dict);
- g_dbus_send_message(connection, msg);
-
- return TRUE;
+ return g_dbus_send_message(connection, msg);
}
dbus_bool_t connman_dbus_setting_changed_dict(const char *owner,
connman_dbus_dict_close(&array, &dict);
- g_dbus_send_message(connection, msg);
-
- return TRUE;
+ return g_dbus_send_message(connection, msg);
}
dbus_bool_t connman_dbus_setting_changed_array(const char *owner,
connman_dbus_dict_close(&array, &dict);
- g_dbus_send_message(connection, msg);
-
- return TRUE;
+ return g_dbus_send_message(connection, msg);
}
dbus_bool_t __connman_dbus_append_objpath_dict_array(DBusMessage *msg,
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);
- DBusMessage *reply;
-
+#if defined TIZEN_EXT
+ /* Power request timed out, send ETIMEDOUT. */
+ if (device->pending_reply_list) {
+ g_list_foreach(device->pending_reply_list, __device_pending_reset, NULL);
+ g_list_free(device->pending_reply_list);
+ device->pending_reply_list = NULL;
+ }
+#endif
/* Power request timedout, reset power pending state. */
device->pending_timeout = 0;
device->powered_pending = PENDING_NONE;
if (err == -EALREADY) {
/* If device is already powered, but connman is not updated */
connman_device_set_powered(device, true);
+#ifdef TIZEN_EXT
+ if (device->type == CONNMAN_DEVICE_TYPE_WIFI) {
+ device->driver->set_mac_policy(device, device->mac_policy);
+ device->driver->set_preassoc_mac_policy(device, device->preassoc_mac_policy);
+ device->driver->set_random_mac_lifetime(device, device->random_mac_lifetime);
+ }
+#endif /* TIZEN_EXT */
goto done;
}
/*
* if err == -EINPROGRESS, then the DBus call to the respective daemon
- * was successful. We set a 10 sec timeout so if the daemon never
+ * was successful. We set a 4 sec timeout so if the daemon never
* returns a reply, we would reset the pending request.
*/
if (err == -EINPROGRESS)
- device->pending_timeout = g_timeout_add_seconds(10,
+ device->pending_timeout = g_timeout_add_seconds(4,
device_pending_reset, device);
done:
return err;
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);
g_dhcp_client_set_request(dhcp_client, G_DHCP_ROUTER);
g_dhcp_client_set_request(dhcp_client, G_DHCP_SUBNET);
- vendor_class_id = connman_option_get_string("VendorClassID");
+ vendor_class_id = connman_setting_get_string("VendorClassID");
if (vendor_class_id)
g_dhcp_client_set_send(dhcp_client, G_DHCP_VENDOR_CLASS_ID,
vendor_class_id);
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));
}
ref_own_address(user_data);
- if (inet_pton(AF_INET6, address, &addr) < 0) {
+ if (inet_pton(AF_INET6, address, &addr) != 1) {
DBG("Invalid IPv6 address %s %d/%s", address,
-errno, strerror(errno));
goto fail;
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,
char **uncompressed_ptr)
{
char *uptr = *uncompressed_ptr; /* position in result buffer */
+ char * const uncomp_end = uncompressed + uncomp_len - 1;
debug("count %d ptr %p end %p uptr %p", field_count, ptr, end, uptr);
* tmp buffer.
*/
- ulen = strlen(name);
- strncpy(uptr, name, uncomp_len - (uptr - uncompressed));
+ ulen = strlen(name) + 1;
+ if ((uptr + ulen) > uncomp_end)
+ goto out;
+ strncpy(uptr, name, ulen);
debug("pos %d ulen %d left %d name %s", pos, ulen,
- (int)(uncomp_len - (uptr - uncompressed)), uptr);
+ (int)(uncomp_end - (uptr + ulen)), uptr);
uptr += ulen;
- *uptr++ = '\0';
ptr += pos;
* We copy also the fixed portion of the result (type, class,
* ttl, address length and the address)
*/
+ if ((uptr + NS_RRFIXEDSZ) > uncomp_end) {
+ debug("uncompressed data too large for buffer");
+ goto out;
+ }
memcpy(uptr, ptr, NS_RRFIXEDSZ);
dns_type = uptr[0] << 8 | uptr[1];
} else if (dns_type == ns_t_a || dns_type == ns_t_aaaa) {
dlen = uptr[-2] << 8 | uptr[-1];
- if (ptr + dlen > end) {
+ if ((ptr + dlen) > end || (uptr + dlen) > uncomp_end) {
debug("data len %d too long", dlen);
goto out;
}
* refresh interval, retry interval, expiration
* limit and minimum ttl). They are 20 bytes long.
*/
+ if ((uptr + 20) > uncomp_end || (ptr + 20) > end) {
+ debug("soa record too long");
+ goto out;
+ }
memcpy(uptr, ptr, 20);
uptr += 20;
ptr += 20;
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;
}
bool server_enabled = false;
GSList *list;
int index;
+ int vpn_index;
DBG("service %p", service);
if (index < 0)
return;
+ /*
+ * In case non-split-routed VPN is set as split routed the DNS servers
+ * the VPN must be enabled as well, when the transport becomes the
+ * default service.
+ */
+ vpn_index = __connman_connection_get_vpn_index(index);
+
for (list = server_list; list; list = list->next) {
struct server_data *data = list->data;
DBG("Enabling DNS server %s", data->server);
data->enabled = true;
server_enabled = true;
+ } else if (data->index == vpn_index) {
+ DBG("Enabling DNS server of VPN %s", data->server);
+ data->enabled = true;
} else {
DBG("Disabling DNS server %s", data->server);
data->enabled = false;
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;
}
const char *address,
const char *peer,
unsigned char prefixlen,
- const char *broadcast)
+ const char *broadcast,
+ bool is_p2p)
{
uint8_t request[NLMSG_ALIGN(sizeof(struct nlmsghdr)) +
NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
int sk, err;
DBG("cmd %#x flags %#x index %d family %d address %s peer %s "
- "prefixlen %hhu broadcast %s", cmd, flags, index, family,
- address, peer, prefixlen, broadcast);
+ "prefixlen %hhu broadcast %s p2p %s", cmd, flags, index,
+ family, address, peer, prefixlen, broadcast,
+ is_p2p ? "true" : "false");
if (!address)
return -EINVAL;
ifaddrmsg->ifa_index = index;
if (family == AF_INET) {
- if (inet_pton(AF_INET, address, &ipv4_addr) < 1)
+ if (inet_pton(AF_INET, address, &ipv4_addr) != 1)
return -1;
- if (broadcast)
- inet_pton(AF_INET, broadcast, &ipv4_bcast);
- else
- ipv4_bcast.s_addr = ipv4_addr.s_addr |
- htonl(0xfffffffflu >> prefixlen);
-
if (peer) {
- if (inet_pton(AF_INET, peer, &ipv4_dest) < 1)
+ if (inet_pton(AF_INET, peer, &ipv4_dest) != 1)
return -1;
err = __connman_inet_rtnl_addattr_l(header,
if (err < 0)
return err;
- err = __connman_inet_rtnl_addattr_l(header,
- sizeof(request),
- IFA_BROADCAST,
- &ipv4_bcast,
- sizeof(ipv4_bcast));
- if (err < 0)
- return err;
+ /*
+ * Broadcast address must not be added for P2P / VPN as
+ * getifaddrs() cannot interpret destination address.
+ */
+ if (!is_p2p) {
+ if (broadcast)
+ inet_pton(AF_INET, broadcast, &ipv4_bcast);
+ else
+ ipv4_bcast.s_addr = ipv4_addr.s_addr |
+ htonl(0xfffffffflu >> prefixlen);
+ err = __connman_inet_rtnl_addattr_l(header,
+ sizeof(request),
+ IFA_BROADCAST,
+ &ipv4_bcast,
+ sizeof(ipv4_bcast));
+ if (err < 0)
+ return err;
+ }
} else if (family == AF_INET6) {
- if (inet_pton(AF_INET6, address, &ipv6_addr) < 1)
+ if (inet_pton(AF_INET6, address, &ipv6_addr) != 1)
return -1;
err = __connman_inet_rtnl_addattr_l(header,
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;
+ struct sockaddr_in6 *in6;
+
+ switch (family) {
+ case AF_INET:
+ in4 = (struct sockaddr_in*) addr;
+ return in4->sin_addr.s_addr == INADDR_ANY;
+ case AF_INET6:
+ in6 = (struct sockaddr_in6*) addr;
+ return IN6_IS_ADDR_UNSPECIFIED(&in6->sin6_addr);
+ default:
+ return false;
+ }
+ }
+
+ static bool is_addr_ll(int family, struct sockaddr *addr)
+ {
+ struct sockaddr_in *in4;
+ struct sockaddr_in6 *in6;
+
+ switch (family) {
+ case AF_INET:
+ in4 = (struct sockaddr_in*) addr;
+ return (in4->sin_addr.s_addr & IN_CLASSB_NET) ==
+ ((in_addr_t) htonl(0xa9fe0000));
+ case AF_INET6:
+ in6 = (struct sockaddr_in6*) addr;
+ return IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr);
+ default:
+ return false;
+ }
+ }
+
bool __connman_inet_is_any_addr(const char *address, int family)
{
bool ret = false;
struct addrinfo hints;
struct addrinfo *result = NULL;
- struct sockaddr_in6 *in6 = NULL;
- struct sockaddr_in *in4 = NULL;
if (!address || !*address)
goto out;
goto out;
if (result) {
- if (result->ai_family == AF_INET6) {
- in6 = (struct sockaddr_in6*)result->ai_addr;
- ret = IN6_IS_ADDR_UNSPECIFIED(&in6->sin6_addr);
- } else if (result->ai_family == AF_INET) {
- in4 = (struct sockaddr_in*)result->ai_addr;
- ret = in4->sin_addr.s_addr == INADDR_ANY;
- }
-
+ ret = is_addr_unspec(result->ai_family, result->ai_addr);
freeaddrinfo(result);
}
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;
int err;
unsigned char prefix_len;
const char *address;
+ bool is_p2p;
if (!ipaddress->local)
return 0;
prefix_len = ipaddress->prefixlen;
address = ipaddress->local;
+ is_p2p = ipaddress->is_p2p;
DBG("index %d address %s prefix_len %d", index, address, prefix_len);
err = __connman_inet_modify_address(RTM_NEWADDR,
NLM_F_REPLACE | NLM_F_ACK, index, AF_INET6,
- address, NULL, prefix_len, NULL);
+ address, NULL, prefix_len, NULL, is_p2p);
if (err < 0) {
connman_error("%s: %s", __func__, strerror(-err));
return err;
int err;
unsigned char prefix_len;
const char *address, *broadcast, *peer;
+ bool is_p2p;
if (!ipaddress->local)
return -1;
address = ipaddress->local;
broadcast = ipaddress->broadcast;
peer = ipaddress->peer;
+ is_p2p = ipaddress->is_p2p;
DBG("index %d address %s prefix_len %d", index, address, prefix_len);
err = __connman_inet_modify_address(RTM_NEWADDR,
NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
- address, peer, prefix_len, broadcast);
+ address, peer, prefix_len, broadcast, is_p2p);
if (err < 0) {
connman_error("%s: %s", __func__, strerror(-err));
return err;
return 0;
}
- int connman_inet_clear_ipv6_address(int index, const char *address,
- int prefix_len)
+ int connman_inet_clear_ipv6_address(int index,
+ struct connman_ipaddress *ipaddress)
{
int err;
+ int prefix_len;
+ const char *address;
+ bool is_p2p;
+
+ address = ipaddress->local;
+ prefix_len = ipaddress->prefixlen;
+ is_p2p = ipaddress->is_p2p;
DBG("index %d address %s prefix_len %d", index, address, prefix_len);
return -EINVAL;
err = __connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET6,
- address, NULL, prefix_len, NULL);
+ address, NULL, prefix_len, NULL, is_p2p);
if (err < 0) {
connman_error("%s: %s", __func__, strerror(-err));
return err;
int err;
unsigned char prefix_len;
const char *address, *broadcast, *peer;
+ bool is_p2p;
prefix_len = ipaddress->prefixlen;
address = ipaddress->local;
broadcast = ipaddress->broadcast;
peer = ipaddress->peer;
+ is_p2p = ipaddress->is_p2p;
DBG("index %d address %s prefix_len %d peer %s broadcast %s", index,
address, prefix_len, peer, broadcast);
return -EINVAL;
err = __connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET,
- address, peer, prefix_len, broadcast);
+ address, peer, prefix_len, broadcast, is_p2p);
if (err < 0) {
connman_error("%s: %s", __func__, strerror(-err));
return err;
rt.rtmsg_dst_len = prefix_len;
- if (inet_pton(AF_INET6, host, &rt.rtmsg_dst) < 0) {
+ if (inet_pton(AF_INET6, host, &rt.rtmsg_dst) != 1) {
err = -errno;
goto out;
}
rt.rtmsg_dst_len = prefix_len;
- if (inet_pton(AF_INET6, host, &rt.rtmsg_dst) < 0) {
+ if (inet_pton(AF_INET6, host, &rt.rtmsg_dst) != 1) {
err = -errno;
goto out;
}
*/
if (gateway && !__connman_inet_is_any_addr(gateway, AF_INET6) &&
- inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) > 0)
+ inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) == 1)
rt.rtmsg_flags |= RTF_GATEWAY;
rt.rtmsg_metric = 1;
memset(&rt, 0, sizeof(rt));
- if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
+ if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) != 1) {
err = -errno;
goto out;
}
return err;
}
- bool connman_inet_compare_subnet(int index, const char *host)
+ #define ADDR_TYPE_MAX 4
+
+ struct interface_address {
+ int index;
+ int family;
+ bool allow_unspec;
+ /* Applies only to ADDR_TYPE_IPADDR in ipaddrs */
+ bool require_ll;
+ /* Real types must be in_addr for AF_INET and in6_addr for AF_INET6 */
+ void *ipaddrs[ADDR_TYPE_MAX];
+ };
+
+ enum ipaddr_type {
+ ADDR_TYPE_IPADDR = 0,
+ ADDR_TYPE_NETMASK,
+ ADDR_TYPE_BRDADDR,
+ ADDR_TYPE_DSTADDR
+ };
+
+ static int get_interface_addresses(struct interface_address *if_addr)
{
- struct ifreq ifr;
- struct in_addr _host_addr;
- in_addr_t host_addr, netmask_addr, if_addr;
- struct sockaddr_in *netmask, *addr;
- int sk;
+ struct ifaddrs *ifaddr;
+ struct ifaddrs *ifa;
+ struct sockaddr *addrs[ADDR_TYPE_MAX] = { 0 };
+ struct sockaddr_in *addr_in;
+ struct sockaddr_in6 *addr_in6;
+ char name[IF_NAMESIZE] = { 0 };
+ size_t len;
+ int err = -ENOENT;
+ int i;
- DBG("host %s", host);
+ if (!if_addr)
+ return -EINVAL;
- if (!host)
- return false;
+ if (!if_indextoname(if_addr->index, name))
+ return -EINVAL;
- if (inet_aton(host, &_host_addr) == 0)
- return false;
- host_addr = _host_addr.s_addr;
+ DBG("index %d interface %s", if_addr->index, name);
- sk = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
- if (sk < 0)
- return false;
+ if (getifaddrs(&ifaddr) < 0) {
+ connman_error("Cannot get addresses err %d/%s", errno,
+ strerror(errno));
+ return -errno;
+ }
- memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_ifindex = index;
+ for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
+ if (!ifa->ifa_addr)
+ continue;
- if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
- close(sk);
- return false;
+ if (g_strcmp0(ifa->ifa_name, name) ||
+ ifa->ifa_addr->sa_family !=
+ if_addr->family)
+ continue;
+
+
+ if (if_addr->ipaddrs[ADDR_TYPE_IPADDR]) {
+ if (!if_addr->allow_unspec && is_addr_unspec(
+ if_addr->family,
+ ifa->ifa_addr))
+ continue;
+
+ if (if_addr->require_ll && !is_addr_ll(if_addr->family,
+ ifa->ifa_addr))
+ continue;
+
+ addrs[ADDR_TYPE_IPADDR] = ifa->ifa_addr;
+ }
+
+ if (if_addr->ipaddrs[ADDR_TYPE_NETMASK]) {
+ if (!if_addr->allow_unspec && is_addr_unspec(
+ if_addr->family,
+ ifa->ifa_netmask))
+ continue;
+
+ addrs[ADDR_TYPE_NETMASK] = ifa->ifa_netmask;
+ }
+
+ if (if_addr->ipaddrs[ADDR_TYPE_BRDADDR] &&
+ (ifa->ifa_flags & IFF_BROADCAST)) {
+ if (!if_addr->allow_unspec && is_addr_unspec(
+ if_addr->family,
+ ifa->ifa_ifu.ifu_broadaddr))
+ continue;
+
+ addrs[ADDR_TYPE_BRDADDR] = ifa->ifa_ifu.ifu_broadaddr;
+ }
+
+ if (if_addr->ipaddrs[ADDR_TYPE_DSTADDR] &&
+ (ifa->ifa_flags & IFF_POINTOPOINT)) {
+ if (!if_addr->allow_unspec && is_addr_unspec(
+ if_addr->family,
+ ifa->ifa_ifu.ifu_dstaddr))
+ continue;
+
+ addrs[ADDR_TYPE_DSTADDR] = ifa->ifa_ifu.ifu_dstaddr;
+ }
+
+ err = 0;
+
+ break;
}
- if (ioctl(sk, SIOCGIFNETMASK, &ifr) < 0) {
- close(sk);
- return false;
+ if (err)
+ goto out;
+
+ for (i = 0; i < ADDR_TYPE_MAX; i++) {
+ if (!addrs[i])
+ continue;
+
+ switch (if_addr->family) {
+ case AF_INET:
+ len = sizeof(struct in_addr);
+ addr_in = (struct sockaddr_in*) addrs[i];
+ memcpy(if_addr->ipaddrs[i], &addr_in->sin_addr, len);
+ break;
+ case AF_INET6:
+ len = sizeof(struct in6_addr);
+ addr_in6 = (struct sockaddr_in6*) addrs[i];
+ memcpy(if_addr->ipaddrs[i], &addr_in6->sin6_addr, len);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
}
- netmask = (struct sockaddr_in *)&ifr.ifr_netmask;
- netmask_addr = netmask->sin_addr.s_addr;
+ out:
+ freeifaddrs(ifaddr);
+ return err;
+ }
- if (ioctl(sk, SIOCGIFADDR, &ifr) < 0) {
- close(sk);
+ bool connman_inet_compare_subnet(int index, const char *host)
+ {
+ struct interface_address if_addr = { 0 };
+ struct in_addr iaddr = { 0 };
+ struct in_addr imask = { 0 };
+ struct in_addr haddr = { 0 };
+
+ DBG("host %s", host);
+
+ if (!host)
return false;
- }
- close(sk);
+ if (inet_pton(AF_INET, host, &haddr) != 1)
+ return false;
- addr = (struct sockaddr_in *)&ifr.ifr_addr;
- if_addr = addr->sin_addr.s_addr;
+ if_addr.index = index;
+ if_addr.family = AF_INET;
+ if_addr.ipaddrs[ADDR_TYPE_IPADDR] = &iaddr;
+ if_addr.ipaddrs[ADDR_TYPE_NETMASK] = &imask;
- return ((if_addr & netmask_addr) == (host_addr & netmask_addr));
+ if (get_interface_addresses(&if_addr))
+ return false;
+
+ return (iaddr.s_addr & imask.s_addr) == (haddr.s_addr & imask.s_addr);
}
static bool mem_mask_equal(const void *a, const void *b,
bool connman_inet_compare_ipv6_subnet(int index, const char *host)
{
- struct ifaddrs *ifaddr, *ifa;
- bool rv = false;
- char name[IF_NAMESIZE];
- struct in6_addr haddr;
-
- if (inet_pton(AF_INET6, host, &haddr) <= 0)
- return false;
+ struct interface_address addr = { 0 };
+ struct in6_addr iaddr = { 0 };
+ struct in6_addr imask = { 0 };
+ struct in6_addr haddr = { 0 };
- if (!if_indextoname(index, name))
+ if (inet_pton(AF_INET6, host, &haddr) != 1)
return false;
- DBG("index %d interface %s", index, name);
+ addr.index = index;
+ addr.family = AF_INET6;
+ addr.ipaddrs[ADDR_TYPE_IPADDR] = &iaddr;
+ addr.ipaddrs[ADDR_TYPE_NETMASK] = &imask;
- if (getifaddrs(&ifaddr) < 0) {
- DBG("Cannot get addresses err %d/%s", errno, strerror(errno));
+ if (get_interface_addresses(&addr))
return false;
- }
-
- for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
- struct sockaddr_in6 *iaddr;
- struct sockaddr_in6 *imask;
-
- if (!ifa->ifa_addr)
- continue;
-
- if (strncmp(ifa->ifa_name, name, IF_NAMESIZE) != 0 ||
- ifa->ifa_addr->sa_family != AF_INET6)
- continue;
-
- iaddr = (struct sockaddr_in6 *)ifa->ifa_addr;
- imask = (struct sockaddr_in6 *)ifa->ifa_netmask;
-
- rv = mem_mask_equal(&iaddr->sin6_addr, &haddr,
- &imask->sin6_addr,
- sizeof(haddr));
- goto out;
- }
- out:
- freeifaddrs(ifaddr);
- return rv;
+ return mem_mask_equal(&iaddr, &haddr, &imask, sizeof(haddr));
}
int connman_inet_remove_from_bridge(int index, const char *bridge)
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;
return prefixes;
}
- static int get_dest_addr(int family, int index, char *buf, int len)
+ int connman_inet_get_dest_addr(int index, char **dest)
{
- struct ifreq ifr;
- void *addr;
- int sk;
+ struct interface_address if_addr = { 0 };
+ struct in_addr dstaddr = { 0 };
+ char buf[INET_ADDRSTRLEN] = { 0 };
+ int err;
- sk = socket(family, SOCK_DGRAM | SOCK_CLOEXEC, 0);
- if (sk < 0)
- return -errno;
+ if (!dest)
+ return -EINVAL;
- memset(&ifr, 0, sizeof(ifr));
- ifr.ifr_ifindex = index;
+ if_addr.index = index;
+ if_addr.family = AF_INET;
+ if_addr.allow_unspec = true;
+ if_addr.ipaddrs[ADDR_TYPE_DSTADDR] = &dstaddr;
- if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
- DBG("SIOCGIFNAME (%d/%s)", errno, strerror(errno));
- close(sk);
- return -errno;
- }
+ err = get_interface_addresses(&if_addr);
+ if (err)
+ return err;
- if (ioctl(sk, SIOCGIFFLAGS, &ifr) < 0) {
- DBG("SIOCGIFFLAGS (%d/%s)", errno, strerror(errno));
- close(sk);
- return -errno;
- }
+ if (inet_ntop(AF_INET, &dstaddr, buf, INET_ADDRSTRLEN))
+ *dest = g_strdup(buf);
- if ((ifr.ifr_flags & IFF_POINTOPOINT) == 0) {
- close(sk);
- errno = EINVAL;
- return -errno;
- }
+ DBG("destination %s", *dest);
- DBG("index %d %s", index, ifr.ifr_name);
+ return *dest && **dest ? 0 : -ENOENT;
+ }
- if (ioctl(sk, SIOCGIFDSTADDR, &ifr) < 0) {
- connman_error("Get destination address failed (%s)",
- strerror(errno));
- close(sk);
- return -errno;
- }
+ int connman_inet_ipv6_get_dest_addr(int index, char **dest)
+ {
+ struct interface_address if_addr = { 0 };
+ struct in_addr dstaddr = { 0 };
+ char buf[INET6_ADDRSTRLEN] = { 0 };
+ int err;
- close(sk);
+ if (!dest)
+ return -EINVAL;
- switch (family) {
- case AF_INET:
- addr = &((struct sockaddr_in *)&ifr.ifr_dstaddr)->sin_addr;
- break;
- case AF_INET6:
- addr = &((struct sockaddr_in6 *)&ifr.ifr_dstaddr)->sin6_addr;
- break;
- default:
- errno = EINVAL;
- return -errno;
- }
+ if_addr.index = index;
+ if_addr.family = AF_INET6;
+ if_addr.allow_unspec = true;
+ if_addr.ipaddrs[ADDR_TYPE_DSTADDR] = &dstaddr;
- if (!inet_ntop(family, addr, buf, len)) {
- DBG("error %d/%s", errno, strerror(errno));
- return -errno;
- }
+ err = get_interface_addresses(&if_addr);
+ if (err)
+ return err;
- return 0;
+ if (inet_ntop(AF_INET6, &dstaddr, buf, INET6_ADDRSTRLEN))
+ *dest = g_strdup(buf);
+
+ DBG("destination %s", *dest);
+
+ return *dest && **dest ? 0 : -ENOENT;
}
- int connman_inet_get_dest_addr(int index, char **dest)
+ /* destination is optional */
+ int connman_inet_get_route_addresses(int index, char **network, char **netmask,
+ char **destination)
{
- char addr[INET_ADDRSTRLEN];
- int ret;
+ struct interface_address if_addr = { 0 };
+ struct in_addr addr = { 0 };
+ struct in_addr mask = { 0 };
+ struct in_addr dest = { 0 };
+ struct in_addr nw_addr = { 0 };
+ char buf[INET_ADDRSTRLEN] = { 0 };
+ int err;
- ret = get_dest_addr(PF_INET, index, addr, INET_ADDRSTRLEN);
- if (ret < 0)
- return ret;
+ if (!network || !netmask)
+ return -EINVAL;
- *dest = g_strdup(addr);
+ if_addr.index = index;
+ if_addr.family = AF_INET;
+ if_addr.ipaddrs[ADDR_TYPE_IPADDR] = &addr;
+ if_addr.ipaddrs[ADDR_TYPE_NETMASK] = &mask;
+ if_addr.ipaddrs[ADDR_TYPE_DSTADDR] = &dest;
- DBG("destination %s", *dest);
+ err = get_interface_addresses(&if_addr);
+ if (err)
+ return err;
- return 0;
+ nw_addr.s_addr = (addr.s_addr & mask.s_addr);
+
+ if (inet_ntop(AF_INET, &nw_addr, buf, INET_ADDRSTRLEN))
+ *network = g_strdup(buf);
+
+ memset(&buf, 0, INET_ADDRSTRLEN);
+
+ if (inet_ntop(AF_INET, &mask, buf, INET_ADDRSTRLEN))
+ *netmask = g_strdup(buf);
+
+ if (destination) {
+ memset(&buf, 0, INET_ADDRSTRLEN);
+
+ if (inet_ntop(AF_INET, &dest, buf, INET_ADDRSTRLEN))
+ *destination = g_strdup(buf);
+ }
+
+ DBG("network %s netmask %s destination %s", *network, *netmask,
+ destination ? *destination : NULL);
+
+ return *network && **network && *netmask && **netmask ? 0 : -ENOENT;
}
- int connman_inet_ipv6_get_dest_addr(int index, char **dest)
+ int connman_inet_ipv6_get_route_addresses(int index, char **network,
+ char **netmask, char **destination)
{
- char addr[INET6_ADDRSTRLEN];
- int ret;
+ struct interface_address if_addr = { 0 };
+ struct in6_addr addr = { 0 };
+ struct in6_addr mask = { 0 };
+ struct in6_addr dest = { 0 };
+ struct in6_addr nw_addr = { 0 };
+ char buf[INET6_ADDRSTRLEN] = { 0 };
+ int err;
- ret = get_dest_addr(PF_INET6, index, addr, INET6_ADDRSTRLEN);
- if (ret < 0)
- return ret;
+ if (!network)
+ return -EINVAL;
- *dest = g_strdup(addr);
+ if_addr.index = index;
+ if_addr.family = AF_INET6;
+ if_addr.ipaddrs[ADDR_TYPE_IPADDR] = &addr;
+ if_addr.ipaddrs[ADDR_TYPE_NETMASK] = &mask;
+ if_addr.ipaddrs[ADDR_TYPE_DSTADDR] = &dest;
- DBG("destination %s", *dest);
+ err = get_interface_addresses(&if_addr);
+ if (err)
+ return err;
- return 0;
+ ipv6_addr_set(&nw_addr, addr.s6_addr32[0] & mask.s6_addr32[0],
+ addr.s6_addr32[1] & mask.s6_addr32[1],
+ addr.s6_addr32[2] & mask.s6_addr32[2],
+ addr.s6_addr32[3] & mask.s6_addr32[3]);
+
+ if (inet_ntop(AF_INET6, &nw_addr, buf, INET6_ADDRSTRLEN))
+ *network = g_strdup(buf);
+
+ memset(&buf, 0, INET6_ADDRSTRLEN);
+
+ if (inet_ntop(AF_INET6, &mask, buf, INET6_ADDRSTRLEN))
+ *netmask = g_strdup(buf);
+
+ if (destination) {
+ memset(&buf, 0, INET6_ADDRSTRLEN);
+
+ if (inet_ntop(AF_INET6, &dest, buf, INET6_ADDRSTRLEN))
+ *destination = g_strdup(buf);
+ }
+
+ DBG("network %s netmask %s destination %s", *network, *netmask,
+ destination ? *destination : NULL);
+
+ return *network && **network && *netmask && **netmask ? 0 : -ENOENT;
}
int __connman_inet_rtnl_open(struct __connman_inet_rtnl_handle *rth)
return true;
}
- int __connman_inet_get_interface_address(int index, int family, void *address)
+ /*
+ * Omits checking of the gateway matching the actual gateway IP since both
+ * connmand and vpnd use inet.c, getting the route is via ipconfig and ipconfig
+ * is different for both. Gateway is left here for possible future use.
+ *
+ * Gateway can be NULL and connection.c then assigns 0.0.0.0 address or ::,
+ * depending on IP family.
+ */
+ bool connman_inet_is_default_route(int family, const char *host,
+ const char *gateway, const char *netmask)
{
- struct ifaddrs *ifaddr, *ifa;
- int err = -ENOENT;
- char name[IF_NAMESIZE];
-
- if (!if_indextoname(index, name))
- return -EINVAL;
-
- DBG("index %d interface %s", index, name);
-
- if (getifaddrs(&ifaddr) < 0) {
- err = -errno;
- DBG("Cannot get addresses err %d/%s", err, strerror(-err));
- return err;
- }
-
- for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
- if (!ifa->ifa_addr)
- continue;
-
- if (strncmp(ifa->ifa_name, name, IF_NAMESIZE) == 0 &&
- ifa->ifa_addr->sa_family == family) {
- if (family == AF_INET) {
- struct sockaddr_in *in4 = (struct sockaddr_in *)
- ifa->ifa_addr;
- if (in4->sin_addr.s_addr == INADDR_ANY)
- continue;
- memcpy(address, &in4->sin_addr,
- sizeof(struct in_addr));
- } else if (family == AF_INET6) {
- struct sockaddr_in6 *in6 =
- (struct sockaddr_in6 *)ifa->ifa_addr;
- if (memcmp(&in6->sin6_addr, &in6addr_any,
- sizeof(struct in6_addr)) == 0)
- continue;
- memcpy(address, &in6->sin6_addr,
- sizeof(struct in6_addr));
+ return __connman_inet_is_any_addr(host, family) &&
+ __connman_inet_is_any_addr(netmask, family);
+ }
- } else {
- err = -EINVAL;
- goto out;
- }
+ int __connman_inet_get_interface_address(int index, int family, void *address)
+ {
+ struct interface_address if_addr = { 0 };
- err = 0;
- break;
- }
- }
+ if_addr.index = index;
+ if_addr.family = family;
+ if_addr.ipaddrs[ADDR_TYPE_IPADDR] = address;
- out:
- freeifaddrs(ifaddr);
- return err;
+ return get_interface_addresses(&if_addr);
}
int __connman_inet_get_interface_mac_address(int index, uint8_t *mac_address)
ret = inet_pton(family, dst ? dst : gateway, buf);
g_free(dst);
- if (ret <= 0)
+ if (ret != 1)
return -EINVAL;
memset(&rth, 0, sizeof(rth));
int __connman_inet_get_interface_ll_address(int index, int family,
void *address)
{
- struct ifaddrs *ifaddr, *ifa;
- int err = -ENOENT;
- char name[IF_NAMESIZE];
-
- if (!if_indextoname(index, name))
- return -EINVAL;
-
- DBG("index %d interface %s", index, name);
+ struct interface_address if_addr = { 0 };
- if (getifaddrs(&ifaddr) < 0) {
- err = -errno;
- DBG("Cannot get addresses err %d/%s", err, strerror(-err));
- return err;
- }
+ if_addr.index = index;
+ if_addr.family = family;
+ if_addr.require_ll = true;
+ if_addr.ipaddrs[ADDR_TYPE_IPADDR] = address;
- for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
- if (!ifa->ifa_addr)
- continue;
-
- if (strncmp(ifa->ifa_name, name, IF_NAMESIZE) == 0 &&
- ifa->ifa_addr->sa_family == family) {
- if (family == AF_INET) {
- struct sockaddr_in *in4 = (struct sockaddr_in *)
- ifa->ifa_addr;
- if (in4->sin_addr.s_addr == INADDR_ANY)
- continue;
- if ((in4->sin_addr.s_addr & IN_CLASSB_NET) !=
- ((in_addr_t) 0xa9fe0000))
- continue;
- memcpy(address, &in4->sin_addr,
- sizeof(struct in_addr));
- } else if (family == AF_INET6) {
- struct sockaddr_in6 *in6 =
- (struct sockaddr_in6 *)ifa->ifa_addr;
- if (memcmp(&in6->sin6_addr, &in6addr_any,
- sizeof(struct in6_addr)) == 0)
- continue;
- if (!IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
- continue;
-
- memcpy(address, &in6->sin6_addr,
- sizeof(struct in6_addr));
- } else {
- err = -EINVAL;
- goto out;
- }
-
- err = 0;
- break;
- }
- }
-
- out:
- freeifaddrs(ifaddr);
- return err;
+ return get_interface_addresses(&if_addr);
}
int __connman_inet_get_address_netmask(int ifindex,
addrstr[len] = '\0';
err = inet_pton(AF_INET, addrstr, addr);
- if (err <= 0) {
+ if (err != 1) {
connman_error("%s: Cannot convert to numeric addr \"%s\"\n",
__func__, addrstr);
err = -1;
ipaddress->peer = NULL;
ipaddress->broadcast = NULL;
ipaddress->gateway = NULL;
+ ipaddress->is_p2p = false;
return ipaddress;
}
+ void connman_ipaddress_set_p2p(struct connman_ipaddress *ipaddress, bool value)
+ {
+ if (!ipaddress)
+ return;
+
+ ipaddress->is_p2p = value;
+ }
+
void connman_ipaddress_free(struct connman_ipaddress *ipaddress)
{
if (!ipaddress)
return false;
err = inet_pton(AF_INET6, address, buf);
- if (err > 0)
+ if (err == 1)
return true;
return false;
copy->peer = g_strdup(ipaddress->peer);
copy->broadcast = g_strdup(ipaddress->broadcast);
copy->gateway = g_strdup(ipaddress->gateway);
+ copy->is_p2p = ipaddress->is_p2p;
return copy;
}
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;
return "";
}
- static bool get_ipv6_state(gchar *ifname)
+ #define PROC_IPV4_CONF_PREFIX "/proc/sys/net/ipv4/conf"
+ #define PROC_IPV6_CONF_PREFIX "/proc/sys/net/ipv6/conf"
+
+ static int read_conf_value(const char *prefix, const char *ifname,
+ const char *suffix, int *value)
{
- int disabled;
gchar *path;
FILE *f;
- bool enabled = false;
-
- if (!ifname)
- path = g_strdup("/proc/sys/net/ipv6/conf/all/disable_ipv6");
- else
- path = g_strdup_printf(
- "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname);
+ int err;
+ path = g_build_filename(prefix, ifname ? ifname : "all", suffix, NULL);
if (!path)
- return enabled;
+ return -ENOMEM;
+ errno = 0;
f = fopen(path, "r");
+ if (!f) {
+ err = -errno;
+ } else {
+ errno = 0; /* Avoid stale errno values with fscanf */
- g_free(path);
+ err = fscanf(f, "%d", value);
+ if (err <= 0 && errno)
+ err = -errno;
- if (f) {
- if (fscanf(f, "%d", &disabled) > 0)
- enabled = !disabled;
fclose(f);
}
- return enabled;
+ if (err <= 0)
+ connman_error("failed to read %s", path);
+
+ g_free(path);
+
+ return err;
}
- static void set_ipv6_state(gchar *ifname, bool enable)
+ static int read_ipv4_conf_value(const char *ifname, const char *suffix,
+ int *value)
{
+ return read_conf_value(PROC_IPV4_CONF_PREFIX, ifname, suffix, value);
+ }
+
+ static int read_ipv6_conf_value(const char *ifname, const char *suffix,
+ int *value)
+ {
+ return read_conf_value(PROC_IPV6_CONF_PREFIX, ifname, suffix, value);
+ }
+
+ static int write_conf_value(const char *prefix, const char *ifname,
+ const char *suffix, int value) {
gchar *path;
FILE *f;
+ int rval;
- if (!ifname)
- path = g_strdup("/proc/sys/net/ipv6/conf/all/disable_ipv6");
- else
- path = g_strdup_printf(
- "/proc/sys/net/ipv6/conf/%s/disable_ipv6", ifname);
-
+ path = g_build_filename(prefix, ifname ? ifname : "all", suffix, NULL);
if (!path)
- return;
+ return -ENOMEM;
f = fopen(path, "r+");
+ if (!f) {
+ rval = -errno;
+ } else {
+ rval = fprintf(f, "%d", value);
+ fclose(f);
+ }
+
+ if (rval <= 0)
+ connman_error("failed to set %s value %d", path, value);
g_free(path);
- if (!f)
- return;
+ return rval;
+ }
- if (!enable)
- fprintf(f, "1");
- else
- fprintf(f, "0");
+ static int write_ipv4_conf_value(const char *ifname, const char *suffix,
+ int value)
+ {
+ return write_conf_value(PROC_IPV4_CONF_PREFIX, ifname, suffix, value);
+ }
- fclose(f);
+ static int write_ipv6_conf_value(const char *ifname, const char *suffix,
+ int value)
+ {
+ return write_conf_value(PROC_IPV6_CONF_PREFIX, ifname, suffix, value);
}
- static int get_ipv6_privacy(gchar *ifname)
+ static bool get_ipv6_state(gchar *ifname)
{
- gchar *path;
- FILE *f;
- int value;
+ int disabled;
+ bool enabled = false;
- if (!ifname)
- return 0;
+ if (read_ipv6_conf_value(ifname, "disable_ipv6", &disabled) > 0)
+ enabled = !disabled;
+
+ return enabled;
+ }
- path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/use_tempaddr",
- ifname);
+ static int set_ipv6_state(gchar *ifname, bool enable)
+ {
+ int disabled = enable ? 0 : 1;
- if (!path)
- return 0;
+ DBG("%s %d", ifname, disabled);
- f = fopen(path, "r");
+ return write_ipv6_conf_value(ifname, "disable_ipv6", disabled);
+ }
- g_free(path);
+ static int get_ipv6_privacy(gchar *ifname)
+ {
+ int value;
- if (!f)
+ if (!ifname)
return 0;
- if (fscanf(f, "%d", &value) <= 0)
+ if (read_ipv6_conf_value(ifname, "use_tempaddr", &value) < 0)
value = 0;
- fclose(f);
-
return value;
}
/* Enable the IPv6 privacy extension for stateless address autoconfiguration.
* The privacy extension is described in RFC 3041 and RFC 4941
*/
- static void set_ipv6_privacy(gchar *ifname, int value)
+ static int set_ipv6_privacy(gchar *ifname, int value)
{
- gchar *path;
- FILE *f;
-
if (!ifname)
- return;
-
- path = g_strdup_printf("/proc/sys/net/ipv6/conf/%s/use_tempaddr",
- ifname);
-
- if (!path)
- return;
+ return -EINVAL;
if (value < 0)
value = 0;
- f = fopen(path, "r+");
-
- g_free(path);
-
- if (!f)
- return;
-
- fprintf(f, "%d", value);
- fclose(f);
+ return write_ipv6_conf_value(ifname, "use_tempaddr", value);
}
static int get_rp_filter(void)
{
- FILE *f;
- int value = -EINVAL, tmp;
+ int value;
- f = fopen("/proc/sys/net/ipv4/conf/all/rp_filter", "r");
-
- if (f) {
- if (fscanf(f, "%d", &tmp) == 1)
- value = tmp;
- fclose(f);
- }
+ if (read_ipv4_conf_value(NULL, "rp_filter", &value) < 0)
+ value = -EINVAL;
return value;
}
- static void set_rp_filter(int value)
+ static int set_rp_filter(int value)
{
- FILE *f;
-
- f = fopen("/proc/sys/net/ipv4/conf/all/rp_filter", "r+");
-
- if (!f)
- return;
-
- fprintf(f, "%d", value);
+ /* 0 = no validation, 1 = strict mode, 2 = loose mode */
+ switch (value) {
+ case -1:
+ value = 0;
+ /* fall through */
+ case 0:
+ case 1:
+ case 2:
+ break;
+ default:
+ return -EINVAL;
+ }
- fclose(f);
+ return write_ipv4_conf_value(NULL, "rp_filter", value);
}
int __connman_ipconfig_set_rp_filter()
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);
return g_strcmp0(addr1->local, addr2->local);
}
+ static bool is_index_p2p_service(int index)
+ {
+ struct connman_service *service;
+ enum connman_service_type type;
+
+ service = __connman_service_lookup_from_index(index);
+ if (!service)
+ return false;
+
+ type = connman_service_get_type(service);
+ switch (type) {
+ case CONNMAN_SERVICE_TYPE_P2P:
+ case CONNMAN_SERVICE_TYPE_VPN:
+ return true;
+ default:
+ return false;
+ }
+ }
+
int __connman_ipconfig_newaddr(int index, int family, const char *label,
unsigned char prefixlen, const char *address)
{
ipaddress->prefixlen = prefixlen;
ipaddress->local = g_strdup(address);
+ if (is_index_p2p_service(index))
+ connman_ipaddress_set_p2p(ipaddress, true);
+
if (g_slist_find_custom(ipdevice->address_list, ipaddress,
check_duplicate_address)) {
connman_ipaddress_free(ipaddress);
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;
ipconfig->address->prefixlen = prefixlen;
}
+ static void ipconfig_set_p2p(int index, struct connman_ipconfig *ipconfig)
+ {
+ if (!is_index_p2p_service(index))
+ return;
+
+ connman_ipaddress_set_p2p(ipconfig->address, true);
+ connman_ipaddress_set_p2p(ipconfig->system, true);
+ }
+
static struct connman_ipconfig *create_ipv6config(int index)
{
struct connman_ipconfig *ipv6config;
ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index));
if (ipdevice)
+#if !defined TIZEN_EXT
ipv6config->ipv6_privacy_config = ipdevice->ipv6_privacy;
+#else
+ ipv6config->ipv6_privacy_config = ipdevice->ipv6_privacy = 2;
+#endif
ipv6config->address = connman_ipaddress_alloc(AF_INET6);
if (!ipv6config->address) {
ipv6config->system = connman_ipaddress_alloc(AF_INET6);
+ ipconfig_set_p2p(index, ipv6config);
+
DBG("ipconfig %p index %d method %s", ipv6config, index,
__connman_ipconfig_method2string(ipv6config->method));
}
ipconfig->system = connman_ipaddress_alloc(AF_INET);
+
+ ipconfig_set_p2p(index, ipconfig);
+
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
DBG("ipconfig %p index %d", ipconfig, index);
return ipconfig;
{
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:
err = connman_inet_clear_address(ipconfig->index,
ipconfig->address);
else if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6)
- err = connman_inet_clear_ipv6_address(
- ipconfig->index,
- ipconfig->address->local,
- ipconfig->address->prefixlen);
+ err = connman_inet_clear_ipv6_address(ipconfig->index,
+ ipconfig->address);
else
err = -EINVAL;
connman_ipaddress_clear(ipdevice->config_ipv4->system);
__connman_ipconfig_unref(ipdevice->config_ipv4);
+
+ g_free(ipdevice->ipv4_gateway);
+ ipdevice->ipv4_gateway = NULL;
}
if (type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
connman_ipaddress_clear(ipdevice->config_ipv6->system);
__connman_ipconfig_unref(ipdevice->config_ipv6);
+
+ g_free(ipdevice->ipv6_gateway);
+ ipdevice->ipv6_gateway = NULL;
}
if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig)
{
struct connman_ipdevice *ipdevice;
-
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
DBG("ipconfig %p", ipconfig);
if (!ipconfig || ipconfig->index < 0)
connman_ipaddress_clear(ipdevice->config_ipv4->system);
__connman_ipconfig_unref(ipdevice->config_ipv4);
ipdevice->config_ipv4 = NULL;
+
+ g_free(ipdevice->ipv4_gateway);
+ ipdevice->ipv4_gateway = NULL;
+
return 0;
}
if (ipdevice->config_ipv6 == ipconfig) {
ipconfig_list = g_list_remove(ipconfig_list, ipconfig);
+#if defined TIZEN_EXT
+ if (ipdevice->config_ipv6->method ==
+ CONNMAN_IPCONFIG_METHOD_AUTO) {
+ disable_ipv6(ipdevice->config_ipv6);
+ enable_ipv6(ipdevice->config_ipv6);
+ }
+#endif
connman_ipaddress_clear(ipdevice->config_ipv6->system);
__connman_ipconfig_unref(ipdevice->config_ipv6);
ipdevice->config_ipv6 = NULL;
+
+ g_free(ipdevice->ipv6_gateway);
+ ipdevice->ipv6_gateway = NULL;
+
return 0;
}
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();
if (!tokens)
return -1;
- if (!inet_pton(AF_INET, tokens[0], ip)) {
+ if (inet_pton(AF_INET, tokens[0], ip) != 1) {
err = -1;
goto out;
}
if (!tokens)
return -1;
- if (!inet_pton(AF_INET6, tokens[0], ip)) {
+ if (inet_pton(AF_INET6, tokens[0], ip) != 1) {
err = -1;
goto out;
}
g_free(table->name);
table->name = g_strdup(table_name);
-
+
hash_table_replace(type, table->name, table);
return table;
break;
if (invert)
- ctx->ip->invflags |= IP6T_INV_DSTIP;
+ ctx->ipv6->invflags |= IP6T_INV_DSTIP;
}
-
+
break;
case 'i':
/* In interface specification */
if (invert)
ctx->ip->invflags |= IPT_INV_VIA_IN;
}
-
+
if (ctx->type == AF_INET6) {
g_stpcpy(ctx->ipv6->iniface, optarg);
memset(ctx->ipv6->iniface_mask, 0xff, len + 1);
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;
#include <sys/stat.h>
#include <net/if.h>
#include <netdb.h>
+#include <sys/time.h>
+#include <sys/resource.h>
#include <gdbus.h>
#define DEFAULT_INPUT_REQUEST_TIMEOUT (120 * 1000)
#define DEFAULT_BROWSER_LAUNCH_TIMEOUT (300 * 1000)
+ /*
+ * We set the integer to 1 sec so that we have a chance to get
+ * necessary IPv6 router advertisement messages that might have
+ * DNS data etc.
+ */
+ #define DEFAULT_ONLINE_CHECK_INITIAL_INTERVAL 1
+ #define DEFAULT_ONLINE_CHECK_MAX_INTERVAL 12
+
+#if defined TIZEN_EXT
+#define DEFAULT_WIFI_INTERFACE "wlan0"
+#define CONTAINER_FILE "/run/systemd/container"
+#endif
+
#define MAINFILE "main.conf"
#define CONFIGMAINFILE CONFIGDIR "/" MAINFILE
bool enable_6to4;
char *vendor_class_id;
bool enable_online_check;
+ bool enable_online_to_ready_transition;
+ unsigned int online_check_initial_interval;
+ unsigned int online_check_max_interval;
bool auto_connect_roaming_services;
bool acd;
bool use_gateways_as_timeservers;
+#if defined TIZEN_EXT
+ char **cellular_interfaces;
+ bool tizen_tv_extension;
+ bool auto_ip;
+ char *global_nameserver;
+ bool supplicant_debug;
+ char *def_wifi_ifname;
+ bool file_log;
+ bool dlog_log;
+ bool simple_log;
+ bool wifi_roam_scan;
+ bool wifi_roam;
+#endif
} connman_settings = {
.bg_scan = true,
.pref_timeservers = NULL,
.enable_6to4 = false,
.vendor_class_id = NULL,
.enable_online_check = true,
+ .enable_online_to_ready_transition = false,
+ .online_check_initial_interval = DEFAULT_ONLINE_CHECK_INITIAL_INTERVAL,
+ .online_check_max_interval = DEFAULT_ONLINE_CHECK_MAX_INTERVAL,
.auto_connect_roaming_services = false,
.acd = false,
.use_gateways_as_timeservers = false,
+#if defined TIZEN_EXT
+ .cellular_interfaces = NULL,
+ .tizen_tv_extension = false,
+ .auto_ip = true,
+ .global_nameserver = NULL,
+ .supplicant_debug = false,
+ .def_wifi_ifname = DEFAULT_WIFI_INTERFACE,
+ .file_log = true,
+ .dlog_log = true,
+ .simple_log = true,
+ .wifi_roam_scan = false,
+ .wifi_roam = false,
+#endif
};
+#if defined TIZEN_EXT
+static struct {
+ /* BSSID */
+ char *ins_preferred_freq_bssid;
+ bool ins_last_connected_bssid;
+ bool ins_assoc_reject;
+ bool ins_signal_bssid;
+ unsigned int ins_preferred_freq_bssid_score;
+ unsigned int ins_last_connected_bssid_score;
+ unsigned int ins_assoc_reject_score;
+ /* SSID */
+ bool ins_last_user_selection;
+ unsigned int ins_last_user_selection_time;
+ bool ins_last_connected;
+ char *ins_preferred_freq;
+ char **ins_security_priority;
+ unsigned int ins_security_priority_count;
+ bool ins_signal;
+ bool ins_internet;
+ unsigned int ins_last_user_selection_score;
+ unsigned int ins_last_connected_score;
+ unsigned int ins_preferred_freq_score;
+ unsigned int ins_security_priority_score;
+ unsigned int ins_internet_score;
+ /* Common */
+ int ins_signal_level3_5ghz;
+ int ins_signal_level3_24ghz;
+} connman_ins_settings = {
+ /* BSSID */
+ .ins_preferred_freq_bssid = NULL,
+ .ins_last_connected_bssid = true,
+ .ins_assoc_reject = true,
+ .ins_signal_bssid = true,
+ .ins_preferred_freq_bssid_score = 20,
+ .ins_last_connected_bssid_score = 20,
+ .ins_assoc_reject_score = 10,
+ /* SSID */
+ .ins_last_user_selection = true,
+ .ins_last_user_selection_time = 480,
+ .ins_last_connected = true,
+ .ins_preferred_freq = NULL,
+ .ins_security_priority = NULL,
+ .ins_security_priority_count = 0,
+ .ins_signal = true,
+ .ins_internet = true,
+ .ins_last_user_selection_score = 30,
+ .ins_last_connected_score = 30,
+ .ins_preferred_freq_score = 60,
+ .ins_security_priority_score = 5,
+ .ins_internet_score = 30,
+ /* Common */
+ .ins_signal_level3_5ghz = -76,
+ .ins_signal_level3_24ghz = -74,
+};
+#endif
+
#define CONF_BG_SCAN "BackgroundScanning"
#define CONF_PREF_TIMESERVERS "FallbackTimeservers"
#define CONF_AUTO_CONNECT_TECHS "DefaultAutoConnectTechnologies"
#define CONF_ENABLE_6TO4 "Enable6to4"
#define CONF_VENDOR_CLASS_ID "VendorClassID"
#define CONF_ENABLE_ONLINE_CHECK "EnableOnlineCheck"
+ #define CONF_ENABLE_ONLINE_TO_READY_TRANSITION "EnableOnlineToReadyTransition"
+ #define CONF_ONLINE_CHECK_INITIAL_INTERVAL "OnlineCheckInitialInterval"
+ #define CONF_ONLINE_CHECK_MAX_INTERVAL "OnlineCheckMaxInterval"
#define CONF_AUTO_CONNECT_ROAMING_SERVICES "AutoConnectRoamingServices"
#define CONF_ACD "AddressConflictDetection"
#define CONF_USE_GATEWAYS_AS_TIMESERVERS "UseGatewaysAsTimeservers"
+#if defined TIZEN_EXT
+#define CONF_CELLULAR_INTERFACE "NetworkCellularInterfaceList"
+#define CONF_TIZEN_TV_EXT "TizenTVExtension"
+#define CONF_ENABLE_AUTO_IP "EnableAutoIp"
+#define CONF_GLOBAL_NAMESERVER "GlobalNameserver"
+#define CONF_CONNMAN_SUPPLICANT_DEBUG "ConnmanSupplicantDebug"
+#define CONF_CONNMAN_WIFI_DEF_IFNAME "DefaultWifiInterface"
+#define CONF_CONNMAN_FILE_LOG "FileLogging"
+#define CONF_CONNMAN_DLOG_LOG "DlogLogging"
+#define CONF_CONNMAN_SIMPLIFIED_LOG "SimplifiedLog"
+#define CONF_CONNMAN_WIFI_ROAM_SCAN "WifiRoamingScan"
+#define CONF_CONNMAN_WIFI_ROAM "WifiRoaming"
+#endif
+
+#if defined TIZEN_EXT
+/* BSSID */
+#define CONF_INS_PREFERRED_FREQ_BSSID "INSPreferredFreqBSSID"
+#define CONF_INS_PREFERRED_FREQ_BSSID_SCORE "INSPreferredFreqBSSIDScore"
+#define CONF_INS_LAST_CONNECTED_BSSID "INSLastConnectedBSSID"
+#define CONF_INS_LAST_CONNECTED_BSSID_SCORE "INSLastConnectedBSSIDScore"
+#define CONF_INS_ASSOC_REJECT "INSAssocReject"
+#define CONF_INS_ASSOC_REJECT_SCORE "INSAssocRejectScore"
+#define CONF_INS_SIGNAL_BSSID "INSSignalBSSID"
+/* SSID */
+#define CONF_INS_LAST_USER_SELECTION "INSLastUserSelection"
+#define CONF_INS_LAST_USER_SELECTION_TIME "INSLastUserSelectionTime"
+#define CONF_INS_LAST_USER_SELECTION_SCORE "INSLastUserSelectionScore"
+#define CONF_INS_LAST_CONNECTED "INSLastConnected"
+#define CONF_INS_LAST_CONNECTED_SCORE "INSLastConnectedScore"
+#define CONF_INS_PREFERRED_FREQ "INSPreferredFreq"
+#define CONF_INS_PREFERRED_FREQ_SCORE "INSPreferredFreqScore"
+#define CONF_INS_SECURITY_PRIORITY "INSSecurityPriority"
+#define CONF_INS_SECURITY_PRIORITY_COUNT "INSSecurityPriorityCount"
+#define CONF_INS_SECURITY_PRIORITY_SCORE "INSSecurityPriorityScore"
+#define CONF_INS_SIGNAL "INSSignal"
+#define CONF_INS_INTERNET "INSInternet"
+#define CONF_INS_INTERNET_SCORE "INSInternetScore"
+/* Common */
+#define CONF_INS_SIGNAL_LEVEL3_5GHZ "INSSignalLevel3_5GHz"
+#define CONF_INS_SIGNAL_LEVEL3_24GHZ "INSSignalLevel3_24GHz"
+#endif
static const char *supported_options[] = {
CONF_BG_SCAN,
CONF_PREF_TIMESERVERS,
CONF_AUTO_CONNECT_TECHS,
+ CONF_FAVORITE_TECHS,
CONF_ALWAYS_CONNECTED_TECHS,
CONF_PREFERRED_TECHS,
CONF_FALLBACK_NAMESERVERS,
CONF_ENABLE_6TO4,
CONF_VENDOR_CLASS_ID,
CONF_ENABLE_ONLINE_CHECK,
+ CONF_ENABLE_ONLINE_TO_READY_TRANSITION,
+ CONF_ONLINE_CHECK_INITIAL_INTERVAL,
+ CONF_ONLINE_CHECK_MAX_INTERVAL,
CONF_AUTO_CONNECT_ROAMING_SERVICES,
CONF_ACD,
CONF_USE_GATEWAYS_AS_TIMESERVERS,
+#if defined TIZEN_EXT
+ CONF_CELLULAR_INTERFACE,
+ CONF_TIZEN_TV_EXT,
+ CONF_ENABLE_AUTO_IP,
+ CONF_GLOBAL_NAMESERVER,
+ CONF_CONNMAN_SUPPLICANT_DEBUG,
+ CONF_CONNMAN_WIFI_DEF_IFNAME,
+ CONF_CONNMAN_FILE_LOG,
+ CONF_CONNMAN_DLOG_LOG,
+ CONF_CONNMAN_SIMPLIFIED_LOG,
+ CONF_CONNMAN_WIFI_ROAM_SCAN,
+ CONF_CONNMAN_WIFI_ROAM,
+#endif
NULL
};
+#if defined TIZEN_EXT
+static const char *supported_ins_options[] = {
+ /* BSSID */
+ CONF_INS_PREFERRED_FREQ_BSSID,
+ CONF_INS_PREFERRED_FREQ_BSSID_SCORE,
+ CONF_INS_LAST_CONNECTED_BSSID,
+ CONF_INS_LAST_CONNECTED_BSSID_SCORE,
+ CONF_INS_ASSOC_REJECT,
+ CONF_INS_ASSOC_REJECT_SCORE,
+ CONF_INS_SIGNAL_BSSID,
+ /* SSID */
+ CONF_INS_LAST_USER_SELECTION,
+ CONF_INS_LAST_USER_SELECTION_TIME,
+ CONF_INS_LAST_USER_SELECTION_SCORE,
+ CONF_INS_LAST_CONNECTED,
+ CONF_INS_LAST_CONNECTED_SCORE,
+ CONF_INS_PREFERRED_FREQ,
+ CONF_INS_PREFERRED_FREQ_SCORE,
+ CONF_INS_SECURITY_PRIORITY,
+ CONF_INS_SECURITY_PRIORITY_COUNT,
+ CONF_INS_SECURITY_PRIORITY_SCORE,
+ CONF_INS_SIGNAL,
+ CONF_INS_INTERNET,
+ CONF_INS_INTERNET_SCORE,
+ /* Common */
+ CONF_INS_SIGNAL_LEVEL3_5GHZ,
+ CONF_INS_SIGNAL_LEVEL3_24GHZ,
+ NULL
+};
+#endif
+
static GKeyFile *load_config(const char *file)
{
GError *err = NULL;
keys = g_key_file_get_groups(config, NULL);
for (j = 0; keys && keys[j]; j++) {
+#if defined TIZEN_EXT
+ if (g_strcmp0(keys[j], "General") != 0 &&
+ g_strcmp0(keys[j], "INS") != 0)
+#else
if (g_strcmp0(keys[j], "General") != 0)
+#endif
connman_warn("Unknown group %s in %s",
keys[j], MAINFILE);
}
}
g_strfreev(keys);
+
+#if defined TIZEN_EXT
+ keys = g_key_file_get_keys(config, "INS", NULL, NULL);
+
+ for (j = 0; keys && keys[j]; j++) {
+ bool found;
+ int i;
+
+ found = false;
+ for (i = 0; supported_ins_options[i]; i++) {
+ if (g_strcmp0(keys[j], supported_ins_options[i]) == 0) {
+ found = true;
+ break;
+ }
+ }
+ if (!found && !supported_ins_options[i])
+ connman_warn("Unknown option %s in %s",
+ keys[j], MAINFILE);
+ }
+
+ g_strfreev(keys);
+#endif
}
+#if defined TIZEN_EXT
+static void check_Tizen_INS_configuration(GKeyFile *config)
+{
+ GError *error = NULL;
+ char *ins_preferred_freq_bssid;
+ char *ins_preferred_freq;
+ char **ins_security_priority;
+ bool boolean;
+ int integer;
+ gsize len;
+
+ ins_preferred_freq_bssid = __connman_config_get_string(config, "INS",
+ CONF_INS_PREFERRED_FREQ_BSSID, &error);
+ if (!error)
+ connman_ins_settings.ins_preferred_freq_bssid = ins_preferred_freq_bssid;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_PREFERRED_FREQ_BSSID_SCORE, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_preferred_freq_bssid_score = integer;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "INS",
+ CONF_INS_LAST_CONNECTED_BSSID, &error);
+ if (!error)
+ connman_ins_settings.ins_last_connected_bssid = boolean;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_LAST_CONNECTED_BSSID_SCORE, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_last_connected_bssid_score = integer;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "INS",
+ CONF_INS_ASSOC_REJECT, &error);
+ if (!error)
+ connman_ins_settings.ins_assoc_reject = boolean;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_ASSOC_REJECT_SCORE, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_assoc_reject_score = integer;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "INS",
+ CONF_INS_SIGNAL_BSSID, &error);
+ if (!error)
+ connman_ins_settings.ins_signal_bssid = boolean;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "INS",
+ CONF_INS_LAST_USER_SELECTION, &error);
+ if (!error)
+ connman_ins_settings.ins_last_user_selection = boolean;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_LAST_USER_SELECTION_TIME, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_last_user_selection_time = integer;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_LAST_USER_SELECTION_SCORE, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_last_user_selection_score = integer;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "INS",
+ CONF_INS_LAST_CONNECTED, &error);
+ if (!error)
+ connman_ins_settings.ins_last_connected = boolean;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_LAST_CONNECTED_SCORE, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_last_connected_score = integer;
+
+ g_clear_error(&error);
+
+ ins_preferred_freq = __connman_config_get_string(config, "INS",
+ CONF_INS_PREFERRED_FREQ, &error);
+ if (!error)
+ connman_ins_settings.ins_preferred_freq = ins_preferred_freq;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_PREFERRED_FREQ_SCORE, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_preferred_freq_score = integer;
+
+ g_clear_error(&error);
+
+ ins_security_priority = g_key_file_get_string_list(config, "INS",
+ CONF_INS_SECURITY_PRIORITY, &len, &error);
+
+ if (error == NULL) {
+ connman_ins_settings.ins_security_priority = ins_security_priority;
+ connman_ins_settings.ins_security_priority_count = len;
+ }
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_SECURITY_PRIORITY_SCORE, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_security_priority_score = integer;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "INS",
+ CONF_INS_SIGNAL, &error);
+ if (!error)
+ connman_ins_settings.ins_signal = boolean;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "INS",
+ CONF_INS_INTERNET, &error);
+ if (!error)
+ connman_ins_settings.ins_internet = boolean;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_INTERNET_SCORE, &error);
+ if (!error && integer >= 0)
+ connman_ins_settings.ins_internet_score = integer;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_SIGNAL_LEVEL3_5GHZ, &error);
+ if (!error)
+ connman_ins_settings.ins_signal_level3_5ghz = integer;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "INS",
+ CONF_INS_SIGNAL_LEVEL3_24GHZ, &error);
+ if (!error)
+ connman_ins_settings.ins_signal_level3_24ghz = integer;
+
+ g_clear_error(&error);
+}
+
+static void check_Tizen_configuration(GKeyFile *config)
+{
+ GError *error = NULL;
+ char **cellular_interfaces;
+ char *global_nameserver;
+ char *default_wifi_ifname;
+ bool boolean;
+ gsize len;
+
+ cellular_interfaces = g_key_file_get_string_list(config, "General",
+ CONF_CELLULAR_INTERFACE, &len, &error);
+
+ if (error == NULL)
+ connman_settings.cellular_interfaces = cellular_interfaces;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "General",
+ CONF_TIZEN_TV_EXT, &error);
+ if (!error)
+ connman_settings.tizen_tv_extension = boolean;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "General",
+ CONF_ENABLE_AUTO_IP, &error);
+ if (!error)
+ connman_settings.auto_ip = boolean;
+
+ g_clear_error(&error);
+
+ global_nameserver = __connman_config_get_string(config, "General",
+ CONF_GLOBAL_NAMESERVER, &error);
+ if (!error)
+ connman_settings.global_nameserver = global_nameserver;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "General",
+ CONF_CONNMAN_SUPPLICANT_DEBUG, &error);
+ if (!error)
+ connman_settings.supplicant_debug = boolean;
+
+ g_clear_error(&error);
+
+ default_wifi_ifname = __connman_config_get_string(config, "General",
+ CONF_CONNMAN_WIFI_DEF_IFNAME, &error);
+ if (!error)
+ connman_settings.def_wifi_ifname = default_wifi_ifname;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "General",
+ CONF_CONNMAN_FILE_LOG, &error);
+ if (!error)
+ connman_settings.file_log = boolean;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "General",
+ CONF_CONNMAN_DLOG_LOG, &error);
+ if (!error)
+ connman_settings.dlog_log = boolean;
+
+ g_clear_error(&error);
+
+ boolean = __connman_config_get_bool(config, "General",
+ CONF_CONNMAN_SIMPLIFIED_LOG, &error);
+ if (!error)
+ connman_settings.simple_log = boolean;
+
+ boolean = __connman_config_get_bool(config, "General",
+ CONF_CONNMAN_WIFI_ROAM_SCAN, &error);
+ if (!error)
+ connman_settings.wifi_roam_scan = boolean;
+
+ boolean = __connman_config_get_bool(config, "General",
+ CONF_CONNMAN_WIFI_ROAM, &error);
+ if (!error)
+ connman_settings.wifi_roam = boolean;
+
+ g_clear_error(&error);
+
+ check_Tizen_INS_configuration(config);
+}
+
+static void set_nofile_inc(void)
+{
+ int err;
+ struct rlimit rlim;
+
+ rlim.rlim_cur = 8192;
+ rlim.rlim_max = 8192;
+
+ err = setrlimit(RLIMIT_NOFILE, &rlim);
+ if (err)
+ DBG("fail to increase FILENO err(%d)", err);
+
+ return;
+}
+#endif
+
static void parse_config(GKeyFile *config)
{
GError *error = NULL;
char **interfaces;
char **str_list;
char **tethering;
- char *vendor_class_id;
+ char *string;
gsize len;
- int timeout;
+ int integer;
if (!config) {
connman_settings.auto_connect =
connman_settings.auto_connect =
parse_service_types(default_auto_connect, CONF_ARRAY_SIZE(default_auto_connect));
+ g_strfreev(str_list);
+
g_clear_error(&error);
str_list = __connman_config_get_string_list(config, "General",
g_clear_error(&error);
- timeout = g_key_file_get_integer(config, "General",
+ integer = g_key_file_get_integer(config, "General",
CONF_TIMEOUT_INPUTREQ, &error);
- if (!error && timeout >= 0)
- connman_settings.timeout_inputreq = timeout * 1000;
+ if (!error && integer >= 0)
+ connman_settings.timeout_inputreq = integer * 1000;
g_clear_error(&error);
- timeout = g_key_file_get_integer(config, "General",
+ integer = g_key_file_get_integer(config, "General",
CONF_TIMEOUT_BROWSERLAUNCH, &error);
- if (!error && timeout >= 0)
- connman_settings.timeout_browserlaunch = timeout * 1000;
+ if (!error && integer >= 0)
+ connman_settings.timeout_browserlaunch = integer * 1000;
g_clear_error(&error);
g_clear_error(&error);
- vendor_class_id = __connman_config_get_string(config, "General",
+ string = __connman_config_get_string(config, "General",
CONF_VENDOR_CLASS_ID, &error);
if (!error)
- connman_settings.vendor_class_id = vendor_class_id;
+ connman_settings.vendor_class_id = string;
g_clear_error(&error);
g_clear_error(&error);
boolean = __connman_config_get_bool(config, "General",
+ CONF_ENABLE_ONLINE_TO_READY_TRANSITION, &error);
+ if (!error) {
+ connman_settings.enable_online_to_ready_transition = boolean;
+ }
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "General",
+ CONF_ONLINE_CHECK_INITIAL_INTERVAL, &error);
+ if (!error && integer >= 0)
+ connman_settings.online_check_initial_interval = integer;
+
+ g_clear_error(&error);
+
+ integer = g_key_file_get_integer(config, "General",
+ CONF_ONLINE_CHECK_MAX_INTERVAL, &error);
+ if (!error && integer >= 0)
+ connman_settings.online_check_max_interval = integer;
+
+ g_clear_error(&error);
+
+ if (connman_settings.online_check_initial_interval < 1 ||
+ connman_settings.online_check_initial_interval >
+ connman_settings.online_check_max_interval) {
+ connman_warn("Incorrect online check intervals [%u, %u]",
+ connman_settings.online_check_initial_interval,
+ connman_settings.online_check_max_interval);
+ connman_settings.online_check_initial_interval =
+ DEFAULT_ONLINE_CHECK_INITIAL_INTERVAL;
+ connman_settings.online_check_max_interval =
+ DEFAULT_ONLINE_CHECK_MAX_INTERVAL;
+ }
+
+ boolean = __connman_config_get_bool(config, "General",
CONF_AUTO_CONNECT_ROAMING_SERVICES, &error);
if (!error)
connman_settings.auto_connect_roaming_services = boolean;
connman_settings.use_gateways_as_timeservers = boolean;
g_clear_error(&error);
+
+#if defined TIZEN_EXT
+ check_Tizen_configuration(config);
+#endif
}
static int config_init(const char *file)
{
GKeyFile *config;
+#if defined TIZEN_EXT
+ set_nofile_inc();
+#endif
config = load_config(file);
check_config(config);
parse_config(config);
if (config)
g_key_file_free(config);
+#if defined TIZEN_EXT
+ set_simple_log_option(connman_settings.simple_log);
+ set_dlog_logging_option(connman_settings.dlog_log);
+ set_file_logging_option(connman_settings.file_log);
+#endif
return 0;
}
{ NULL },
};
- const char *connman_option_get_string(const char *key)
+ char *connman_setting_get_string(const char *key)
{
if (g_str_equal(key, CONF_VENDOR_CLASS_ID))
return connman_settings.vendor_class_id;
return option_wifi;
}
+#if defined TIZEN_EXT
+ if (g_str_equal(key, CONF_GLOBAL_NAMESERVER))
+ return connman_settings.global_nameserver;
+
+ if (g_str_equal(key, CONF_INS_PREFERRED_FREQ_BSSID))
+ return connman_ins_settings.ins_preferred_freq_bssid;
+
+ if (g_str_equal(key, CONF_INS_PREFERRED_FREQ))
+ return connman_ins_settings.ins_preferred_freq;
+
+ if (g_str_equal(key, CONF_CONNMAN_WIFI_DEF_IFNAME))
+ return connman_settings.def_wifi_ifname;
+#endif
return NULL;
}
if (g_str_equal(key, CONF_ENABLE_ONLINE_CHECK))
return connman_settings.enable_online_check;
+ if (g_str_equal(key, CONF_ENABLE_ONLINE_TO_READY_TRANSITION))
+ return connman_settings.enable_online_to_ready_transition;
+
if (g_str_equal(key, CONF_AUTO_CONNECT_ROAMING_SERVICES))
return connman_settings.auto_connect_roaming_services;
if (g_str_equal(key, CONF_USE_GATEWAYS_AS_TIMESERVERS))
return connman_settings.use_gateways_as_timeservers;
- #endif
+#if defined TIZEN_EXT
+ if (g_str_equal(key, CONF_ENABLE_AUTO_IP))
+ return connman_settings.auto_ip;
+
+ if (g_str_equal(key, CONF_CONNMAN_SUPPLICANT_DEBUG))
+ return connman_settings.supplicant_debug;
+
+ if (g_str_equal(key, CONF_CONNMAN_FILE_LOG))
+ return connman_settings.file_log;
+
+ if (g_str_equal(key, CONF_CONNMAN_DLOG_LOG))
+ return connman_settings.dlog_log;
+
+ if (g_str_equal(key, CONF_CONNMAN_SIMPLIFIED_LOG))
+ return connman_settings.simple_log;
+
+ if (g_str_equal(key, CONF_CONNMAN_WIFI_ROAM_SCAN))
+ return connman_settings.wifi_roam_scan;
+
+ if (g_str_equal(key, CONF_CONNMAN_WIFI_ROAM))
+ return connman_settings.wifi_roam;
- #if defined TIZEN_EXT
+
+ if (g_str_equal(key, CONF_INS_LAST_CONNECTED_BSSID))
+ return connman_ins_settings.ins_last_connected_bssid;
+
+ if (g_str_equal(key, CONF_INS_ASSOC_REJECT))
+ return connman_ins_settings.ins_assoc_reject;
+
+ if (g_str_equal(key, CONF_INS_SIGNAL_BSSID))
+ return connman_ins_settings.ins_signal_bssid;
+
+ if (g_str_equal(key, CONF_INS_LAST_USER_SELECTION))
+ return connman_ins_settings.ins_last_user_selection;
+
+ if (g_str_equal(key, CONF_INS_LAST_CONNECTED))
+ return connman_ins_settings.ins_last_connected;
+
+ if (g_str_equal(key, CONF_INS_SIGNAL))
+ return connman_ins_settings.ins_signal;
+
+ if (g_str_equal(key, CONF_INS_INTERNET))
+ return connman_ins_settings.ins_internet;
+#endif
+
return false;
}
- #if defined TIZEN_EXT
unsigned int connman_setting_get_uint(const char *key)
{
-
+ if (g_str_equal(key, CONF_ONLINE_CHECK_INITIAL_INTERVAL))
+ return connman_settings.online_check_initial_interval;
+
+ if (g_str_equal(key, CONF_ONLINE_CHECK_MAX_INTERVAL))
+ return connman_settings.online_check_max_interval;
+
++#if defined TIZEN_EXT
+ if (g_str_equal(key, CONF_INS_PREFERRED_FREQ_BSSID_SCORE))
+ return connman_ins_settings.ins_preferred_freq_bssid_score;
+
+ if (g_str_equal(key, CONF_INS_LAST_CONNECTED_BSSID_SCORE))
+ return connman_ins_settings.ins_last_connected_bssid_score;
+
+ if (g_str_equal(key, CONF_INS_ASSOC_REJECT_SCORE))
+ return connman_ins_settings.ins_assoc_reject_score;
+
+ if (g_str_equal(key, CONF_INS_LAST_USER_SELECTION_TIME))
+ return connman_ins_settings.ins_last_user_selection_time;
+
+ if (g_str_equal(key, CONF_INS_SECURITY_PRIORITY_COUNT))
+ return connman_ins_settings.ins_security_priority_count;
+
+ if (g_str_equal(key, CONF_INS_LAST_USER_SELECTION_SCORE))
+ return connman_ins_settings.ins_last_user_selection_score;
+
+ if (g_str_equal(key, CONF_INS_LAST_CONNECTED_SCORE))
+ return connman_ins_settings.ins_last_connected_score;
+
+ if (g_str_equal(key, CONF_INS_PREFERRED_FREQ_SCORE))
+ return connman_ins_settings.ins_preferred_freq_score;
+
+ if (g_str_equal(key, CONF_INS_SECURITY_PRIORITY_SCORE))
+ return connman_ins_settings.ins_security_priority_score;
+
+ if (g_str_equal(key, CONF_INS_INTERNET_SCORE))
+ return connman_ins_settings.ins_internet_score;
++#endif
return 0;
}
++#if defined TIZEN_EXT
+int connman_setting_get_int(const char *key)
+{
+ if (g_str_equal(key, CONF_INS_SIGNAL_LEVEL3_5GHZ))
+ return connman_ins_settings.ins_signal_level3_5ghz;
+
+ if (g_str_equal(key, CONF_INS_SIGNAL_LEVEL3_24GHZ))
+ return connman_ins_settings.ins_signal_level3_24ghz;
+
+ return 0;
+}
+#endif
+
char **connman_setting_get_string_list(const char *key)
{
if (g_str_equal(key, CONF_PREF_TIMESERVERS))
if (g_str_equal(key, CONF_TETHERING_TECHNOLOGIES))
return connman_settings.tethering_technologies;
+#if defined TIZEN_EXT
+ if (g_str_equal(key, CONF_CELLULAR_INTERFACE))
+ return connman_settings.cellular_interfaces;
+#endif
+
+#if defined TIZEN_EXT
+ if (g_str_equal(key, CONF_INS_SECURITY_PRIORITY))
+ return connman_ins_settings.ins_security_priority;
+#endif
+
return NULL;
}
__connman_dbus_init(conn);
+#if defined TIZEN_EXT
+ if (access(CONTAINER_FILE, F_OK) == 0) {
+ g_main_loop_run(main_loop);
+
+ g_source_remove(signal);
+ dbus_connection_unref(conn);
+ g_main_loop_unref(main_loop);
+
+ __connman_dbus_cleanup();
+ __connman_log_cleanup(option_backtrace);
+
+ return 0;
+ }
+#endif
+
if (!option_config)
config_init(CONFIGMAINFILE);
else
__connman_service_init();
__connman_peer_service_init();
__connman_peer_init();
+#if defined TIZEN_EXT_WIFI_MESH
+ __connman_mesh_init();
+#endif /* TIZEN_EXT_WIFI_MESH */
__connman_provider_init();
__connman_network_init();
__connman_config_init();
__connman_clock_init();
__connman_ipconfig_init();
+#if defined TIZEN_EXT
+ __connman_rtnl_init(GIO_SOCKET_RETRY_COUNT);
+#else /* TIZEN_EXT */
__connman_rtnl_init();
+#endif /* TIZEN_EXT */
__connman_task_init();
__connman_proxy_init();
__connman_detect_init();
__connman_dhcpv6_init();
__connman_wpad_init();
__connman_wispr_init();
+#if !defined TIZEN_EXT
__connman_rfkill_init();
__connman_machine_init();
+#endif
g_free(option_config);
g_free(option_device);
g_source_remove(signal);
+#if !defined TIZEN_EXT
__connman_machine_cleanup();
__connman_rfkill_cleanup();
+#endif
__connman_wispr_cleanup();
__connman_wpad_cleanup();
__connman_dhcpv6_cleanup();
__connman_firewall_cleanup();
__connman_peer_service_cleanup();
__connman_peer_cleanup();
+#if defined TIZEN_EXT_WIFI_MESH
+ __connman_mesh_cleanup();
+#endif /* TIZEN_EXT_WIFI_MESH */
__connman_ippool_cleanup();
__connman_device_cleanup();
__connman_network_cleanup();
g_strfreev(connman_settings.fallback_nameservers);
g_strfreev(connman_settings.blacklisted_interfaces);
g_strfreev(connman_settings.tethering_technologies);
+ g_free(connman_settings.vendor_class_id);
+#if defined TIZEN_EXT
+ g_free(connman_ins_settings.ins_preferred_freq_bssid);
+ g_free(connman_ins_settings.ins_preferred_freq);
+ if (connman_ins_settings.ins_security_priority)
+ g_strfreev(connman_ins_settings.ins_security_priority);
+#endif
+
g_free(option_debug);
g_free(option_wifi);
# 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
# Default value is true.
# EnableOnlineCheck = false
+ # Range of intervals between two online check requests.
+ # When an online check request fails, another one is triggered after a
+ # longer interval. The intervals follow the power of two series of numbers
+ # between OnlineCheckInitialInterval and OnlineCheckMaxInterval.
+ # Default range is [1, 12], corresponding to the following intervals, in
+ # seconds: 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121 and 144.
+ # OnlineCheckInitialInterval = 1
+ # OnlineCheckMaxInterval = 12
+
+ # WARNING: Experimental feature!!!
+ # In addition to EnableOnlineCheck setting, enable or disable use of HTTP GET
+ # to detect the loss of end-to-end connectivity.
+ # If this setting is false, when the default service transitions to ONLINE
+ # state, the HTTP GET request is no more called until next cycle, initiated
+ # by a transition of the default service to DISCONNECT state.
+ # If this setting is true, the HTTP GET request keeps beeing called to guarantee
+ # that end-to-end connectivity is still successful. If not, the default service
+ # will transition to READY state, enabling another service to become the
+ # default one, in replacement.
+ # EnableOnlineToReadyTransition = false
+
# List of technologies with AutoConnect = true which are always connected
# regardless of PreferredTechnologies setting. Default value is empty and
# will connect a technology only if it is at a higher preference than any
# This setting has no effect if SingleConnectedTechnologies is enabled.
# AlwaysConnectedTechnologies =
+# Allow connman to add service gateway to the time server list.
+# Default value is false.
+# UseGatewaysAsTimeservers = false
+
# Enable auto connection of services in roaming.
# If this setting is false, roaming services are not auto-connected by ConnMan.
# Default value is false.
# to an interface (in accordance with RFC 5227).
# Default value is false.
# AddressConflictDetection = false
+
+NetworkCellularInterfaceList = pdp,rmnet,seth_td,seth_w
+
+# Enable use of link-local address for auto-configuration.
+# When a device fails to get IP address from DHCP server,
+# ConnMan will start link-local address autoconfiguration and
+# assign a link-local IP address to device.
+# If this setting is false and device fails to get IP address
+# from DHCP server then device state will be set to disconnected.
+# Default value is true.
+# EnableAutoIp = false
+
+# Allow connman to set additional global nameserver and it will be used
+# if all nameservers are failed to resolve DNS query. The nameserver
+# entries must be in numeric format.
+# GlobalNameserver = 8.8.8.8
+
+# Enable supplicant debugging log
+ConnmanSupplicantDebug = false
+
+# Save ConnMan log to file
+FileLogging = false
+
+# Use dlog for ConnMan logging
+DlogLogging = true
+
+# Some logs of low importance are omitted to reduce the amount of logs
+SimplifiedLog = true
+
+# This value specifies which will be the default when there are multiple wifi interfaces.
+# Default value is wlan0.
+DefaultWifiInterface = wlan0
+
+# Allow ConnMan to start scan for wifi roaming when SNR and signal are weakened
+# Default value is false.
+# WifiRoamingScan = true
+
+# Allow ConnMan to start wifi roaming when SNR and signal are weakened
+# and there is another BSS in better condition.
+# Default value is false.
+# WifiRoaming = true
+
+
+[INS]
+# INS(Intelligent Network Selection) configuration: BSSID Selection.
+INSPreferredFreqBSSID = 5GHz
+INSPreferredFreqBSSIDScore = 20
+INSLastConnectedBSSID = true
+INSLastConnectedBSSIDScore = 20
+INSAssocReject = true
+INSAssocRejectScore = 10
+INSSignalBSSID = true
+
+# INS(Intelligent Network Selection) configuration: SSID Selection.
+INSLastUserSelection = true
+INSLastUserSelectionTime = 480
+INSLastUserSelectionScore = 30
+# (INSLastUserSelectionTime - selection time diff) / (INSLastUserSelectionTime / INSLastUserSelectionScore)
+# This means '(480 - selection time) / x) <= 30'
+INSLastConnected = true
+INSLastConnectedScore = 30
+INSPreferredFreq = 5GHz
+INSPreferredFreqScore = 60
+INSSecurityPriority = SAE,RSN
+INSSecurityPriorityScore = 5
+# In this case, SAE(10 score), RSN(5 score)
+INSSignal = true
+INSInternet = true
+INSInternetScore = 30
+
+# INS(Intelligent Network Selection) configuration: Common.
+INSSignalLevel3_5GHz = -76
+INSSignalLevel3_24GHz = -74
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;
}
- const char *default_interface = connman_option_get_string("DefaultWifiInterface");
+#if defined TIZEN_EXT
+static DBusMessage *get_interfaces(DBusConnection *conn, DBusMessage *msg, void *data)
+{
+ DBusMessage *reply;
+ DBusMessageIter iter, array;
++ const char *default_interface = connman_setting_get_string("DefaultWifiInterface");
+
+ DBG("DefaultWifiInterface %s", default_interface);
+
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return NULL;
+
+ dbus_message_iter_init_append(reply, &iter);
+ dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_STRING_AS_STRING, &array);
+
+ dbus_message_iter_append_basic(&array,
+ DBUS_TYPE_STRING, &default_interface);
+
+ __connman_technology_append_interfaces(&array,
+ CONNMAN_SERVICE_TYPE_WIFI, default_interface);
+
+ dbus_message_iter_close_container(&iter, &array);
+ return reply;
+}
+
+static DBusMessage *get_default_service(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ struct connman_service *service = connman_service_get_default_connection();
+ DBG("service %p", service);
+
+ return connman_service_create_dbus_service_reply(msg, service);
+}
+
+static DBusMessage *get_connected_service(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ const char *ifname;
+ struct connman_service *service;
+
+ dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &ifname,
+ DBUS_TYPE_INVALID);
+
+ service = connman_service_get_connected_service(ifname);
+ DBG("Interface Name %s, service %p", ifname, service);
+
+ return connman_service_create_dbus_service_reply(msg, service);
+}
+#endif
+
+#if defined TIZEN_EXT_INS
+static void append_ins_structs(DBusMessageIter *iter, void *user_data)
+{
+ __connman_ins_list_struct(iter);
+}
+
+static DBusMessage *get_ins(DBusConnection *conn,
+ DBusMessage *msg, void *data)
+{
+ DBusMessage *reply;
+
+ reply = dbus_message_new_method_return(msg);
+ if (!reply)
+ return NULL;
+
+ __connman_dbus_append_objpath_dict_array(reply,
+ append_ins_structs, NULL);
+
+ return reply;
+}
+#endif
+
static void append_peer_structs(DBusMessageIter *iter, void *user_data)
{
__connman_peer_list_struct(iter);
}
+#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
{ },
};
#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;
}
return 0;
}
+ int connman_network_set_autoconnect(struct connman_network *network,
+ bool autoconnect)
+ {
+ if (!network->driver || !network->driver->set_autoconnect)
+ return 0;
+ return network->driver->set_autoconnect(network, autoconnect);
+ }
+
+ bool __connman_network_native_autoconnect(struct connman_network *network)
+ {
+ if (!network->driver || !network->driver->set_autoconnect)
+ return false;
+ return true;
+ }
+
uint16_t connman_network_get_wifi_channel(struct connman_network *network)
{
return network->wifi.channel;
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;
}
err = __connman_inet_modify_address(RTM_NEWADDR,
NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
- gateway, NULL, prefixlen, broadcast);
+ gateway, NULL, prefixlen, broadcast, true);
if (err < 0)
goto error;
service = g_malloc0(sizeof(struct _peer_service));
service->type = type;
- service->data = g_memdup(data, data_length * sizeof(unsigned char));
+ if (data_length > 0) {
+ service->data = g_malloc(data_length * sizeof(unsigned char));
+ memcpy(service->data, data, data_length * sizeof(unsigned char));
+ }
service->length = data_length;
peer->services = g_slist_prepend(peer->services, service);
DBusMessageIter *iter)
{
const char *host, *domain, *type;
+ dbus_bool_t split_routing;
if (!provider->driver || !provider->driver->get_property)
return;
if (type)
connman_dbus_dict_append_basic(iter, "Type", DBUS_TYPE_STRING,
&type);
+
+ if (provider->vpn_service) {
+ split_routing = connman_provider_is_split_routing(provider);
+ connman_dbus_dict_append_basic(iter, "SplitRouting",
+ DBUS_TYPE_BOOLEAN, &split_routing);
+ }
}
struct connman_provider *
}
__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 provider->identifier;
}
+ const char * __connman_provider_get_transport_ident(
+ struct connman_provider *provider)
+ {
+ if (provider && provider && provider->driver && provider->driver->get_property)
+ return provider->driver->get_property(provider, "Transport");
+
+ return NULL;
+ }
+
int connman_provider_set_string(struct connman_provider *provider,
const char *key, const char *value)
{
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;
}
__connman_service_save(provider->vpn_service);
}
+ bool connman_provider_is_split_routing(struct connman_provider *provider)
+ {
+ if (!provider || !provider->vpn_service)
+ return false;
+
+ return __connman_service_is_split_routing(provider->vpn_service);
+ }
+
+ int connman_provider_set_split_routing(struct connman_provider *provider,
+ bool split_routing)
+ {
+ struct connman_service *service;
+ enum connman_ipconfig_type type;
+ int service_index;
+ int vpn_index;
+ bool service_split_routing;
+ int err = 0;
+
+ DBG("");
+
+ if (!provider || !provider->vpn_service)
+ return -EINVAL;
+
+ service_split_routing = __connman_service_is_split_routing(
+ provider->vpn_service);
+
+ if (service_split_routing == split_routing) {
+ DBG("split_routing already set %s",
+ split_routing ? "true" : "false");
+ return -EALREADY;
+ }
+
+ switch (provider->family) {
+ case AF_INET:
+ type = CONNMAN_IPCONFIG_TYPE_IPV4;
+ break;
+ case AF_INET6:
+ type = CONNMAN_IPCONFIG_TYPE_IPV6;
+ break;
+ case AF_UNSPEC:
+ type = CONNMAN_IPCONFIG_TYPE_ALL;
+ break;
+ default:
+ type = CONNMAN_IPCONFIG_TYPE_UNKNOWN;
+ }
+
+ if (!__connman_service_is_connected_state(provider->vpn_service,
+ type)) {
+ DBG("%p VPN not connected", provider->vpn_service);
+ goto save;
+ }
+
+ vpn_index = __connman_service_get_index(provider->vpn_service);
+ service_index = __connman_connection_get_vpn_phy_index(vpn_index);
+ service = __connman_service_lookup_from_index(service_index);
+ if (!service)
+ goto save;
+
+ if (split_routing)
+ err = __connman_service_move(service, provider->vpn_service,
+ true);
+ else
+ err = __connman_service_move(provider->vpn_service, service,
+ true);
+
+ if (err) {
+ connman_warn("cannot move service %p and VPN %p error %d",
+ service, provider->vpn_service, err);
+
+ /*
+ * In case of error notify vpnd about the current split routing
+ * state.
+ */
+ __connman_service_split_routing_changed(provider->vpn_service);
+ goto out;
+ }
+
+ save:
+ __connman_service_set_split_routing(provider->vpn_service,
+ split_routing);
+ __connman_service_save(provider->vpn_service);
+
+ out:
+ return err;
+ }
+
+ int connman_provider_get_family(struct connman_provider *provider)
+ {
+ if (!provider)
+ return AF_UNSPEC;
+
+ return provider->family;
+ }
+
static void unregister_provider(gpointer data)
{
struct connman_provider *provider = data;
#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;
} else if (strcmp(line + 8, "bond") == 0) {
interface->service_type = CONNMAN_SERVICE_TYPE_ETHERNET;
interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET;
+ } else if (strcmp(line + 8, "dsa") == 0) {
+ interface->service_type = CONNMAN_SERVICE_TYPE_ETHERNET;
+ interface->device_type = CONNMAN_DEVICE_TYPE_ETHERNET;
} else {
interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN;
interface->device_type = CONNMAN_DEVICE_TYPE_UNKNOWN;
if (found_devtype)
goto out;
+#if !defined TIZEN_EXT
+ /* TIZEN does not use old wext interface */
/* We haven't got a DEVTYPE, let's check if it's a wireless device */
if (wext_interface(name)) {
interface->service_type = CONNMAN_SERVICE_TYPE_WIFI;
connman_error("%s runs an unsupported 802.11 driver", name);
}
+#endif
out:
g_free(name);
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 vpn_autoconnect_id = 0;
static struct connman_service *current_default = NULL;
static bool services_dirty = false;
+ static bool enable_online_to_ready_transition = false;
+ static unsigned int online_check_initial_interval = 0;
+ static unsigned int online_check_max_interval = 0;
+#if defined TIZEN_EXT
+static bool auto_connect_mode = TRUE;
+
+struct saved_profiles {
+ GTimeVal modified;
+ gchar *profile_name;
+};
+
+static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+#endif
+
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+enum connman_ins_preferred_freq {
+ CONNMAN_INS_PREFERRED_FREQ_UNKNOWN,
+ CONNMAN_INS_PREFERRED_FREQ_24GHZ,
+ CONNMAN_INS_PREFERRED_FREQ_5GHZ,
+};
+
+struct connman_ins_settings {
+ bool last_user_selection;
+ unsigned int last_user_selection_time;
+ unsigned int last_user_selection_score;
+ bool last_connected;
+ unsigned int last_connected_score;
+ enum connman_ins_preferred_freq preferred_freq;
+ unsigned int preferred_freq_score;
+ unsigned int security_priority[CONNMAN_SERVICE_SECURITY_MAX];
+ unsigned int security_priority_count;
+ unsigned int security_priority_score;
+ bool signal;
+ bool internet;
+ unsigned int internet_score;
+ int signal_level3_5ghz;
+ int signal_level3_24ghz;
+};
+
+static struct connman_ins_settings ins_settings;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
struct connman_stats {
bool valid;
bool enabled;
bool wps;
bool wps_advertizing;
guint online_timeout;
- int online_check_interval_ipv4;
- int online_check_interval_ipv6;
+ unsigned int online_check_interval_ipv4;
+ unsigned int online_check_interval_ipv6;
bool do_split_routing;
bool new_service;
bool hidden_service;
char *config_file;
char *config_entry;
+#if defined TIZEN_EXT
+ /*
+ * Description: TIZEN implements system global connection management.
+ * It's only for PDP (cellular) bearer. Wi-Fi is managed
+ * by ConnMan automatically. Reference count can help to
+ * manage open/close connection requests by each application.
+ */
+ int user_pdn_connection_refcount;
+ bool storage_reload;
+ /*
+ * Description: In case of EAP security type,
+ * user can select the keymgmt type for roaming(802.11r).
+ * - FT, CCKM, OKC, ...
+ */
+ char *keymgmt_type;
+ int disconnect_reason;
+ int assoc_status_code;
+ /*
+ * Only for EAP-FAST and EAP-PEAP in EAPoL.
+ */
+ char *phase1;
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * Only for EAP-FAST
+ */
+ char *pac_file;
+#endif
+ /*
+ * Description: To indicate that disconnection triggered by user.
+ */
+ bool disconnection_requested;
+
+ enum connman_dnsconfig_method dns_config_method_ipv4;
+ enum connman_dnsconfig_method dns_config_method_ipv6;
+#endif
+#if defined TIZEN_EXT
+ char *connector;
+ char *c_sign_key;
+ char *net_access_key;
+ unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
+ bool is_internet_connection;
+ int assoc_reject_count;
+#if defined TIZEN_EXT_INS
+ int score_last_user_selection;
+ int score_last_connected;
+ int score_frequency;
+ int score_security_priority;
+ int score_internet_connection;
+ int score_strength;
+#endif
+ int ins_score;
+#endif
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ /*
+ * To indicate use of EAP over Ethernet.
+ */
+ bool use_eapol;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
};
static bool allow_property_changed(struct connman_service *service);
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 "auto";
case CONNMAN_SERVICE_CONNECT_REASON_SESSION:
return "session";
+ case CONNMAN_SERVICE_CONNECT_REASON_NATIVE:
+ return "native";
}
return "unknown";
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;
}
- static void set_split_routing(struct connman_service *service, bool value)
+#ifdef TIZEN_EXT
+static const char *__connman_dnsconfig_method2string(enum connman_dnsconfig_method method)
+{
+ switch (method) {
+ case CONNMAN_DNSCONFIG_METHOD_UNKNOWN:
+ return "unknown";
+ case CONNMAN_DNSCONFIG_METHOD_MANUAL:
+ return "manual";
+ case CONNMAN_DNSCONFIG_METHOD_DHCP:
+ return "dhcp";
+ }
+
+ return NULL;
+}
+
+static enum connman_dnsconfig_method __connman_dnsconfig_string2method(
+ const char *method)
+{
+ if (g_strcmp0(method, "manual") == 0)
+ return CONNMAN_DNSCONFIG_METHOD_MANUAL;
+ else if (g_strcmp0(method, "dhcp") == 0)
+ return CONNMAN_DNSCONFIG_METHOD_DHCP;
+ else
+ return CONNMAN_DNSCONFIG_METHOD_UNKNOWN;
+}
+#endif
+
+ void __connman_service_split_routing_changed(struct connman_service *service)
+ {
+ dbus_bool_t split_routing;
+
+ if (!service->path)
+ return;
+
+ if (!allow_property_changed(service))
+ return;
+
+ split_routing = service->do_split_routing;
+ if (!connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE, "SplitRouting",
+ DBUS_TYPE_BOOLEAN, &split_routing))
+ connman_warn("cannot send SplitRouting property change on %s",
+ service->identifier);
+ }
+
+ void __connman_service_set_split_routing(struct connman_service *service,
+ bool value)
{
if (service->type != CONNMAN_SERVICE_TYPE_VPN)
return;
service->order = 0;
else
service->order = 10;
+
+ /*
+ * In order to make sure the value is propagated also when loading the
+ * VPN service signal the value regardless of the value change.
+ */
+ __connman_service_split_routing_changed(service);
}
int __connman_service_load_modifiable(struct connman_service *service)
case CONNMAN_SERVICE_TYPE_SYSTEM:
case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
break;
case CONNMAN_SERVICE_TYPE_VPN:
- set_split_routing(service, g_key_file_get_boolean(keyfile,
- service->identifier,
- "SplitRouting", NULL));
+ __connman_service_set_split_routing(service,
+ g_key_file_get_boolean(keyfile,
+ service->identifier,
+ "SplitRouting", NULL));
/* fall through */
case CONNMAN_SERVICE_TYPE_WIFI:
return 0;
}
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+static void __connman_service_cleanup_8021x(struct connman_service *service)
+{
+ if (service == NULL)
+ return;
+
+ DBG("service %p ", service);
+
+ __connman_service_set_string(service, "EAP", NULL);
+ __connman_service_set_string(service, "Identity", NULL);
+ __connman_service_set_string(service, "Passphrase", NULL);
+ __connman_service_set_string(service, "AnonymousIdentity", NULL);
+ __connman_service_set_string(service, "CACertFile", NULL);
+ __connman_service_set_string(service, "ClientCertFile", NULL);
+ __connman_service_set_string(service, "PrivateKeyFile", NULL);
+ __connman_service_set_string(service, "PrivateKeyPassphrase", NULL);
+ __connman_service_set_string(service, "Phase1", NULL);
+ __connman_service_set_string(service, "Phase2", NULL);
+ __connman_service_set_string(service, "PacFile", NULL);
+}
+
+static int connman_service_set_eapol_property(struct connman_service *service,
+ DBusMessageIter *array)
+{
+ DBusMessageIter dict;
+ char *str = NULL;
+
+ __connman_service_cleanup_8021x(service);
+
+ if (dbus_message_iter_get_arg_type(array) != DBUS_TYPE_ARRAY)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(array, &dict);
+
+ while(dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter entry, value;
+ const char *key;
+ int type;
+
+ dbus_message_iter_recurse(&dict, &entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&entry, &key);
+ dbus_message_iter_next(&entry);
+
+ if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
+ return -EINVAL;
+
+ dbus_message_iter_recurse(&entry, &value);
+
+ type = dbus_message_iter_get_arg_type(&value);
+
+ if (g_str_equal(key, "UseEapol")) {
+ dbus_bool_t use_eapol;
+
+ if (type != DBUS_TYPE_BOOLEAN)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &use_eapol);
+ service->use_eapol = use_eapol;
+
+ } else if (g_str_equal(key, "EAP")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "EAP", str);
+
+ } else if (g_str_equal(key, "Identity")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "Identity", str);
+
+ } else if (g_str_equal(key, "AnonymousIdentity")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "AnonymousIdentity", str);
+
+ } else if (g_str_equal(key, "CACertFile")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "CACertFile", str);
+ } else if (g_str_equal(key, "ClientCertFile")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "ClientCertFile", str);
+ } else if (g_str_equal(key, "PrivateKeyFile")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "PrivateKeyFile", str);
+ } else if (g_str_equal(key, "PrivateKeyPassphrase")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "PrivateKeyPassphrase", str);
+ } else if (g_str_equal(key, "Phase2")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "Phase2", str);
+ } else if (g_str_equal(key, "Phase1")) {
+ int val;
+ char phase1[5] = {0,};
+
+ if (type != DBUS_TYPE_INT32)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &val);
+ sprintf(phase1, "%d", val);
+ __connman_service_set_string(service, "Phase1", phase1);
+ } else if (g_str_equal(key, "PacFile")) {
+ if (type != DBUS_TYPE_STRING)
+ return -EINVAL;
+
+ dbus_message_iter_get_basic(&value, &str);
+ __connman_service_set_string(service, "PacFile", str);
+ }
+
+ dbus_message_iter_next(&dict);
+ }
+
+ return 0;
+}
+#endif
+
+#if defined TIZEN_EXT
+static void save_assoc_reject(gpointer key, gpointer value, gpointer user_data)
+{
+ struct assoc_reject_data *assoc_rd = value;
+ GString *assoc_reject_str = user_data;
+ GSList *list;
+ char *val_str;
+
+ if (g_slist_length(assoc_rd->reject_time_list) < 1)
+ return;
+
+ for (list = assoc_rd->reject_time_list; list; list = list->next) {
+ time_t assoc_reject_time = GPOINTER_TO_INT(list->data);
+
+ val_str = g_strdup_printf("%s_%ld", assoc_rd->bssid, assoc_reject_time);
+
+ if (assoc_reject_str->len > 0)
+ g_string_append_printf(assoc_reject_str, " %s", val_str);
+ else
+ g_string_append(assoc_reject_str, val_str);
+
+ g_free(val_str);
+ }
+}
+
+static void count_assoc_reject(gpointer key, gpointer value, gpointer user_data)
+{
+ struct assoc_reject_data *assoc_data = value;
+ int *assoc_reject_count = user_data;
+
+ if (assoc_data)
+ *assoc_reject_count += g_slist_length(assoc_data->reject_time_list);
+}
+
+static bool update_assoc_reject(struct connman_service *service)
+{
+ GHashTable *assoc_reject_table;
+ int assoc_reject_count;
+
+ if (!service->network)
+ return false;
+
+ assoc_reject_table = connman_network_get_assoc_reject_table(service->network);
+ if (assoc_reject_table) {
+ assoc_reject_count = 0;
+ g_hash_table_foreach(assoc_reject_table, count_assoc_reject, &assoc_reject_count);
+#if defined TIZEN_EXT_INS
+ DBG("assoc reject count [%d -> %d]",
+ service->assoc_reject_count, assoc_reject_count);
+#endif
+ if (service->assoc_reject_count != assoc_reject_count) {
+ service->assoc_reject_count = assoc_reject_count;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static int service_ext_load(struct connman_service *service)
+{
+ GKeyFile *keyfile;
+ GHashTable *reject_table;
+ char **reject_list;
+ gsize reject_len;
+ struct assoc_reject_data *reject_data;
+ char **bssid_time;
+ char *bssid;
+ time_t reject_time;
+ time_t curr_time;
+ time_t ref_time;
+ struct tm* ref_timeinfo;
+ int i;
+ int err = 0;
+
+ if (!simplified_log)
+ DBG("service %p", service);
+
+ if (!service->network)
+ return -EINVAL;
+
+ if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
+ return -EINVAL;
+
+ keyfile = connman_storage_load_service(service->identifier);
+ if (!keyfile)
+ return -EIO;
+
+ reject_table = connman_network_get_assoc_reject_table(service->network);
+
+ reject_list = g_key_file_get_string_list(keyfile,
+ service->identifier, "AssocReject", &reject_len, NULL);
+
+ if (!reject_list || reject_len == 0) {
+ g_strfreev(reject_list);
+ goto done;
+ }
+
+ /* Only events that occur within one hour are appened. */
+ curr_time = time(NULL);
+ ref_timeinfo = localtime(&curr_time);
+ ref_timeinfo->tm_hour -= 1;
+ ref_time = mktime(ref_timeinfo);
+
+ for (i = 0; reject_list[i]; i++) {
+ bssid_time = g_strsplit(reject_list[i], "_", 0);
+ if (!bssid_time) {
+ err = -ERANGE;
+ continue;
+ }
+
+ bssid = bssid_time[0];
+ reject_time = strtol(bssid_time[1], NULL, 10);
+
+ if (reject_time < ref_time) {
+ g_strfreev(bssid_time);
+ err = -ERANGE;
+ continue;
+ }
+
+ reject_data = g_hash_table_lookup(reject_table, bssid);
+ if (!reject_data) {
+ reject_data = g_try_new0(struct assoc_reject_data, 1);
+ if (!reject_data) {
+ g_strfreev(bssid_time);
+ err = -ERANGE;
+ continue;
+ }
+
+ reject_data->bssid = g_strdup(bssid);
+ g_hash_table_insert(reject_table, reject_data->bssid, reject_data);
+ }
+
+ reject_data->reject_time_list = g_slist_append(reject_data->reject_time_list,
+ GINT_TO_POINTER(reject_time));
+
+#if defined TIZEN_EXT_INS
+ DBG("assoc reject [%s_%ld]", bssid, reject_time);
+#endif
+
+ g_strfreev(bssid_time);
+ }
+
+ g_strfreev(reject_list);
+
+done:
+ g_key_file_free(keyfile);
+ return err;
+}
+
+static int service_ext_save(struct connman_service *service)
+{
+ GKeyFile *keyfile;
+ GHashTable *reject_table;
+ GString *reject_str;
+ char **reject_list;
+ guint reject_len;
+ int err = 0;
+
+ DBG("service %p", service);
+
+ if (!service->network)
+ return -EINVAL;
+
+ if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
+ return -EINVAL;
+
+ keyfile = g_key_file_new();
+ if (!keyfile)
+ return -EIO;
+
+ /* Last connected BSSID */
+ if (memcmp(service->last_connected_bssid, invalid_bssid, WIFI_BSSID_LEN_MAX)) {
+ char *identifier = service->identifier;
+ GString *bssid_str;
+ unsigned int i;
+
+ bssid_str = g_string_sized_new(MAC_ADDRESS_LENGTH);
+ if (!bssid_str) {
+ err = -ENOMEM;
+ goto next;
+ }
+
+ for (i = 0; i < WIFI_BSSID_LEN_MAX; i++) {
+ g_string_append_printf(bssid_str,
+ "%02x", service->last_connected_bssid[i]);
+ if (i < WIFI_BSSID_LEN_MAX - 1)
+ g_string_append(bssid_str, ":");
+ }
+
+ g_key_file_set_string(keyfile, identifier,
+ "LastConnectedBSSID", bssid_str->str);
+
+#if defined TIZEN_EXT_INS
+ DBG("last connected bssid[%s]", bssid_str->str);
+#endif
+
+ g_string_free(bssid_str, TRUE);
+ }
+
+next:
+
+ /* Assoc reject */
+ reject_table = connman_network_get_assoc_reject_table(service->network);
+ if (reject_table && g_hash_table_size(reject_table) > 0) {
+ reject_str = g_string_new(NULL);
+ if (!reject_str) {
+ err = -ENOMEM;
+ goto done;
+ }
+
+ g_hash_table_foreach(reject_table, save_assoc_reject, reject_str);
+
+ reject_list = g_strsplit_set(reject_str->str, " ", 0);
+ reject_len = g_strv_length(reject_list);
+
+ g_key_file_set_string_list(keyfile, service->identifier,
+ "AssocReject", (const gchar **)reject_list, reject_len);
+
+#if defined TIZEN_EXT_INS
+ DBG("assoc reject table [%d]", reject_len);
+#endif
+
+ g_strfreev(reject_list);
+ g_string_free(reject_str, TRUE);
+ } else {
+ g_key_file_remove_key(keyfile, service->identifier, "AssocReject", NULL);
+ }
+
+done:
+ __connman_storage_save_service(keyfile, service->identifier);
+
+ g_key_file_free(keyfile);
+ return err;
+}
+#endif
+
static int service_load(struct connman_service *service)
{
GKeyFile *keyfile;
bool autoconnect;
unsigned int ssid_len;
int err = 0;
-
+#if defined TIZEN_EXT
+ bool internet_connection;
+#endif
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ bool use_eapol;
+#endif
+#if defined TIZEN_EXT
+ if (!simplified_log)
+#endif
DBG("service %p", service);
keyfile = connman_storage_load_service(service->identifier);
case CONNMAN_SERVICE_TYPE_SYSTEM:
case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
break;
case CONNMAN_SERVICE_TYPE_VPN:
- set_split_routing(service, g_key_file_get_boolean(keyfile,
- service->identifier,
- "SplitRouting", NULL));
+ __connman_service_set_split_routing(service,
+ g_key_file_get_boolean(keyfile,
+ service->identifier,
+ "SplitRouting", NULL));
autoconnect = g_key_file_get_boolean(keyfile,
service->identifier, "AutoConnect", &error);
g_free(hex_ssid);
}
+
+#if defined TIZEN_EXT
+ /* Last connected BSSID */
+ if (service->network) {
+ gchar *bssid_str;
+ unsigned char last_connected_bssid[WIFI_BSSID_LEN_MAX];
+ char **str_list;
+ unsigned int i;
+
+ bssid_str = g_key_file_get_string(keyfile,
+ service->identifier, "LastConnectedBSSID", NULL);
+
+ if (bssid_str) {
+ str_list = g_strsplit(bssid_str, ":", 0);
+
+ if (str_list) {
+ for (i = 0; i < WIFI_BSSID_LEN_MAX; i++)
+ last_connected_bssid[i] = strtol(str_list[i], NULL, 16);
+
+ memcpy(service->last_connected_bssid,
+ last_connected_bssid, WIFI_BSSID_LEN_MAX);
+
+ connman_network_set_last_connected_bssid(service->network,
+ last_connected_bssid);
+
+ g_strfreev(str_list);
+ }
+
+ g_free(bssid_str);
+ }
+ }
+
+ /* Internet connection */
+ internet_connection = g_key_file_get_boolean(keyfile,
+ service->identifier, "InternetConnection", &error);
+ if (!error)
+ service->is_internet_connection = internet_connection;
+
+ g_clear_error(&error);
+#endif
/* fall through */
case CONNMAN_SERVICE_TYPE_GADGET:
if (!error)
service->autoconnect = autoconnect;
g_clear_error(&error);
+
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ use_eapol = g_key_file_get_boolean(keyfile,
+ service->identifier, "UseEapol", &error);
+ if (!error)
+ service->use_eapol = use_eapol;
+ g_clear_error(&error);
+#endif
break;
}
str = g_key_file_get_string(keyfile,
service->identifier, "Passphrase", NULL);
if (str) {
+ char *dec = g_strcompress(str);
+ g_free(str);
g_free(service->passphrase);
- service->passphrase = str;
+ service->passphrase = dec;
}
if (service->ipconfig_ipv4)
service->nameservers_config = NULL;
}
+#ifdef TIZEN_EXT
+ char *dns_method;
+
+ dns_method = g_key_file_get_string(keyfile, service->identifier,
+ "Nameservers.IPv4method", NULL);
+ if (dns_method) {
+ service->dns_config_method_ipv4 = __connman_dnsconfig_string2method(dns_method);
+ g_free(dns_method);
+ }
+
+ dns_method = g_key_file_get_string(keyfile, service->identifier,
+ "Nameservers.IPv6method", NULL);
+ if (dns_method) {
+ service->dns_config_method_ipv6 = __connman_dnsconfig_string2method(dns_method);
+ g_free(dns_method);
+ }
+#endif
+
service->timeservers_config = g_key_file_get_string_list(keyfile,
service->identifier, "Timeservers", &length, NULL);
if (service->timeservers_config && length == 0) {
service->hidden_service = g_key_file_get_boolean(keyfile,
service->identifier, "Hidden", NULL);
+#if defined TIZEN_EXT
+ if ((service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+ service->security == CONNMAN_SERVICE_SECURITY_8021X)
+#if defined TIZEN_EXT_EAP_ON_ETHERNET
+ || (service->type == CONNMAN_SERVICE_TYPE_ETHERNET && service->use_eapol)
+#endif
+ ) {
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "EAP", NULL);
+ if (str != NULL) {
+ g_free(service->eap);
+ service->eap = str;
+ }
+
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "Phase2", NULL);
+ if (str != NULL) {
+ g_free(service->phase2);
+ service->phase2 = str;
+ }
+
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "Identity", NULL);
+ if (str != NULL) {
+ g_free(service->identity);
+ service->identity = str;
+ }
+
+#if defined TIZEN_EXT_EAP_ON_ETHERNET
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "AnonymousIdentity", NULL);
+ if (str != NULL) {
+ g_free(service->anonymous_identity);
+ service->anonymous_identity = str;
+ }
+#endif
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "CACertFile", NULL);
+ if (str != NULL) {
+ g_free(service->ca_cert_file);
+ service->ca_cert_file = str;
+ }
+
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "ClientCertFile", NULL);
+ if (str != NULL) {
+ g_free(service->client_cert_file);
+ service->client_cert_file = str;
+ }
+
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "PrivateKeyFile", NULL);
+ if (str != NULL) {
+ g_free(service->private_key_file);
+ service->private_key_file = str;
+ }
+
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "PrivateKeyPassphrase", NULL);
+ if (str != NULL) {
+ g_free(service->private_key_passphrase);
+ service->private_key_passphrase = str;
+ }
+
+#if defined TIZEN_EXT_EAP_ON_ETHERNET
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "Phase1", NULL);
+ if (str != NULL) {
+ g_free(service->phase1);
+ service->phase1 = str;
+ }
+
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "PacFile", NULL);
+ if (str != NULL) {
+ g_free(service->pac_file);
+ service->pac_file = str;
+ }
+#endif
+ }
+#endif
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+ service->security == CONNMAN_SERVICE_SECURITY_DPP) {
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "Connector", NULL);
+ if (str != NULL) {
+ g_free(service->connector);
+ service->connector = str;
+ }
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "CSignKey", NULL);
+ if (str != NULL) {
+ g_free(service->c_sign_key);
+ service->c_sign_key = str;
+ }
+ str = g_key_file_get_string(keyfile,
+ service->identifier, "NetAccessKey", NULL);
+ if (str != NULL) {
+ g_free(service->net_access_key);
+ service->net_access_key = str;
+ }
+ }
+#endif
+
done:
g_key_file_free(keyfile);
case CONNMAN_SERVICE_TYPE_SYSTEM:
case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
break;
case CONNMAN_SERVICE_TYPE_VPN:
g_key_file_set_boolean(keyfile, service->identifier,
if (service->network) {
const unsigned char *ssid;
unsigned int ssid_len = 0;
+#if defined TIZEN_EXT
+ GHashTable *assoc_reject_table;
+#endif
ssid = connman_network_get_blob(service->network,
"WiFi.SSID", &ssid_len);
freq = connman_network_get_frequency(service->network);
g_key_file_set_integer(keyfile, service->identifier,
"Frequency", freq);
+
+#if defined TIZEN_EXT
+ /* Last connected BSSID */
+ if (memcmp(service->last_connected_bssid, invalid_bssid, WIFI_BSSID_LEN_MAX)) {
+ char *identifier = service->identifier;
+ GString *bssid_str;
+ unsigned int i;
+
+ bssid_str = g_string_sized_new(18);
+ if (!bssid_str) {
+ err = -ENOMEM;
+ goto done;
+ }
+
+ for (i = 0; i < WIFI_BSSID_LEN_MAX; i++) {
+ g_string_append_printf(bssid_str,
+ "%02x", service->last_connected_bssid[i]);
+ if (i < WIFI_BSSID_LEN_MAX - 1)
+ g_string_append(bssid_str, ":");
+ }
+
+ g_key_file_set_string(keyfile, identifier,
+ "LastConnectedBSSID", bssid_str->str);
+
+#if defined TIZEN_EXT_INS
+ DBG("last connected bssid[%s]", bssid_str->str);
+#endif
+
+ g_string_free(bssid_str, TRUE);
+ }
+
+ /* Assoc reject */
+ assoc_reject_table = connman_network_get_assoc_reject_table(service->network);
+ if (assoc_reject_table && g_hash_table_size(assoc_reject_table) > 0) {
+ GString *assoc_reject_str;
+ char **assoc_reject_list;
+ guint assoc_reject_len;
+
+ assoc_reject_str = g_string_new(NULL);
+ if (!assoc_reject_str) {
+ err = -ENOMEM;
+ goto done;
+ }
+
+ g_hash_table_foreach(assoc_reject_table, save_assoc_reject, assoc_reject_str);
+
+ assoc_reject_list = g_strsplit_set(assoc_reject_str->str, " ", 0);
+ assoc_reject_len = g_strv_length(assoc_reject_list);
+
+ g_key_file_set_string_list(keyfile, service->identifier,
+ "AssocReject", (const gchar **)assoc_reject_list, assoc_reject_len);
+
+#if defined TIZEN_EXT_INS
+ DBG("assoc reject table [%d]", assoc_reject_len);
+#endif
+
+ g_strfreev(assoc_reject_list);
+ g_string_free(assoc_reject_str, TRUE);
+ } else
+ g_key_file_remove_key(keyfile, service->identifier, "AssocReject", NULL);
+
+ /* Internet connection */
+ g_key_file_set_boolean(keyfile, service->identifier,
+ "InternetConnection", service->is_internet_connection);
+#if defined TIZEN_EXT_INS
+ DBG("internet connection [%s]", service->is_internet_connection ? "true" : "false");
+#endif
+#endif
}
/* fall through */
if (service->favorite)
g_key_file_set_boolean(keyfile, service->identifier,
"AutoConnect", service->autoconnect);
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ g_key_file_set_boolean(keyfile, service->identifier,
+ "UseEapol", service->use_eapol);
+#endif
break;
}
g_free(str);
}
- if (service->passphrase && strlen(service->passphrase) > 0)
+ if (service->passphrase && strlen(service->passphrase) > 0) {
+ char *enc = g_strescape(service->passphrase, NULL);
g_key_file_set_string(keyfile, service->identifier,
- "Passphrase", service->passphrase);
+ "Passphrase", enc);
+ g_free(enc);
+ }
if (service->ipconfig_ipv4)
__connman_ipconfig_save(service->ipconfig_ipv4, keyfile,
(const gchar **) service->nameservers_config, len);
}
+#if defined TIZEN_EXT
+ if(service->dns_config_method_ipv4 != 0) {
+ const char *method;
+ method = __connman_dnsconfig_method2string(
+ service->dns_config_method_ipv4);
+ g_key_file_set_string(keyfile, service->identifier,
+ "Nameservers.IPv4method", method);
+ } else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "Nameservers.IPv4method", NULL);
+
+ if(service->dns_config_method_ipv6 != 0) {
+ const char *method;
+ method = __connman_dnsconfig_method2string(
+ service->dns_config_method_ipv6);
+ g_key_file_set_string(keyfile, service->identifier,
+ "Nameservers.IPv6method", method);
+ } else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "Nameservers.IPv6method", NULL);
+#endif
+
if (service->timeservers_config) {
guint len = g_strv_length(service->timeservers_config);
"mDNS", TRUE);
if (service->hidden_service)
- g_key_file_set_boolean(keyfile, service->identifier, "Hidden",
- TRUE);
+ g_key_file_set_boolean(keyfile, service->identifier,
+ "Hidden", TRUE);
if (service->config_file && strlen(service->config_file) > 0)
g_key_file_set_string(keyfile, service->identifier,
"Config.file", service->config_file);
- if (service->config_entry &&
- strlen(service->config_entry) > 0)
+ if (service->config_entry && strlen(service->config_entry) > 0)
g_key_file_set_string(keyfile, service->identifier,
"Config.ident", service->config_entry);
+#if defined TIZEN_EXT
+ if ((service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+ service->security == CONNMAN_SERVICE_SECURITY_8021X)
+#if defined TIZEN_EXT_EAP_ON_ETHERNET
+ || (service->type == CONNMAN_SERVICE_TYPE_ETHERNET)
+#endif
+ ) {
+ if (service->eap != NULL && strlen(service->eap) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "EAP", service->eap);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "EAP", NULL);
+
+ if (service->phase2 != NULL && strlen(service->phase2) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "Phase2", service->phase2);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "Phase2", NULL);
+
+ if (service->identity != NULL && strlen(service->identity) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "Identity", service->identity);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "Identity", NULL);
+#if defined TIZEN_EXT_EAP_ON_ETHERNET
+ if (service->anonymous_identity != NULL && strlen(service->anonymous_identity) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "AnonymousIdentity", service->anonymous_identity);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "AnonymousIdentity", NULL);
+#endif
+
+ if (service->ca_cert_file != NULL && strlen(service->ca_cert_file) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "CACertFile", service->ca_cert_file);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "CACertFile", NULL);
+
+ if (service->client_cert_file != NULL && strlen(service->client_cert_file) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "ClientCertFile", service->client_cert_file);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "ClientCertFile", NULL);
+
+ if (service->private_key_file != NULL && strlen(service->private_key_file) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "PrivateKeyFile", service->private_key_file);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "PrivateKeyFile", NULL);
+
+ if (service->private_key_passphrase != NULL && strlen(service->private_key_passphrase) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "PrivateKeyPassphrase", service->private_key_passphrase);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "PrivateKeyPassphrase", NULL);
+#if defined TIZEN_EXT_EAP_ON_ETHERNET
+ if (service->phase1 != NULL && strlen(service->phase1) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "Phase1", service->phase1);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "Phase1", NULL);
+ if (service->pac_file != NULL && strlen(service->pac_file) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "PacFile", service->pac_file);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "PacFile", NULL);
+#endif
+ }
+
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+ service->security == CONNMAN_SERVICE_SECURITY_DPP) {
+ if (service->connector != NULL && strlen(service->connector) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "Connector", service->connector);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "Connector", NULL);
+
+ if (service->c_sign_key != NULL && strlen(service->c_sign_key) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "CSignKey", service->c_sign_key);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "CSignKey", NULL);
+
+ if (service->net_access_key != NULL && strlen(service->net_access_key) > 0)
+ g_key_file_set_string(keyfile, service->identifier,
+ "NetAccessKey", service->net_access_key);
+ else
+ g_key_file_remove_key(keyfile, service->identifier,
+ "NetAccessKey", NULL);
+ }
+#endif
+
done:
__connman_storage_save_service(keyfile, service->identifier);
return err;
}
+#if defined TIZEN_EXT
+static gint sort_entry(gconstpointer a, gconstpointer b, gpointer user_data)
+{
+ GTimeVal *aval = (GTimeVal *)a;
+ GTimeVal *bval = (GTimeVal *)b;
+
+ /* Note that the sort order is ascending */
+ if (aval->tv_sec > bval->tv_sec)
+ return 1;
+
+ if (aval->tv_sec < bval->tv_sec)
+ return -1;
+
+ return 0;
+}
+
+static void free_entry(gpointer data)
+{
+ struct saved_profiles *entry = data;
+ g_free(entry->profile_name);
+ g_free(entry);
+}
+
+static void __connman_manage_saved_profiles()
+{
+ GKeyFile *keyfile;
+ gchar **services = NULL;
+ GTimeVal modified;
+ int i, num_profiles = 0;
+ GSequenceIter *iter;
+ GSequence *profile_list;
+ struct saved_profiles *entry;
+
+ profile_list = g_sequence_new(free_entry);
+ if (!profile_list)
+ return;
+
+ services = connman_storage_get_services();
+
+ /* Check the count of saved profiles */
+ for (i = 0; services && services[i]; i++) {
+ if (strncmp(services[i], "wifi_", 5) != 0)
+ continue;
+
+ keyfile = connman_storage_load_service(services[i]);
+ if (!keyfile)
+ continue;
+
+ gchar *str = g_key_file_get_string(keyfile,
+ services[i], "Modified", NULL);
+ if (!str) {
+ g_key_file_free(keyfile);
+ continue;
+ }
+
+ g_time_val_from_iso8601(str, &modified);
+ g_free(str);
+
+ entry = g_try_new(struct saved_profiles, 1);
+ if (!entry) {
+ g_sequence_free(profile_list);
+ g_key_file_free(keyfile);
+ g_strfreev(services);
+ return;
+ }
+
+ entry->modified = modified;
+ entry->profile_name = g_strdup(services[i]);
+
+ g_sequence_insert_sorted(profile_list, entry,
+ sort_entry, NULL);
+
+ num_profiles++;
+ }
+ DBG("number of profiles: %d", num_profiles);
+
+ if (num_profiles > MAX_WIFI_PROFILES) {
+ iter = g_sequence_get_begin_iter(profile_list);
+
+ entry = g_sequence_get(iter);
+
+ if (__connman_storage_remove_service(entry->profile_name) == false)
+ DBG("Failed to remove service profile: %s", entry->profile_name);
+ }
+
+ g_sequence_free(profile_list);
+ g_strfreev(services);
+}
+#endif
+
void __connman_service_save(struct connman_service *service)
{
if (!service)
return;
service_save(service);
+#if defined TIZEN_EXT
+ /*
+ * Description: Manage the wireless profiles saved in connman.
+ * If the number of saved profiles is more than 200, remove the
+ * profile that is not updated for longer duration.
+ */
+ __connman_manage_saved_profiles();
+#endif
}
static enum connman_service_state combine_state(
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();
- const char *global_dns = connman_option_get_string("GlobalNameserver");
+#if defined TIZEN_EXT
++ const char *global_dns = connman_setting_get_string("GlobalNameserver");
+ if (global_dns)
+ nameserver_add(service, type, global_dns);
+#endif
+
searchdomain_add_all(service);
return 0;
if (index < 0)
return -ENXIO;
+#if defined TIZEN_EXT
+ DBG("Resolver remove nameserver: %s", nameserver);
+#endif
ret = connman_resolver_remove(index, NULL, nameserver);
if (ret >= 0)
nameservers_changed(service);
static int nameserver_remove_all(struct connman_service *service,
enum connman_ipconfig_type type)
{
+#if defined TIZEN_EXT
+ /**
+ * Skip this function if there is any connected profiles
+ * that use same interface
+ */
+ if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
+ __connman_service_get_connected_count_of_iface(service) > 0)
+ return 0;
+#endif
int index, i = 0;
index = __connman_service_get_index(service);
while (service->nameservers_config && service->nameservers_config[i]) {
+#if defined TIZEN_EXT
+ DBG("type %d Remove service->nameservers_config[%d]: %s",
+ type, i, service->nameservers_config[i]);
+ switch(type) {
+ case CONNMAN_IPCONFIG_TYPE_IPV4:
+ if (connman_inet_check_ipaddress(
+ service->nameservers_config[i]) == AF_INET &&
+ (service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP ||
+ service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL)) {
+ nameserver_remove(service, type,
+ service->nameservers_config[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_IPV6:
+ if (connman_inet_check_ipaddress(
+ service->nameservers_config[i]) == AF_INET6 &&
+ (service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP ||
+ service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL)) {
+ nameserver_remove(service, type,
+ service->nameservers_config[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_ALL:
+ if (connman_inet_check_ipaddress(
+ service->nameservers_config[i]) == AF_INET &&
+ (service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP ||
+ service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL)) {
+ nameserver_remove(service, type,
+ service->nameservers_config[i]);
+ }
+ if (connman_inet_check_ipaddress(
+ service->nameservers_config[i]) == AF_INET6 &&
+ (service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP ||
+ service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL)) {
+ nameserver_remove(service, type,
+ service->nameservers_config[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
+ DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing");
+ break;
+ default:
+ DBG("default case do nothing");
+ break;
+ }
+#else
nameserver_remove(service, type,
service->nameservers_config[i]);
+#endif
i++;
}
i = 0;
while (service->nameservers && service->nameservers[i]) {
+#if defined TIZEN_EXT
+ DBG("type %d Remove service->nameservers[%d]: %s",type, i,
+ service->nameservers[i]);
+ switch(type) {
+ case CONNMAN_IPCONFIG_TYPE_IPV4:
+ if (connman_inet_check_ipaddress(
+ service->nameservers[i]) == AF_INET &&
+ (service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL ||
+ service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP)) {
+ nameserver_remove(service, type,
+ service->nameservers[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_IPV6:
+ if (connman_inet_check_ipaddress(
+ service->nameservers[i]) == AF_INET6 &&
+ (service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL ||
+ service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP)) {
+ nameserver_remove(service, type,
+ service->nameservers[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_ALL:
+ if (connman_inet_check_ipaddress(
+ service->nameservers[i]) == AF_INET &&
+ (service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL ||
+ service->dns_config_method_ipv4 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP)) {
+ nameserver_remove(service, type,
+ service->nameservers[i]);
+ }
+ if (connman_inet_check_ipaddress(
+ service->nameservers[i]) == AF_INET6 &&
+ (service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_MANUAL ||
+ service->dns_config_method_ipv6 ==
+ CONNMAN_DNSCONFIG_METHOD_DHCP)) {
+ nameserver_remove(service, type,
+ service->nameservers[i]);
+ }
+ break;
+ case CONNMAN_IPCONFIG_TYPE_UNKNOWN:
+ DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing");
+ break;
+ default:
+ DBG("default case do nothing");
+ break;
+ }
+#else
nameserver_remove(service, type, service->nameservers[i]);
+#endif
i++;
}
- const char *global_dns = connman_option_get_string("GlobalNameserver");
+#if defined TIZEN_EXT
++ const char *global_dns = connman_setting_get_string("GlobalNameserver");
+ if (global_dns)
+ nameserver_remove(service, type, global_dns);
+#endif
searchdomain_remove_all(service);
return 0;
* inserted to resolver via netlink message (see rtnl.c:rtnl_newnduseropt()
* for details) and not through service.c
*/
+#if defined TIZEN_EXT
+int __connman_service_nameserver_append(struct connman_service *service,
+ const char *nameserver, bool is_auto,
+ enum connman_ipconfig_type type)
+#else
int __connman_service_nameserver_append(struct connman_service *service,
const char *nameserver, bool is_auto)
+#endif
{
char **nameservers;
int len, i;
if (nameservers) {
for (i = 0; nameservers[i]; i++) {
+#if defined TIZEN_EXT
+ DBG("nameservers[%d] %s, nameserver %s", i, nameservers[i], nameserver);
+#endif
if (g_strcmp0(nameservers[i], nameserver) == 0)
return -EEXIST;
}
nameservers[len] = g_strdup(nameserver);
nameservers[len + 1] = NULL;
+#ifdef TIZEN_EXT
+ if(type == CONNMAN_IPCONFIG_TYPE_IPV4 &&
+ service->dns_config_method_ipv4 == CONNMAN_DNSCONFIG_METHOD_UNKNOWN)
+ service->dns_config_method_ipv4 = CONNMAN_DNSCONFIG_METHOD_DHCP;
+
+ if(type == CONNMAN_IPCONFIG_TYPE_IPV6 &&
+ service->dns_config_method_ipv6 == CONNMAN_DNSCONFIG_METHOD_UNKNOWN)
+ service->dns_config_method_ipv6 = CONNMAN_DNSCONFIG_METHOD_DHCP;
+#endif
+
if (is_auto) {
service->nameservers_auto = nameservers;
} else {
return 0;
}
+#if defined TIZEN_EXT
+int __connman_service_nameserver_remove(struct connman_service *service,
+ const char *nameserver, bool is_auto,
+ enum connman_ipconfig_type type)
+#else
int __connman_service_nameserver_remove(struct connman_service *service,
const char *nameserver, bool is_auto)
+#endif
{
char **servers, **nameservers;
bool found = false;
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;
"Default service remains in READY state.");
return;
}
+ enable_online_to_ready_transition =
+ connman_setting_get_bool("EnableOnlineToReadyTransition");
+ online_check_initial_interval =
+ connman_setting_get_uint("OnlineCheckInitialInterval");
+ online_check_max_interval =
+ connman_setting_get_uint("OnlineCheckMaxInterval");
if (type != CONNMAN_IPCONFIG_TYPE_IPV4 || check_proxy_setup(service)) {
cancel_online_check(service);
g_timer_reset(service->stats_roaming.timer);
}
+#if defined TIZEN_EXT
+static gboolean __connman_service_is_internet_profile(
+ struct connman_service *cellular)
+{
+ const char internet_suffix[] = "_1";
+
+ DBG("Service path: %s", cellular->path);
+
+ if (g_str_has_suffix(cellular->path, internet_suffix) == TRUE)
+ return TRUE;
+
+ return FALSE;
+}
+
+struct connman_service *connman_service_get_default_connection(void)
+{
+ GList *list;
+ struct connman_service *service;
+ struct connman_service *default_service = NULL;
+
+ for (list = service_list; list; list = list->next) {
+ service = list->data;
+
+ DBG("service: %p %s %s %s", service, service->name,
+ state2string(service->state),
+ __connman_service_type2string(service->type));
+
+#if defined TIZEN_MAINTAIN_ONLINE
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+ service->state == CONNMAN_SERVICE_STATE_ONLINE) {
+#else
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI &&
+ is_connected(service->state) == TRUE) {
+#endif
+ return service;
+ } else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
+ __connman_service_is_internet_profile(service) == TRUE) {
+ if (default_service == NULL)
+ default_service = service;
+ else if (is_connected(service->state) == TRUE &&
+ is_connected(default_service->state) == FALSE)
+ default_service = service;
+ } else if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET &&
+ is_connected(service->state) == TRUE) {
+ if (default_service == NULL)
+ default_service = service;
+ } else if (service->type == CONNMAN_SERVICE_TYPE_BLUETOOTH &&
+ is_connected(service->state) == TRUE) {
+ if (default_service == NULL)
+ default_service = service;
+ }
+ }
+
+ return default_service;
+}
+
+struct connman_service *connman_service_get_connected_service(const char *ifname)
+{
+ GList *list;
+ const char *svc_ifname;
+ struct connman_service *service;
+
+ if (!ifname)
+ return NULL;
+
+ for (list = service_list; list; list = list->next) {
+ service = list->data;
+
+ if (!is_connected(service->state))
+ continue;
+
+ svc_ifname = connman_device_get_string(
+ connman_network_get_device(service->network), "Interface");
+
+ if (svc_ifname && g_strcmp0(svc_ifname, ifname) == 0)
+ return service;
+ }
+
+ return NULL;
+}
+#endif
+
struct connman_service *connman_service_get_default(void)
{
+#if defined TIZEN_MAINTAIN_ONLINE
+ return connman_service_get_default_connection();
+#else
struct connman_service *service;
if (!service_list)
return NULL;
return service;
+#endif
}
bool __connman_service_index_is_default(int index)
static void default_changed(void)
{
+#if defined TIZEN_EXT
+ struct connman_service *service = connman_service_get_default_connection();
+#else
struct connman_service *service = connman_service_get_default();
+#endif
if (service == current_default)
return;
current_default ? current_default->identifier : "");
DBG("new default %p %s", service, service ? service->identifier : "");
+#if defined TIZEN_EXT
+ current_default = service;
+
+ __connman_service_timeserver_changed(service, NULL);
+#else
__connman_service_timeserver_changed(current_default, NULL);
current_default = service;
+#endif
if (service) {
if (service->hostname &&
connman_setting_get_bool("AllowDomainnameUpdates"))
__connman_utsname_set_domainname(service->domainname);
+ if (__connman_service_is_connected_state(service,
+ CONNMAN_IPCONFIG_TYPE_IPV4))
+ __connman_service_wispr_start(service,
+ CONNMAN_IPCONFIG_TYPE_IPV4);
+
+ if (__connman_service_is_connected_state(service,
+ CONNMAN_IPCONFIG_TYPE_IPV6))
+ __connman_service_wispr_start(service,
+ CONNMAN_IPCONFIG_TYPE_IPV6);
+
/*
* Connect VPN automatically when new default service
* is set and connected, unless new default is VPN
__connman_notifier_default_changed(service);
}
+#if defined TIZEN_EXT
+static void append_struct(gpointer value, gpointer user_data);
+
+static void emit_state_changed_with_properties(struct connman_service *service)
+{
+ DBusMessage *signal;
+ DBusMessageIter iter;
+
+ if (!service)
+ return;
+
+ signal = dbus_message_new_signal(service->path, CONNMAN_SERVICE_INTERFACE,
+ "StateChangedProperties");
+ if (!signal)
+ return;
+
+ dbus_message_iter_init_append(signal, &iter);
+ append_struct(service, &iter);
+
+ g_dbus_send_message(connection, signal);
+
+ return;
+}
+#endif
+
static void state_changed(struct connman_service *service)
{
const char *str;
if (!str)
return;
+#if !defined TIZEN_EXT
if (!allow_property_changed(service))
return;
+#else
+ DBG(" %s, %s", str, service->path);
+#endif
connman_dbus_property_changed_basic(service->path,
CONNMAN_SERVICE_INTERFACE, "State",
DBUS_TYPE_STRING, &str);
+
+#if defined TIZEN_EXT
+ emit_state_changed_with_properties(service);
+#endif
+}
+
+#if defined TIZEN_EXT
+static void connect_reason_changed(struct connman_service *service)
+{
+#if defined TIZEN_EXT_INS
+ struct connman_device *device;
+#endif
+ if (!service->path)
+ return;
+
+ if (!allow_property_changed(service))
+ return;
+
+#if defined TIZEN_EXT_INS
+ if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) {
+ device = connman_network_get_device(service->network);
+ if (device) {
+ bool need_save = false;
+
+ need_save |= connman_device_set_last_user_selection_ident(device, service->identifier);
+ need_save |= connman_device_set_last_user_selection_time(device, time(NULL));
+
+ DBG("last user selection ident[%s] time[%ld]",
+ connman_device_get_last_user_selection_ident(device),
+ connman_device_get_last_user_selection_time(device));
+
+ if (need_save)
+ connman_device_save_last_user_selection(device);
+ }
+ }
+#endif
+
+ connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE,
+ "ConnectReason",
+ DBUS_TYPE_INT32,
+ &service->connect_reason);
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
+#if defined TIZEN_EXT
+static void disconnection_requested_changed(struct connman_service *service)
+{
+ dbus_bool_t disconnection_requested;
+
+ if (!service->path)
+ return;
+
+ if (!allow_property_changed(service))
+ return;
+
+ disconnection_requested = service->disconnection_requested;
+ connman_dbus_property_changed_basic(service->path,
+ CONNMAN_SERVICE_INTERFACE,
+ "DisconnectionRequested",
+ DBUS_TYPE_BOOLEAN,
+ &disconnection_requested);
+}
+
+void connman_service_set_disconnection_requested(struct connman_service *service,
+ bool disconnection_requested)
+{
+ if (service == NULL)
+ return;
+
+ service->disconnection_requested = disconnection_requested;
+ disconnection_requested_changed(service);
}
+#endif
static void strength_changed(struct connman_service *service)
{
DBUS_TYPE_BYTE, &service->strength);
}
+#if defined TIZEN_EXT
+static bool update_last_connected_bssid(struct connman_service *service)
+{
+ const unsigned char *last_connected_bssid;
+
+ if (!service->network)
+ return false;
+
+ last_connected_bssid = connman_network_get_last_connected_bssid(service->network);
+ if (memcmp(last_connected_bssid, invalid_bssid, WIFI_BSSID_LEN_MAX) == 0)
+ return false;
+
+ if (memcmp(last_connected_bssid, service->last_connected_bssid, WIFI_BSSID_LEN_MAX) != 0) {
+ memcpy(service->last_connected_bssid, last_connected_bssid, WIFI_BSSID_LEN_MAX);
+ return true;
+ }
+
+ return false;
+}
+#endif
+
static void favorite_changed(struct connman_service *service)
{
dbus_bool_t favorite;
service->autoconnect = autoconnect;
autoconnect_changed(service);
+ connman_network_set_autoconnect(service->network, autoconnect);
+
return true;
}
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)
{
return;
/*
+ * Only user interaction should get VPN or WIFI connected in failure
+ * state.
+ */
+ if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
+ reason != CONNMAN_SERVICE_CONNECT_REASON_USER &&
+ (service->type == CONNMAN_SERVICE_TYPE_VPN ||
+ service->type == CONNMAN_SERVICE_TYPE_WIFI))
+ return;
+
+ /*
+ * Do not use the builtin auto connect, instead rely on the
+ * native auto connect feature of the service.
+ */
+ if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_NATIVE)
+ return;
+
+ /*
* Run service auto connect for other than VPN services. Afterwards
* start also VPN auto connect process.
*/
if (service->type != CONNMAN_SERVICE_TYPE_VPN)
__connman_service_auto_connect(reason);
- /* Only user interaction should get VPN connected in failure state. */
- else if (service->state == CONNMAN_SERVICE_STATE_FAILURE &&
- reason != CONNMAN_SERVICE_CONNECT_REASON_USER)
- return;
vpn_auto_connect();
}
return err;
}
- /*
- * We set the timeout to 1 sec so that we have a chance to get
- * necessary IPv6 router advertisement messages that might have
- * DNS data etc.
- */
- #define ONLINE_CHECK_INITIAL_INTERVAL 1
- #define ONLINE_CHECK_MAX_INTERVAL 12
-
void __connman_service_wispr_start(struct connman_service *service,
enum connman_ipconfig_type type)
{
if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
service->online_check_interval_ipv4 =
- ONLINE_CHECK_INITIAL_INTERVAL;
+ online_check_initial_interval;
else
service->online_check_interval_ipv6 =
- ONLINE_CHECK_INITIAL_INTERVAL;
+ online_check_initial_interval;
__connman_wispr_start(service, type);
}
GString *str;
int index;
const char *gw;
+#if defined TIZEN_EXT
+ enum connman_ipconfig_type ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
+ DBG("%s", name);
+#endif
if (__connman_provider_is_immutable(service->provider) ||
service->immutable)
gw = __connman_ipconfig_get_gateway_from_index(index,
CONNMAN_IPCONFIG_TYPE_ALL);
+#if !defined TIZEN_EXT
if (gw && strlen(gw))
__connman_service_nameserver_del_routes(service,
CONNMAN_IPCONFIG_TYPE_ALL);
+#endif
dbus_message_iter_recurse(&value, &entry);
+#if defined TIZEN_EXT
+ /* IPv4/IPv6 Last DNS config method */
+ int last_dns_ipv4 = service->dns_config_method_ipv4;
+ int last_dns_ipv6 = service->dns_config_method_ipv6;
+ DBG("Last DNS Config Method IPv4: %d IPv6: %d", last_dns_ipv4, last_dns_ipv6);
+#endif
+
while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) {
const char *val;
dbus_message_iter_get_basic(&entry, &val);
dbus_message_iter_next(&entry);
+#ifdef TIZEN_EXT
+ /* First unpack the DNS Config Method */
+ DBG("DNS Config Method: %s", val);
+ if((g_strcmp0(val, "ipv4.manual") == 0)) {
+ service->dns_config_method_ipv4 =
+ CONNMAN_DNSCONFIG_METHOD_MANUAL;
+
+ if(last_dns_ipv4 != CONNMAN_DNSCONFIG_METHOD_MANUAL) {
+ if(ip_type == CONNMAN_IPCONFIG_TYPE_UNKNOWN)
+ ip_type = CONNMAN_IPCONFIG_TYPE_IPV4;
+ else
+ ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
+ }
+ continue;
+ } else if(g_strcmp0(val, "ipv4.dhcp") == 0) {
+ service->dns_config_method_ipv4 =
+ CONNMAN_DNSCONFIG_METHOD_DHCP;
+ if(last_dns_ipv4 == CONNMAN_DNSCONFIG_METHOD_MANUAL)
+ ip_type = CONNMAN_IPCONFIG_TYPE_IPV4;
+
+ continue;
+ } else if(g_strcmp0(val, "ipv6.manual") == 0) {
+ service->dns_config_method_ipv6 =
+ CONNMAN_DNSCONFIG_METHOD_MANUAL;
+ if(last_dns_ipv6 != CONNMAN_DNSCONFIG_METHOD_MANUAL) {
+ if(ip_type == CONNMAN_IPCONFIG_TYPE_UNKNOWN)
+ ip_type = CONNMAN_IPCONFIG_TYPE_IPV6;
+ else
+ ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
+ }
+ continue;
+ } else if(g_strcmp0(val, "ipv6.dhcp") == 0) {
+ service->dns_config_method_ipv6 =
+ CONNMAN_DNSCONFIG_METHOD_DHCP;
+ if(last_dns_ipv6 == CONNMAN_DNSCONFIG_METHOD_MANUAL)
+ ip_type = CONNMAN_IPCONFIG_TYPE_IPV6;
+ continue;
+ }
+#endif
if (!val[0])
continue;
g_string_append(str, val);
}
+#if defined TIZEN_EXT
+ if (service->dns_config_method_ipv4 == CONNMAN_DNSCONFIG_METHOD_DHCP &&
+ service->dns_config_method_ipv6 == CONNMAN_DNSCONFIG_METHOD_DHCP) {
+ DBG("Both IPv4 and IPv6 DNS Method DHCP");
+ ip_type = CONNMAN_IPCONFIG_TYPE_ALL;
+ }
+ if (gw && strlen(gw))
+ __connman_service_nameserver_del_routes(service,
+ ip_type);
+
+ DBG("%s ip_type: %d nameserver remove all", name, ip_type);
+ nameserver_remove_all(service, ip_type);
+#else
nameserver_remove_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
+#endif
g_strfreev(service->nameservers_config);
if (str->len > 0) {
if (gw && strlen(gw))
__connman_service_nameserver_add_routes(service, gw);
+#if defined TIZEN_EXT
+ DBG("%s ip_type: %d nameserver add all", name, ip_type);
+ nameserver_add_all(service, ip_type);
+#else
nameserver_add_all(service, CONNMAN_IPCONFIG_TYPE_ALL);
+#endif
dns_configuration_changed(service);
if (__connman_service_is_connected_state(service,
service_save(service);
timeservers_configuration_changed(service);
-
- if (service == connman_service_get_default())
- __connman_timeserver_sync(service);
+ __connman_timeserver_conf_update(service);
} else if (g_str_equal(name, "Domains.Configuration")) {
DBusMessageIter entry;
}
service_save(service);
+#if defined TIZEN_EXT
+ /* When AP is connected using WPS without SSID then its password needs
+ * to be saved for autoconnection */
+ } else if (g_str_equal(name, "Passphrase")) {
+ char *passphrase;
+
+ if (type != DBUS_TYPE_STRING)
+ return __connman_error_invalid_arguments(msg);
+
+ dbus_message_iter_get_basic(&value, &passphrase);
+
+ __connman_service_set_passphrase(service, passphrase);
+#endif
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ } else if (g_str_equal(name, "EapOverEthernet")) {
+ int err = connman_service_set_eapol_property(service, &value);
+ if (err < 0)
+ return __connman_error_failed(msg, -err);
+
+ service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_USER;
+ service_save(service);
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
} else
return __connman_error_invalid_property(msg);
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);
+ continue;
+ }
+
if (service->pending ||
is_connecting(service->state) ||
is_connected(service->state)) {
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
+ int index = connman_network_get_index(service->network);
+ wifi_ignore = g_slist_prepend(wifi_ignore, GINT_TO_POINTER(index));
+
+ autoconnecting = true;
+ continue;
+ }
+#else
if (autoconnect_no_session_active(service))
return true;
-
+#endif
ignore[service->type] = true;
autoconnecting = true;
if (preferred)
continue;
+#if defined TIZEN_EXT
+ DBG("Service is not favorite, autoconnecting %d",
+ autoconnecting);
+ g_slist_free(wifi_ignore);
+#endif
return autoconnecting;
}
+#if defined TIZEN_EXT
+ DBG("service %p identifier %s roaming %d ignore %d "
+ "ipconfig_usable %d autoconnect %d state %d",
+ service,
+ service->identifier, service->roaming,
+ service->ignore, is_ipconfig_usable(service),
+ service->autoconnect, service->state);
+#endif
if (is_ignore(service) || service->state !=
CONNMAN_SERVICE_STATE_IDLE)
continue;
-
+#if defined TIZEN_EXT
+ if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
+#endif
if (autoconnect_already_connecting(service, autoconnecting)) {
DBG("service %p type %s has no users", service,
__connman_service_type2string(service->type));
DBG("service %p %s %s", service, service->name,
(preferred) ? "preferred" : reason2string(reason));
+#if defined TIZEN_EXT
+ __connman_service_connect(service, reason);
+#else
if (__connman_service_connect(service, reason) == 0)
service_indicate_state(service);
if (autoconnect_no_session_active(service))
return true;
-
+#endif
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_WIFI) {
+ int index = connman_network_get_index(service->network);
+ wifi_ignore = g_slist_prepend(wifi_ignore, GINT_TO_POINTER(index));
+ autoconnecting = true;
+ }
+#endif
ignore[service->type] = true;
}
-
+#if defined TIZEN_EXT
+ g_slist_free(wifi_ignore);
+#endif
return autoconnecting;
}
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))
- break;
+ continue;
if (service == temp)
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);
services_notify->id = g_timeout_add(100, service_send_changed, NULL);
}
- static DBusMessage *move_service(DBusConnection *conn,
- DBusMessage *msg, void *user_data,
- bool before)
+ int __connman_service_move(struct connman_service *service,
+ struct connman_service *target, bool before)
{
- struct connman_service *service = user_data;
- struct connman_service *target;
- const char *path;
enum connman_ipconfig_method target4, target6;
enum connman_ipconfig_method service4, service6;
DBG("service %p", service);
- dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
- DBUS_TYPE_INVALID);
+ if (!service)
+ return -EINVAL;
if (!service->favorite)
- return __connman_error_not_supported(msg);
+ return -EOPNOTSUPP;
- target = find_service(path);
if (!target || !target->favorite || target == service)
- return __connman_error_invalid_service(msg);
+ return -EINVAL;
if (target->type == CONNMAN_SERVICE_TYPE_VPN) {
/*
connman_info("Cannot move service. "
"No routes defined for provider %s",
__connman_provider_get_ident(target->provider));
- return __connman_error_invalid_service(msg);
+ return -EINVAL;
}
- set_split_routing(target, true);
+ __connman_service_set_split_routing(target, true);
} else
- set_split_routing(target, false);
+ __connman_service_set_split_routing(target, false);
- set_split_routing(service, false);
+ __connman_service_set_split_routing(service, false);
target4 = __connman_ipconfig_get_method(target->ipconfig_ipv4);
target6 = __connman_ipconfig_get_method(target->ipconfig_ipv6);
if (service6 != CONNMAN_IPCONFIG_METHOD_OFF) {
if (!check_suitable_state(target->state_ipv6,
service->state_ipv6))
- return __connman_error_invalid_service(msg);
+ return -EINVAL;
}
}
if (service4 != CONNMAN_IPCONFIG_METHOD_OFF) {
if (!check_suitable_state(target->state_ipv4,
service->state_ipv4))
- return __connman_error_invalid_service(msg);
+ return -EINVAL;
}
}
if (target6 != CONNMAN_IPCONFIG_METHOD_OFF) {
if (!check_suitable_state(target->state_ipv6,
service->state_ipv6))
- return __connman_error_invalid_service(msg);
+ return -EINVAL;
}
}
if (target4 != CONNMAN_IPCONFIG_METHOD_OFF) {
if (!check_suitable_state(target->state_ipv4,
service->state_ipv4))
- return __connman_error_invalid_service(msg);
+ return -EINVAL;
}
}
service_schedule_changed();
+ return 0;
+ }
+
+ static DBusMessage *move_service(DBusConnection *conn,
+ DBusMessage *msg, void *user_data,
+ bool before)
+ {
+ struct connman_service *service = user_data;
+ struct connman_service *target;
+ const char *path;
+ int err;
+
+ DBG("service %p", service);
+
+ dbus_message_get_args(msg, NULL, DBUS_TYPE_OBJECT_PATH, &path,
+ DBUS_TYPE_INVALID);
+
+ target = find_service(path);
+
+ err = __connman_service_move(service, target, before);
+ switch (err) {
+ case 0:
+ break;
+ case -EINVAL:
+ return __connman_error_invalid_service(msg);
+ case -EOPNOTSUPP:
+ return __connman_error_not_supported(msg);
+ default:
+ connman_warn("unsupported error code %d in move_service()",
+ err);
+ break;
+ }
+
return g_dbus_create_reply(msg, DBUS_TYPE_INVALID);
}
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;
- #endif
- #if defined TIZEN_EXT
+#if defined TIZEN_EXT
+ memset(service->last_connected_bssid, 0, WIFI_BSSID_LEN_MAX);
+ service->is_internet_connection = false;
+ service->assoc_reject_count = 0;
++
+ service->disconnection_requested = false;
+ service->storage_reload = false;
+ /*
+ * Description: TIZEN implements system global connection management.
+ */
+ service->user_pdn_connection_refcount = 0;
+ __sync_synchronize();
+#endif
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ service->use_eapol = false;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
}
/**
g_hash_table_remove(service_hash, service->identifier);
}
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+static int calculate_score_last_user_selection(struct connman_service *service)
+{
+ int score = 0;
+ struct connman_device *device;
+ const char *last_user_selection_ident;
+ time_t last_user_selection_time;
+ unsigned int frequency;
+ time_t curr_time;
+ time_t ref_time;
+ struct tm* ref_timeinfo;
+
+ device = connman_network_get_device(service->network);
+ if (!device)
+ return 0;
+
+ last_user_selection_time = connman_device_get_last_user_selection_time(device);
+ last_user_selection_ident = connman_device_get_last_user_selection_ident(device);
+ frequency = connman_network_get_frequency(service->network);
+
+ if (ins_settings.last_user_selection) {
+ if (g_strcmp0(last_user_selection_ident, service->identifier) == 0 &&
+ (((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
+ frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
+ service->strength >= ins_settings.signal_level3_24ghz) ||
+ ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
+ frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
+ service->strength >= ins_settings.signal_level3_5ghz))) {
+
+ /* Only events that occur within 8 hours are counted. */
+ curr_time = time(NULL);
+ ref_timeinfo = localtime(&curr_time);
+ ref_timeinfo->tm_hour -= 8;
+ ref_time = mktime(ref_timeinfo);
+
+ if (last_user_selection_time > ref_time) {
+ int time_diff = (curr_time - last_user_selection_time) / 60;
+ int denominator = ins_settings.last_user_selection_time - time_diff;
+ int numerator = ins_settings.last_user_selection_time /
+ ins_settings.last_user_selection_score;
+ int last_user_score = denominator / numerator;
+
+ score += (last_user_score > ins_settings.last_user_selection_score ?
+ ins_settings.last_user_selection_score : last_user_score);
+ }
+ }
+ }
+
+ return score;
+}
+
+static int calculate_score_last_connected(struct connman_service *service)
+{
+ int score = 0;
+ struct connman_device *device;
+ const char *last_connected_ident;
+ unsigned int frequency;
+
+ device = connman_network_get_device(service->network);
+ if (!device)
+ return 0;
+
+ last_connected_ident = connman_device_get_last_connected_ident(device);
+ frequency = connman_network_get_frequency(service->network);
+
+ if (ins_settings.last_connected) {
+ if (g_strcmp0(last_connected_ident, service->identifier) == 0 &&
+ (((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
+ frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
+ service->strength >= ins_settings.signal_level3_24ghz) ||
+ ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
+ frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
+ service->strength >= ins_settings.signal_level3_5ghz))) {
+ score += ins_settings.last_connected_score;
+ }
+ }
+
+ return score;
+}
+
+static int calculate_score_frequency(struct connman_service *service)
+{
+ int score = 0;
+ unsigned int frequency;
+
+ frequency = connman_network_get_frequency(service->network);
+
+ switch (ins_settings.preferred_freq) {
+ case CONNMAN_INS_PREFERRED_FREQ_24GHZ:
+ if ((frequency >= FREQ_RANGE_24GHZ_CHANNEL_1 &&
+ frequency <= FREQ_RANGE_24GHZ_CHANNEL_14) &&
+ (service->strength >= ins_settings.signal_level3_24ghz))
+ score += ins_settings.preferred_freq_score;
+
+ break;
+ case CONNMAN_INS_PREFERRED_FREQ_5GHZ:
+ if ((frequency >= FREQ_RANGE_5GHZ_CHANNEL_32 &&
+ frequency <= FREQ_RANGE_5GHZ_CHANNEL_165) &&
+ (service->strength >= ins_settings.signal_level3_5ghz))
+ score += ins_settings.preferred_freq_score;
+
+ break;
+ default:
+ break;
+ }
+
+ return score;
+}
+
+static int calculate_score_security_priority(struct connman_service *service)
+{
+ int score = 0;
+
+ if (ins_settings.security_priority_count)
+ score += ins_settings.security_priority[service->security];
+
+ return score;
+}
+
+static int calculate_score_internet_connection(struct connman_service *service)
+{
+ int score = 0;
+
+ if (ins_settings.internet) {
+ if (service->is_internet_connection)
+ score += ins_settings.internet_score;
+ }
+
+ return score;
+}
+
+static int calculate_score_strength(struct connman_service *service)
+{
+ int score = 0;
+
+ if (ins_settings.signal)
+ score += (((service->strength > 60) ? 60 : service->strength) - 35);
+
+ return score;
+}
+
+static int calculate_score(struct connman_service *service)
+{
+ int score_last_user_selection;
+ int score_last_connected;
+ int score_frequency;
+ int score_security_priority;
+ int score_internet_connection;
+ int score_strength;
+ int score = 0;
+
+ if (service->type != CONNMAN_SERVICE_TYPE_WIFI) {
+ score += calculate_score_internet_connection(service);
+ service->ins_score = score;
+ return score;
+ }
+
+ score_last_user_selection = calculate_score_last_user_selection(service);
+ score_last_connected = calculate_score_last_connected(service);
+ score_frequency = calculate_score_frequency(service);
+ score_security_priority = calculate_score_security_priority(service);
+ score_internet_connection = calculate_score_internet_connection(service);
+ score_strength = calculate_score_strength(service);
+
+ score = score_last_user_selection + score_last_connected +
+ score_frequency + score_security_priority +
+ score_internet_connection + score_strength;
+
+ service->score_last_user_selection = score_last_user_selection;
+ service->score_last_connected = score_last_connected;
+ service->score_frequency = score_frequency;
+ service->score_security_priority = score_security_priority;
+ service->score_internet_connection = score_internet_connection;
+ service->score_strength = score_strength;
+
+ service->ins_score = score;
+ return score;
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
+ static gint service_compare(gconstpointer a, gconstpointer b);
+
+ static gint service_compare_vpn(struct connman_service *a,
+ struct connman_service *b)
+ {
+ struct connman_provider *provider;
+ struct connman_service *service;
+ struct connman_service *transport;
+ const char *ident;
+ bool reverse;
+
+ if (a->provider) {
+ provider = a->provider;
+ service = b;
+ reverse = false;
+ } else if (b->provider) {
+ provider = b->provider;
+ service = a;
+ reverse = true;
+ } else {
+ return 0;
+ }
+
+ ident = __connman_provider_get_transport_ident(provider);
+ transport = connman_service_lookup_from_identifier(ident);
+ if (!transport)
+ return 0;
+
+ if (reverse)
+ return service_compare(service, transport);
+
+ return service_compare(transport, service);
+ }
+
static gint service_compare(gconstpointer a, gconstpointer b)
{
struct connman_service *service_a = (void *) a;
struct connman_service *service_b = (void *) b;
enum connman_service_state state_a, state_b;
bool a_connected, b_connected;
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+ int score_a;
+ int score_b;
+#else /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
gint strength;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
state_a = service_a->state;
state_b = service_b->state;
a_connected = is_connected(state_a);
b_connected = is_connected(state_b);
- connman_option_get_string("DefaultWifiInterface");
+#if defined TIZEN_EXT
+ if ((a_connected && b_connected) &&
+ state_a == state_b &&
+ service_a->type == CONNMAN_SERVICE_TYPE_WIFI &&
+ service_b->type == CONNMAN_SERVICE_TYPE_WIFI) {
+ const char *default_interface =
++ connman_setting_get_string("DefaultWifiInterface");
+ const char *ifname_a = connman_device_get_string(
+ connman_network_get_device(service_a->network), "Interface");
+ const char *ifname_b = connman_device_get_string(
+ connman_network_get_device(service_b->network), "Interface");
+
+ if (g_strcmp0(default_interface, ifname_a) == 0)
+ return -1;
+ else if (g_strcmp0(default_interface, ifname_b) == 0)
+ return 1;
+ }
+#endif
+
if (a_connected && b_connected) {
+ int rval;
+
+ /* Compare the VPN transport and the service */
+ if ((service_a->type == CONNMAN_SERVICE_TYPE_VPN ||
+ service_b->type == CONNMAN_SERVICE_TYPE_VPN) &&
+ service_b->type != service_a->type) {
+ rval = service_compare_vpn(service_a, service_b);
+ if (rval)
+ return rval;
+ }
+
if (service_a->order > service_b->order)
return -1;
return 1;
}
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+ score_a = calculate_score(service_a);
+ score_b = calculate_score(service_b);
+ if (score_b != score_a)
+ return score_b - score_a;
+#else /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
strength = (gint) service_b->strength - (gint) service_a->strength;
if (strength)
return strength;
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
return g_strcmp0(service_a->name, service_b->name);
}
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+static void print_service_sort(gpointer data, gpointer user_data)
+{
+ struct connman_service *service = data;
+
+ if (service->type != CONNMAN_SERVICE_TYPE_WIFI)
+ return;
+
+ DBG("name[%-20s] total[%2d] last_usr[%2d] last_conn[%2d] "
+ "freq[%2d] sec[%2d] internet[%2d] strength[%2d]",
+ service->name, service->ins_score, service->score_last_user_selection,
+ service->score_last_connected, service->score_frequency,
+ service->score_security_priority, service->score_internet_connection,
+ service->score_strength);
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
static void service_list_sort(void)
{
if (service_list && service_list->next) {
service_list = g_list_sort(service_list, service_compare);
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+ g_list_foreach(service_list, print_service_sort, NULL);
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
service_schedule_changed();
}
}
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();
}
}
goto done;
}
- if (service->hidden && name_len > 0 && name_len <= 32) {
- device = connman_network_get_device(service->network);
- security = connman_network_get_string(service->network,
- "WiFi.Security");
- err = __connman_device_request_hidden_scan(device,
- name, name_len,
- identity, passphrase,
- security, user_data);
+ if (service->hidden) {
+ if (name_len > 0 && name_len <= 32) {
+ device = connman_network_get_device(service->network);
+ security = connman_network_get_string(service->network,
+ "WiFi.Security");
+ err = __connman_device_request_hidden_scan(device,
+ name, name_len,
+ identity, passphrase,
+ security, user_data);
+ } else {
+ err = -EINVAL;
+ }
if (err < 0)
__connman_service_return_error(service, -err,
user_data);
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),
report_error_cb,
get_dbus_sender(service),
NULL);
+ goto notifier;
}
service_complete(service);
break;
service_list_sort();
+#if defined TIZEN_EXT
+#if defined TIZEN_MAINTAIN_ONLINE
+ __connman_service_connect_default(service, old_state);
+#else
+ __connman_service_connect_default(service);
+#endif
+ /* Update Wi-Fi Roaming result */
+ if (connman_setting_get_bool("WifiRoaming") &&
+ connman_network_get_bool(service->network, "WiFi.Roaming")) {
+ const char *cur_bssid;
+ const char *dst_bssid;
+ const char *ifname;
+ struct connman_device *device;
+
+ device = connman_network_get_device(service->network);
+ if (device) {
+ ifname = connman_device_get_string(device, "Interface");
+ cur_bssid = connman_network_get_string(service->network,
+ "WiFi.RoamingCurBSSID");
+ dst_bssid = connman_network_get_string(service->network,
+ "WiFi.RoamingDstBSSID");
+ }
+
+ if (device && ifname && cur_bssid && dst_bssid) {
+ switch(new_state) {
+ case CONNMAN_SERVICE_STATE_UNKNOWN:
+ case CONNMAN_SERVICE_STATE_ASSOCIATION:
+ case CONNMAN_SERVICE_STATE_CONFIGURATION:
+ break;
+ case CONNMAN_SERVICE_STATE_READY:
+ case CONNMAN_SERVICE_STATE_ONLINE:
+ __connman_technology_notify_roaming_state(ifname,
+ "success", cur_bssid, dst_bssid);
+ connman_network_set_bool(service->network,
+ "WiFi.Roaming", false);
+ connman_network_set_string(service->network,
+ "WiFi.RoamingCurBSSID", NULL);
+ connman_network_set_string(service->network,
+ "WiFi.RoamingDstBSSID", NULL);
+ break;
+ case CONNMAN_SERVICE_STATE_DISCONNECT:
+ case CONNMAN_SERVICE_STATE_FAILURE:
+ case CONNMAN_SERVICE_STATE_IDLE:
+ __connman_technology_notify_roaming_state(ifname,
+ "failure", cur_bssid, dst_bssid);
+ connman_network_set_bool(service->network,
+ "WiFi.Roaming", false);
+ connman_network_set_string(service->network,
+ "WiFi.RoamingCurBSSID", NULL);
+ connman_network_set_string(service->network,
+ "WiFi.RoamingDstBSSID", NULL);
+ break;
+ }
+ }
+ }
+#endif
+
__connman_connection_update_gateway();
+ notifier:
if ((old_state == CONNMAN_SERVICE_STATE_ONLINE &&
new_state != CONNMAN_SERVICE_STATE_READY) ||
(old_state == CONNMAN_SERVICE_STATE_READY &&
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;
}
return FALSE;
}
- int __connman_service_online_check_failed(struct connman_service *service,
- enum connman_ipconfig_type type)
+ void __connman_service_online_check(struct connman_service *service,
+ enum connman_ipconfig_type type,
+ bool success)
{
GSourceFunc redo_func;
- int *interval;
+ unsigned int *interval;
+ enum connman_service_state current_state;
if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
interval = &service->online_check_interval_ipv4;
redo_func = redo_wispr_ipv6;
}
+ if(!enable_online_to_ready_transition)
+ goto redo_func;
+
+ if (success) {
+ *interval = online_check_max_interval;
+ } else {
+ current_state = service->state;
+ downgrade_state(service);
+ if (current_state != service->state)
+ *interval = online_check_initial_interval;
+ if (service != connman_service_get_default()) {
+ return;
+ }
+ }
+
+ redo_func:
DBG("service %p type %s interval %d", service,
__connman_ipconfig_type2string(type), *interval);
redo_func, connman_service_ref(service));
/* Increment the interval for the next time, set a maximum timeout of
- * ONLINE_CHECK_MAX_INTERVAL * ONLINE_CHECK_MAX_INTERVAL seconds.
+ * online_check_max_interval seconds * online_check_max_interval seconds.
*/
- if (*interval < ONLINE_CHECK_MAX_INTERVAL)
+ if (*interval < online_check_max_interval)
(*interval)++;
-
- return EAGAIN;
}
int __connman_service_ipconfig_indicate_state(struct connman_service *service,
connman_warn("ipconfig state %d ipconfig method %d",
new_state, method);
+#if defined TIZEN_EXT
+ if (old_state != CONNMAN_SERVICE_STATE_READY &&
+ old_state != CONNMAN_SERVICE_STATE_ONLINE)
+#endif
new_state = CONNMAN_SERVICE_STATE_IDLE;
break;
if (old_state == new_state)
return -EALREADY;
+#if defined TIZEN_EXT
+ __sync_synchronize();
+ if (service->user_pdn_connection_refcount > 0 &&
+ service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
+ if (new_state == CONNMAN_SERVICE_STATE_FAILURE ||
+ new_state == CONNMAN_SERVICE_STATE_DISCONNECT ||
+ new_state == CONNMAN_SERVICE_STATE_IDLE) {
+ service->user_pdn_connection_refcount = 0;
+ __sync_synchronize();
+ }
+#endif
+
DBG("service %p (%s) old state %d (%s) new state %d (%s) type %d (%s)",
service, service ? service->identifier : NULL,
old_state, state2string(old_state),
case CONNMAN_SERVICE_STATE_CONFIGURATION:
break;
case CONNMAN_SERVICE_STATE_READY:
+#if defined TIZEN_EXT
+ if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR &&
+ __connman_service_is_internet_profile(service) != TRUE) {
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
+ service_rp_filter(service, TRUE);
+
+ break;
+ }
+#endif
+ if (connman_setting_get_bool("EnableOnlineCheck"))
+ if (type == CONNMAN_IPCONFIG_TYPE_IPV4) {
+#if !defined TIZEN_EXT
+ check_proxy_setup(service);
+#endif
+#if defined TIZEN_MAINTAIN_ONLINE
+/* if (old_state == CONNMAN_SERVICE_STATE_ONLINE) */
+ check_proxy_setup(service);
+#endif
+ } else {
+ __connman_service_wispr_start(service, type);
+ }
+ else
+ connman_info("Online check disabled. "
+ "Default service remains in READY state.");
if (type == CONNMAN_IPCONFIG_TYPE_IPV4)
service_rp_filter(service, true);
set_mdns(service, service->mdns_config);
__connman_timeserver_sync(service);
+#if defined TIZEN_EXT
+ int ret = service_indicate_state(service);
+ /*Sent the Ready changed signal again in case IPv4 IP set
+ after IPv6 IP set*/
+
+ if(ret == -EALREADY && type == CONNMAN_IPCONFIG_TYPE_IPV4
+ && new_state == CONNMAN_SERVICE_STATE_READY) {
+ DBG("Notify IPv4 state new/old %d/%d", new_state,old_state);
+ state_changed(service);
+ }
+
+ return ret;
+#endif
return service_indicate_state(service);
}
if (service->phase2)
connman_network_set_string(service->network, "WiFi.Phase2",
service->phase2);
- #if defined TIZEN_EXT
+
+#if defined TIZEN_EXT
+ if (service->keymgmt_type)
+ connman_network_set_string(service->network, "WiFi.KeymgmtType",
+ service->keymgmt_type);
+
+ DBG("service->phase1 : %s", service->phase1);
+ if (service->phase1)
+ connman_network_set_string(service->network, "WiFi.Phase1",
+ service->phase1);
+#endif
+}
+
++#if defined TIZEN_EXT
+static bool has_valid_configuration_object(struct connman_service *service)
+{
+ return service->connector && service->c_sign_key && service->net_access_key;
}
+static void prepare_dpp(struct connman_service *service)
+{
+ DBG("prepare dpp");
+ if (service->connector)
+ connman_network_set_string(service->network, "WiFi.Connector",
+ service->connector);
+
+ if (service->c_sign_key)
+ connman_network_set_string(service->network, "WiFi.CSignKey",
+ service->c_sign_key);
+
+ if (service->net_access_key)
+ connman_network_set_string(service->network, "WiFi.NetAccessKey",
+ service->net_access_key);
+}
+#endif
+
static int service_connect(struct connman_service *service)
{
int err;
if (service->hidden)
return -EPERM;
+#if defined TIZEN_EXT
+ GList *list;
+ int index;
+
+ index = __connman_service_get_index(service);
+
+ for (list = service_list; list; list = list->next) {
+ struct connman_service *temp = list->data;
+
+ if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR)
+ break;
+
+ if (!is_connecting(temp->state) && !is_connected(temp->state))
+ break;
+
+ if (service == temp)
+ continue;
+
+ if (service->type != temp->type)
+ continue;
+
+ if (__connman_service_get_index(temp) == index &&
+ __connman_service_disconnect(temp) == -EINPROGRESS)
+ return -EINPROGRESS;
+ }
+#endif
+
switch (service->type) {
case CONNMAN_SERVICE_TYPE_UNKNOWN:
case CONNMAN_SERVICE_TYPE_SYSTEM:
case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
return -EINVAL;
case CONNMAN_SERVICE_TYPE_ETHERNET:
case CONNMAN_SERVICE_TYPE_GADGET:
switch (service->security) {
case CONNMAN_SERVICE_SECURITY_UNKNOWN:
case CONNMAN_SERVICE_SECURITY_NONE:
+#if defined TIZEN_EXT
+ case CONNMAN_SERVICE_SECURITY_OWE:
+#endif
break;
case CONNMAN_SERVICE_SECURITY_WEP:
case CONNMAN_SERVICE_SECURITY_PSK:
case CONNMAN_SERVICE_SECURITY_WPA:
case CONNMAN_SERVICE_SECURITY_RSN:
+#if defined TIZEN_EXT
+ case CONNMAN_SERVICE_SECURITY_SAE:
+#endif
if (service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY)
return -ENOKEY;
}
break;
+#if defined TIZEN_EXT
+ case CONNMAN_SERVICE_SECURITY_DPP:
+ if (has_valid_configuration_object(service) &&
+ !service->network)
+ return -EINVAL;
+ break;
+#endif
case CONNMAN_SERVICE_SECURITY_8021X:
if (!service->eap) {
connman_warn("EAP type has not been found. "
return -EINVAL;
}
+#if defined TIZEN_EXT
+ /*
+ * never request credentials if using EAP-TLS, EAP-SIM
+ * or EAP-AKA (EAP-TLS, EAP-SIM and EAP-AKA networks
+ * need to be fully provisioned)
+ */
+ DBG("service eap: %s", service->eap);
+ if (g_str_equal(service->eap, "tls") ||
+ g_str_equal(service->eap, "sim") ||
+ g_str_equal(service->eap, "aka") ||
+ g_str_equal(service->eap, "aka'") ||
+ g_str_equal(service->eap, "pwd") ||
+ g_str_equal(service->eap, "fast"))
+ break;
+#else
/*
* never request credentials if using EAP-TLS
* (EAP-TLS networks need to be fully provisioned)
if (g_str_equal(service->eap, "tls"))
break;
+#endif
/*
* Return -ENOKEY if either identity or passphrase is
* missing. Agent provided credentials can be used as
case CONNMAN_SERVICE_SECURITY_PSK:
case CONNMAN_SERVICE_SECURITY_WPA:
case CONNMAN_SERVICE_SECURITY_RSN:
+#if defined TIZEN_EXT
+ case CONNMAN_SERVICE_SECURITY_SAE:
+ case CONNMAN_SERVICE_SECURITY_OWE:
+ break;
+ case CONNMAN_SERVICE_SECURITY_DPP:
+ prepare_dpp(service);
+#endif
break;
case CONNMAN_SERVICE_SECURITY_8021X:
prepare_8021x(service);
case CONNMAN_SERVICE_TYPE_SYSTEM:
case CONNMAN_SERVICE_TYPE_GPS:
case CONNMAN_SERVICE_TYPE_P2P:
+#if defined TIZEN_EXT_WIFI_MESH
+ case CONNMAN_SERVICE_TYPE_MESH:
+#endif
return -EINVAL;
case CONNMAN_SERVICE_TYPE_ETHERNET:
__connman_service_clear_error(service);
+ if (service->network && service->autoconnect &&
+ __connman_network_native_autoconnect(service->network)) {
+ DBG("service %p switch connecting reason to native", service);
+ reason = CONNMAN_SERVICE_CONNECT_REASON_NATIVE;
+ }
+
err = service_connect(service);
DBG("service %p err %d", service, err);
service->connect_reason = reason;
+#if defined TIZEN_EXT
+ connect_reason_changed(service);
+#endif
if (err >= 0)
return 0;
__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,
NULL, service, NULL);
+ if (__connman_config_provision_service(service) < 0)
+ service_load(service);
+
service_list_sort();
__connman_connection_update_gateway();
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)
{
service_list_sort();
}
+ static void trigger_autoconnect(struct connman_service *service)
+ {
+ struct connman_device *device;
+ bool native;
+
+ if (!service->favorite)
+ return;
+
+ native = __connman_network_native_autoconnect(service->network);
+ if (native && service->autoconnect) {
+ DBG("trigger native autoconnect");
+ connman_network_set_autoconnect(service->network, true);
+ return;
+ }
+
+ device = connman_network_get_device(service->network);
+ if (device && connman_device_get_scanning(device, CONNMAN_SERVICE_TYPE_UNKNOWN))
+ return;
+
+ switch (service->type) {
+ case CONNMAN_SERVICE_TYPE_UNKNOWN:
+ case CONNMAN_SERVICE_TYPE_SYSTEM:
+ case CONNMAN_SERVICE_TYPE_P2P:
++#if defined TIZEN_EXT_WIFI_MESH
++ case CONNMAN_SERVICE_TYPE_MESH:
++#endif
+ break;
+
+ case CONNMAN_SERVICE_TYPE_GADGET:
+ case CONNMAN_SERVICE_TYPE_ETHERNET:
+ if (service->autoconnect) {
+ __connman_service_connect(service,
+ CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+ break;
+ }
+
+ /* fall through */
+ case CONNMAN_SERVICE_TYPE_BLUETOOTH:
+ case CONNMAN_SERVICE_TYPE_GPS:
+ case CONNMAN_SERVICE_TYPE_VPN:
+ case CONNMAN_SERVICE_TYPE_WIFI:
+ case CONNMAN_SERVICE_TYPE_CELLULAR:
+ do_auto_connect(service, CONNMAN_SERVICE_CONNECT_REASON_AUTO);
+ break;
+ }
++
++#if defined TIZEN_EXT
++ /* TIZEN synchronizes below information when the service creates */
++ if (service->eap != NULL)
++ connman_network_set_string(service->network, "WiFi.EAP",
++ service->eap);
++ if (service->identity != NULL)
++ connman_network_set_string(service->network, "WiFi.Identity",
++ service->identity);
++ if (service->phase2 != NULL)
++ connman_network_set_string(service->network, "WiFi.Phase2",
++ service->phase2);
++ if (service->eap != NULL)
++ connman_network_set_string(service->network, "WiFi.Connector",
++ service->connector);
++ if (service->identity != NULL)
++ connman_network_set_string(service->network, "WiFi.CSignKey",
++ service->c_sign_key);
++ if (service->phase2 != NULL)
++ connman_network_set_string(service->network, "WiFi.NetAccessKey",
++ service->net_access_key);
++#endif
+ }
+
/**
* __connman_service_create_from_network:
* @network: network structure
struct connman_service * __connman_service_create_from_network(struct connman_network *network)
{
struct connman_service *service;
- struct connman_device *device;
const char *ident, *group;
char *name;
unsigned int *auto_connect_types, *favorite_types;
service_register(service);
service_schedule_added(service);
- if (service->favorite) {
- device = connman_network_get_device(service->network);
- if (device && !connman_device_get_scanning(device,
- CONNMAN_SERVICE_TYPE_UNKNOWN)) {
-
- switch (service->type) {
- case CONNMAN_SERVICE_TYPE_UNKNOWN:
- case CONNMAN_SERVICE_TYPE_SYSTEM:
- case CONNMAN_SERVICE_TYPE_P2P:
- #if defined TIZEN_EXT_WIFI_MESH
- case CONNMAN_SERVICE_TYPE_MESH:
- #endif
- break;
-
- case CONNMAN_SERVICE_TYPE_GADGET:
- case CONNMAN_SERVICE_TYPE_ETHERNET:
- if (service->autoconnect) {
- __connman_service_connect(service,
- CONNMAN_SERVICE_CONNECT_REASON_AUTO);
- break;
- }
-
- /* fall through */
- case CONNMAN_SERVICE_TYPE_BLUETOOTH:
- case CONNMAN_SERVICE_TYPE_GPS:
- case CONNMAN_SERVICE_TYPE_VPN:
- case CONNMAN_SERVICE_TYPE_WIFI:
- case CONNMAN_SERVICE_TYPE_CELLULAR:
- do_auto_connect(service,
- CONNMAN_SERVICE_CONNECT_REASON_AUTO);
- break;
- }
- }
-
- #if defined TIZEN_EXT
- /* TIZEN synchronizes below information when the service creates */
- if (service->eap != NULL)
- connman_network_set_string(service->network, "WiFi.EAP",
- service->eap);
- if (service->identity != NULL)
- connman_network_set_string(service->network, "WiFi.Identity",
- service->identity);
- if (service->phase2 != NULL)
- connman_network_set_string(service->network, "WiFi.Phase2",
- service->phase2);
- if (service->eap != NULL)
- connman_network_set_string(service->network, "WiFi.Connector",
- service->connector);
- if (service->identity != NULL)
- connman_network_set_string(service->network, "WiFi.CSignKey",
- service->c_sign_key);
- if (service->phase2 != NULL)
- connman_network_set_string(service->network, "WiFi.NetAccessKey",
- service->net_access_key);
- #endif
- }
+ trigger_autoconnect(service);
__connman_notifier_service_add(service, service->name);
return service;
}
+#if defined TIZEN_EXT
+void __connman_service_notify_strength_changed(struct connman_network *network)
+{
+ struct connman_service *service;
+ uint8_t strength = 0;
+
+ service = connman_service_lookup_from_network(network);
+ if (!service)
+ return;
+
+ if (!service->network)
+ return;
+
+ strength = connman_network_get_strength(service->network);
+ if (strength == service->strength)
+ return;
+
+ service->strength = strength;
+ if (!simplified_log)
+ DBG("Strength %d", strength);
+ strength_changed(service);
+ service_list_sort();
+}
+#endif
+
void __connman_service_update_from_network(struct connman_network *network)
{
bool need_sort = false;
bool roaming;
const char *name;
bool stats_enable;
+#if defined TIZEN_EXT
+ bool need_save = false;
+#endif
service = connman_service_lookup_from_network(network);
if (!service)
if (!service->network)
return;
+#if defined TIZEN_EXT
+ if (service->storage_reload) {
+ service_load(service);
+ __connman_service_set_storage_reload(service, false);
+ }
+#endif
+
name = connman_network_get_string(service->network, "Name");
if (g_strcmp0(service->name, name) != 0) {
g_free(service->name);
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,
};
- string = connman_option_get_string("INSPreferredFreq");
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+static void ins_setting_init(void)
+{
+ int i;
+ const char *string;
+ char **string_list;
+ unsigned int string_count;
+
+ ins_settings.last_user_selection = connman_setting_get_bool("INSLastUserSelection");
+ ins_settings.last_user_selection_time = connman_setting_get_uint("INSLastUserSelectionTime");
+ ins_settings.last_connected = connman_setting_get_bool("INSLastConnected");
+
++ string = connman_setting_get_string("INSPreferredFreq");
+ if (g_strcmp0(string, "5GHz") == 0)
+ ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_5GHZ;
+ else if (g_strcmp0(string, "2.4GHz") == 0)
+ ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_24GHZ;
+ else
+ ins_settings.preferred_freq = CONNMAN_INS_PREFERRED_FREQ_UNKNOWN;
+
+ ins_settings.security_priority_count = connman_setting_get_uint("INSSecurityPriorityCount");
+ ins_settings.security_priority_score = connman_setting_get_uint("INSSecurityPriorityScore");
+ string_count = ins_settings.security_priority_count;
+
+ memset(ins_settings.security_priority, 0, sizeof(ins_settings.security_priority));
+ string_list = connman_setting_get_string_list("INSSecurityPriority");
+ for (i = 0; string_list && string_list[i]; i++) {
+ unsigned int security_score = string_count * ins_settings.security_priority_score;
+
+ if (g_strcmp0(string_list[i], "WEP") == 0)
+ ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_WEP] = security_score;
+ else if (g_strcmp0(string_list[i], "PSK") == 0)
+ ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_PSK] = security_score;
+ else if (g_strcmp0(string_list[i], "8021X") == 0)
+ ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_8021X] = security_score;
+ else if (g_strcmp0(string_list[i], "WPA") == 0)
+ ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_WPA] = security_score;
+ else if (g_strcmp0(string_list[i], "RSN") == 0)
+ ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_RSN] = security_score;
+ else if (g_strcmp0(string_list[i], "SAE") == 0)
+ ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_SAE] = security_score;
+ else if (g_strcmp0(string_list[i], "OWE") == 0)
+ ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_OWE] = security_score;
+ else if (g_strcmp0(string_list[i], "DPP") == 0)
+ ins_settings.security_priority[CONNMAN_SERVICE_SECURITY_DPP] = security_score;
+
+ string_count--;
+ }
+
+ ins_settings.signal = connman_setting_get_bool("INSSignal");
+ ins_settings.internet = connman_setting_get_bool("INSInternet");
+
+ ins_settings.last_user_selection_score = connman_setting_get_uint("INSLastUserSelectionScore");
+ ins_settings.last_connected_score = connman_setting_get_uint("INSLastConnectedScore");
+ ins_settings.preferred_freq_score = connman_setting_get_uint("INSPreferredFreqScore");
+ ins_settings.internet_score = connman_setting_get_uint("INSInternetScore");
+
+ /*
+ * In ConnMan, signal strength is used after being converted
+ * to positive value(signal strength + 120).
+ * So the value for comparison should also be converted to the same.
+ */
+ ins_settings.signal_level3_5ghz = connman_setting_get_int("INSSignalLevel3_5GHz") + 120;
+ ins_settings.signal_level3_24ghz = connman_setting_get_int("INSSignalLevel3_24GHz") + 120;
+
+ DBG("last_user_selection [%s]", ins_settings.last_user_selection ? "true" : "false");
+ DBG("last_user_selection_time [%d]", ins_settings.last_user_selection_time);
+ DBG("last_user_selection_score [%d]", ins_settings.last_user_selection_score);
+
+ DBG("last_connected [%s]", ins_settings.last_connected ? "true" : "false");
+ DBG("last_connected_score [%d]", ins_settings.last_connected_score);
+
+ DBG("preferred_freq [%s]", ins_settings.preferred_freq ? "true" : "false");
+ DBG("preferred_freq_score [%d]", ins_settings.preferred_freq_score);
+
+ DBG("security_priority_count [%d]", ins_settings.security_priority_count);
+ for (i = 0; i < CONNMAN_SERVICE_SECURITY_MAX; i++) {
+ if (ins_settings.security_priority[i])
+ DBG("security_priority %s [%d]", security2string(i),
+ ins_settings.security_priority[i]);
+ }
+ DBG("security_priority_score [%d]", ins_settings.security_priority_score);
+
+ DBG("signal [%s]", ins_settings.signal ? "true" : "false");
+
+ DBG("internet [%s]", ins_settings.internet ? "true" : "false");
+ DBG("internet_score [%d]", ins_settings.internet_score);
+
+ DBG("signal_level3_5ghz [%d]", ins_settings.signal_level3_5ghz);
+ DBG("signal_level3_24ghz [%d]", ins_settings.signal_level3_24ghz);
+}
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
int __connman_service_init(void)
{
int err;
remove_unprovisioned_services();
+#if defined TIZEN_EXT && defined TIZEN_EXT_INS
+ ins_setting_init();
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */
+
return 0;
}
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 ||
struct connman_service *service;
struct connman_service_info *info;
GSList *service_list = NULL;
- enum connman_service_state state = CONNMAN_SESSION_STATE_DISCONNECTED;
+ enum connman_service_state state = CONNMAN_SERVICE_STATE_DISCONNECT;
g_hash_table_iter_init(&iter, service_hash);
#include <stdio.h>
#include <ctype.h>
#include <stdarg.h>
+ #include <string.h>
#include "src/shared/util.h"
#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;
"Tethering.Identifier",
technology->tethering_ident);
- if (technology->tethering_passphrase)
+ if (technology->tethering_passphrase) {
+ char *enc = g_strescape(technology->tethering_passphrase, NULL);
g_key_file_set_string(keyfile, identifier,
- "Tethering.Passphrase",
- technology->tethering_passphrase);
+ "Tethering.Passphrase", enc);
+ g_free(enc);
+ }
+#ifdef TIZEN_EXT
+ if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
+ g_key_file_set_uint64(keyfile, identifier, "MacPolicy",
+ technology->mac_policy);
+
+ g_key_file_set_uint64(keyfile, identifier, "PreassocMacPolicy",
+ technology->preassoc_mac_policy);
+
+ g_key_file_set_uint64(keyfile, identifier, "RandomMacLifetime",
+ technology->random_mac_lifetime);
+ }
+#endif /* TIZEN_EXT */
+
done:
g_free(identifier);
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;
gchar *identifier;
GError *error = NULL;
bool enable, need_saving = false;
+ char *enc;
DBG("technology %p", technology);
if (!identifier)
goto done;
+#ifdef TIZEN_EXT
+ gsize length;
+ technology->enabled_devices = g_key_file_get_string_list(keyfile,
+ identifier, "Enable.Devices", &length, NULL);
+ if (technology->enabled_devices && length == 0) {
+ g_strfreev(technology->enabled_devices);
+ technology->enabled_devices = NULL;
+ }
+#endif
+
enable = g_key_file_get_boolean(keyfile, identifier, "Enable", &error);
if (!error)
technology->enable_persistent = enable;
technology->tethering_ident = g_key_file_get_string(keyfile,
identifier, "Tethering.Identifier", NULL);
- technology->tethering_passphrase = g_key_file_get_string(keyfile,
+ enc = g_key_file_get_string(keyfile,
identifier, "Tethering.Passphrase", NULL);
-
+ if (enc)
+ technology->tethering_passphrase = g_strcompress(enc);
+#ifdef TIZEN_EXT
+ if (technology->type == CONNMAN_SERVICE_TYPE_WIFI) {
+ unsigned int val = 0;
+
+ val = g_key_file_get_uint64(keyfile,
+ identifier, "MacPolicy", NULL);
+ if (val <= 2)
+ technology->mac_policy = val;
+ else
+ technology->mac_policy = 0;
+
+ val = g_key_file_get_uint64(keyfile,
+ identifier, "PreassocMacPolicy", NULL);
+ if (val <= 2)
+ technology->preassoc_mac_policy = val;
+ else
+ technology->preassoc_mac_policy = 0;
+
+ val = g_key_file_get_uint64(keyfile,
+ identifier, "RandomMacLifetime", NULL);
+ if (val > 0)
+ technology->random_mac_lifetime = val;
+ else
+ technology->random_mac_lifetime = 60;
+ }
+#endif /* TIZEN_EXT */
+
done:
g_free(identifier);
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;
if ((__connman_inet_modify_address(RTM_NEWADDR,
NLM_F_REPLACE | NLM_F_ACK, pn->index, AF_INET,
- server_ip, peer_ip, prefixlen, NULL)) < 0) {
+ server_ip, peer_ip, prefixlen, NULL, true))
+ < 0) {
DBG("address setting failed");
return;
}
#include <stdlib.h>
#include <gweb/gresolv.h>
#include <netdb.h>
+ #include <sys/time.h>
#include "connman.h"
static char *ts_current = NULL;
static int ts_recheck_id = 0;
static int ts_backoff_id = 0;
+ static bool ts_is_synced = false;
static GResolv *resolv = NULL;
static int resolv_id = 0;
static void ntp_callback(bool success, void *user_data)
{
+ dbus_uint64_t timestamp;
+ struct timeval tv;
+
DBG("success %d", success);
- if (!success)
+ __connman_timeserver_set_synced(success);
+ if (!success) {
sync_next();
+ return;
+ }
+
+ if (gettimeofday(&tv, NULL) < 0) {
+ connman_warn("Failed to get current time");
+ }
+
+ timestamp = tv.tv_sec;
+ connman_dbus_property_changed_basic(
+ CONNMAN_MANAGER_PATH,
+ CONNMAN_CLOCK_INTERFACE, "Time",
+ DBUS_TYPE_UINT64, ×tamp);
}
static void save_timeservers(char **servers)
{
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;
}
static gboolean ts_recheck(gpointer user_data)
{
+ struct connman_service *service;
GSList *ts;
ts = __connman_timeserver_get_all(connman_service_get_default());
g_slist_free_full(ts, g_free);
- __connman_timeserver_sync(NULL);
+ service = connman_service_get_default();
+ __connman_timeserver_sync(service);
return FALSE;
}
NULL);
}
- /*
- * This function must be called every time the default service changes, the
- * service timeserver(s) or gateway changes or the global timeserver(s) changes.
- */
- int __connman_timeserver_sync(struct connman_service *default_service)
+ static void ts_reset(struct connman_service *service)
{
- struct connman_service *service;
char **nameservers;
int i;
- if (default_service)
- service = default_service;
- else
- service = connman_service_get_default();
-
- if (!service)
- return -EINVAL;
+ if (!resolv)
+ return;
- #if !defined TIZEN_EXT
- if (service == ts_service)
- return -EALREADY;
- #endif
+ __connman_timeserver_set_synced(false);
- if (!resolv)
- return 0;
/*
* Before we start creating the new timeserver list we must stop
* any ongoing ntp query and server resolution.
g_resolv_flush_nameservers(resolv);
nameservers = connman_service_get_nameservers(service);
- if (!nameservers)
- return -EINVAL;
-
- for (i = 0; nameservers[i]; i++)
- g_resolv_add_nameserver(resolv, nameservers[i], 53, 0);
+ if (nameservers) {
+ for (i = 0; nameservers[i]; i++)
+ g_resolv_add_nameserver(resolv, nameservers[i], 53, 0);
- g_strfreev(nameservers);
+ g_strfreev(nameservers);
+ }
g_slist_free_full(timeservers_list, g_free);
if (!timeservers_list) {
DBG("No timeservers set.");
- return 0;
+ return;
}
ts_recheck_enable();
ts_service = service;
timeserver_sync_start();
+ }
- return 0;
+ void __connman_timeserver_sync(struct connman_service *service)
+ {
+ if (!service || ts_service == service)
+ return;
+
+ ts_reset(service);
+ }
+
+ void __connman_timeserver_conf_update(struct connman_service *service)
+ {
+ if (!service || (ts_service && ts_service != service))
+ return;
+
+ ts_reset(service);
+ }
+
+
+ bool __connman_timeserver_is_synced(void)
+ {
+ return ts_is_synced;
+ }
+
+ void __connman_timeserver_set_synced(bool status)
+ {
+ dbus_bool_t is_synced;
+
+ if (ts_is_synced == status)
+ return;
+
+ ts_is_synced = status;
+ is_synced = status;
+ connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH,
+ CONNMAN_CLOCK_INTERFACE, "TimeserverSynced",
+ DBUS_TYPE_BOOLEAN, &is_synced);
}
static int timeserver_start(struct connman_service *service)
g_strfreev(nameservers);
}
- return __connman_timeserver_sync(service);
+ __connman_timeserver_sync(service);
+
+ return 0;
}
static void timeserver_stop(void)
int __connman_timeserver_system_set(char **servers)
{
+ struct connman_service *service;
+
save_timeservers(servers);
- __connman_timeserver_sync(NULL);
+ service = connman_service_get_default();
+ if (service)
+ ts_reset(service);
return 0;
}
static GHashTable *wispr_portal_list = NULL;
+ static bool enable_online_to_ready_transition = false;
+
static void connman_wispr_message_init(struct connman_wispr_message *msg)
{
DBG("");
DBG("Failed to proceed wispr/portal web request");
wp_context->wispr_result = CONNMAN_WISPR_RESULT_FAILED;
+
+#if defined TIZEN_EXT
+ connman_service_set_internet_connection(wp_context->service, false);
+#endif
}
static void portal_manage_status(GWebResult *result,
&str))
connman_info("Client-Timezone: %s", str);
- free_connman_wispr_portal_context(wp_context);
+ if (!enable_online_to_ready_transition)
+ free_connman_wispr_portal_context(wp_context);
__connman_service_ipconfig_indicate_state(service,
CONNMAN_SERVICE_STATE_ONLINE, type);
+
+ if (enable_online_to_ready_transition)
+ __connman_service_online_check(service, type, true);
}
static bool wispr_route_request(const char *address, int ai_family,
const char *str = NULL;
guint16 status;
gsize length;
+#if defined TIZEN_MAINTAIN_ONLINE
+ static int retried = 0;
+#endif
DBG("");
wp_context->status_url, wp_context);
break;
case 200:
+#if defined TIZEN_MAINTAIN_ONLINE
+ retried = 0;
+#endif
if (wp_context->wispr_msg.message_type >= 0)
break;
wp_context->redirect_url, wp_context);
break;
+ case 300:
+ case 301:
case 302:
+ case 303:
+ case 307:
+ case 308:
if (!g_web_supports_tls() ||
!g_web_result_get_header(result, "Location",
&redirect)) {
goto done;
case 400:
case 404:
- if (__connman_service_online_check_failed(wp_context->service,
- wp_context->type) == 0) {
+ __connman_service_online_check(wp_context->service,
+ wp_context->type, false);
-
+#if defined TIZEN_MAINTAIN_ONLINE
+ if (wp_context->type == CONNMAN_IPCONFIG_TYPE_IPV4) {
+ if (retried == 0) {
+ connman_agent_report_error(wp_context->service,
+ __connman_service_get_path(wp_context->service),
+ "internet-unreachable",
+ NULL, NULL, NULL);
+
+ retried = 1;
+ }
+ break;
+ }
+#endif
- wispr_portal_error(wp_context);
- free_connman_wispr_portal_context(wp_context);
- return false;
- }
-
break;
case 505:
__connman_agent_request_browser(wp_context->service,
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;
void __connman_wispr_stop(struct connman_service *service)
{
+ struct connman_wispr_portal *wispr_portal;
int index;
DBG("service %p", service);
if (index < 0)
return;
- g_hash_table_remove(wispr_portal_list, GINT_TO_POINTER(index));
+ wispr_portal = g_hash_table_lookup(wispr_portal_list,
+ GINT_TO_POINTER(index));
+ if (!wispr_portal)
+ return;
+
+ if (wispr_portal->ipv4_context) {
+ if (service == wispr_portal->ipv4_context->service)
+ g_hash_table_remove(wispr_portal_list,
+ GINT_TO_POINTER(index));
+ }
+
+ if (wispr_portal->ipv6_context) {
+ if (service == wispr_portal->ipv6_context->service)
+ g_hash_table_remove(wispr_portal_list,
+ GINT_TO_POINTER(index));
+ }
}
int __connman_wispr_init(void)
g_direct_equal, NULL,
free_connman_wispr_portal);
+ enable_online_to_ready_transition =
+ connman_setting_get_bool("EnableOnlineToReadyTransition");
+
return 0;
}
#define CONFIGMAINFILE CONFIGDIR "/connman-vpn.conf"
- #define DEFAULT_INPUT_REQUEST_TIMEOUT 300 * 1000
- #define DEFAULT_BROWSER_LAUNCH_TIMEOUT 300 * 1000
-
static GMainLoop *main_loop = NULL;
static unsigned int __terminated = 0;
- static struct {
- unsigned int timeout_inputreq;
- unsigned int timeout_browserlaunch;
- } connman_vpn_settings = {
- .timeout_inputreq = DEFAULT_INPUT_REQUEST_TIMEOUT,
- .timeout_browserlaunch = DEFAULT_BROWSER_LAUNCH_TIMEOUT,
- };
-
- static GKeyFile *load_config(const char *file)
- {
- GError *err = NULL;
- GKeyFile *keyfile;
-
- keyfile = g_key_file_new();
-
- g_key_file_set_list_separator(keyfile, ',');
-
- if (!g_key_file_load_from_file(keyfile, file, 0, &err)) {
- if (err->code != G_FILE_ERROR_NOENT) {
- connman_error("Parsing %s failed: %s", file,
- err->message);
- }
-
- g_error_free(err);
- g_key_file_free(keyfile);
- return NULL;
- }
-
- return keyfile;
- }
-
- static void parse_config(GKeyFile *config, const char *file)
- {
- GError *error = NULL;
- int timeout;
-
- if (!config)
- return;
-
- DBG("parsing %s", file);
-
- timeout = g_key_file_get_integer(config, "General",
- "InputRequestTimeout", &error);
- if (!error && timeout >= 0)
- connman_vpn_settings.timeout_inputreq = timeout * 1000;
-
- g_clear_error(&error);
- }
-
- static int config_init(const char *file)
- {
- GKeyFile *config;
-
- config = load_config(file);
- parse_config(config, file);
- if (config)
- g_key_file_free(config);
-
- return 0;
- }
-
static gboolean signal_handler(GIOChannel *channel, GIOCondition cond,
gpointer user_data)
{
static gchar *option_noplugin = NULL;
static bool option_detach = true;
static bool option_version = false;
- static bool option_routes = false;
static bool parse_debug(const char *key, const char *value,
gpointer user_data, GError **error)
{ "nodaemon", 'n', G_OPTION_FLAG_REVERSE,
G_OPTION_ARG_NONE, &option_detach,
"Don't fork daemon to background" },
- { "routes", 'r', 0, G_OPTION_ARG_NONE, &option_routes,
- "Create/delete VPN routes" },
{ "version", 'v', 0, G_OPTION_ARG_NONE, &option_version,
"Show version information and exit" },
{ NULL },
};
- #if defined TIZEN_EXT
++#if defined TIZEN_EXT
+bool connman_setting_get_bool(const char *key)
+{
+ return false;
+}
+
- #endif
+unsigned int connman_setting_get_uint(const char *key)
+{
+ return 0;
+}
+
+int connman_setting_get_int(const char *key)
+{
+ return 0;
+}
++
++char *connman_setting_get_string(const char *key)
++{
++ return NULL;
++}
+
+char **connman_setting_get_string_list(const char *key)
+{
+ return NULL;
+}
+
+unsigned int *connman_setting_get_uint_list(const char *key)
+{
+ return NULL;
+}
+
++unsigned int connman_timeout_browser_launch(void)
++{
++ return 0;
++}
++#endif
++
/*
* This function will be called from generic src/agent.c code so we have
* to use connman_ prefix instead of vpn_ one.
return __vpn_settings_get_timeout_inputreq();
}
- unsigned int connman_timeout_browser_launch(void)
- {
- return connman_vpn_settings.timeout_browserlaunch;
- }
-
- const char *connman_option_get_string(const char *key)
- {
- return NULL;
- }
-
int main(int argc, char *argv[])
{
GOptionContext *context;
__connman_inotify_init();
__connman_agent_init();
- __vpn_provider_init(option_routes);
+ __vpn_provider_init();
__vpn_manager_init();
__vpn_ipconfig_init();
__vpn_rtnl_init();
connman_ipaddress_set_ipv4(ipaddress, addressv4, netmask,
gateway);
+ connman_ipaddress_set_p2p(ipaddress, true);
+
vpn_provider_set_ipaddress(provider, ipaddress);
vpn_provider_set_nameservers(provider, nameservers);
#include <connman/setting.h>
#include <connman/vpn-dbus.h>
+ #include <openconnect.h>
+
#include "../vpn-provider.h"
#include "../vpn-agent.h"
static const char *connect_types[] = {"cookie", "cookie_with_userpass",
"userpass", "publickey", "pkcs", NULL};
- static const char *protocols[] = { "anyconnect", "nc", "gp", NULL};
struct oc_private_data {
struct vpn_provider *provider;
char *dbus_sender;
vpn_provider_connect_cb_t cb;
void *user_data;
+
+ GThread *cookie_thread;
+ struct openconnect_info *vpninfo;
+ int fd_cmd;
+ int err;
+
int fd_in;
- int out_ch_id;
int err_ch_id;
- GIOChannel *out_ch;
GIOChannel *err_ch;
enum oc_connect_type connect_type;
- bool interactive;
+ bool tried_passphrase;
};
+ typedef void (*request_input_reply_cb_t) (DBusMessage *reply,
+ void *user_data);
+
+ static int run_connect(struct oc_private_data *data, const char *cookie);
+ static int request_input_credentials_full(
+ struct oc_private_data *data,
+ request_input_reply_cb_t cb,
+ void *user_data);
+
static bool is_valid_protocol(const char* protocol)
{
+ int num_protocols;
+ int i;
+ struct oc_vpn_proto *protos;
+
if (!protocol || !*protocol)
return false;
- return g_strv_contains(protocols, protocol);
+ num_protocols = openconnect_get_supported_protocols(&protos);
+
+ for (i = 0; i < num_protocols; i++)
+ if (!strcmp(protos[i].name, protocol))
+ break;
+
+ openconnect_free_supported_protocols(protos);
+
+ return i < num_protocols;
}
static void oc_connect_done(struct oc_private_data *data, int err)
if (!data || !channel)
return;
- if (data->out_ch == channel) {
- id = data->out_ch_id;
- data->out_ch = NULL;
- data->out_ch_id = 0;
- } else if (data->err_ch == channel) {
+ if (data->err_ch == channel) {
id = data->err_ch_id;
data->err_ch = NULL;
data->err_ch_id = 0;
connman_info("provider %p", data->provider);
+ if (data->vpninfo)
+ openconnect_vpninfo_free(data->vpninfo);
+
if (vpn_provider_get_plugin_data(data->provider) == data)
vpn_provider_set_plugin_data(data->provider, NULL);
if (data->fd_in > 0)
close(data->fd_in);
data->fd_in = -1;
- close_io_channel(data, data->out_ch);
close_io_channel(data, data->err_ch);
g_free(data->dbus_sender);
else
connman_ipaddress_set_ipv6(ipaddress, addressv6,
prefix_len, gateway);
+
+ connman_ipaddress_set_p2p(ipaddress, true);
vpn_provider_set_ipaddress(provider, ipaddress);
vpn_provider_set_domain(provider, domain);
return VPN_STATE_CONNECT;
}
- static ssize_t full_write(int fd, const void *buf, size_t len)
+ static ssize_t full_write(int fd, const char *buf, size_t len)
{
ssize_t byte_write;
free_private_data(data);
}
- static gboolean io_channel_out_cb(GIOChannel *source, GIOCondition condition,
- gpointer user_data)
- {
- struct oc_private_data *data;
- char *str;
-
- data = user_data;
-
- if (data->out_ch != source)
- return G_SOURCE_REMOVE;
-
- if ((condition & G_IO_IN) &&
- g_io_channel_read_line(source, &str, NULL, NULL, NULL) ==
- G_IO_STATUS_NORMAL) {
-
- g_strchomp(str);
-
- /* Only cookie is printed to stdout */
- vpn_provider_set_string_hide_value(data->provider,
- "OpenConnect.Cookie", str);
-
- g_free(str);
- } else if (condition & (G_IO_ERR | G_IO_HUP)) {
- connman_info("Out channel termination");
- close_io_channel(data, source);
- return G_SOURCE_REMOVE;
- }
-
- return G_SOURCE_CONTINUE;
- }
-
static bool strv_contains_prefix(const char *strv[], const char *str)
{
int i;
return false;
}
- static void clear_provider_credentials(struct vpn_provider *provider)
+ static void clear_provider_credentials(struct vpn_provider *provider,
+ bool clear_pkcs_pass)
{
- const char *keys[] = { "OpenConnect.Username",
+ const char *keys[] = { "OpenConnect.PKCSPassword",
+ "OpenConnect.Username",
"OpenConnect.Password",
- "OpenConnect.PKCSPassword",
"OpenConnect.Cookie",
NULL
};
- int i;
+ size_t i;
connman_info("provider %p", provider);
- for (i = 0; keys[i]; i++) {
+ for (i = !clear_pkcs_pass; keys[i]; i++) {
if (!vpn_provider_get_string_immutable(provider, keys[i]))
vpn_provider_set_string_hide_value(provider, keys[i],
"-");
}
}
- typedef void (* request_input_reply_cb_t) (DBusMessage *reply,
- void *user_data);
+ static void __attribute__ ((format(printf, 3, 4))) oc_progress(void *user_data,
+ int level, const char *fmt, ...)
+ {
+ va_list ap;
+ char *msg;
- static int request_input_credentials(struct oc_private_data *data,
- request_input_reply_cb_t cb);
+ va_start(ap, fmt);
+ msg = g_strdup_vprintf(fmt, ap);
+
+ connman_debug("%s", msg);
+ g_free(msg);
+
+ va_end(ap);
+ }
+
+ /*
+ * There is no enum / defines for these in openconnect.h, but these values
+ * are based on the comment for openconnect_validate_peer_cert_vfn.
+ */
+ enum oc_cert_status {
+ OC_CERT_ACCEPT = 0,
+ OC_CERT_REJECT = 1
+ };
+
+ struct validate_cert_data {
+ GMutex mutex;
+ GCond cond;
+ const char *reason;
+ struct oc_private_data *data;
+ bool processed;
+ enum oc_cert_status status;
+ };
+
+ static gboolean validate_cert(void *user_data)
+ {
+ struct validate_cert_data *cert_data = user_data;
+ struct oc_private_data *data;
+ const char *server_cert;
+ bool allow_self_signed;
+
+ DBG("");
+
+ g_mutex_lock(&cert_data->mutex);
+
+ data = cert_data->data;
+ server_cert = vpn_provider_get_string(data->provider,
+ "OpenConnect.ServerCert");
+ allow_self_signed = vpn_provider_get_boolean(data->provider,
+ "OpenConnect.AllowSelfSignedCert",
+ false);
+ if (!allow_self_signed) {
+ cert_data->status = OC_CERT_REJECT;
+ } else if (server_cert) {
+ /*
+ * Check peer cert hash may return negative values on errors,
+ * but anything non-zero is acceptable.
+ */
+ cert_data->status = openconnect_check_peer_cert_hash(
+ data->vpninfo,
+ server_cert);
+ } else {
+ /*
+ * We could verify this from the agent at this point, and
+ * release the thread upon reply.
+ */
+ DBG("Server cert hash: %s",
+ openconnect_get_peer_cert_hash(data->vpninfo));
+ vpn_provider_set_string(data->provider,
+ "OpenConnect.ServerCert",
+ openconnect_get_peer_cert_hash(data->vpninfo));
+ cert_data->status = OC_CERT_ACCEPT;
+ }
+
+ cert_data->processed = true;
+ g_cond_signal(&cert_data->cond);
+ g_mutex_unlock(&cert_data->mutex);
+
+ return G_SOURCE_REMOVE;
+ }
+
+ static int oc_validate_peer_cert(void *user_data, const char *reason)
+ {
+ struct validate_cert_data data = { .reason = reason,
+ .data = user_data,
+ .processed = false };
+
+ g_cond_init(&data.cond);
+ g_mutex_init(&data.mutex);
+
+ g_mutex_lock(&data.mutex);
+
+ g_idle_add(validate_cert, &data);
+
+ while (!data.processed)
+ g_cond_wait(&data.cond, &data.mutex);
+
+ g_mutex_unlock(&data.mutex);
+
+ g_mutex_clear(&data.mutex);
+ g_cond_clear(&data.cond);
+
+ return data.status;
+ }
+
+ struct process_form_data {
+ GMutex mutex;
+ GCond cond;
+ struct oc_auth_form *form;
+ struct oc_private_data *data;
+ bool processed;
+ int status;
+ };
static void request_input_pkcs_reply(DBusMessage *reply, void *user_data)
{
- struct oc_private_data *data = user_data;
- const char *password = NULL;
+ struct process_form_data *form_data = user_data;
+ struct oc_private_data *data = form_data->data;
+ struct oc_form_opt *opt;
const char *key;
+ const char *password = NULL;
DBusMessageIter iter, dict;
- int err;
connman_info("provider %p", data->provider);
- if (!reply)
+ if (!reply) {
+ data->err = ENOENT;
goto err;
+ }
- err = vpn_agent_check_and_process_reply_error(reply, data->provider,
- data->task, data->cb, data->user_data);
- if (err) {
- /* Ensure cb is called only once */
+ if ((data->err = vpn_agent_check_and_process_reply_error(reply,
+ data->provider,
+ data->task,
+ data->cb,
+ data->user_data))) {
data->cb = NULL;
data->user_data = NULL;
goto err;
}
- if (!vpn_agent_check_reply_has_dict(reply))
+ if (!vpn_agent_check_reply_has_dict(reply)) {
+ data->err = ENOENT;
goto err;
+ }
dbus_message_iter_init(reply, &iter);
dbus_message_iter_recurse(&iter, &dict);
dbus_message_iter_next(&dict);
}
- if (data->connect_type != OC_CONNECT_PKCS || !password)
+ if (!password)
goto err;
- if (write_data(data->fd_in, password) != 0) {
- connman_error("openconnect failed to take PKCS pass phrase on"
- " stdin");
- goto err;
+ for (opt = form_data->form->opts; opt; opt = opt->next) {
+ if (opt->flags & OC_FORM_OPT_IGNORE)
+ continue;
+
+ if (opt->type == OC_FORM_OPT_PASSWORD &&
+ g_str_has_prefix(opt->name,
+ "openconnect_pkcs")) {
+ opt->_value = strdup(password);
+ form_data->status = OC_FORM_RESULT_OK;
+ data->tried_passphrase = true;
+ break;
+ }
}
- clear_provider_credentials(data->provider);
+ goto out;
- return;
err:
- oc_connect_done(data, EACCES);
+ form_data->status = OC_FORM_RESULT_ERR;
+
+ out:
+ form_data->processed = true;
+ g_cond_signal(&form_data->cond);
+ g_mutex_unlock(&form_data->mutex);
}
static gboolean io_channel_err_cb(GIOChannel *source, GIOCondition condition,
- gpointer user_data)
+ gpointer user_data)
{
struct oc_private_data *data;
const char *auth_failures[] = {
- /* Login failed */
- "Got HTTP response: HTTP/1.1 401 Unauthorized",
- "Failed to obtain WebVPN cookie",
/* Cookie not valid */
"Got inappropriate HTTP CONNECT response: "
"HTTP/1.1 401 Unauthorized",
/* Invalid cookie */
"VPN service unavailable",
- /* Problem with certificates */
- "SSL connection failure",
- "Creating SSL connection failed",
- "SSL connection cancelled",
NULL
};
const char *conn_failures[] = {
"Failed to open HTTPS connection to",
NULL
};
- /* Handle both PKCS#12 and PKCS#8 failures */
- const char *pkcs_failures[] = {
- "Failed to decrypt PKCS#12 certificate file",
- "Failed to decrypt PKCS#8 certificate file",
- NULL
- };
- /* Handle both PKCS#12 and PKCS#8 requests */
- const char *pkcs_requests[] = {
- "Enter PKCS#12 pass phrase",
- "Enter PKCS#8 pass phrase",
- NULL
- };
- const char *server_key_hash = " --servercert";
+ const char *server_key_hash = " --servercert ";
char *str;
- bool close = false;
int err = 0;
data = user_data;
if ((condition & G_IO_IN)) {
gsize len;
- int pos;
-
- if (!data->interactive) {
- if (g_io_channel_read_line(source, &str, &len, NULL,
- NULL) != G_IO_STATUS_NORMAL)
- err = EIO;
- else
- str[len - 1] = '\0';
- } else {
- GIOStatus status;
- str = g_try_new0(char, OC_MAX_READBUF_LEN);
- if (!str)
- return G_SOURCE_REMOVE;
- for (pos = 0; pos < OC_MAX_READBUF_LEN - 1 ; ++pos) {
- status = g_io_channel_read_chars(source,
- str+pos, 1, &len, NULL);
-
- if (status == G_IO_STATUS_EOF) {
- break;
- } else if (status != G_IO_STATUS_NORMAL) {
- err = EIO;
- break;
- }
-
- /* Ignore control chars and digits at start */
- if (!pos && (g_ascii_iscntrl(str[pos]) ||
- g_ascii_isdigit(str[pos])))
- --pos;
-
- /* Read zero length or no more to read */
- if (!len || g_io_channel_get_buffer_condition(
- source) != G_IO_IN ||
- str[pos] == '\n')
- break;
- }
-
- /*
- * When self signed certificates are allowed and server
- * SHA1 fingerprint is printed to stderr there is a
- * newline char at the end of SHA1 fingerprint.
- */
- if (str[pos] == '\n')
- str[pos] = '\0';
- }
+ if (g_io_channel_read_line(source, &str, &len, NULL,
+ NULL) != G_IO_STATUS_NORMAL)
+ err = EIO;
+ else
+ g_strchomp(str);
connman_info("openconnect: %s", str);
vpn_provider_set_string(data->provider,
"OpenConnect.ServerCert",
- fingerprint);
-
- /*
- * OpenConnect waits for "yes" or "no" as
- * response to certificate acceptance request.
- */
- if (write_data(data->fd_in, "yes") != 0)
- connman_error("openconnect: cannot "
- "write answer to certificate "
- "accept request");
-
+ str + strlen(server_key_hash));
} else {
connman_warn("Self signed certificate is not "
- " allowed");
-
- /*
- * Close IO channel to avoid deadlock as an
- * answer is expected for the certificate
- * accept request.
- */
- close = true;
+ "allowed");
err = ECONNREFUSED;
}
- } else if (strv_contains_prefix(pkcs_failures, str)) {
- connman_warn("PKCS failure: %s", str);
- close = true;
- err = EACCES;
- } else if (strv_contains_prefix(pkcs_requests, str)) {
- connman_info("PKCS file pass phrase request: %s", str);
- err = request_input_credentials(data,
- request_input_pkcs_reply);
-
- if (err != -EINPROGRESS) {
- err = EACCES;
- close = true;
- } else {
- err = 0;
- }
} else if (strv_contains_prefix(auth_failures, str)) {
connman_warn("authentication failed: %s", str);
err = EACCES;
g_free(str);
} else if (condition & (G_IO_ERR | G_IO_HUP)) {
connman_info("Err channel termination");
- close = true;
+ close_io_channel(data, source);
+ return G_SOURCE_REMOVE;
}
if (err) {
switch (err) {
case EACCES:
- clear_provider_credentials(data->provider);
+ clear_provider_credentials(data->provider, true);
break;
case ECONNREFUSED:
/*
oc_connect_done(data, err);
}
- if (close) {
- close_io_channel(data, source);
- return G_SOURCE_REMOVE;
- }
-
return G_SOURCE_CONTINUE;
}
- static int run_connect(struct oc_private_data *data)
+ static gboolean process_auth_form(void *user_data)
{
- struct vpn_provider *provider;
- struct connman_task *task;
- const char *vpnhost;
- const char *vpncookie = NULL;
- const char *username;
- const char *password = NULL;
- const char *certificate = NULL;
- const char *private_key;
- const char *setting_str;
- bool setting;
- bool use_stdout = false;
- int fd_out = -1;
- int fd_err;
- int err = 0;
-
- if (!data)
- return -EINVAL;
+ struct process_form_data *form_data = user_data;
+ struct oc_private_data *data = form_data->data;
+ struct oc_form_opt *opt;
+ const char *password;
- provider = data->provider;
- task = data->task;
+ g_mutex_lock(&form_data->mutex);
- connman_info("provider %p task %p", provider, task);
+ DBG("");
switch (data->connect_type) {
- case OC_CONNECT_COOKIE:
- vpncookie = vpn_provider_get_string(provider,
- "OpenConnect.Cookie");
- if (!vpncookie || !g_strcmp0(vpncookie, "-")) {
- err = -EACCES;
- goto done;
- }
-
- connman_task_add_argument(task, "--cookie-on-stdin", NULL);
- break;
+ case OC_CONNECT_USERPASS:
case OC_CONNECT_COOKIE_WITH_USERPASS:
- vpncookie = vpn_provider_get_string(provider,
- "OpenConnect.Cookie");
- /* No cookie set yet, username and password used first */
- if (!vpncookie || !g_strcmp0(vpncookie, "-")) {
- username = vpn_provider_get_string(provider,
- "OpenConnect.Username");
- password = vpn_provider_get_string(provider,
- "OpenConnect.Password");
- if (!username || !password ||
- !g_strcmp0(username, "-") ||
- !g_strcmp0(password, "-")) {
- err = -EACCES;
- goto done;
- }
+ break;
+
+ case OC_CONNECT_PKCS:
+ password = vpn_provider_get_string(data->provider,
+ "OpenConnect.PKCSPassword");
- connman_task_add_argument(task, "--cookieonly", NULL);
- connman_task_add_argument(task, "--user", username);
- connman_task_add_argument(task, "--passwd-on-stdin",
- NULL);
+ for (opt = form_data->form->opts; opt; opt = opt->next) {
+ if (opt->flags & OC_FORM_OPT_IGNORE)
+ continue;
- /* Use stdout only when cookie is to be read. */
- use_stdout = true;
- } else {
- connman_task_add_argument(task, "--cookie-on-stdin",
- NULL);
+ if (opt->type == OC_FORM_OPT_PASSWORD &&
+ g_str_has_prefix(opt->name,
+ "openconnect_pkcs"))
+ break;
}
- break;
- case OC_CONNECT_USERPASS:
- username = vpn_provider_get_string(provider,
- "OpenConnect.Username");
- password = vpn_provider_get_string(provider,
- "OpenConnect.Password");
- if (!username || !password || !g_strcmp0(username, "-") ||
- !g_strcmp0(password, "-")) {
- err = -EACCES;
- goto done;
+ if (opt) {
+ if (password && g_strcmp0(password, "-")) {
+ opt->_value = strdup(password);
+ data->tried_passphrase = true;
+ form_data->status = OC_FORM_RESULT_OK;
+ goto out;
+ } else {
+ if (data->tried_passphrase) {
+ vpn_provider_add_error(data->provider,
+ VPN_PROVIDER_ERROR_AUTH_FAILED);
+ clear_provider_credentials(
+ data->provider,
+ true);
+ }
+ request_input_credentials_full(data,
+ request_input_pkcs_reply,
+ form_data);
+ return G_SOURCE_REMOVE;
+ }
}
- connman_task_add_argument(task, "--user", username);
- connman_task_add_argument(task, "--passwd-on-stdin", NULL);
- break;
+ /* fall-through */
+
+ /*
+ * In case of public key, reaching here means that the
+ * passphrase previously provided was incorrect.
+ */
case OC_CONNECT_PUBLICKEY:
- certificate = vpn_provider_get_string(provider,
- "OpenConnect.ClientCert");
- private_key = vpn_provider_get_string(provider,
- "OpenConnect.UserPrivateKey");
+ data->err = -EACCES;
+ clear_provider_credentials(data->provider, true);
- if (!certificate || !private_key) {
- err = -EACCES;
- goto done;
- }
+ /* fall-through */
+ default:
+ form_data->status = OC_FORM_RESULT_ERR;
+ goto out;
+ }
- connman_task_add_argument(task, "--certificate", certificate);
- connman_task_add_argument(task, "--sslkey", private_key);
- break;
- case OC_CONNECT_PKCS:
- certificate = vpn_provider_get_string(provider,
- "OpenConnect.PKCSClientCert");
- if (!certificate) {
- err = -EACCES;
- goto done;
+ /*
+ * Form values are released with free(), so always use strdup()
+ * instead of g_strdup()
+ */
+ for (opt = form_data->form->opts; opt; opt = opt->next) {
+ if (opt->flags & OC_FORM_OPT_IGNORE)
+ continue;
+
+ if (opt->type == OC_FORM_OPT_TEXT &&
+ g_str_has_prefix(opt->name, "user")) {
+ const char *user = vpn_provider_get_string(
+ data->provider,
+ "OpenConnect.Username");
+ if (user)
+ opt->_value = strdup(user);
+ } else if (opt->type == OC_FORM_OPT_PASSWORD) {
+ const char *pass = vpn_provider_get_string(
+ data->provider,
+ "OpenConnect.Password");
+ if (pass)
+ opt->_value = strdup(pass);
}
+ }
- connman_task_add_argument(task, "--certificate", certificate);
+ form_data->status = OC_FORM_RESULT_OK;
- password = vpn_provider_get_string(data->provider,
- "OpenConnect.PKCSPassword");
- /* Add password only if it is has been set */
- if (!password || !g_strcmp0(password, "-"))
- break;
+ out:
+ form_data->processed = true;
+ g_cond_signal(&form_data->cond);
+ g_mutex_unlock(&form_data->mutex);
+
+ return G_SOURCE_REMOVE;
+ }
+
+ static int oc_process_auth_form(void *user_data, struct oc_auth_form *form)
+ {
+ struct process_form_data data = { .form = form,
+ .data = user_data,
+ .processed = false };
+
+ DBG("");
+
+ g_cond_init(&data.cond);
+ g_mutex_init(&data.mutex);
+
+ g_mutex_lock(&data.mutex);
+ g_idle_add(process_auth_form, &data);
+
+ while (!data.processed)
+ g_cond_wait(&data.cond, &data.mutex);
+
+ g_mutex_unlock(&data.mutex);
+
+ g_mutex_clear(&data.mutex);
+ g_cond_clear(&data.cond);
+
+ return data.status;
+ }
+
+ static gboolean authenticated(void *user_data)
+ {
+ struct oc_private_data *data = user_data;
+ int rv = GPOINTER_TO_INT(g_thread_join(data->cookie_thread));
+
+ DBG("");
+
+ data->cookie_thread = NULL;
+
+ if (rv == 0)
+ rv = run_connect(data, openconnect_get_cookie(data->vpninfo));
+ else if (rv < 0)
+ clear_provider_credentials(data->provider, true);
+
+ openconnect_vpninfo_free(data->vpninfo);
+ data->vpninfo = NULL;
+
+ if (rv != -EINPROGRESS) {
+ oc_connect_done(data, data->err ? data->err : rv);
+ free_private_data(data);
+ }
- connman_task_add_argument(task, "--passwd-on-stdin", NULL);
+ return G_SOURCE_REMOVE;
+ }
+
+ static void *obtain_cookie_thread(void *user_data)
+ {
+ struct oc_private_data *data = user_data;
+ int ret;
+
+ DBG("%p", data->vpninfo);
+
+ ret = openconnect_obtain_cookie(data->vpninfo);
+
+ g_idle_add(authenticated, data);
+
+ return GINT_TO_POINTER(ret);
+ }
+
+ static int authenticate(struct oc_private_data *data)
+ {
+ const char *cert = NULL;
+ const char *key = NULL;
+ const char *urlpath;
+ const char *vpnhost;
+
+ DBG("");
+
+ switch (data->connect_type) {
+ case OC_CONNECT_PKCS:
+ cert = vpn_provider_get_string(data->provider,
+ "OpenConnect.PKCSClientCert");
break;
+ case OC_CONNECT_PUBLICKEY:
+ cert = vpn_provider_get_string(data->provider,
+ "OpenConnect.ClientCert");
+ key = vpn_provider_get_string(data->provider,
+ "OpenConnect.UserPrivateKey");
+ break;
+
+ case OC_CONNECT_USERPASS:
+ case OC_CONNECT_COOKIE_WITH_USERPASS:
+ break;
+
+ default:
+ return -EINVAL;
}
- vpnhost = vpn_provider_get_string(provider, "OpenConnect.VPNHost");
+ openconnect_init_ssl();
+ data->vpninfo = openconnect_vpninfo_new("ConnMan VPN Agent",
+ oc_validate_peer_cert,
+ NULL,
+ oc_process_auth_form,
+ oc_progress,
+ data);
+
+ /* Replicating how openconnect's --usergroup argument works */
+ urlpath = vpn_provider_get_string(data->provider,
+ "OpenConnect.Usergroup");
+ if (urlpath)
+ openconnect_set_urlpath(data->vpninfo, urlpath);
+
+ if (vpn_provider_get_boolean(data->provider,
+ "OpenConnect.DisableIPv6", false))
+ openconnect_disable_ipv6(data->vpninfo);
+
+ vpnhost = vpn_provider_get_string(data->provider,
+ "OpenConnect.VPNHost");
if (!vpnhost || !*vpnhost)
- vpnhost = vpn_provider_get_string(provider, "Host");
+ vpnhost = vpn_provider_get_string(data->provider, "Host");
- task_append_config_data(provider, task);
+ openconnect_set_hostname(data->vpninfo, vpnhost);
+
+ if (cert)
+ openconnect_set_client_cert(data->vpninfo, cert, key);
+
+ data->fd_cmd = openconnect_setup_cmd_pipe(data->vpninfo);
/*
- * To clarify complex situation, if cookie is expected to be printed
- * to stdout all other output must go to syslog. But with PKCS all
- * output must be caught in order to get message about file decryption
- * error. For this reason, the mode has to be interactive as well.
+ * openconnect_obtain_cookie blocks, so run it in background thread
+ * instead
*/
- switch (data->connect_type) {
- case OC_CONNECT_COOKIE:
- /* fall through */
- case OC_CONNECT_COOKIE_WITH_USERPASS:
- /* fall through */
- case OC_CONNECT_USERPASS:
- /* fall through */
- case OC_CONNECT_PUBLICKEY:
- connman_task_add_argument(task, "--syslog", NULL);
+ data->cookie_thread = g_thread_try_new("obtain_cookie",
+ obtain_cookie_thread,
+ data, NULL);
+
+ if (!data->cookie_thread)
+ return -EIO;
+
+ return -EINPROGRESS;
+ }
- setting = vpn_provider_get_boolean(provider,
+ static int run_connect(struct oc_private_data *data, const char *cookie)
+ {
+ struct vpn_provider *provider;
+ struct connman_task *task;
+ const char *vpnhost;
+ int fd_err;
+ int err = 0;
+ bool allow_self_signed;
+ const char *server_cert;
+
+ if (!data || !cookie)
+ return -EINVAL;
+
+ provider = data->provider;
+ task = data->task;
+
+ server_cert = vpn_provider_get_string(provider,
+ "OpenConnect.ServerCert");
+ allow_self_signed = vpn_provider_get_boolean(provider,
"OpenConnect.AllowSelfSignedCert",
false);
- setting_str = vpn_provider_get_string(provider,
- "OpenConnect.ServerCert");
- /*
- * Run in interactive mode if self signed certificates are
- * allowed and there is no set server SHA1 fingerprint.
- */
- if (setting_str || !setting)
- connman_task_add_argument(task, "--non-inter", NULL);
- else
- data->interactive = true;
- break;
- case OC_CONNECT_PKCS:
- data->interactive = true;
- break;
- }
+ DBG("provider %p task %p", provider, task);
+
+ connman_task_add_argument(task, "--cookie-on-stdin", NULL);
+
+ vpnhost = vpn_provider_get_string(provider, "OpenConnect.VPNHost");
+ if (!vpnhost || !*vpnhost)
+ vpnhost = vpn_provider_get_string(provider, "Host");
+
+ task_append_config_data(provider, task);
connman_task_add_argument(task, "--script", SCRIPTDIR "/vpn-script");
connman_task_add_argument(task, (char *)vpnhost, NULL);
- err = connman_task_run(task, oc_died, data, &data->fd_in, use_stdout ?
- &fd_out : NULL, &fd_err);
+ err = connman_task_run(task, oc_died, data, &data->fd_in,
+ NULL, &fd_err);
if (err < 0) {
err = -EIO;
goto done;
}
- switch (data->connect_type) {
- case OC_CONNECT_COOKIE:
- if (write_data(data->fd_in, vpncookie) != 0) {
- connman_error("openconnect failed to take cookie on "
- "stdin");
- err = -EIO;
- }
-
- break;
- case OC_CONNECT_USERPASS:
- if (write_data(data->fd_in, password) != 0) {
- connman_error("openconnect failed to take password on "
- "stdin");
- err = -EIO;
- }
-
- break;
- case OC_CONNECT_COOKIE_WITH_USERPASS:
- if (!vpncookie || !g_strcmp0(vpncookie, "-")) {
- if (write_data(data->fd_in, password) != 0) {
- connman_error("openconnect failed to take "
- "password on stdin");
- err = -EIO;
- }
- } else {
- if (write_data(data->fd_in, vpncookie) != 0) {
- connman_error("openconnect failed to take "
- "cookie on stdin");
- err = -EIO;
- }
- }
-
- break;
- case OC_CONNECT_PUBLICKEY:
- break;
- case OC_CONNECT_PKCS:
- if (!password || !g_strcmp0(password, "-"))
- break;
+ if (write_data(data->fd_in, cookie) != 0) {
+ connman_error("openconnect failed to take cookie on "
+ "stdin");
+ err = -EIO;
+ }
- if (write_data(data->fd_in, password) != 0) {
- connman_error("openconnect failed to take PKCS "
- "pass phrase on stdin");
+ if (!server_cert || !allow_self_signed) {
+ if (write_data(data->fd_in,
+ (allow_self_signed ? "yes" : "no"))) {
+ connman_error("openconnect failed to take certificate "
+ "acknowledgement on stdin");
err = -EIO;
}
-
- break;
}
if (err) {
- if (fd_out > 0)
- close(fd_out);
-
- if (fd_err > 0)
+ if (fd_err >= 0)
close(fd_err);
goto done;
err = -EINPROGRESS;
- if (use_stdout) {
- data->out_ch = g_io_channel_unix_new(fd_out);
-
- /* Use ASCII encoding only */
- if (g_io_channel_set_encoding(data->out_ch, NULL, NULL) !=
- G_IO_STATUS_NORMAL) {
- close_io_channel(data, data->out_ch);
- err = -EIO;
- } else {
- data->out_ch_id = g_io_add_watch(data->out_ch,
- G_IO_IN | G_IO_ERR | G_IO_HUP,
- (GIOFunc)io_channel_out_cb,
- data);
- }
- }
-
data->err_ch = g_io_channel_unix_new(fd_err);
/* Use ASCII encoding only */
}
done:
- clear_provider_credentials(data->provider);
+ clear_provider_credentials(data->provider, err != -EINPROGRESS);
return err;
}
connman_info("provider %p", data->provider);
- if (!reply)
+ if (!reply) {
+ err = ENOENT;
goto err;
+ }
err = vpn_agent_check_and_process_reply_error(reply, data->provider,
data->task, data->cb, data->user_data);
goto out;
}
- if (!vpn_agent_check_reply_has_dict(reply))
+ if (!vpn_agent_check_reply_has_dict(reply)) {
+ err = ENOENT;
goto err;
+ }
dbus_message_iter_init(reply, &iter);
dbus_message_iter_recurse(&iter, &dict);
switch (data->connect_type) {
case OC_CONNECT_COOKIE:
- if (!cookie)
+ if (!cookie) {
+ err = EACCES;
goto err;
+ }
break;
case OC_CONNECT_USERPASS:
/* fall through */
case OC_CONNECT_COOKIE_WITH_USERPASS:
- if (!username || !password)
+ if (!username || !password) {
+ err = EACCES;
goto err;
+ }
break;
case OC_CONNECT_PUBLICKEY:
break; // This should not be reached.
case OC_CONNECT_PKCS:
- if (!pkcspassword)
+ if (!pkcspassword) {
+ err = EACCES;
goto err;
+ }
break;
}
- err = run_connect(data);
+ if (cookie)
+ err = run_connect(data, cookie);
+ else
+ err = authenticate(data);
+
if (err != -EINPROGRESS)
goto err;
return;
err:
- oc_connect_done(data, EACCES);
+ oc_connect_done(data, err);
out:
free_private_data(data);
}
- static int request_input_credentials(struct oc_private_data *data,
- request_input_reply_cb_t cb)
+ static int request_input_credentials_full(
+ struct oc_private_data *data,
+ request_input_reply_cb_t cb,
+ void *user_data)
{
DBusMessage *message;
const char *path;
/*
* For backwards compatibility add OpenConnect.ServerCert and
- * OpenConnect.VPNHost as madnatory only in the default authentication
+ * OpenConnect.VPNHost as mandatory only in the default authentication
* mode. Otherwise. add the fields as informational. These should be
* set in provider settings and not to be queried with every connection
* attempt.
request_input_append_informational,
"OpenConnect.PKCSClientCert");
+ /* Do not allow to store or retrieve the encrypted PKCS pass */
+ vpn_agent_append_allow_credential_storage(&dict, false);
+ vpn_agent_append_allow_credential_retrieval(&dict, false);
+
+ /*
+ * Indicate to keep credentials, the PKCS password should not
+ * affect the credential storing.
+ */
+ vpn_agent_append_keep_credentials(&dict, true);
+
request_input_append_to_dict(data->provider, &dict,
request_input_append_password,
"OpenConnect.PKCSPassword");
connman_dbus_dict_close(&iter, &dict);
err = connman_agent_queue_message(data->provider, message,
- connman_timeout_input_request(), cb, data, agent);
+ connman_timeout_input_request(), cb, user_data, agent);
dbus_message_unref(message);
return -EINPROGRESS;
}
+ static int request_input_credentials(struct oc_private_data *data,
+ request_input_reply_cb_t cb)
+ {
+ return request_input_credentials_full(data, cb, data);
+ }
+
static enum oc_connect_type get_authentication_type(
struct vpn_provider *provider)
{
const char *dbus_sender, void *user_data)
{
struct oc_private_data *data;
- const char *vpncookie;
+ const char *vpncookie = NULL;
const char *certificate;
const char *username;
const char *password;
break;
}
- return run_connect(data);
+ if (vpncookie && g_strcmp0(vpncookie, "-"))
+ return run_connect(data, vpncookie);
+ return authenticate(data);
request_input:
err = request_input_credentials(data, request_input_credentials_reply);
static void oc_disconnect(struct vpn_provider *provider)
{
+ struct oc_private_data *data;
+
connman_info("provider %p", provider);
if (!provider)
* agent request to avoid having multiple ones visible.
*/
connman_agent_cancel(provider);
+
+ data = vpn_provider_get_plugin_data(provider);
+
+ if (!data)
+ return;
+
+ if (data->cookie_thread) {
+ char cmd = OC_CMD_CANCEL;
+ int w = write(data->fd_cmd, &cmd, 1);
+ if (w != 1)
+ DBG("Write failed, might be leaking a thread");
+ }
+
}
static int oc_save(struct vpn_provider *provider, GKeyFile *keyfile)
switch (exit_code) {
case 2:
/* Cookie has failed */
- clear_provider_credentials(provider);
+ clear_provider_credentials(provider, false);
return VPN_PROVIDER_ERROR_LOGIN_FAILED;
case 1:
/* fall through */
}
static int oc_route_env_parse(struct vpn_provider *provider, const char *key,
- int *family, unsigned long *idx, enum vpn_provider_route_type *type)
+ int *family, unsigned long *idx,
+ enum vpn_provider_route_type *type)
{
char *end;
const char *start;
#include "../vpn-agent.h"
#include "vpn.h"
- #include "../vpn.h"
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
{ "OpenVPN.ConfigFile", "--config", 1 },
{ "OpenVPN.DeviceType", NULL, 1 },
{ "OpenVPN.Verb", "--verb", 1 },
+ { "OpenVPN.Ping", "--ping", 1},
+ { "OpenVPN.PingExit", "--ping-exit", 1},
+ { "OpenVPN.RemapUsr1", "--remap-usr1", 1},
};
struct ov_private_data {
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_ipaddress_set_ipv4(ipaddress, address, netmask, gateway);
connman_ipaddress_set_peer(ipaddress, peer);
+ connman_ipaddress_set_p2p(ipaddress, true);
vpn_provider_set_ipaddress(provider, ipaddress);
if (nameserver_list) {
connman_task_add_argument(task, "--persist-tun", NULL);
+#if !defined TIZEN_EXT
connman_task_add_argument(task, "--route-noexec", NULL);
connman_task_add_argument(task, "--ifconfig-noexec", NULL);
+#endif
/*
- * Disable client restarts because we can't handle this at the
- * moment. The problem is that when OpenVPN decides to switch
+ * Disable client restarts with TCP because we can't handle this at
+ * the moment. The problem is that when OpenVPN decides to switch
* from CONNECTED state to RECONNECTING and then to RESOLVE,
* it is not possible to do a DNS lookup. The DNS server is
* not accessible through the tunnel anymore and so we end up
* trying to resolve the OpenVPN servers address.
- */
- connman_task_add_argument(task, "--ping-restart", "0");
-
- /*
+ *
* Disable connetion retrying when OpenVPN is connected over TCP.
* With TCP OpenVPN attempts to handle reconnection silently without
* reporting the error back when establishing a connection or
* including DNS.
*/
option = vpn_provider_get_string(provider, "OpenVPN.Proto");
- if (option && g_str_has_prefix(option, "tcp"))
+ if (option && g_str_has_prefix(option, "tcp")) {
+ option = vpn_provider_get_string(provider, "OpenVPN.PingExit");
+ if (!option)
+ connman_task_add_argument(task, "--ping-restart", "0");
+
connman_task_add_argument(task, "--connect-retry-max", "1");
+ /* Apply defaults for --ping and --ping-exit only with UDP protocol. */
+ } else {
+ /* Apply default of 10 second interval for ping if omitted. */
+ option = vpn_provider_get_string(provider, "OpenVPN.Ping");
+ if (!option)
+ connman_task_add_argument(task, "--ping", "10");
+
+ /* Apply default of 60 seconds for ping exit if omitted. */
+ option = vpn_provider_get_string(provider, "OpenVPN.PingExit");
+ if (!option)
+ connman_task_add_argument(task, "--ping-exit", "60");
+ }
err = connman_task_run(task, ov_died, data, NULL, NULL, NULL);
if (err < 0) {
enum {
OPT_STRING = 1,
OPT_BOOL = 2,
+ OPT_PPTP_ONLY = 3,
};
struct {
const char *cm_opt;
const char *pptp_opt;
- const char *vpnc_default;
+ const char *pptp_default;
int type;
} pptp_options[] = {
{ "PPTP.User", "user", NULL, OPT_STRING },
+ { "PPTP.IdleWait", "--idle-wait", NULL, OPT_PPTP_ONLY},
+ { "PPTP.MaxEchoWait", "--max-echo-wait", NULL, OPT_PPTP_ONLY},
{ "PPPD.EchoFailure", "lcp-echo-failure", "0", OPT_STRING },
{ "PPPD.EchoInterval", "lcp-echo-interval", "0", OPT_STRING },
{ "PPPD.Debug", "debug", NULL, OPT_STRING },
connman_ipaddress_set_ipv4(ipaddress, addressv4, netmask,
gateway);
+ connman_ipaddress_set_p2p(ipaddress, true);
vpn_provider_set_ipaddress(provider, ipaddress);
vpn_provider_set_nameservers(provider, nameservers);
vpn_provider_connect_cb_t cb, void *user_data,
const char *username, const char *password)
{
- const char *opt_s, *host;
+ GString *pptp_opt_s;
+ const char *opt_s;
+ const char *host;
char *str;
int err, i;
DBG("username %s password %p", username, password);
host = vpn_provider_get_string(provider, "Host");
- str = g_strdup_printf("%s %s --nolaunchpppd --loglevel 2",
- PPTP, host);
- if (!str) {
- connman_error("can not allocate memory");
- err = -ENOMEM;
- goto done;
- }
- connman_task_add_argument(task, "pty", str);
- g_free(str);
+ /* Create PPTP options for pppd "pty" */
+ pptp_opt_s = g_string_new(NULL);
+ g_string_append_printf(pptp_opt_s, "%s %s --nolaunchpppd --loglevel 2",
+ PPTP, host);
connman_task_add_argument(task, "nodetach", NULL);
connman_task_add_argument(task, "lock", NULL);
opt_s = vpn_provider_get_string(provider,
pptp_options[i].cm_opt);
if (!opt_s)
- opt_s = pptp_options[i].vpnc_default;
+ opt_s = pptp_options[i].pptp_default;
if (!opt_s)
continue;
else if (pptp_options[i].type == OPT_BOOL)
pptp_write_bool_option(task,
pptp_options[i].pptp_opt, opt_s);
+ else if (pptp_options[i].type == OPT_PPTP_ONLY)
+ g_string_append_printf(pptp_opt_s, " %s %s",
+ pptp_options[i].pptp_opt, opt_s);
}
+ str = g_string_free(pptp_opt_s, FALSE);
+ connman_task_add_argument(task, "pty", str);
+ g_free(str);
+
connman_task_add_argument(task, "plugin",
SCRIPTDIR "/libppp-plugin.so");
struct vpn_driver_data {
const char *name;
const char *program;
- struct vpn_driver *vpn_driver;
+ const struct vpn_driver *vpn_driver;
struct vpn_provider_driver provider_driver;
};
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);
return ret;
}
- static gboolean is_numeric(const char *str)
+ static gid_t get_gid(const char *group_name)
{
- gint i;
-
- if(!str || !(*str))
- return false;
-
- for(i = 0; str[i] ; i++) {
- if(!g_ascii_isdigit(str[i]))
- return false;
- }
-
- return true;
- }
-
- static gint get_gid(const char *group_name)
- {
- gint gid = -1;
struct group *grp;
- if(!group_name || !(*group_name))
- return gid;
-
- if (is_numeric(group_name)) {
- gid_t group_id = (gid_t)g_ascii_strtoull(group_name, NULL, 10);
- grp = getgrgid(group_id);
- } else {
- grp = getgrnam(group_name);
- }
-
+ grp = vpn_util_get_group(group_name);
if (grp)
- gid = grp->gr_gid;
+ return grp->gr_gid;
- return gid;
+ return -1;
}
- static gint get_uid(const char *user_name)
+ static uid_t get_uid(const char *user_name)
{
- gint uid = -1;
struct passwd *pw;
- if(!user_name || !(*user_name))
- return uid;
-
- if (is_numeric(user_name)) {
- uid_t user_id = (uid_t)g_ascii_strtoull(user_name, NULL, 10);
- pw = getpwuid(user_id);
- } else {
- pw = getpwnam(user_name);
- }
-
+ pw = vpn_util_get_passwd(user_name);
if (pw)
- uid = pw->pw_uid;
+ return pw->pw_uid;
- return uid;
+ return -1;
}
static gint get_supplementary_gids(gchar **groups, gid_t **gid_list)
static void vpn_task_setup(gpointer user_data)
{
struct vpn_plugin_data *data;
- gint uid;
- gint gid;
+ uid_t uid;
+ gid_t gid;
gid_t *gid_list = NULL;
size_t gid_list_size;
const gchar *user;
vpn_driver_data->vpn_driver->flags & VPN_FLAG_NO_DAEMON) {
ret = vpn_driver_data->vpn_driver->connect(provider,
- NULL, NULL, NULL, NULL, NULL);
+ NULL, NULL, cb, dbus_sender, user_data);
if (ret) {
stop_vpn(provider);
goto exist_err;
goto exist_err;
}
-
+#if defined TIZEN_EXT
+ if(vpn_driver_data->vpn_driver->set_event_cb)
+ vpn_driver_data->vpn_driver->set_event_cb(vpn_event, provider);
+#endif
+
ret = vpn_driver_data->vpn_driver->connect(provider, data->task,
data->if_name, cb, dbus_sender,
user_data);
return 0;
}
- int vpn_register(const char *name, struct vpn_driver *vpn_driver,
+ int vpn_register(const char *name, const struct vpn_driver *vpn_driver,
const char *program)
{
struct vpn_driver_data *data;
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,
enum vpn_provider_route_type *type);
};
- int vpn_register(const char *name, struct vpn_driver *driver,
+ int vpn_register(const char *name, const struct vpn_driver *driver,
const char *program);
void vpn_unregister(const char *provider_name);
void vpn_died(struct connman_task *task, int exit_code, void *user_data);
#include <stdio.h>
#include <net/if.h>
#include <linux/if_tun.h>
+ #include <sys/types.h>
+ #include <pwd.h>
+ #include <grp.h>
+ #include <fcntl.h>
#include <glib.h>
#include "../vpn.h"
#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
+ #define PID_PATH_ROOT "/var/run/user"
enum {
OPT_STRING = 1,
}
connman_ipaddress_set_ipv4(ipaddress, address, netmask, gateway);
+ connman_ipaddress_set_p2p(ipaddress, true);
vpn_provider_set_ipaddress(provider, ipaddress);
g_free(address);
return G_SOURCE_CONTINUE;
}
+ static char *create_pid_path(const char *user, const char *group)
+ {
+ struct passwd *pwd;
+ struct group *grp;
+ char *uid_str;
+ char *pid_path = NULL;
+ int mode = S_IRWXU|S_IRWXG;
+ gid_t gid;
+
+ if (!user || !*user)
+ return NULL;
+
+ if (vpn_settings_is_system_user(user))
+ return NULL;
+
+ pwd = vpn_util_get_passwd(user);
+ uid_str = g_strdup_printf("%d", pwd->pw_uid);
+
+ grp = vpn_util_get_group(group);
+ gid = grp ? grp->gr_gid : pwd->pw_gid;
+
+ pid_path = g_build_filename(PID_PATH_ROOT, uid_str, "vpnc", "pid",
+ NULL);
+ if (vpn_util_create_path(pid_path, pwd->pw_uid, gid, mode)) {
+ g_free(pid_path);
+ pid_path = NULL;
+ }
+
+ g_free(uid_str);
+
+ return pid_path;
+ }
+
static int run_connect(struct vc_private_data *data)
{
struct vpn_provider *provider;
struct connman_task *task;
+ struct vpn_plugin_data *plugin_data;
const char *credentials[] = {"VPNC.IPSec.Secret", "VPNC.Xauth.Username",
"VPNC.Xauth.Password", NULL};
const char *if_name;
const char *option;
+ char *pid_path;
int err;
int fd_in;
int fd_err;
connman_task_add_argument(task, "--ifmode", "tun");
}
+ plugin_data = vpn_settings_get_vpn_plugin_config("vpnc");
+
+ option = vpn_settings_get_binary_user(plugin_data);
+ if (option) {
+ pid_path = create_pid_path(option,
+ vpn_settings_get_binary_group(
+ plugin_data));
+ if (pid_path)
+ connman_task_add_argument(task, "--pid-file",
+ pid_path);
+
+ g_free(pid_path);
+ }
+
connman_task_add_argument(task, "--script", SCRIPTDIR "/vpn-script");
option = vpn_provider_get_string(provider, "VPNC.Debug");
DBG("provider %p", data->provider);
- if (!reply)
+ if (!reply) {
+ err = ENOENT;
goto err;
+ }
err = vpn_agent_check_and_process_reply_error(reply, data->provider,
data->task, data->cb, data->user_data);
return;
}
- if (!vpn_agent_check_reply_has_dict(reply))
+ if (!vpn_agent_check_reply_has_dict(reply)) {
+ err = ENOENT;
goto err;
+ }
dbus_message_iter_init(reply, &iter);
dbus_message_iter_recurse(&iter, &dict);
dbus_message_iter_next(&dict);
}
- if (!secret || !username || !password)
+ if (!secret || !username || !password) {
+ vpn_provider_indicate_error(data->provider,
+ VPN_PROVIDER_ERROR_AUTH_FAILED);
+ err = EACCES;
goto err;
+ }
- err = run_connect(data);
- if (err != -EINPROGRESS)
+ /* vpn_provider.c:connect_cb() expects positive errors */
+ err = -run_connect(data);
+ if (err != EINPROGRESS)
goto err;
return;
err:
- vc_connect_done(data, EACCES);
+ vc_connect_done(data, err);
}
static int request_input_credentials(struct vc_private_data *data,
#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;
err = -EINVAL;
}
+ connman_ipaddress_set_p2p(*ipaddress, true);
+
g_strfreev(tokens);
if (err)
connman_ipaddress_free(*ipaddress);
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 {
- DBG("invalid values host %s domain %s name %s", host, domain, name);
+#if !defined TIZEN_EXT
+ DBG("invalid values host %s domain %s", host, domain);
+#else
+ DBG("invalid configuration: no host specified");
+#endif
err = -EINVAL;
goto err;
}
return strlist;
}
+
+ bool __vpn_config_get_boolean(GKeyFile *key_file, const char *group_name,
+ const char *key, bool default_value)
+ {
+ GError *error = NULL;
+ bool val;
+
+ val = g_key_file_get_boolean(key_file, group_name, key, &error);
+ if (error) {
+ g_error_free(error);
+ return default_value;
+ }
+
+ return val;
+ }
<!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>
if (family == AF_INET)
return connman_inet_set_address(ipconfig->index,
- ipconfig->address);
+ ipconfig->address);
else if (family == AF_INET6)
return connman_inet_set_ipv6_address(ipconfig->index,
ipconfig->address);
return NULL;
}
+ connman_ipaddress_set_p2p(ipv6config->address, true);
+
ipv6config->system = connman_ipaddress_alloc(AF_INET6);
+ connman_ipaddress_set_p2p(ipv6config->system, true);
DBG("ipconfig %p", ipv6config);
return NULL;
}
+ connman_ipaddress_set_p2p(ipconfig->address, true);
+
ipconfig->system = connman_ipaddress_alloc(AF_INET);
+ connman_ipaddress_set_p2p(ipconfig->system, true);
DBG("ipconfig %p", ipconfig);
static GHashTable *provider_hash;
static GSList *driver_list;
static int configuration_count;
- static bool handle_routes;
struct vpn_route {
int family;
char *host;
char *domain;
int family;
+ bool do_split_routing;
GHashTable *routes;
struct vpn_provider_driver *driver;
void *driver_data;
void *plugin_data;
unsigned int auth_error_counter;
unsigned int conn_error_counter;
+ unsigned int signal_watch;
};
static void append_properties(DBusMessageIter *iter,
static void del_routes(struct vpn_provider *provider)
{
GHashTableIter hash;
- gpointer value, key;
g_hash_table_iter_init(&hash, provider->user_routes);
- while (handle_routes && g_hash_table_iter_next(&hash,
- &key, &value)) {
- struct vpn_route *route = value;
- if (route->family == AF_INET6) {
- unsigned char prefixlen = atoi(route->netmask);
- connman_inet_del_ipv6_network_route(provider->index,
- route->network,
- prefixlen);
- } else
- connman_inet_del_host_route(provider->index,
- route->network);
- }
-
g_hash_table_remove_all(provider->user_routes);
g_slist_free_full(provider->user_networks, free_route);
provider->user_networks = NULL;
&str);
}
+ static void send_value_boolean(const char *path, const char *key,
+ dbus_bool_t value)
+ {
+ connman_dbus_property_changed_basic(path,
+ VPN_CONNECTION_INTERFACE,
+ key,
+ DBUS_TYPE_BOOLEAN,
+ &value);
+ }
+
static gboolean provider_send_changed(gpointer data)
{
struct vpn_provider *provider = data;
return true;
}
+ static const char *bool2str(bool value)
+ {
+ return value ? "true" : "false";
+ }
+
static int set_provider_property(struct vpn_provider *provider,
const char *name, DBusMessageIter *value, int type)
{
del_routes(provider);
provider->user_networks = networks;
set_user_networks(provider, provider->user_networks);
+ send_routes(provider, provider->user_routes, "UserRoutes");
+ } else if (g_str_equal(name, "SplitRouting")) {
+ dbus_bool_t split_routing;
+
+ if (type != DBUS_TYPE_BOOLEAN)
+ return -EINVAL;
- if (!handle_routes)
- send_routes(provider, provider->user_routes,
- "UserRoutes");
+ dbus_message_iter_get_basic(value, &split_routing);
+
+ DBG("property %s value %s ", name, bool2str(split_routing));
+ vpn_provider_set_boolean(provider, name, split_routing, false);
} else {
const char *str;
dbus_message_iter_recurse(&entry, &value);
type = dbus_message_iter_get_arg_type(&value);
- /* Ignore and report back all invalid property types */
- if (type != DBUS_TYPE_STRING && type != DBUS_TYPE_ARRAY) {
+ switch (type) {
+ case DBUS_TYPE_STRING:
+ case DBUS_TYPE_ARRAY:
+ case DBUS_TYPE_BOOLEAN:
+ break;
+ default:
+ /* Ignore and report back all invalid property types */
invalid = append_to_gstring(invalid, key);
continue;
}
del_routes(provider);
- if (!handle_routes)
- send_routes(provider, provider->user_routes, name);
+ send_routes(provider, provider->user_routes, name);
} else if (vpn_provider_get_string(provider, name)) {
err = vpn_provider_set_string(provider, name, NULL);
switch (err) {
void __vpn_provider_append_properties(struct vpn_provider *provider,
DBusMessageIter *iter)
{
+ dbus_bool_t split_routing;
+
if (provider->host)
connman_dbus_dict_append_basic(iter, "Host",
DBUS_TYPE_STRING, &provider->host);
if (provider->type)
connman_dbus_dict_append_basic(iter, "Type", DBUS_TYPE_STRING,
&provider->type);
+
+ split_routing = provider->do_split_routing;
+ connman_dbus_dict_append_basic(iter, "SplitRouting", DBUS_TYPE_BOOLEAN,
+ &split_routing);
}
int __vpn_provider_append_user_route(struct vpn_provider *provider,
static int provider_load_from_keyfile(struct vpn_provider *provider,
GKeyFile *keyfile)
{
- gsize idx = 0;
+ gsize idx;
gchar **settings;
gchar *key, *value;
gsize length, num_user_networks;
return -ENOENT;
}
- while (idx < length) {
+ for (idx = 0; idx < length; idx++) {
key = settings[idx];
- if (key) {
- if (g_str_equal(key, "Networks")) {
- networks = __vpn_config_get_string_list(keyfile,
- provider->identifier,
- key,
- &num_user_networks,
+ if (!key)
+ continue;
+
+ if (g_str_equal(key, "Networks")) {
+ networks = __vpn_config_get_string_list(keyfile,
+ provider->identifier,key,
+ &num_user_networks, NULL);
+ provider->user_networks = get_routes(networks);
+ } else {
+ value = __vpn_config_get_string(keyfile,
+ provider->identifier, key,
NULL);
- provider->user_networks = get_routes(networks);
-
- } else {
- value = __vpn_config_get_string(keyfile,
- provider->identifier,
- key, NULL);
- vpn_provider_set_string(provider, key,
- value);
- g_free(value);
- }
+
+ vpn_provider_set_string(provider, key, value);
+ g_free(value);
}
- idx += 1;
}
+
g_strfreev(settings);
g_strfreev(networks);
"Host", provider->host);
g_key_file_set_string(keyfile, provider->identifier,
"VPN.Domain", provider->domain);
+
if (provider->user_networks) {
gchar **networks;
gsize network_count;
GHashTableIter hash;
gpointer value, key;
dbus_bool_t immutable;
+ dbus_bool_t split_routing;
connman_dbus_dict_open(iter, &dict);
connman_dbus_dict_append_basic(&dict, "Immutable", DBUS_TYPE_BOOLEAN,
&immutable);
+ split_routing = provider->do_split_routing;
+ connman_dbus_dict_append_basic(&dict, "SplitRouting",
+ DBUS_TYPE_BOOLEAN, &split_routing);
+
if (provider->family == AF_INET)
connman_dbus_dict_append_dict(&dict, "IPv4", append_ipv4,
provider);
while (g_hash_table_iter_next(&hash, &key, &value)) {
struct vpn_setting *setting = value;
- if (!setting->hide_value &&
- setting->value)
+ if (!setting->hide_value && setting->value)
connman_dbus_dict_append_basic(&dict, key,
DBUS_TYPE_STRING,
&setting->value);
dbus_message_unref(signal);
}
- static bool check_host(char **hosts, char *host)
- {
- int i;
-
- if (!hosts)
- return false;
-
- for (i = 0; hosts[i]; i++) {
- if (g_strcmp0(hosts[i], host) == 0)
- return true;
- }
-
- return false;
- }
-
- static void provider_append_routes(gpointer key, gpointer value,
- gpointer user_data)
- {
- struct vpn_route *route = value;
- struct vpn_provider *provider = user_data;
- int index = provider->index;
-
- if (!handle_routes)
- return;
-
- /*
- * If the VPN administrator/user has given a route to
- * VPN server, then we must discard that because the
- * server cannot be contacted via VPN tunnel.
- */
- if (check_host(provider->host_ip, route->network)) {
- DBG("Discarding VPN route to %s via %s at index %d",
- route->network, route->gateway, index);
- return;
- }
-
- if (route->family == AF_INET6) {
- unsigned char prefix_len = atoi(route->netmask);
-
- connman_inet_add_ipv6_network_route(index, route->network,
- route->gateway,
- prefix_len);
- } else {
- connman_inet_add_network_route(index, route->network,
- route->gateway,
- route->netmask);
- }
- }
-
static int set_connected(struct vpn_provider *provider,
bool connected)
{
__vpn_ipconfig_address_add(ipconfig, provider->family);
- if (handle_routes)
- __vpn_ipconfig_gateway_add(ipconfig, provider->family);
-
provider_indicate_state(provider,
VPN_PROVIDER_STATE_READY);
-
- g_hash_table_foreach(provider->routes, provider_append_routes,
- provider);
-
- g_hash_table_foreach(provider->user_routes,
- provider_append_routes, provider);
-
} else {
provider_indicate_state(provider,
VPN_PROVIDER_STATE_DISCONNECT);
return 0;
}
+ static gboolean provider_property_changed(DBusConnection *conn,
+ DBusMessage *message, void *user_data)
+ {
+ DBusMessageIter iter;
+ DBusMessageIter value;
+ struct vpn_provider *provider = user_data;
+ const char *key;
+
+ if (!dbus_message_iter_init(message, &iter))
+ return TRUE;
+
+ dbus_message_iter_get_basic(&iter, &key);
+
+ dbus_message_iter_next(&iter);
+ dbus_message_iter_recurse(&iter, &value);
+
+ DBG("provider %p key %s", provider, key);
+
+ if (g_str_equal(key, "SplitRouting")) {
+ dbus_bool_t split_routing;
+
+ if (dbus_message_iter_get_arg_type(&value) !=
+ DBUS_TYPE_BOOLEAN)
+ goto out;
+
+ dbus_message_iter_get_basic(&value, &split_routing);
+
+ DBG("property %s value %s", key, bool2str(split_routing));
+
+ /*
+ * Even though this is coming from connmand, signal the value
+ * for other components listening to the changes via VPN API
+ * only. provider.c will skip setting the same value in order
+ * to avoid signaling loop. This is needed for ensuring that
+ * all components using VPN API will be informed about the
+ * correct status of SplitRouting. Especially when loading the
+ * services after a crash, for instance.
+ */
+ vpn_provider_set_boolean(provider, "SplitRouting",
+ split_routing, true);
+ }
+
+ out:
+ return TRUE;
+ }
+
static int connection_unregister(struct vpn_provider *provider)
{
DBG("provider %p path %s", provider, provider->path);
+ if (provider->signal_watch) {
+ g_dbus_remove_watch(connection, provider->signal_watch);
+ provider->signal_watch = 0;
+ }
+
if (!provider->path)
return -EALREADY;
static int connection_register(struct vpn_provider *provider)
{
+ char *connmand_vpn_path;
+
DBG("provider %p path %s", provider, provider->path);
if (provider->path)
connection_methods, connection_signals,
NULL, provider, NULL);
+ connmand_vpn_path = g_strdup_printf("%s/service/vpn_%s", CONNMAN_PATH,
+ provider->identifier);
+
+ provider->signal_watch = g_dbus_add_signal_watch(connection,
+ CONNMAN_SERVICE, connmand_vpn_path,
+ CONNMAN_SERVICE_INTERFACE,
+ PROPERTY_CHANGED,
+ provider_property_changed,
+ provider, NULL);
+
+ g_free(connmand_vpn_path);
+
return 0;
}
provider->domain = NULL;
provider->identifier = NULL;
provider->immutable = false;
+ provider->do_split_routing = false;
provider->user_networks = NULL;
provider->routes = g_hash_table_new_full(g_direct_hash, g_direct_equal,
NULL, free_route);
return NULL;
}
- if (provider_register(provider) == 0)
+ if (!provider_register(provider)) {
connection_register(provider);
+ connection_added_signal(provider);
+ }
}
+
return provider;
}
g_strfreev(providers);
}
+#if !defined TIZEN_EXT
char *__vpn_provider_create_identifier(const char *host, const char *domain)
{
char *ident;
return ident;
}
+#else
+char *__vpn_provider_create_identifier(const char *host, const char *domain, const char *name)
+{
+ char *ident;
+
+ if (domain)
+ ident = g_strdup_printf("%s_%s_%s", host, domain, name);
+ else
+ ident = g_strdup_printf("%s_%s", host, name);
+ if (!ident)
+ return NULL;
+
+ provider_dbus_ident(ident);
+
+ return ident;
+}
+#endif
int __vpn_provider_create(DBusMessage *msg)
{
GSList *networks = NULL;
char *ident;
int err;
+ dbus_bool_t split_routing = false;
dbus_message_iter_init(msg, &iter);
dbus_message_iter_recurse(&iter, &array);
g_str_equal(key, "Domain"))
dbus_message_iter_get_basic(&value, &domain);
break;
+ case DBUS_TYPE_BOOLEAN:
+ if (g_str_equal(key, "SplitRouting"))
+ dbus_message_iter_get_basic(&value,
+ &split_routing);
+ break;
case DBUS_TYPE_ARRAY:
if (g_str_equal(key, "UserRoutes"))
networks = get_user_networks(&value);
if (!type || !name)
return -EOPNOTSUPP;
+#if !defined TIZEN_EXT
ident = __vpn_provider_create_identifier(host, domain);
+#else
+ ident = __vpn_provider_create_identifier(host, domain, name);
+#endif
DBG("ident %s", ident);
provider = __vpn_provider_lookup(ident);
provider->domain = g_strdup(domain);
provider->name = g_strdup(name);
provider->type = g_strdup(type);
+ provider->do_split_routing = split_routing;
if (provider_register(provider) == 0)
vpn_provider_load(provider);
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;
g_free(provider->domain);
provider->domain = g_strdup(value);
send_value(provider->path, "Domain", provider->domain);
+ } else if (g_str_equal(key, "SplitRouting")) {
+ connman_warn("VPN SplitRouting value attempted to set as "
+ "string, is boolean");
+ return -EINVAL;
} else {
struct vpn_setting *setting;
bool replace = true;
return setting->value;
}
+ int vpn_provider_set_boolean(struct vpn_provider *provider, const char *key,
+ bool value, bool force_change)
+ {
+ DBG("provider %p key %s", provider, key);
+
+ if (g_str_equal(key, "SplitRouting")) {
+ if (provider->do_split_routing == value && !force_change)
+ return -EALREADY;
+
+ DBG("SplitRouting set to %s", bool2str(value));
+
+ provider->do_split_routing = value;
+ send_value_boolean(provider->path, key,
+ provider->do_split_routing);
+ }
+
+ return 0;
+ }
+
bool vpn_provider_get_boolean(struct vpn_provider *provider, const char *key,
bool default_value)
{
void *vpn_provider_get_plugin_data(struct vpn_provider *provider)
{
+#if defined TIZEN_EXT
+ if (!provider)
+ return NULL;
+#endif
return provider->plugin_data;
}
break;
}
- if (!handle_routes) {
- if (route->netmask && route->gateway &&
- route->network)
- provider_schedule_changed(provider);
- }
+ if (route->netmask && route->gateway && route->network)
+ provider_schedule_changed(provider);
return 0;
}
if (provider && provider->driver &&
g_strcmp0(provider->driver->name,
driver->name) == 0) {
+ /*
+ * Cancel VPN agent request to avoid segfault at
+ * shutdown as the callback, if set can point to a
+ * function in the plugin that is to be removed.
+ */
+ connman_agent_cancel(provider);
provider->driver = NULL;
}
}
DBG("ipv6 %s/%d", address, len);
connman_inet_clear_ipv6_address(provider->index,
- address, len);
+ provider->prev_ipv6_addr);
connman_ipaddress_free(provider->prev_ipv6_addr);
provider->prev_ipv6_addr = NULL;
g_strfreev(providers);
}
- int __vpn_provider_init(bool do_routes)
+ int __vpn_provider_init(void)
{
int err;
DBG("");
- handle_routes = do_routes;
-
err = connman_agent_driver_register(&agent_driver);
if (err < 0) {
connman_error("Cannot register agent driver for %s",
const char *key);
bool vpn_provider_get_string_immutable(struct vpn_provider *provider,
const char *key);
+ int vpn_provider_set_boolean(struct vpn_provider *provider, const char *key,
+ bool value,
+ bool force_change);
bool vpn_provider_get_boolean(struct vpn_provider *provider, const char *key,
bool default_value);
const char *vpn_provider_get_name(struct vpn_provider *provider);
const char *vpn_provider_get_host(struct vpn_provider *provider);
const char *vpn_provider_get_path(struct vpn_provider *provider);
+ const char *vpn_provider_get_ident(struct vpn_provider *provider);
unsigned int vpn_provider_get_authentication_errors(
struct vpn_provider *provider);
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,
int __vpn_provider_set_string_immutable(struct vpn_provider *provider,
const char *key, const char *value);
DBusMessage *__vpn_provider_get_connections(DBusMessage *msg);
- const char *vpn_provider_get_ident(struct vpn_provider *provider);
struct vpn_provider *__vpn_provider_lookup(const char *identifier);
int __vpn_provider_indicate_state(struct vpn_provider *provider,
enum vpn_provider_state state);
int __vpn_provider_remove(const char *path);
int __vpn_provider_delete(struct vpn_provider *provider);
void __vpn_provider_cleanup(void);
- int __vpn_provider_init(bool handle_routes);
+ int __vpn_provider_init();
#include "vpn-rtnl.h"
int __vpn_config_init(void);
void __vpn_config_cleanup(void);
- char *__vpn_config_get_string(GKeyFile *key_file,
- const char *group_name, const char *key, GError **error);
- char **__vpn_config_get_string_list(GKeyFile *key_file,
- const char *group_name, const char *key, gsize *length, GError **error);
+ char *__vpn_config_get_string(GKeyFile *key_file, const char *group_name,
+ const char *key, GError **error);
+ char **__vpn_config_get_string_list(GKeyFile *key_file, const char *group_name,
+ const char *key, gsize *length, GError **error);
+ bool __vpn_config_get_boolean(GKeyFile *key_file, const char *group_name,
+ const char *key, bool default_value);
int __vpn_settings_init(const char *file);
void __vpn_settings_cleanup(void);
const char * vpn_settings_get_binary_group(struct vpn_plugin_data *data);
char ** vpn_settings_get_binary_supplementary_groups(
struct vpn_plugin_data *data);
+ bool vpn_settings_is_system_user(const char *user);
+
+ struct passwd *vpn_util_get_passwd(const char *username);
+ struct group *vpn_util_get_group(const char *groupname);
+ int vpn_util_create_path(const char *path, uid_t uid, gid_t grp, int mode);