diff options
70 files changed, 3434 insertions, 1136 deletions
@@ -145,7 +145,7 @@ André Draszik <andre.draszik@jci.com> Chris Novakovic <chris@chrisn.me.uk> Ryan Schaefer <ryan.schaefer@flukenetworks.com> Nicolas Cornu <n.cornu@overkiz.com> -Rahul Jain <rahul.jain@samsung.com +Rahul Jain <rahul.jain@samsung.com> Benoît Monin <benoit.monin@gmx.fr> Jussi Laakkonen <jussi.laakkonen@jolla.com> Vivien Henriet <v.henriet@overkiz.com> @@ -171,3 +171,8 @@ Gabriel FORTE <gforte@wyplay.com> Colin Wee <cwee@tesla.com> Valery Kashcheev <v.kascheev@omp.ru> Alyssa Ross <hi@alyssa.is> +Ariel D'Alessandro <ariel.dalessandro@collabora.com> +Lukáš Karas <lukas.karas@centrum.cz> +Michael Nazzareno Trimarchi <michael@amarulasolutions.com> +Christian Taedcke <christian.taedcke@lemonbeat.com> +Matthias Gerstner <mgerstner@suse.de> @@ -1,3 +1,11 @@ +ver 1.41: + Fix issue with RTNL netlink message alignment. + Fix issue with dnsproxy and timeout for TCP feature. + Fix issue with dnsproxy and busy loop in TCP server. + Fix issue with WiFi connection with no passphrase. + Add support for wpa_supplicant and WPA3-SAE functionality. + Add support for D-Bus ObjectManager interface. + ver 1.40: Fix issue with handling WiFi disconnecting status. Fix issue with handling WiFi auto-connect and iwd backend. diff --git a/Makefile.am b/Makefile.am index e8662e48..9a756a49 100644 --- a/Makefile.am +++ b/Makefile.am @@ -373,9 +373,7 @@ 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 @@ -633,5 +631,10 @@ include/connman/%.h: $(abs_top_srcdir)/include/%.h $(AM_V_at)$(MKDIR_P) include/connman $(AM_V_GEN)$(LN_S) $< $@ +isudir = /etc/isu/connman +isu_DATA = isu/isu.cfg +isusystemservicedir = /etc/isu/connman/system-services/ +isusystemservice_DATA = isu/system-services/connman.service + clean-local: @$(RM) -rf include/connman $(MANUAL_PAGES) @@ -408,8 +408,17 @@ from ipv4.connman.net (for IPv4 connectivity) and ipv6.connman.net (for IPv6 connectivity). The used URL looks like this http://ipv{4|6}.connman.net/online/status.html +When an online check request fails, another one is triggered after a +longer interval. The intervals follow the square series of numbers +in a specific range, by default [1, 12], corresponding to the following +intervals, in seconds: 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121 and 144. + See connman.conf(5) for the EnableOnlineCheck option, if you need to disable the feature. +It is also possible to specify other URLs via OnlineCheckIPv4URL and +OnlineCheckIPv6URL options. +The range of intervals between two online check requests can be fine-tuned +via OnlineCheckInitialInterval and OnlineCheckMaxInterval options. During the online check procedure, ConnMan will temporarily install a host route to both the ipv4.connman.net and ipv6.connman.net so that @@ -453,3 +462,7 @@ send a (empty) message from your email account to Mailing list archive: https://lore.kernel.org/connman + +IRC: + ircs://irc.oftc.net:6697/#connman (for SSL) + irc://irc.oftc.net:6667/#connman (for non-SSL) diff --git a/acinclude.m4 b/acinclude.m4 index 9e8e0dc5..262465d8 100755 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -21,7 +21,9 @@ AC_DEFUN([COMPILER_FLAGS], [ CFLAGS+=" -Wdeclaration-after-statement" CFLAGS+=" -Wmissing-declarations" CFLAGS+=" -Wredundant-decls" - CFLAGS+=" -Wcast-align" + if ( $CC -v 2>/dev/null | grep "gcc version" ); then + CFLAGS+=" -Wcast-align" + fi CFLAGS="$CFLAGS -DG_DISABLE_DEPRECATED" fi ]) diff --git a/client/agent.c b/client/agent.c index 1cad3e03..94ace7cd 100755 --- a/client/agent.c +++ b/client/agent.c @@ -100,6 +100,8 @@ static struct agent_input_data vpnagent_input_handler[] = { request_input_string_return }, { "OpenConnect.VPNHost", false, "OpenConnect VPN server? ", request_input_string_return }, + { "OpenConnect.SecondPassword", false, "VPN one-time password? ", + request_input_string_return }, { "Username", false, "VPN username? ", request_input_string_return }, { "Password", false, "VPN password? ", request_input_string_return }, { }, diff --git a/client/commands.c b/client/commands.c index dab62099..2fd8af54 100755 --- a/client/commands.c +++ b/client/commands.c @@ -39,7 +39,7 @@ #include "dbus_helpers.h" #include "input.h" #include "services.h" -#if defined TIZEN_EXT_INS +#if defined TIZEN_EXT #include "ins.h" #endif #include "tethering.h" @@ -331,9 +331,9 @@ static int services_list(DBusMessageIter *iter, int errnum, const char *error, return 0; } -#if defined TIZEN_EXT_INS -static int ins_list(DBusMessageIter *iter, const char *error, - void *user_data) +#if defined TIZEN_EXT +static int ins_list(DBusMessageIter *iter, int errnum, + const char *error, void *user_data) { char *filter = user_data; @@ -445,7 +445,7 @@ static int cmd_services(char *args[], int num, struct connman_option *options) object_properties, path, NULL, NULL); } -#if defined TIZEN_EXT_INS +#if defined TIZEN_EXT static int cmd_ins(char *args[], int num, struct connman_option *options) { char *filter = NULL; @@ -593,20 +593,23 @@ struct tether_properties { int ssid_result; int passphrase_result; int set_tethering; + int freq_result; }; static int tether_update(struct tether_properties *tether) { int ret; - if (tether->ssid_result == 0 && tether->passphrase_result == 0) { + if (tether->ssid_result == 0 && tether->passphrase_result == 0 && + tether->freq_result == 0) { ret = tether_set("wifi", tether->set_tethering); g_free(tether); return ret; } if (tether->ssid_result != -EINPROGRESS && - tether->passphrase_result != -EINPROGRESS) { + tether->passphrase_result != -EINPROGRESS && + tether->freq_result != -EINPROGRESS) { g_free(tether); return 0; } @@ -646,9 +649,25 @@ static int tether_set_passphrase_return(DBusMessageIter *iter, int errnum, return tether_update(tether); } -static int tether_set_ssid(char *ssid, char *passphrase, int set_tethering) +static int tether_set_freq_return(DBusMessageIter *iter, int errnum, + const char *error, void *user_data) +{ + struct tether_properties *tether = user_data; + + if (!error) { + fprintf(stdout, "Wifi access point frequency set\n"); + tether->freq_result = 0; + } else { + fprintf(stderr, "Error setting wifi frequency: %s\n", error); + tether->freq_result = -EINVAL; + } + + return tether_update(tether); +} + +static int tether_set_ssid(char *ssid, char *passphrase, int set_tethering, int freq) { - struct tether_properties *tether = g_new(struct tether_properties, 1); + struct tether_properties *tether = g_new0(struct tether_properties, 1); tether->set_tethering = set_tethering; @@ -664,12 +683,24 @@ static int tether_set_ssid(char *ssid, char *passphrase, int set_tethering) tether_set_passphrase_return, tether, "TetheringPassphrase", DBUS_TYPE_STRING, &passphrase); + if (freq > 0) { + tether->freq_result =__connmanctl_dbus_set_property(connection, + "/net/connman/technology/wifi", + "net.connman.Technology", + tether_set_freq_return, tether, + "TetheringFreq", DBUS_TYPE_INT32, &freq); + } + if (tether->ssid_result != -EINPROGRESS && - tether->passphrase_result != -EINPROGRESS) { + tether->passphrase_result != -EINPROGRESS && + tether->freq_result != -EINPROGRESS) { g_free(tether); return -ENXIO; } +#if defined TIZEN_EXT + g_free(tether); +#endif return -EINPROGRESS; } @@ -1253,24 +1284,30 @@ static int cmd_tether(char *args[], int num, struct connman_option *options) if (num < 3) return -EINVAL; - passphrase = args[num - 1]; - ssid = args[num - 2]; - set_tethering = parse_boolean(args[2]); if (strcmp(args[1], "wifi") == 0) { + int freq = 0; - if (num > 5) + if (num > 6) return -E2BIG; - if (num == 5 && set_tethering == -1) + if (num >= 5 && set_tethering == -1) return -EINVAL; if (num == 4) set_tethering = -1; + if (num == 6) { + freq = atoi(args[num - 1]); + num --; + } + + passphrase = args[num - 1]; + ssid = args[num - 2]; + if (num > 3) - return tether_set_ssid(ssid, passphrase, set_tethering); + return tether_set_ssid(ssid, passphrase, set_tethering, freq); } if (num > 3) @@ -2040,7 +2077,6 @@ static void monitor_del(char *interface) int i; char *rule; - for (i = 0; monitor[i].interface; i++) { if (g_strcmp0(interface, monitor[i].interface) == 0) { if (monitor[i].enabled == false) @@ -2426,7 +2462,6 @@ static int session_connect_cb(DBusMessageIter *iter, int errnum, return -EINPROGRESS; } - static int session_connect(void) { return __connmanctl_dbus_method_call(connection, "net.connman", @@ -3008,7 +3043,7 @@ static struct connman_option service_options[] = { { NULL, } }; -#if defined TIZEN_EXT_INS +#if defined TIZEN_EXT static struct connman_option ins_options[] = { {"all", 'a', ""}, {"filter-ssid", 's', "ssid"}, @@ -3018,7 +3053,12 @@ static struct connman_option ins_options[] = { #endif static struct connman_option config_options[] = { +#if defined TIZEN_EXT + {"nameservers", 'n', "ipv4.manual|ipv4.dhcp|ipv6.manual|ipv6.dhcp\n" + "\t\t\t<dns1> [<dns2>] [<dns3>]"}, +#else {"nameservers", 'n', "<dns1> [<dns2>] [<dns3>]"}, +#endif {"timeservers", 't', "<ntp1> [<ntp2>] [...]"}, {"domains", 'd', "<domain1> [<domain2>] [...]"}, {"mdns", 'm', "yes|no"}, @@ -3459,7 +3499,7 @@ static const struct { lookup_mesh }, #endif { "tether", "<technology> on|off\n" - " wifi [on|off] <ssid> <passphrase> ", + " wifi [on|off] <ssid> <passphrase> [<freq>] ", NULL, cmd_tether, "Enable, disable tethering, set SSID and passphrase for wifi", lookup_tether }, @@ -3467,7 +3507,7 @@ static const struct { "Display tethering clients", NULL }, { "services", "[<service>]", service_options, cmd_services, "Display services", lookup_service_arg }, -#if defined TIZEN_EXT_INS +#if defined TIZEN_EXT { "ins", NULL, ins_options, cmd_ins, "Display intelligent network selection", NULL }, #endif diff --git a/client/ins.c b/client/ins.c index 6403f610..929c6a93 100755 --- a/client/ins.c +++ b/client/ins.c @@ -95,7 +95,7 @@ static GSList *get_bssid_list(DBusMessageIter *iter, struct ins_info_s *ins_info if (strcmp(property, "BSSID") == 0) { bssid_info = g_try_new0(struct bssid_info_s, 1); if (!bssid_info) - continue; + break; dbus_message_iter_next(&entry); dbus_message_iter_recurse(&entry, &val); @@ -157,19 +157,19 @@ static void print_ins_info(int *rank, struct ins_info_s *ins_info, char *path, char *filter, DBusMessageIter *iter) { char *name = ""; - char *security; + char *security = ""; char *str = NULL; int count = 0; char *property; - unsigned char strength; - unsigned int frequency; - int score_INS; - int score_last_user_selection; - int score_last_connected; - int score_frequency; - int score_security_priority; - int score_internet_connection; - int score_strength; + unsigned char strength = 0; + unsigned int frequency = 0; + int score_INS = 0; + int score_last_user_selection = 0; + int score_last_connected = 0; + int score_frequency = 0; + int score_security_priority = 0; + int score_internet_connection = 0; + int score_strength = 0; GSList *bssid_list = NULL; DBusMessageIter entry, val, dict; diff --git a/configure.ac b/configure.ac index 220d62b8..9a2f65d5 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.60) -AC_INIT(connman, 1.40) +AC_INIT(connman, 1.41) AC_CONFIG_MACRO_DIR([m4]) @@ -36,14 +36,14 @@ AC_PROG_LIBTOOL gl_CONFIGMAKE_PREP -AC_ARG_ENABLE(optimization, AC_HELP_STRING([--disable-optimization], +AC_ARG_ENABLE(optimization, AS_HELP_STRING([--disable-optimization], [disable code optimization through compiler]), [ if (test "${enableval}" = "no"); then CFLAGS="$CFLAGS -O0 -U_FORTIFY_SOURCE" fi ]) -AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], +AC_ARG_ENABLE(debug, AS_HELP_STRING([--enable-debug], [enable compiling with debugging information]), [ if (test "${enableval}" = "yes" && test "${ac_cv_prog_cc_g}" = "yes"); then @@ -51,7 +51,7 @@ AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], fi ]) -AC_ARG_ENABLE(pie, AC_HELP_STRING([--enable-pie], +AC_ARG_ENABLE(pie, AS_HELP_STRING([--enable-pie], [enable position independent executables flag]), [ if (test "${enableval}" = "yes" && test "${ac_cv_prog_cc_pie}" = "yes"); then @@ -61,54 +61,47 @@ AC_ARG_ENABLE(pie, AC_HELP_STRING([--enable-pie], ]) AC_ARG_ENABLE(hh2serial-gps, - AC_HELP_STRING([--enable-hh2serial-gps], [enable hh2serial GPS support]), + AS_HELP_STRING([--enable-hh2serial-gps], [enable hh2serial GPS support]), [enable_hh2serial_gps=${enableval}], [enable_hh2serial_gps="no"]) 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]), + AS_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]), + AS_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]), + AS_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]), + AS_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]), + AS_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], +AC_ARG_WITH(openconnect, AS_HELP_STRING([--with-openconnect=PROGRAM], [specify location of openconnect binary]), [path_openconnect=${withval}]) AC_ARG_ENABLE(openconnect, - AC_HELP_STRING([--enable-openconnect], [enable openconnect support]), + AS_HELP_STRING([--enable-openconnect], [enable openconnect support]), [enable_openconnect=${enableval}], [enable_openconnect="no"]) if (test "${enable_openconnect}" != "no"); then if (test -z "${path_openconnect}"); then @@ -126,11 +119,11 @@ fi AM_CONDITIONAL(OPENCONNECT, test "${enable_openconnect}" != "no") AM_CONDITIONAL(OPENCONNECT_BUILTIN, test "${enable_openconnect}" = "builtin") -AC_ARG_WITH(openvpn, AC_HELP_STRING([--with-openvpn=PROGRAM], +AC_ARG_WITH(openvpn, AS_HELP_STRING([--with-openvpn=PROGRAM], [specify location of openvpn binary]), [path_openvpn=${withval}]) AC_ARG_ENABLE(openvpn, - AC_HELP_STRING([--enable-openvpn], [enable openvpn support]), + AS_HELP_STRING([--enable-openvpn], [enable openvpn support]), [enable_openvpn=${enableval}], [enable_openvpn="no"]) if (test "${enable_openvpn}" != "no"); then if (test -z "${path_openvpn}"); then @@ -146,11 +139,11 @@ 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], +AC_ARG_WITH(ipsec, AS_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]), + AS_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, @@ -170,11 +163,11 @@ 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], +AC_ARG_WITH(vpnc, AS_HELP_STRING([--with-vpnc=PROGRAM], [specify location of vpnc binary]), [path_vpnc=${withval}]) AC_ARG_ENABLE(vpnc, - AC_HELP_STRING([--enable-vpnc], [enable vpnc support]), + AS_HELP_STRING([--enable-vpnc], [enable vpnc support]), [enable_vpnc=${enableval}], [enable_vpnc="no"]) if (test "${enable_vpnc}" != "no"); then if (test -z "${path_vpnc}"); then @@ -190,11 +183,11 @@ fi AM_CONDITIONAL(VPNC, test "${enable_vpnc}" != "no") AM_CONDITIONAL(VPNC_BUILTIN, test "${enable_vpnc}" = "builtin") -AC_ARG_WITH(l2tp, AC_HELP_STRING([--with-l2tp=PROGRAM], +AC_ARG_WITH(l2tp, AS_HELP_STRING([--with-l2tp=PROGRAM], [specify location of l2tp binary]), [path_l2tp=${withval}]) AC_ARG_ENABLE(l2tp, - AC_HELP_STRING([--enable-l2tp], [enable l2tp support]), + AS_HELP_STRING([--enable-l2tp], [enable l2tp support]), [enable_l2tp=${enableval}], [enable_l2tp="no"]) if (test "${enable_l2tp}" != "no"); then if (test -z "${path_pppd}"); then @@ -215,11 +208,11 @@ fi AM_CONDITIONAL(L2TP, test "${enable_l2tp}" != "no") AM_CONDITIONAL(L2TP_BUILTIN, test "${enable_l2tp}" = "builtin") -AC_ARG_WITH(pptp, AC_HELP_STRING([--with-pptp=PROGRAM], +AC_ARG_WITH(pptp, AS_HELP_STRING([--with-pptp=PROGRAM], [specify location of pptp binary]), [path_pptp=${withval}]) AC_ARG_ENABLE(pptp, - AC_HELP_STRING([--enable-pptp], [enable pptp support]), + AS_HELP_STRING([--enable-pptp], [enable pptp support]), [enable_pptp=${enableval}], [enable_pptp="no"]) if (test "${enable_pptp}" != "no"); then if (test -z "${path_pppd}"); then @@ -258,23 +251,23 @@ AC_CHECK_FUNC(signalfd, dummy=yes, AC_CHECK_LIB(dl, dlopen, dummy=yes, AC_MSG_ERROR(dynamic linking loader is required)) -AC_ARG_ENABLE(iospm, AC_HELP_STRING([--enable-iospm], +AC_ARG_ENABLE(iospm, AS_HELP_STRING([--enable-iospm], [enable Intel OSPM support]), [enable_iospm=${enableval}]) AM_CONDITIONAL(IOSPM, test "${enable_iospm}" = "yes") AC_ARG_ENABLE(tist, - AC_HELP_STRING([--enable-tist], [enable TI Shared Transport support]), + AS_HELP_STRING([--enable-tist], [enable TI Shared Transport support]), [enable_tist=${enableval}], [enable_tist="no"]) AM_CONDITIONAL(TIST, test "${enable_tist}" != "no") AM_CONDITIONAL(TIST_BUILTIN, test "${enable_tist}" = "builtin") AC_ARG_ENABLE(session-policy-local, - AC_HELP_STRING([--enable-session-policy-local], [enable local file Session policy configuration support]), + AS_HELP_STRING([--enable-session-policy-local], [enable local file Session policy configuration support]), [enable_session_policy_local=${enableval}], [enable_session_policy_local="no"]) AM_CONDITIONAL(SESSION_POLICY_LOCAL, test "${enable_session_policy_local}" != "no") AM_CONDITIONAL(SESSION_POLICY_LOCAL_BUILTIN, test "${enable_session_policy_local}" = "builtin") -AC_ARG_WITH(stats-max-file-size, AC_HELP_STRING([--with-stats-max-file-size=SIZE], +AC_ARG_WITH(stats-max-file-size, AS_HELP_STRING([--with-stats-max-file-size=SIZE], [Maximal size of a statistics round robin file]), [stats_max_file_size=${withval}]) @@ -315,7 +308,7 @@ PKG_CHECK_MODULES(DLOG, dlog, dummy=yes, AC_SUBST(DLOG_CFLAGS) AC_SUBST(DLOG_LIBS) -AC_ARG_WITH(dbusconfdir, AC_HELP_STRING([--with-dbusconfdir=PATH], +AC_ARG_WITH(dbusconfdir, AS_HELP_STRING([--with-dbusconfdir=PATH], [path to D-Bus config directory]), [path_dbusconf=${withval}], [path_dbusconf="`$PKG_CONFIG --variable=sysconfdir dbus-1`"]) if (test -z "${path_dbusconf}"); then @@ -325,7 +318,7 @@ else fi AC_SUBST(DBUS_CONFDIR) -AC_ARG_WITH(dbusdatadir, AC_HELP_STRING([--with-dbusdatadir=PATH], +AC_ARG_WITH(dbusdatadir, AS_HELP_STRING([--with-dbusdatadir=PATH], [path to D-Bus data directory]), [path_dbusdata=${withval}], [path_dbusdata="`$PKG_CONFIG --variable=datadir dbus-1`"]) if (test -z "${path_dbusdata}"); then @@ -335,7 +328,7 @@ else fi AC_SUBST(DBUS_DATADIR) -AC_ARG_WITH([systemdunitdir], AC_HELP_STRING([--with-systemdunitdir=DIR], +AC_ARG_WITH([systemdunitdir], AS_HELP_STRING([--with-systemdunitdir=DIR], [path to systemd service directory]), [path_systemdunit=${withval}], [path_systemdunit="`$PKG_CONFIG --variable=systemdsystemunitdir systemd`"]) if (test -n "${path_systemdunit}"); then @@ -344,7 +337,7 @@ if (test -n "${path_systemdunit}"); then fi AM_CONDITIONAL(SYSTEMD, test -n "${path_systemdunit}") -AC_ARG_WITH([tmpfilesdir], AC_HELP_STRING([--with-tmpfilesdir=DIR], +AC_ARG_WITH([tmpfilesdir], AS_HELP_STRING([--with-tmpfilesdir=DIR], [path to systemd tmpfiles.d directory]), [path_tmpfiles=${withval}], [path_tmpfiles="`$PKG_CONFIG --variable=tmpfilesdir systemd`"]) if (test -n "${path_tmpfiles}"); then @@ -352,7 +345,7 @@ if (test -n "${path_tmpfiles}"); then AC_SUBST(SYSTEMD_TMPFILESDIR) fi -AC_ARG_WITH(firewall, AC_HELP_STRING([--with-firewall=TYPE], +AC_ARG_WITH(firewall, AS_HELP_STRING([--with-firewall=TYPE], [specify which firewall type is used iptables or nftables [default=iptables]]), [firewall_type=${withval}], [firewall_type="iptables"]) @@ -390,16 +383,16 @@ if (test "${firewall_type}" = "nftables"); then fi AM_CONDITIONAL(NFTABLES, test "${found_nftables}" != "no") -AC_ARG_ENABLE(test, AC_HELP_STRING([--enable-test], +AC_ARG_ENABLE(test, AS_HELP_STRING([--enable-test], [enable test/example scripts]), [enable_test=${enableval}]) AM_CONDITIONAL(TEST, test "${enable_test}" = "yes") -AC_ARG_ENABLE(nmcompat, AC_HELP_STRING([--enable-nmcompat], +AC_ARG_ENABLE(nmcompat, AS_HELP_STRING([--enable-nmcompat], [enable Network Manager support]), [enable_nmcompat=${enableval}], [enable_nmcompat="no"]) AM_CONDITIONAL(NMCOMPAT, test "${enable_nmcompat}" != "no") -AC_ARG_ENABLE(polkit, AC_HELP_STRING([--enable-polkit], +AC_ARG_ENABLE(polkit, AS_HELP_STRING([--enable-polkit], [enable PolicyKit support]), [enable_polkit=${enableval}], [enable_polkit="no"]) if (test "${enable_polkit}" != "no"); then @@ -412,83 +405,83 @@ if (test "${enable_polkit}" != "no"); then fi AM_CONDITIONAL(POLKIT, test "${enable_polkit}" != "no") -AC_ARG_ENABLE(selinux, AC_HELP_STRING([--enable-selinux], +AC_ARG_ENABLE(selinux, AS_HELP_STRING([--enable-selinux], [enable selinux support]), [enable_selinux=${enableval}], [enable_selinux="no"]) AM_CONDITIONAL(SELINUX, test "${enable_selinux}" != "no") -AC_ARG_ENABLE(loopback, AC_HELP_STRING([--disable-loopback], +AC_ARG_ENABLE(loopback, AS_HELP_STRING([--disable-loopback], [disable loopback support]), [enable_loopback=${enableval}]) AM_CONDITIONAL(LOOPBACK, test "${enable_loopback}" != "no") -AC_ARG_ENABLE(ethernet, AC_HELP_STRING([--disable-ethernet], +AC_ARG_ENABLE(ethernet, AS_HELP_STRING([--disable-ethernet], [disable Ethernet support]), [enable_ethernet=${enableval}]) AM_CONDITIONAL(ETHERNET, test "${enable_ethernet}" != "no") -AC_ARG_ENABLE(wireguard, AC_HELP_STRING([--disable-wireguard], +AC_ARG_ENABLE(wireguard, AS_HELP_STRING([--disable-wireguard], [disable Wireguard support]), [enable_wireguard=${enableval}]) AM_CONDITIONAL(WIREGUARD, test "${enable_wireguard}" != "no") AM_CONDITIONAL(WIREGUARD_BUILTIN, test "${enable_wireguard}" = "builtin") -AC_ARG_ENABLE(gadget, AC_HELP_STRING([--disable-gadget], +AC_ARG_ENABLE(gadget, AS_HELP_STRING([--disable-gadget], [disable USB Gadget support]), [enable_gadget=${enableval}]) AM_CONDITIONAL(GADGET, test "${enable_gadget}" != "no") -AC_ARG_ENABLE(wifi, AC_HELP_STRING([--disable-wifi], +AC_ARG_ENABLE(wifi, AS_HELP_STRING([--disable-wifi], [disable WiFi support]), [enable_wifi=${enableval}]) AM_CONDITIONAL(WIFI, test "${enable_wifi}" != "no") -AC_ARG_ENABLE(iwd, AC_HELP_STRING([--enable-iwd], +AC_ARG_ENABLE(iwd, AS_HELP_STRING([--enable-iwd], [enable iwd support]), [enable_iwd=${enableval}]) AM_CONDITIONAL(IWD, test "${enable_iwd}" = "yes") -AC_ARG_ENABLE(bluetooth, AC_HELP_STRING([--disable-bluetooth], +AC_ARG_ENABLE(bluetooth, AS_HELP_STRING([--disable-bluetooth], [disable Bluetooth support]), [enable_bluetooth=${enableval}]) AM_CONDITIONAL(BLUETOOTH, test "${enable_bluetooth}" != "no") -AC_ARG_ENABLE(ofono, AC_HELP_STRING([--disable-ofono], +AC_ARG_ENABLE(ofono, AS_HELP_STRING([--disable-ofono], [disable oFono support]), [enable_ofono=${enableval}]) AM_CONDITIONAL(OFONO, test "${enable_ofono}" != "no") -AC_ARG_ENABLE(dundee, AC_HELP_STRING([--disable-dundee], +AC_ARG_ENABLE(dundee, AS_HELP_STRING([--disable-dundee], [disable dundee support (Bluetooth DUN)]), [enable_dundee=${enableval}]) AM_CONDITIONAL(DUNDEE, test "${enable_dundee}" != "no") -AC_ARG_ENABLE(pacrunner, AC_HELP_STRING([--disable-pacrunner], +AC_ARG_ENABLE(pacrunner, AS_HELP_STRING([--disable-pacrunner], [disable PACrunner support]), [enable_pacrunner=${enableval}]) AM_CONDITIONAL(PACRUNNER, test "${enable_pacrunner}" != "no") -AC_ARG_ENABLE(neard, AC_HELP_STRING([--disable-neard], +AC_ARG_ENABLE(neard, AS_HELP_STRING([--disable-neard], [disable Neard support]), [enable_neard=${enableval}]) AM_CONDITIONAL(NEARD, test "${enable_neard}" != "no") -AC_ARG_ENABLE(wispr, AC_HELP_STRING([--disable-wispr], +AC_ARG_ENABLE(wispr, AS_HELP_STRING([--disable-wispr], [disable WISPr support]), [enable_wispr=${enableval}]) AM_CONDITIONAL(WISPR, test "${enable_wispr}" != "no") -AC_ARG_ENABLE(backtrace, AC_HELP_STRING([--disable-backtrace], +AC_ARG_ENABLE(backtrace, AS_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], +AC_ARG_ENABLE(tools, AS_HELP_STRING([--disable-tools], [disable testing tools]), [enable_tools=${enableval}]) AM_CONDITIONAL(TOOLS, test "${enable_tools}" != "no") -AC_ARG_ENABLE(stats, AC_HELP_STRING([--disable-stats], +AC_ARG_ENABLE(stats, AS_HELP_STRING([--disable-stats], [disable statistics round robin file generation]), [enable_stats=${enableval}]) AM_CONDITIONAL(STATS, test "${enable_stats}" != "no") @@ -507,7 +500,7 @@ fi AC_SUBST(IPTABLES_SAVE) AC_SUBST(IP6TABLES_SAVE) -AC_ARG_ENABLE(client, AC_HELP_STRING([--disable-client], +AC_ARG_ENABLE(client, AS_HELP_STRING([--disable-client], [disable command line client]), [enable_client=${enableval}]) AM_CONDITIONAL(CLIENT, test "${enable_client}" != "no") @@ -535,7 +528,7 @@ if (test "${enable_wifi}" != "no"); then $PATH:/bin:/usr/bin) fi -AC_ARG_ENABLE(datafiles, AC_HELP_STRING([--disable-datafiles], +AC_ARG_ENABLE(datafiles, AS_HELP_STRING([--disable-datafiles], [don't install configuration and data files]), [enable_datafiles=${enableval}]) AM_CONDITIONAL(DATAFILES, test "${enable_datafiles}" != "no") @@ -554,7 +547,7 @@ AM_CONDITIONAL(VPN, test "${enable_openconnect}" != "no" -o \ "${enable_wireguard}" != "no") AC_MSG_CHECKING(which DNS backend to use) -AC_ARG_WITH(dns-backend, AC_HELP_STRING([--with-dns-backend=TYPE], +AC_ARG_WITH(dns-backend, AS_HELP_STRING([--with-dns-backend=TYPE], [specify which DNS backend to use: internal or systemd-resolved [default=internal]]), [dns_backend=${withval}], [dns_backend="internal"]) diff --git a/doc/connman.conf.5.in b/doc/connman.conf.5.in index 2e06b3ef..82cceb72 100644 --- a/doc/connman.conf.5.in +++ b/doc/connman.conf.5.in @@ -167,13 +167,16 @@ transitioned to ONLINE state. If this setting is false, the default service will remain in READY state. Default value is true. .TP +.BI OnlineCheckIPv4URL= url, OnlineCheckIPv6URL= url +Urls (IPv4 and IPv6 respectively) used during the online status check. +Please refer to the README for more detailed information. +Default values are http://ipv4.connman.net/online/status.html and +http://ipv6.connman.net/online/status.html respectively. +.TP .BI OnlineCheckInitialInterval= secs, OnlineCheckMaxInterval= secs 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. +Please refer to the README for more detailed information. +Default values are 1 and 12 respectively. .TP .BI EnableOnlineToReadyTransition=true\ \fR|\fB\ false WARNING: Experimental feature!!! diff --git a/doc/technology-api.txt b/doc/technology-api.txt index f22e9b29..cdf30396 100755 --- a/doc/technology-api.txt +++ b/doc/technology-api.txt @@ -100,3 +100,10 @@ Properties boolean Powered [readwrite] This property is only valid for the WiFi technology, and is then mapped to the WPA pre-shared key clients will have to use in order to establish a connection. + + int TetheringFreq [readwrite] + + The tethering access point frequency + + This property is only valid for the WiFi technology and it's + optional. Default frequency is 2412 Mhz. diff --git a/doc/vpn-agent-api.txt b/doc/vpn-agent-api.txt index ffa6fadd..ecc8faaa 100644 --- a/doc/vpn-agent-api.txt +++ b/doc/vpn-agent-api.txt @@ -85,6 +85,10 @@ Fields string Username Return the OpenConnect cookie value that is used for authenticating the VPN session. + string OpenConnect.Group + + Choose authentication login group. + string OpenConnect.PKCSClientCert Informational field containing a PKCS#1/PKCS#8/PKCS#12 @@ -96,12 +100,21 @@ Fields string Username Password for decrypting PKCS#8/PKCS#12 client certificate. + string OpenConnect.SecondPassword + + Second factor password for authentication. + string OpenConnect.ServerCert Return the OpenConnect server hash used to identify the final server after possible web authentication logins, selections and redirections. + boolean OpenConnect.UseSecondPassword + + Indicates that second factor password is used + for selected authentication group. + string OpenConnect.VPNHost Return the final VPN server to use after possible diff --git a/doc/vpn-connection-api.txt b/doc/vpn-connection-api.txt index 6e6293e4..2d3e0078 100755 --- a/doc/vpn-connection-api.txt +++ b/doc/vpn-connection-api.txt @@ -235,6 +235,19 @@ Properties string State [readonly] The VPN server activated route. These routes are pushed to connman by VPN server. + string AuthErrorLimit + + This value defines the amount of authentication errors + that are allowed before informing VPN agent to clear + the credentials in case there was a previous successful + VPN connection made within one hour. This is to be used + with providers that allow only one login from one + account at a time to prevent clearing of credentials + when networks are rapidly changed. This value is used + as an integer and if unset this default to "1" for all + except OpenVPN that uses value "10". Setting value "0" + disables the feature for the provider. + There can be other properties also but as the VPN technologies are so different, they have different kind of options that they need, so not all options diff --git a/gdhcp/client.c b/gdhcp/client.c index cc0379ec..905cecf2 100755 --- a/gdhcp/client.c +++ b/gdhcp/client.c @@ -52,10 +52,11 @@ #if defined TIZEN_EXT #define REQUEST_TIMEOUT 1 +#define REQUEST_RETRIES 14 #else #define REQUEST_TIMEOUT 5 -#endif #define REQUEST_RETRIES 3 +#endif #if defined TIZEN_EXT #define DISCOVER_TIMEOUT_WIFI 1 @@ -2432,6 +2433,9 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition, dhcp_client->retry_times = 0; option = dhcp_get_option(&packet, pkt_len, DHCP_SERVER_ID); + if (!option) + return TRUE; + dhcp_client->server_ip = get_be32(option); dhcp_client->requested_ip = ntohl(packet.yiaddr); @@ -2497,6 +2501,8 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition, if (dhcp_client->state == REBOOTING) { option = dhcp_get_option(&packet, pkt_len, DHCP_SERVER_ID); + if (!option) + return TRUE; dhcp_client->server_ip = get_be32(option); } @@ -3130,6 +3136,13 @@ int g_dhcp_client_get_index(GDHCPClient *dhcp_client) return dhcp_client->ifindex; } +#if defined TIZEN_EXT +char *g_dhcp_client_get_interface(GDHCPClient *dhcp_client) +{ + return dhcp_client->interface; +} +#endif + char *g_dhcp_client_get_server_address(GDHCPClient *dhcp_client) { if (!dhcp_client) diff --git a/gdhcp/gdhcp.h b/gdhcp/gdhcp.h index d9944882..041ae81b 100755 --- a/gdhcp/gdhcp.h +++ b/gdhcp/gdhcp.h @@ -157,6 +157,7 @@ char *g_dhcp_client_get_server_address(GDHCPClient *client); #if defined TIZEN_EXT int g_dhcp_client_get_dhcp_lease_duration(GDHCPClient *client); +char *g_dhcp_client_get_interface(GDHCPClient *dhcp_client); #endif char *g_dhcp_client_get_address(GDHCPClient *client); diff --git a/gsupplicant/dbus.c b/gsupplicant/dbus.c index 9ad8e080..73c9acec 100755 --- a/gsupplicant/dbus.c +++ b/gsupplicant/dbus.c @@ -497,7 +497,10 @@ int supplicant_dbus_method_call(const char *path, if (!path || !interface || !method) return -EINVAL; - +#if defined TIZEN_EXT + if (strlen(path) == 0) + return -EINVAL; +#endif method_call = g_try_new0(struct method_call_data, 1); if (!method_call) return -ENOMEM; diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h index 0823a394..61b63dd6 100755 --- a/gsupplicant/gsupplicant.h +++ b/gsupplicant/gsupplicant.h @@ -71,6 +71,7 @@ extern "C" { #define G_SUPPLICANT_KEYMGMT_WPS (1 << 9) #if defined TIZEN_EXT #define G_SUPPLICANT_KEYMGMT_SAE (1 << 10) +#define G_SUPPLICANT_KEYMGMT_FT_SAE (1 << 11) #define G_SUPPLICANT_KEYMGMT_OWE (1 << 22) #define G_SUPPLICANT_KEYMGMT_DPP (1 << 23) #endif @@ -127,6 +128,7 @@ typedef enum { G_SUPPLICANT_SECURITY_SAE, G_SUPPLICANT_SECURITY_OWE, G_SUPPLICANT_SECURITY_DPP, + G_SUPPLICANT_SECURITY_PSK_SHA256, #endif } GSupplicantSecurity; @@ -187,6 +189,12 @@ typedef enum { } GSupplicantINSPreferredFreq; #endif +typedef enum { + G_SUPPLICANT_MFP_NONE, + G_SUPPLICANT_MFP_OPTIONAL, + G_SUPPLICANT_MFP_REQUIRED, +} GSupplicantMfpOptions; + struct _GSupplicantSSID { #if defined TIZEN_EXT void *ssid; @@ -224,12 +232,16 @@ struct _GSupplicantSSID { GSupplicantEapKeymgmt eap_keymgmt; const char *phase1; const char *pac_file; - uint16_t ieee80211w; unsigned int keymgmt; const char *connector; const char *c_sign_key; const char *net_access_key; + bool is_passphrase_alloc; + bool is_connector_alloc; + bool is_c_sign_key_alloc; + bool is_net_access_key_alloc; #endif + GSupplicantMfpOptions ieee80211w; }; typedef struct _GSupplicantSSID GSupplicantSSID; @@ -281,6 +293,10 @@ struct _GSupplicantP2PServiceParams { typedef struct _GSupplicantP2PServiceParams GSupplicantP2PServiceParams; #if defined TIZEN_EXT +#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 WIFI_BSSID_LEN_MAX 6 struct g_connman_bssids { @@ -289,14 +305,13 @@ struct g_connman_bssids { uint16_t frequency; uint16_t assoc_reject_cnt; bool is_last_connected; + unsigned int est_throughput; int score_snr; -#if defined TIZEN_EXT_INS int score_last_connected_bssid; int score_assoc_reject; int score_frequency; int score_strength; int score_est_throughput; -#endif int ins_score; }; #endif @@ -326,7 +341,8 @@ typedef void (*GSupplicantInterfaceCallback) (int result, #if defined TIZEN_EXT typedef void (*GSupplicantMaxSpeedCallback) (int result, int maxspeed, - int strength, int snr, void *user_data); + int strength, int snr, void *user_data, + unsigned int est_throughput); #endif void g_supplicant_interface_cancel(GSupplicantInterface *interface); @@ -395,6 +411,11 @@ int g_supplicant_interface_disconnect(GSupplicantInterface *interface, int g_supplicant_interface_set_bss_expiration_age(GSupplicantInterface *interface, unsigned int bss_expiration_age); +#if defined TIZEN_EXT +void g_supplicant_interface_remove_network(GSupplicantInterface *interface, + GSupplicantSSID *ssid); +#endif + int g_supplicant_interface_set_apscan(GSupplicantInterface *interface, unsigned int ap_scan); @@ -404,6 +425,7 @@ void *g_supplicant_interface_get_data(GSupplicantInterface *interface); const char *g_supplicant_interface_get_ifname(GSupplicantInterface *interface); #if defined TIZEN_EXT bool g_supplicant_interface_get_is_5_0_ghz_supported(GSupplicantInterface *interface); +bool g_supplicant_interface_get_is_6_0_ghz_supported(GSupplicantInterface *interface); unsigned char *g_supplicant_interface_get_add_network_bssid(GSupplicantInterface *interface); typedef void (*GSupplicantMacPolicyCallback) (int result, unsigned int policy, void *user_data); @@ -530,16 +552,18 @@ dbus_bool_t g_supplicant_network_get_transition_mode(GSupplicantNetwork *network const unsigned char *g_supplicant_network_get_transition_mode_bssid(GSupplicantNetwork *network); const void *g_supplicant_network_get_transition_mode_ssid(GSupplicantNetwork *network, unsigned int *transition_mode_ssid_len); +void g_supplicant_network_set_signal(GSupplicantNetwork *network, int signal); +void g_supplicant_network_set_bss_signal(GSupplicantNetwork *network, + int signal, int snr); +GSupplicantNetwork *g_supplicant_interface_get_network(GSupplicantInterface *interface, + const char *group); -#endif -#if defined TIZEN_EXT void g_supplicant_network_set_last_connected_bssid(GSupplicantNetwork *network, const unsigned char *bssid); const unsigned char *g_supplicant_network_get_last_connected_bssid(GSupplicantNetwork *network); void g_supplicant_network_update_assoc_reject(GSupplicantInterface *interface, GSupplicantNetwork *network); GHashTable *g_supplicant_network_get_assoc_reject_table(GSupplicantNetwork *network); -GSupplicantNetwork *g_supplicant_interface_get_network(GSupplicantInterface *interface, - const char *group); +GHashTable *g_supplicant_network_clone_assoc_reject_table(GSupplicantNetwork *network); #endif #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET @@ -598,12 +622,12 @@ struct _GSupplicantCallbacks { typedef struct _GSupplicantCallbacks GSupplicantCallbacks; -#if defined TIZEN_EXT && defined TIZEN_EXT_INS +#if defined TIZEN_EXT void g_supplicant_set_ins_settings(GSupplicantINSPreferredFreq preferred_freq_bssid, bool last_connected_bssid, bool assoc_reject, bool signal_bssid, unsigned int preferred_freq_bssid_score, unsigned int last_connected_bssid_score, unsigned int assoc_reject_score, int signal_level3_5ghz, int signal_level3_24ghz); -#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ +#endif /* defined TIZEN_EXT */ #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET void g_supplicant_replace_config_file(const char *ifname, const char *config_file); diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c index 5d1eb8f8..8329975b 100755 --- a/gsupplicant/supplicant.c +++ b/gsupplicant/supplicant.c @@ -122,6 +122,7 @@ static struct strvalmap keymgmt_map[] = { { "wps", G_SUPPLICANT_KEYMGMT_WPS }, #if defined TIZEN_EXT { "sae", G_SUPPLICANT_KEYMGMT_SAE }, + { "ft-sae", G_SUPPLICANT_KEYMGMT_FT_SAE }, { "owe", G_SUPPLICANT_KEYMGMT_OWE }, { "dpp", G_SUPPLICANT_KEYMGMT_DPP }, #endif @@ -174,7 +175,7 @@ static struct strvalmap mode_capa_map[] = { { } }; -#if defined TIZEN_EXT && defined TIZEN_EXT_INS +#if defined TIZEN_EXT struct _GSupplicantINSSettings { GSupplicantINSPreferredFreq preferred_freq_bssid; unsigned int preferred_freq_bssid_score; @@ -188,13 +189,11 @@ struct _GSupplicantINSSettings { }; 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 +#endif /* defined TIZEN_EXT */ static GHashTable *interface_table; static GHashTable *bss_mapping; @@ -264,6 +263,7 @@ struct _GSupplicantInterface { struct added_network_information network_info; #if defined TIZEN_EXT dbus_bool_t is_5_0_Ghz_supported; + dbus_bool_t is_6_0_Ghz_supported; int disconnect_reason; #endif #if defined TIZEN_EXT @@ -307,6 +307,7 @@ struct g_supplicant_bss { GSupplicantPhy_mode phy_mode; dbus_int16_t snr; dbus_uint32_t est_throughput; + dbus_bool_t psk_sha256; #endif unsigned int wps_capabilities; #if defined TIZEN_EXT @@ -538,6 +539,8 @@ static const char *security2string(GSupplicantSecurity security) case G_SUPPLICANT_SECURITY_IEEE8021X: return "ieee8021x"; #if defined TIZEN_EXT + case G_SUPPLICANT_SECURITY_PSK_SHA256: + return "psk_sha256"; case G_SUPPLICANT_SECURITY_FT_PSK: return "ft_psk"; case G_SUPPLICANT_SECURITY_FT_IEEE8021X: @@ -669,6 +672,7 @@ static int store_network_information(GSupplicantInterface * interface, ssid->security == G_SUPPLICANT_SECURITY_PSK || #if defined TIZEN_EXT ssid->security == G_SUPPLICANT_SECURITY_SAE || + ssid->security == G_SUPPLICANT_SECURITY_PSK_SHA256 || #endif ssid->security == G_SUPPLICANT_SECURITY_NONE) && ssid->passphrase) { @@ -1307,6 +1311,11 @@ static void interface_capability(const char *key, DBusMessageIter *iter, dbus_message_iter_get_basic(iter, &is_5_0_Ghz_supported); interface->is_5_0_Ghz_supported = is_5_0_Ghz_supported; + } else if (g_strcmp0(key, "Is6GhzSupported") == 0) { + dbus_bool_t is_6_0_Ghz_supported; + + dbus_message_iter_get_basic(iter, &is_6_0_Ghz_supported); + interface->is_6_0_Ghz_supported = is_6_0_Ghz_supported; #endif } else SUPPLICANT_DBG("key %s type %c", @@ -1418,11 +1427,19 @@ const char *g_supplicant_interface_get_ifname(GSupplicantInterface *interface) bool g_supplicant_interface_get_is_5_0_ghz_supported(GSupplicantInterface *interface) { if (!interface) - return NULL; + return false; return interface->is_5_0_Ghz_supported; } +bool g_supplicant_interface_get_is_6_0_ghz_supported(GSupplicantInterface *interface) +{ + if (!interface) + return false; + + return interface->is_6_0_Ghz_supported; +} + unsigned char *g_supplicant_interface_get_add_network_bssid(GSupplicantInterface *interface) { if (!interface) @@ -1568,7 +1585,7 @@ const char *g_supplicant_network_get_path(GSupplicantNetwork *network) const char *g_supplicant_network_get_mode(GSupplicantNetwork *network) { if (!network) - return G_SUPPLICANT_MODE_UNKNOWN; + return NULL; return mode2string(network->mode); } @@ -1576,7 +1593,7 @@ const char *g_supplicant_network_get_mode(GSupplicantNetwork *network) const char *g_supplicant_network_get_security(GSupplicantNetwork *network) { if (!network) - return G_SUPPLICANT_SECURITY_UNKNOWN; + return NULL; return security2string(network->security); } @@ -1601,6 +1618,32 @@ dbus_int16_t g_supplicant_network_get_signal(GSupplicantNetwork *network) return network->signal; } +#if defined TIZEN_EXT +void g_supplicant_network_set_signal(GSupplicantNetwork *network, int signal) +{ + if (!network) + return; + + network->signal = (dbus_int16_t)signal; +} + +void g_supplicant_network_set_bss_signal(GSupplicantNetwork *network, + int signal, int snr) +{ + struct g_supplicant_bss *best_bss; + + if (!network) + return; + + best_bss = network->best_bss; + if (!best_bss) + return; + + best_bss->signal = (dbus_int16_t)signal; + best_bss->snr = (dbus_int16_t)snr; +} +#endif + dbus_uint16_t g_supplicant_network_get_frequency(GSupplicantNetwork *network) { if (!network) @@ -1768,8 +1811,8 @@ const unsigned char *g_supplicant_network_get_countrycode(GSupplicantNetwork dbus_bool_t g_supplicant_network_is_pmf_required(GSupplicantNetwork *network) { - if (!network) - return 0; + if (!network || !network->best_bss) + return FALSE; return network->best_bss->pmf_required; } @@ -1914,6 +1957,7 @@ const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network) 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_PSK_SHA256 || network->best_bss->security == G_SUPPLICANT_SECURITY_IEEE8021X) { unsigned int pairwise; @@ -2009,7 +2053,6 @@ static gchar *convert_bssid_to_str(unsigned char *bssid) 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); @@ -2151,7 +2194,6 @@ static int calculate_score(bool is_last_connected, uint16_t assoc_reject_cnt, return score; } -#endif static void update_bssid_list(gpointer key, gpointer value, gpointer user_data) { @@ -2171,24 +2213,26 @@ static void update_bssid_list(gpointer key, gpointer value, gpointer user_data) bssids->strength = 100; bssids->frequency = bss->frequency; + bssids->est_throughput = bss->est_throughput; 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); + if (TIZEN_INS_ENABLED) { + 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->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; + } - 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"); @@ -2205,21 +2249,31 @@ static gint cmp_bss(gconstpointer a, gconstpointer b) if (entry_a->ins_score < entry_b->ins_score) return 1; + if (entry_a->ins_score == entry_b->ins_score) { + if (entry_a->strength >= entry_b->strength) + return -1; + else + 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, + GSupplicantNetwork *network = (GSupplicantNetwork *) user_data; + + if (!bssids || !network) + return; + + SUPPLICANT_DBG("ssid [%-20s] bssid[" MACSTR "] total[%2d] freq[%2d] " + "last_conn[%2d] assoc_reject[%2d] strength[%2d] rssi[%2d]", + network->ssid, MAC2STR(bssids->bssid), bssids->ins_score, bssids->score_frequency, bssids->score_last_connected_bssid, - bssids->score_assoc_reject, bssids->score_strength); + bssids->score_assoc_reject, bssids->score_strength, bssids->strength - 120); } -#endif void *g_supplicant_network_get_bssid_list(GSupplicantNetwork *network) { @@ -2235,9 +2289,8 @@ void *g_supplicant_network_get_bssid_list(GSupplicantNetwork *network) 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 + if (TIZEN_INS_ENABLED && !simplified_log) + g_slist_foreach(bssid_data.bssid_list, print_bssid_sort, (gpointer)network); return bssid_data.bssid_list; } @@ -2307,6 +2360,42 @@ GHashTable *g_supplicant_network_get_assoc_reject_table(GSupplicantNetwork *netw return network->assoc_reject_table; } +static void copy_assoc_reject(gpointer key, gpointer value, gpointer user_data) +{ + struct assoc_reject_data *cloned_assoc_data; + struct assoc_reject_data *assoc_data = value; + GHashTable *cloned_assoc_reject_table = user_data; + + if (assoc_data && cloned_assoc_reject_table) { + cloned_assoc_data = g_try_new0(struct assoc_reject_data, 1); + if (!cloned_assoc_data) + return; + + cloned_assoc_data->bssid = g_strdup(assoc_data->bssid); + cloned_assoc_data->reject_time_list = g_slist_copy(assoc_data->reject_time_list); + g_hash_table_insert(cloned_assoc_reject_table, + cloned_assoc_data->bssid, cloned_assoc_data); + } +} + +GHashTable *g_supplicant_network_clone_assoc_reject_table(GSupplicantNetwork *network) +{ + GHashTable *cloned_assoc_reject_table; + + if (!network) + return NULL; + + GHashTable *assoc_reject_table = g_supplicant_network_get_assoc_reject_table(network); + if (!assoc_reject_table) + return NULL; + + cloned_assoc_reject_table = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, remove_assoc_data); + g_hash_table_foreach(assoc_reject_table, copy_assoc_reject, cloned_assoc_reject_table); + + return cloned_assoc_reject_table; +} + GSupplicantNetwork *g_supplicant_interface_get_network(GSupplicantInterface *interface, const char *group) { @@ -2315,7 +2404,7 @@ GSupplicantNetwork *g_supplicant_interface_get_network(GSupplicantInterface *int return g_hash_table_lookup(interface->network_table, group); } -#endif +#endif /* defined TIZEN_EXT */ static void merge_network(GSupplicantNetwork *network) { @@ -2368,8 +2457,16 @@ static void merge_network(GSupplicantNetwork *network) g_string_append_printf(str, "_mesh"); #endif +#if defined TIZEN_EXT if (g_strcmp0(key_mgmt, "WPA-PSK") == 0) g_string_append_printf(str, "_psk"); + else if (g_strcmp0(key_mgmt, "SAE") == 0) + g_string_append_printf(str, "_sae"); +#else + if ((g_strcmp0(key_mgmt, "WPA-PSK") == 0) || + (g_strcmp0(key_mgmt, "SAE") == 0)) + g_string_append_printf(str, "_psk"); +#endif #if defined TIZEN_EXT else if (g_strcmp0(key_mgmt, "WPA-EAP") == 0) g_string_append_printf(str, "_ieee8021x"); @@ -2545,7 +2642,14 @@ static char *create_group(struct g_supplicant_bss *bss) if (mode) g_string_append_printf(str, "_%s", mode); +#if defined TIZEN_EXT + if (bss->security == G_SUPPLICANT_SECURITY_PSK_SHA256) + security = "psk"; + else + security = security2string(bss->security); +#else security = security2string(bss->security); +#endif if (security) g_string_append_printf(str, "_%s", security); @@ -2558,11 +2662,12 @@ static void update_network_with_best_bss(GSupplicantNetwork *network, /* * Do not change best BSS if we are connected. */ - if (network->interface->state == G_SUPPLICANT_STATE_COMPLETED) + if (network->interface->state == G_SUPPLICANT_STATE_COMPLETED && network->best_bss) return; network->signal = best_bss->signal; network->frequency = best_bss->frequency; + network->phy_mode = best_bss->phy_mode; network->best_bss = best_bss; } @@ -2577,24 +2682,24 @@ static bool update_best_bss(GSupplicantNetwork *network, 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); + if (TIZEN_INS_ENABLED) { + 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 + 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; + } if (score_new > score_best) { - SUPPLICANT_DBG("new[" MACSTR "][%u] : best[" MACSTR "][%u]", + SUPPLICANT_DBG("new[" MACSTR "][%d] : best[" MACSTR "][%d]", MAC2STR(bss->bssid), score_new, MAC2STR(network->best_bss->bssid), score_best); @@ -2645,6 +2750,7 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss) network->name = create_name(bss->ssid, bss->ssid_len); network->mode = bss->mode; network->security = bss->security; + network->keymgmt = bss->keymgmt; network->ssid_len = bss->ssid_len; memcpy(network->ssid, bss->ssid, bss->ssid_len); network->signal = bss->signal; @@ -3139,7 +3245,7 @@ static void bss_compute_security(struct g_supplicant_bss *bss) #if defined TIZEN_EXT if (bss->keymgmt & (G_SUPPLICANT_KEYMGMT_WPA_EAP | - G_SUPPLICANT_KEYMGMT_WPA_EAP_256)) + G_SUPPLICANT_KEYMGMT_WPA_EAP_256)) bss->ieee8021x = TRUE; else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_EAP) bss->ft_ieee8021x = TRUE; @@ -3153,8 +3259,13 @@ static void bss_compute_security(struct g_supplicant_bss *bss) #if defined TIZEN_EXT if (bss->keymgmt & + G_SUPPLICANT_KEYMGMT_WPA_PSK_256) { + bss->psk_sha256 = TRUE; + } + + if (bss->keymgmt & (G_SUPPLICANT_KEYMGMT_WPA_PSK | - G_SUPPLICANT_KEYMGMT_WPA_PSK_256)) + G_SUPPLICANT_KEYMGMT_WPA_PSK_256)) bss->psk = TRUE; else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK) bss->ft_psk = TRUE; @@ -3167,7 +3278,9 @@ static void bss_compute_security(struct g_supplicant_bss *bss) #endif #if defined TIZEN_EXT - if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_SAE) + if (bss->keymgmt & + (G_SUPPLICANT_KEYMGMT_SAE | + G_SUPPLICANT_KEYMGMT_FT_SAE)) bss->sae = TRUE; if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_OWE) bss->owe = TRUE; @@ -3182,6 +3295,8 @@ static void bss_compute_security(struct g_supplicant_bss *bss) bss->security = G_SUPPLICANT_SECURITY_IEEE8021X; else if (bss->sae) bss->security = G_SUPPLICANT_SECURITY_SAE; + else if (bss->psk_sha256) + bss->security = G_SUPPLICANT_SECURITY_PSK_SHA256; #endif else if (bss->psk) bss->security = G_SUPPLICANT_SECURITY_PSK; @@ -3426,6 +3541,8 @@ static void update_signal(gpointer key, gpointer value, if (!network->best_bss || (network->best_bss == bss)) { if (bss->signal > network->signal) { network->signal = bss->signal; + network->frequency = bss->frequency; + network->phy_mode = bss->phy_mode; network->best_bss = bss; } return; @@ -3502,7 +3619,7 @@ static void remove_timer_for_last_connected(GSupplicantInterface *interface) } } } -#endif +#endif /* defined TIZEN_EXT */ static void interface_current_bss(GSupplicantInterface *interface, DBusMessageIter *iter) @@ -3510,6 +3627,13 @@ static void interface_current_bss(GSupplicantInterface *interface, GSupplicantNetwork *network; struct g_supplicant_bss *bss; const char *path; +#if defined TIZEN_EXT + char curr_bssid_buff[WIFI_BSSID_STR_LEN] = {0,}; + char best_bssid_buff[WIFI_BSSID_STR_LEN] = {0,}; + char *curr_bssid_str = curr_bssid_buff; + char *best_bssid_str = best_bssid_buff; + gboolean update = FALSE; +#endif dbus_message_iter_get_basic(iter, &path); if (g_strcmp0(path, "/") == 0) { @@ -3529,7 +3653,17 @@ static void interface_current_bss(GSupplicantInterface *interface, interface->current_network = network; #if defined TIZEN_EXT - SUPPLICANT_DBG("current network [%p]", interface->current_network); + snprintf(curr_bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bss->bssid)); + snprintf(best_bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(network->best_bss->bssid)); + + SUPPLICANT_DBG("current network [%p], Passed bss %s, best bss %s", + interface->current_network, curr_bssid_str, best_bssid_str); + + if (network->frequency != bss->frequency) { + network->frequency = bss->frequency; + network->phy_mode = bss->phy_mode; + update = TRUE; + } #endif if (bss != network->best_bss) { @@ -3542,24 +3676,25 @@ static void interface_current_bss(GSupplicantInterface *interface, network->best_bss = bss; -#if defined TIZEN_EXT - if (network->frequency != bss->frequency) - network->frequency = bss->frequency; -#endif - if (network->signal != bss->signal) { SUPPLICANT_DBG("New network signal %d dBm", bss->signal); network->signal = bss->signal; callback_network_changed(network, "Signal"); - } #if defined TIZEN_EXT - else - callback_network_changed(network, ""); + update = FALSE; + } else { + update = TRUE; #endif + } } +#if defined TIZEN_EXT + if (update) + callback_network_changed(network, ""); +#endif + /* * wpa_s could notify about CurrentBSS in any state once * it got associated. It is not sure such notification will @@ -3582,7 +3717,8 @@ static void interface_current_bss(GSupplicantInterface *interface, case G_SUPPLICANT_STATE_COMPLETED: callback_network_associated(network); #if defined TIZEN_EXT - add_timer_for_last_connected(interface); + if (TIZEN_INS_ENABLED) + add_timer_for_last_connected(interface); #endif break; } @@ -3741,15 +3877,17 @@ static void interface_property(const char *key, DBusMessageIter *iter, 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; + if (TIZEN_INS_ENABLED) { + 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) { @@ -4218,10 +4356,20 @@ static void signal_network_removed(const char *path, DBusMessageIter *iter) interface_network_removed(iter, interface); } + #if defined TIZEN_EXT -void *copy_vsie_list(gconstpointer src, gpointer data) +gpointer copy_vsie_list(gconstpointer src, gpointer data) { - return g_strdup(src); + unsigned char *str = (unsigned char *)src; + unsigned char *vsie; + vsie = g_try_malloc0(str[1]+2); + + if (vsie) + memcpy(vsie, str, str[1]+2); + else + SUPPLICANT_DBG("Failed to allocate memory"); + + return vsie; } #endif @@ -4324,7 +4472,8 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter) supplicant_dbus_property_foreach(iter, bss_property, bss); #if defined TIZEN_EXT - if (network->interface->state != G_SUPPLICANT_STATE_COMPLETED) { + if (network->interface->state != G_SUPPLICANT_STATE_COMPLETED && + bss == network->best_bss) { network->frequency = bss->frequency; network->phy_mode = bss->phy_mode; } @@ -6474,6 +6623,7 @@ static void interface_signalpoll_result(const char *error, dbus_int32_t maxspeed = 0; dbus_int32_t strength = 0; dbus_int32_t snr = 0; + dbus_uint32_t est_throughput = 0; DBusMessageIter sub_iter, dict; if (error) { @@ -6505,23 +6655,27 @@ static void interface_signalpoll_result(const char *error, 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; } + break; + case DBUS_TYPE_UINT32: + if (g_strcmp0(key, "est_throughput") == 0) { + dbus_message_iter_get_basic(&value, &est_throughput); + SUPPLICANT_DBG("est_throughput = %u", est_throughput); + } + break; } dbus_message_iter_next(&dict); } out: if(data->callback) - data->callback(err, maxspeed, strength, snr, data->user_data); + data->callback(err, maxspeed, strength, snr, data->user_data, est_throughput); g_free(data->path); dbus_free(data); @@ -6614,10 +6768,14 @@ static void interface_select_network_result(const char *error, #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); + if (data->ssid->is_passphrase_alloc) + g_free((char *)data->ssid->passphrase); + if (data->ssid->is_connector_alloc) + g_free((char *)data->ssid->connector); + if (data->ssid->is_c_sign_key_alloc) + g_free((char *)data->ssid->c_sign_key); + if (data->ssid->is_net_access_key_alloc) + g_free((char *)data->ssid->net_access_key); #endif g_free(data->ssid); dbus_free(data); @@ -6706,10 +6864,14 @@ error: g_free(data->path); #if defined TIZEN_EXT g_free(data->ssid->ssid); - g_free((char *)data->ssid->passphrase); - g_free((char *)data->ssid->connector); - g_free((char *)data->ssid->c_sign_key); - g_free((char *)data->ssid->net_access_key); + if (data->ssid->is_passphrase_alloc) + g_free((char *)data->ssid->passphrase); + if (data->ssid->is_connector_alloc) + g_free((char *)data->ssid->connector); + if (data->ssid->is_c_sign_key_alloc) + g_free((char *)data->ssid->c_sign_key); + if (data->ssid->is_net_access_key_alloc) + g_free((char *)data->ssid->net_access_key); #endif g_free(data->ssid); g_free(data); @@ -7167,17 +7329,6 @@ static void add_network_security_proto(DBusMessageIter *dict, } #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) { @@ -7243,8 +7394,16 @@ static void add_network_security_net_access_key(DBusMessageIter *dict, GSupplica #endif +static void add_network_ieee80211w(DBusMessageIter *dict, GSupplicantSSID *ssid, + GSupplicantMfpOptions ieee80211w) +{ + supplicant_dbus_dict_append_basic(dict, "ieee80211w", DBUS_TYPE_UINT32, + &ieee80211w); +} + static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid) { + GSupplicantMfpOptions ieee80211w; char *key_mgmt; switch (ssid->security) { @@ -7260,7 +7419,14 @@ static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid) add_network_security_ciphers(dict, ssid); break; case G_SUPPLICANT_SECURITY_PSK: +#if defined TIZEN_EXT + if (ssid->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK) + key_mgmt = "FT-PSK WPA-PSK"; + else + key_mgmt = "WPA-PSK"; +#else key_mgmt = "WPA-PSK"; +#endif add_network_security_psk(dict, ssid); add_network_security_ciphers(dict, ssid); add_network_security_proto(dict, ssid); @@ -7272,6 +7438,15 @@ static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid) add_network_security_proto(dict, ssid); break; #if defined TIZEN_EXT + case G_SUPPLICANT_SECURITY_PSK_SHA256: + if (ssid->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_PSK) + key_mgmt = "WPA-PSK-SHA256 WPA-PSK"; + else + key_mgmt = "WPA-PSK-SHA256"; + add_network_security_psk(dict, ssid); + add_network_security_ciphers(dict, ssid); + add_network_security_proto(dict, ssid); + break; case G_SUPPLICANT_SECURITY_FT_PSK: key_mgmt = "FT-PSK"; add_network_security_psk(dict, ssid); @@ -7285,11 +7460,24 @@ static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *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"; + if (ssid->keymgmt & G_SUPPLICANT_KEYMGMT_FT_SAE) { + if (ssid->keymgmt & G_SUPPLICANT_KEYMGMT_SAE) + key_mgmt = "FT-SAE SAE"; + else + key_mgmt = "FT-SAE"; + } else { + if (ssid->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_PSK) { + key_mgmt = "SAE WPA-PSK"; + ieee80211w = G_SUPPLICANT_MFP_OPTIONAL; + } else { + key_mgmt = "SAE"; + ieee80211w = G_SUPPLICANT_MFP_REQUIRED; + } + add_network_ieee80211w(dict, ssid, ieee80211w); + } add_network_security_psk(dict, ssid); + add_network_security_ciphers(dict, ssid); + add_network_security_proto(dict, ssid); break; case G_SUPPLICANT_SECURITY_OWE: key_mgmt = "OWE"; @@ -7362,10 +7550,6 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data) 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); @@ -7547,6 +7731,12 @@ static void decryption_request_reply(DBusPendingCall *call, goto done; } + if (!g_str_has_prefix(data->interface->path, "/")) { + SUPPLICANT_DBG("Invalid path %s", data->interface->path); + ret = -EINVAL; + goto done; + } + if (dbus_message_iter_init(reply, &args) == FALSE) { SUPPLICANT_DBG("dbus_message_iter_init() failed"); ret = -EINVAL; @@ -7555,6 +7745,7 @@ static void decryption_request_reply(DBusPendingCall *call, dbus_message_iter_get_basic(&args, &out_data); data->ssid->passphrase = g_strdup((const gchar *)out_data); + data->ssid->is_passphrase_alloc = true; ret = supplicant_dbus_method_call(data->interface->path, SUPPLICANT_INTERFACE ".Interface", "AddNetwork", @@ -7568,10 +7759,14 @@ done: 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); + if (data->ssid->is_passphrase_alloc) + g_free((char *)data->ssid->passphrase); + if (data->ssid->is_connector_alloc) + g_free((char *)data->ssid->connector); + if (data->ssid->is_c_sign_key_alloc) + g_free((char *)data->ssid->c_sign_key); + if (data->ssid->is_net_access_key_alloc) + g_free((char *)data->ssid->net_access_key); g_free(data->ssid); dbus_free(data); } @@ -7677,14 +7872,17 @@ static void decrypt_conf_obj_reply(DBusPendingCall *call, if (g_strcmp0(key, "connector") == 0) { dbus_message_iter_get_basic(&value, &out_data); data->ssid->connector = g_strdup((const gchar *)out_data); + data->ssid->is_connector_alloc = true; 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); + data->ssid->is_c_sign_key_alloc = true; 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); + data->ssid->is_net_access_key_alloc = true; SUPPLICANT_DBG("net_access_key %s", data->ssid->net_access_key); } } @@ -7703,9 +7901,12 @@ done: 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); + if (data->ssid->is_connector_alloc) + g_free((char *)data->ssid->connector); + if (data->ssid->is_c_sign_key_alloc) + g_free((char *)data->ssid->c_sign_key); + if (data->ssid->is_net_access_key_alloc) + g_free((char *)data->ssid->net_access_key); g_free(data->ssid); dbus_free(data); } @@ -8089,6 +8290,49 @@ int g_supplicant_interface_disconnect(GSupplicantInterface *interface, return ret; } +#if defined TIZEN_EXT +void g_supplicant_interface_remove_network(GSupplicantInterface *interface, + GSupplicantSSID *ssid) +{ + struct interface_data *data; + int ret; + + SUPPLICANT_DBG(""); + + if (!interface) + return; + + if (interface->network_path == NULL) + return; + + if (!interface->network_info.ssid) + return; + + if (memcmp(interface->network_info.ssid, ssid->ssid, ssid->ssid_len)) + return; + + if (interface->network_info.security != ssid->security) + return; + + data = dbus_malloc0(sizeof(*data)); + if (!data) + return; + + data->interface = interface; + data->path = g_strdup(interface->path); + + ret = supplicant_dbus_method_call(interface->path, + SUPPLICANT_INTERFACE ".Interface", "RemoveNetwork", + network_remove_params, network_remove_result, data, + interface); + + if (ret < 0) { + g_free(data->path); + dbus_free(data); + } +} +#endif + static void interface_p2p_find_result(const char *error, DBusMessageIter *iter, void *user_data) { @@ -8588,7 +8832,7 @@ static void invoke_introspect_method(void) dbus_message_unref(message); } -#if defined TIZEN_EXT && defined TIZEN_EXT_INS +#if defined TIZEN_EXT 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, @@ -8614,7 +8858,7 @@ void g_supplicant_set_ins_settings(GSupplicantINSPreferredFreq preferred_freq_bs 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 */ +#endif /* defined TIZEN_EXT */ #if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET void g_supplicant_register_eap_callback(g_supplicant_eap_callback cb) diff --git a/include/device.h b/include/device.h index 8cc8ccef..acbd1d54 100755 --- a/include/device.h +++ b/include/device.h @@ -118,7 +118,10 @@ void connman_device_set_max_scan_ssids(struct connman_device *device, int connman_device_get_max_scan_ssids(struct connman_device *device); void connman_device_set_wifi_5ghz_supported(struct connman_device *device, bool is_5_0_ghz_supported); +void connman_device_set_wifi_6ghz_supported(struct connman_device *device, + bool is_6_0_ghz_supported); bool connman_device_get_wifi_5ghz_supported(struct connman_device *device); +bool connman_device_get_wifi_6ghz_supported(struct connman_device *device); #endif int connman_device_remove_network(struct connman_device *device, struct connman_network *network); diff --git a/include/network.h b/include/network.h index 4d09dfff..f9bd3c0a 100755 --- a/include/network.h +++ b/include/network.h @@ -79,12 +79,10 @@ struct connman_bssids { 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; }; @@ -235,25 +233,30 @@ 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 +unsigned int connman_network_get_max_bssid_count(struct connman_network *network); + 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 +unsigned int connman_network_get_est_throughput(struct connman_network *network); +void connman_network_set_est_throughput(struct connman_network *network, + unsigned int est_throughput); 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); +int set_connected_dhcp(struct connman_network *network); #endif int connman_network_set_name(struct connman_network *network, diff --git a/include/service.h b/include/service.h index 041949f5..f27e4243 100755 --- a/include/service.h +++ b/include/service.h @@ -209,7 +209,8 @@ 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); + bool disconnection_requested); +void connman_service_notify_reconnection_roaming(struct connman_service *service); #endif #if defined TIZEN_EXT diff --git a/include/setting.h b/include/setting.h index f141bf68..4fb4957b 100755 --- a/include/setting.h +++ b/include/setting.h @@ -28,10 +28,20 @@ extern "C" { #endif -bool connman_setting_get_bool(const char *key); #if defined TIZEN_EXT +/* AP selection method to be used */ +typedef enum { + AP_SELECTION_METHOD_NORMAL = 0, + AP_SELECTION_METHOD_INS = 1, +} ap_selection_method_e; + +#define TIZEN_INS_ENABLED \ + (connman_setting_get_int("ApSelectionMethod") == AP_SELECTION_METHOD_INS) + int connman_setting_get_int(const char *key); #endif + +bool connman_setting_get_bool(const char *key); 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); diff --git a/include/technology.h b/include/technology.h index d47f5666..c7898396 100755 --- a/include/technology.h +++ b/include/technology.h @@ -65,8 +65,10 @@ void connman_technology_regdom_notify(struct connman_technology *technology, enum connman_service_type connman_technology_get_type (struct connman_technology *technology); -bool connman_technology_get_wifi_tethering(const char **ssid, - const char **psk); + +bool connman_technology_get_wifi_tethering(const struct connman_technology *technology, + const char **ssid, const char **psk, int *freq); + bool connman_technology_is_tethering_allowed(enum connman_service_type type); struct connman_technology_driver { @@ -81,7 +83,6 @@ struct connman_technology_driver { void (*remove_interface) (struct connman_technology *technology, int index); int (*set_tethering) (struct connman_technology *technology, - const char *identifier, const char *passphrase, const char *bridge, bool enabled); int (*set_regdom) (struct connman_technology *technology, const char *alpha2); @@ -94,6 +95,8 @@ const char *connman_techonology_get_path(enum connman_service_type type); void __connman_technology_notify_scan_done(const char *ifname, int val); void __connman_technology_append_interfaces(DBusMessageIter *array, enum connman_service_type type, const char *ifname); +void __connman_technology_notify_device_detected_by_device( + struct connman_device *device, const char *ifname, bool val); void __connman_technology_notify_roaming_state(const char *ifname, const char *state, const char *cur_bssid, const char *dst_bssid); #endif diff --git a/isu/isu.cfg b/isu/isu.cfg new file mode 100644 index 00000000..ebfaa2dd --- /dev/null +++ b/isu/isu.cfg @@ -0,0 +1,8 @@ +[isu] +name=#NAME# +version=#VERSION# +system_service=connman.service + +[files] +/usr/bin/connmand +/etc/connman/main.conf diff --git a/isu/system-services/connman.service b/isu/system-services/connman.service new file mode 100644 index 00000000..78abb6e7 --- /dev/null +++ b/isu/system-services/connman.service @@ -0,0 +1,24 @@ +[Unit] +Description=Connection service +Conflicts=shutdown.target +RequiresMountsFor=/var/lib/connman +After=dbus.service network-pre.target systemd-sysusers.service net-config.service +Before=network.target multi-user.target shutdown.target +Wants=network.target + +[Service] +Type=dbus +User=network_fw +Group=network_fw +BusName=net.connman +Restart=on-failure +SmackProcessLabel=System +BindReadOnlyPaths=#ISU_RUN_PATH#/connman/rootfs/etc/connman:/etc/connman +BindPaths=#ISU_RUN_PATH#/connman/rootfs/usr/bin/connmand:/usr/bin/connmand +ExecStart=/usr/bin/connmand -n --nobacktrace --noplugin vpn +Capabilities=cap_setgid,cap_net_admin,cap_net_bind_service,cap_net_broadcast,cap_net_raw,cap_dac_override=i +StandardOutput=null +SecureBits=keep-caps + +[Install] +WantedBy=multi-user.target diff --git a/packaging/connman.spec b/packaging/connman.spec index 3f73b7b1..c97b261d 100644 --- a/packaging/connman.spec +++ b/packaging/connman.spec @@ -5,8 +5,8 @@ %bcond_without connman_vpnd Name: connman -Version: 1.40 -Release: 1 +Version: 1.41 +Release: 2 License: GPL-2.0+ Summary: Connection Manager Url: http://connman.net @@ -153,6 +153,12 @@ Requires: %{name} = %{version}-%{release} %description profile_robot connman extension for Tizen robot profile +%package isu +Summary: connman ISU pacakge +Group: Network & Connectivity/Connection Management +%description isu +Configuration files to generate the ISU (Individual Service Upgrade) package + %prep %setup -q @@ -168,8 +174,7 @@ chmod +x bootstrap --sysconfdir=/etc \ --enable-client \ --enable-tizen-ext \ - --disable-tizen-ext-ins \ - --enable-tizen-ext-eap-on-ethernet \ + --enable-tizen-ext-eap-on-ethernet \ --enable-pacrunner \ --enable-wifi=builtin \ %if %{with connman_openconnect} @@ -350,3 +355,7 @@ mv -f %{_sysconfdir}/connman/main.conf.robot %{_sysconfdir}/connman/main.conf %manifest %{name}.manifest %attr(644,root,root) %{_sysconfdir}/dbus-1/system.d/connman-robot.conf %attr(644,network_fw,network_fw) %{_sysconfdir}/connman/main.conf.robot + +%files isu +/etc/isu/connman/isu.cfg +/etc/isu/connman/system-services/connman.service diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c index a8383e75..0b59a656 100755 --- a/plugins/bluetooth.c +++ b/plugins/bluetooth.c @@ -903,7 +903,6 @@ static void bluetooth_tech_remove(struct connman_technology *technology) } static int bluetooth_tech_set_tethering(struct connman_technology *technology, - const char *identifier, const char *passphrase, const char *bridge, bool enabled) { GHashTableIter hash_iter; diff --git a/plugins/ethernet.c b/plugins/ethernet.c index 766f8e44..9d64abe4 100644 --- a/plugins/ethernet.c +++ b/plugins/ethernet.c @@ -57,6 +57,11 @@ #include <gsupplicant/gsupplicant.h> #endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */ +#if defined TIZEN_EXT +#include "connman.h" +#include "dbus.h" +#endif + static bool eth_tethering = false; struct ethernet_data { @@ -669,7 +674,6 @@ static void eth_tech_disable_tethering(struct connman_technology *technology, } static int eth_tech_set_tethering(struct connman_technology *technology, - const char *identifier, const char *passphrase, const char *bridge, bool enabled) { if (!connman_technology_is_tethering_allowed( diff --git a/plugins/gadget.c b/plugins/gadget.c index 1b44bbb5..2d58df3e 100755 --- a/plugins/gadget.c +++ b/plugins/gadget.c @@ -294,7 +294,6 @@ static void gadget_tech_disable_tethering(struct connman_technology *technology, } static int gadget_tech_set_tethering(struct connman_technology *technology, - const char *identifier, const char *passphrase, const char *bridge, bool enabled) { DBG("bridge %s enabled %d", bridge, enabled); diff --git a/plugins/iwd.c b/plugins/iwd.c index 194a99dd..2aed75b6 100644 --- a/plugins/iwd.c +++ b/plugins/iwd.c @@ -209,18 +209,13 @@ static int cm_network_probe(struct connman_network *network) static void update_network_connected(struct iwd_network *iwdn) { struct iwd_device *iwdd; - int index; iwdd = g_hash_table_lookup(devices, iwdn->device); if (!iwdd) return; - index = connman_inet_ifindex(iwdd->name); - if (index < 0) - return; - - DBG("interface name %s index %d", iwdd->name, index); - connman_network_set_index(iwdn->network, index); + DBG("interface name %s index %d", iwdd->name, + connman_network_get_index(iwdn->network)); connman_network_set_connected(iwdn->network, true); } @@ -316,11 +311,13 @@ static int cm_network_disconnect(struct connman_network *network) if (!iwds) return -EIO; + connman_network_set_associating(network, false); + if (!g_dbus_proxy_method_call(iwds->proxy, "Disconnect", NULL, cm_network_disconnect_cb, g_strdup(iwdn->path), g_free)) return -EIO; - return -EINPROGRESS; + return 0; } struct auto_connect_cb_data { @@ -558,7 +555,7 @@ static void cm_device_scan_cb(DBusMessage *message, void *user_data) const char *path = user_data; struct iwd_station *iwds; - iwds = g_hash_table_lookup(networks, path); + iwds = g_hash_table_lookup(stations, path); if (!iwds) return; @@ -818,12 +815,16 @@ static int cm_change_tethering(struct iwd_device *iwdd, } static int cm_tech_tethering(struct connman_technology *technology, - const char *identifier, const char *passphrase, const char *bridge, bool enabled) { GHashTableIter iter; gpointer key, value; int err = 0, res; + const char *ssid; + const char *psk; + int freq; + + connman_technology_get_wifi_tethering(technology, &ssid, &psk, &freq); g_hash_table_iter_init(&iter, devices); @@ -840,8 +841,8 @@ static int cm_tech_tethering(struct connman_technology *technology, continue; if (!enabled && !g_strcmp0("ap", iwdd->mode)) { - res = cm_change_tethering(iwdd, technology, identifier, - passphrase, bridge, enabled); + res = cm_change_tethering(iwdd, technology, ssid, + psk, bridge, enabled); if (res) connman_warn("%s switching to Station mode failed", iwdd->path); @@ -851,8 +852,8 @@ static int cm_tech_tethering(struct connman_technology *technology, } if (enabled && !g_strcmp0("station", iwdd->mode)) { - err = cm_change_tethering(iwdd, technology, identifier, - passphrase, bridge, enabled); + err = cm_change_tethering(iwdd, technology, ssid, + psk, bridge, enabled); if (err) connman_warn("%s switching to AccessPoint mode failed", iwdd->path); @@ -912,6 +913,7 @@ static void add_network(const char *path, struct iwd_network *iwdn) { struct iwd_device *iwdd; char *identifier; + int index; iwdd = g_hash_table_lookup(devices, iwdn->device); if (!iwdd) @@ -920,6 +922,11 @@ static void add_network(const char *path, struct iwd_network *iwdn) identifier = create_identifier(path, iwdn->type); iwdn->network = connman_network_create(identifier, CONNMAN_NETWORK_TYPE_WIFI); + + index = connman_inet_ifindex(iwdd->name); + if (index >= 0) + connman_network_set_index(iwdn->network, index); + connman_network_set_data(iwdn->network, iwdn); connman_network_set_name(iwdn->network, iwdn->name); @@ -936,7 +943,9 @@ static void add_network(const char *path, struct iwd_network *iwdn) } iwdn->iwdd = iwdd; - connman_network_set_available(iwdn->network, true); + if (connman_network_get_strength(iwdn->network)) + connman_network_set_available(iwdn->network, true); + connman_network_set_group(iwdn->network, identifier); g_free(identifier); @@ -1372,13 +1381,7 @@ static void create_adapter(GDBusProxy *proxy) struct iwd_adapter *iwda; GSList *modes, *list; - iwda = g_try_new0(struct iwd_adapter, 1); - - if (!iwda) { - connman_error("Out of memory creating IWD adapter"); - return; - } - + iwda = g_new0(struct iwd_adapter, 1); iwda->path = g_strdup(path); g_hash_table_replace(adapters, iwda->path, iwda); @@ -1423,13 +1426,7 @@ static void create_device(GDBusProxy *proxy) const char *path = g_dbus_proxy_get_path(proxy); struct iwd_device *iwdd; - iwdd = g_try_new0(struct iwd_device, 1); - - if (!iwdd) { - connman_error("Out of memory creating IWD device"); - return; - } - + iwdd = g_new0(struct iwd_device, 1); iwdd->path = g_strdup(path); g_hash_table_replace(devices, iwdd->path, iwdd); @@ -1494,6 +1491,8 @@ static DBusMessage *agent_request_passphrase(DBusConnection *dbus_conn, return get_reply_on_error(message, EINVAL); passwd = connman_network_get_string(iwdn->network, "WiFi.Passphrase"); + if (!passwd) + return get_reply_on_error(message, ENOKEY); return g_dbus_create_reply(message, DBUS_TYPE_STRING, &passwd, DBUS_TYPE_INVALID); @@ -1596,13 +1595,7 @@ static void create_network(GDBusProxy *proxy) const char *path = g_dbus_proxy_get_path(proxy); struct iwd_network *iwdn; - iwdn = g_try_new0(struct iwd_network, 1); - - if (!iwdn) { - connman_error("Out of memory creating IWD network"); - return; - } - + iwdn = g_new0(struct iwd_network, 1); iwdn->path = g_strdup(path); g_hash_table_replace(networks, iwdn->path, iwdn); @@ -1762,12 +1755,7 @@ static void create_know_network(GDBusProxy *proxy) const char *path = g_dbus_proxy_get_path(proxy); struct iwd_known_network *iwdkn; - iwdkn = g_try_new0(struct iwd_known_network, 1); - if (!iwdkn) { - connman_error("Out of memory creating IWD known network"); - return; - } - + iwdkn = g_new0(struct iwd_known_network, 1); iwdkn->path = g_strdup(path); g_hash_table_replace(known_networks, iwdkn->path, iwdkn); @@ -1801,12 +1789,7 @@ static void create_station(GDBusProxy *proxy) const char *path = g_dbus_proxy_get_path(proxy); struct iwd_station *iwds; - iwds = g_try_new0(struct iwd_station, 1); - if (!iwds) { - connman_error("Out of memory creating IWD station"); - return; - } - + iwds = g_new0(struct iwd_station, 1); iwds->path = g_strdup(path); g_hash_table_replace(stations, iwds->path, iwds); @@ -1834,11 +1817,7 @@ static void create_ap(GDBusProxy *proxy) const char *path = g_dbus_proxy_get_path(proxy); struct iwd_ap *iwdap; - iwdap = g_try_new0(struct iwd_ap, 1); - if (!iwdap) { - connman_error("Out of memory creating IWD access point"); - return; - } + iwdap = g_new0(struct iwd_ap, 1); iwdap->index = -1; iwdap->path = g_strdup(path); diff --git a/plugins/loopback.c b/plugins/loopback.c index 3809d8f9..d0ed6268 100755 --- a/plugins/loopback.c +++ b/plugins/loopback.c @@ -63,14 +63,14 @@ static void _create_hostname(void) fp = fopen(WIFI_MAC, "r"); if(!fp){ connman_error("Failed to get current hostname"); - strncpy(system_hostname, dev_id, strlen(dev_id)); + strncpy(system_hostname, dev_id, sizeof(system_hostname) - 1); 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)); + strncpy(system_hostname, dev_id, sizeof(system_hostname) - 1); fclose(fp); return; } diff --git a/plugins/neard.c b/plugins/neard.c index 45effd44..caaea853 100755 --- a/plugins/neard.c +++ b/plugins/neard.c @@ -223,9 +223,9 @@ static DBusMessage *create_request_oob_reply(DBusMessage *message) DBusMessageIter dict; const char *ssid, *psk; uint8_t *tlv_msg; - int length; + int length, freq; - if (!connman_technology_get_wifi_tethering(&ssid, &psk)) + if (!connman_technology_get_wifi_tethering(NULL, &ssid, &psk, &freq)) return get_reply_on_error(message, ENOTSUP); tlv_msg = encode_to_tlv(ssid, psk, &length); diff --git a/plugins/vpn.c b/plugins/vpn.c index d708d1ff..42396d2a 100755 --- a/plugins/vpn.c +++ b/plugins/vpn.c @@ -3,6 +3,7 @@ * Connection Manager * * Copyright (C) 2012-2013 Intel Corporation. All rights reserved. + * Copyright (C) 2019-2021 Jolla Ltd. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -491,6 +492,9 @@ static int errorstr2val(const char *error) { if (g_strcmp0(error, CONNMAN_ERROR_INTERFACE ".AlreadyConnected") == 0) return -EISCONN; + if (g_strcmp0(error, CONNMAN_ERROR_INTERFACE ".NoCarrier") == 0) + return -ENOLINK; + if (g_strcmp0(error, CONNMAN_ERROR_INTERFACE ".OperationCanceled") == 0) return -ECANCELED; @@ -529,16 +533,23 @@ static void connect_reply(DBusPendingCall *call, void *user_data) if (dbus_set_error_from_message(&error, reply)) { int err = errorstr2val(error.name); + switch (err) { + case -EINPROGRESS: + break; /* * ECANCELED means that user has canceled authentication * dialog. That's not really an error, it's part of a normal * workflow. We also take it as a request to turn autoconnect * off, in case if it was on. */ - if (err == -ECANCELED) { + case -ECANCELED: DBG("%s connect canceled", data->path); connman_provider_set_autoconnect(data->provider, false); - } else if (err != -EINPROGRESS) { + break; + case -ENOLINK: /* vpnd reports that connmand is not online. */ + case -EISCONN: + case -ECONNREFUSED: + default: connman_error("Connect reply: %s (%s)", error.message, error.name); DBG("data %p cb_data %p", data, cb_data); @@ -1016,7 +1027,7 @@ static int disconnect_provider(struct connection_data *data) if (data->disconnect_call) { DBG("already disconnecting"); - return -EINVAL; + return -EALREADY; } message = dbus_message_new_method_call(VPN_SERVICE, data->path, diff --git a/plugins/wifi.c b/plugins/wifi.c index bcb93445..68f34313 100755 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -33,6 +33,10 @@ #include <net/ethernet.h> #include <linux/wireless.h> +#if defined TIZEN_EXT +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + #ifndef IFF_LOWER_UP #define IFF_LOWER_UP 0x10000 #endif @@ -98,20 +102,38 @@ * Weak : -77 ~ -82 * Very weak : -83 ~ -88 * No signal : -89 ~ + * + * Wi-Fi Signal Strength (for 6G (dB)) + * + * Excellent : ~ -72 + * Good : -73 ~ -77 + * Weak : -78 ~ -82 + * Very weak : -83 ~ -88 + * No signal : -89 ~ */ +#define RSSI_LEVEL_2_6G -78 #define RSSI_LEVEL_2_5G -77 -#define RSSI_LEVEL_2_24G -75 +#define RSSI_LEVEL_2_2_4G -75 +#define RSSI_LEVEL_3_6G -73 #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 RSSI_LEVEL_3_2_4G -64 #define ROAM_SCAN_INTERVAL 60 /* 60 seconds */ +#define FREQUENCY_5G_BASE 5000 +#define FREQUENCY_6G_BASE 5925 + +static int min_snr = 0; +static int min_rssi_2_4GHz = 0; +static int min_rssi_5GHz = 0; +static int min_rssi_6GHz = 0; #endif static struct connman_technology *wifi_technology = NULL; static struct connman_technology *p2p_technology = NULL; +#if defined TIZEN_EXT +static GSupplicantState assoc_last_state = G_SUPPLICANT_STATE_UNKNOWN; +#endif + enum wifi_ap_capability{ WIFI_AP_UNKNOWN = 0, WIFI_AP_SUPPORTED = 1, @@ -211,6 +233,10 @@ struct wifi_data { #endif }; +struct wifi_network { + unsigned int keymgmt; +}; + struct disconnect_data { struct wifi_data *wifi; struct connman_network *network; @@ -237,7 +263,6 @@ static bool wfd_service_registered = false; static void start_autoscan(struct connman_device *device); static int tech_set_tethering(struct connman_technology *technology, - const char *identifier, const char *passphrase, const char *bridge, bool enabled); #if defined TIZEN_EXT @@ -252,6 +277,8 @@ struct enc_method_call_data { static struct enc_method_call_data encrypt_request_data; +static GSupplicantSecurity network_security(const char *security); + static void encryption_request_reply(DBusPendingCall *call, void *user_data) { @@ -2137,46 +2164,180 @@ static gboolean need_bss_transition(uint16_t freq, int snr, int strength) /* * 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 + * - SNR is less than min_snr or RSSI is less than + * min_rssi_2_4GHz, min_rssi_5GHz or min_rssi_6GHz. */ - if (snr < 20 && snr != 0) + if (min_snr != 0 && snr != 0 && snr < min_snr) return TRUE; - else if (freq > 4900 && signal <= RSSI_LEVEL_2_5G) + else if (freq > FREQUENCY_6G_BASE && signal <= min_rssi_6GHz) return TRUE; - else if (freq <= 4900 && signal <= RSSI_LEVEL_2_24G) + else if (freq > FREQUENCY_5G_BASE && signal <= min_rssi_5GHz) + return TRUE; + else if (signal <= min_rssi_2_4GHz) return TRUE; return FALSE; } -static gboolean check_bss_condition(uint16_t freq, int snr, uint16_t strength) +static gboolean check_bss_diff(int cur_level, int sel_level, int to_5ghz, + unsigned int cur_est, unsigned int sel_est) +{ + int min_diff; + int diff; + + /* This code is from wpa_supplicant. */ + if (cur_level < -85) /* ..-86 dBm */ + min_diff = 1; + else if (cur_level < -80) /* -85..-81 dBm */ + min_diff = 2; + else if (cur_level < -75) /* -80..-76 dBm */ + min_diff = 3; + else if (cur_level < -70) /* -75..-71 dBm */ + min_diff = 4; + else if (cur_level < 0) /* -70..-1 dBm */ + min_diff = 5; + else /* unspecified units (not in dBm) */ + min_diff = 2; + + if (cur_est > sel_est * 1.5) + min_diff += 10; + else if (cur_est > sel_est * 1.2) + min_diff += 5; + else if (cur_est > sel_est * 1.1) + min_diff += 2; + else if (cur_est > sel_est) + min_diff++; + else if (sel_est > cur_est * 1.5) + min_diff -= 10; + else if (sel_est > cur_est * 1.2) + min_diff -= 5; + else if (sel_est > cur_est * 1.1) + min_diff -= 2; + else if (sel_est > cur_est) + min_diff--; + + if (to_5ghz) + min_diff -= 2; + + diff = sel_level - cur_level; + + if (diff < min_diff) + return FALSE; + + return TRUE; +} + +static gboolean check_bss_condition(uint16_t freq, uint16_t strength, + unsigned int est_throughput, uint16_t cur_freq, uint16_t cur_strength, + unsigned int cur_est_throughput) { /* * Since bssid->strength is a positive value, * it need to be changed to its original value. */ int signal = strength - 120; + int cur_signal = cur_strength - 120; + int to_5ghz = freq > 4000 && cur_freq < 4000; + + DBG("cur_freq=%d cur_level=%d cur_est=%d sel_freq=%d sel_level=%d sel_est=%d", + cur_freq, cur_strength, cur_est_throughput, + freq, strength, est_throughput); /* * 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 (freq > 4900 && signal > RSSI_LEVEL_3_5G) - return TRUE; - else if (freq <= 4900 && signal > RSSI_LEVEL_3_24G) + if (est_throughput > cur_est_throughput + 5000) return TRUE; - return FALSE; + if (cur_signal > signal + to_5ghz * 2 && + est_throughput < cur_est_throughput * 1.2) + return FALSE; + + if (cur_est_throughput > est_throughput + 5000) + return FALSE; + + return check_bss_diff(cur_signal, signal, + to_5ghz, cur_est_throughput, est_throughput); } static void scan_callback_hidden(int result, GSupplicantInterface *interface, void *user_data); static int network_disconnect(struct connman_network *network); + +static void start_roaming(struct wifi_data *wifi) +{ + bool roaming_ap_found = false; + GSList *bssid_list = NULL; + + if (!wifi || !wifi->network) + return; + + if (!connman_setting_get_bool("WifiRoaming")) + return; + + struct connman_network *network = wifi->network; + bssid_list = connman_network_get_bssid_list(network); + + if (g_slist_length(bssid_list) <= 1) + return; + + if (!connman_network_get_connected(network)) + return; + + if (connman_network_get_bool(network, "WiFi.Roaming")) + return; + + uint16_t cur_freq = connman_network_get_frequency(network); + uint8_t cur_strength = connman_network_get_strength(network); + unsigned int cur_est_throughput = connman_network_get_est_throughput(network); + + if (!need_bss_transition( + cur_freq, + connman_network_get_snr(network), + cur_strength)) + return; + + unsigned char *cur_bssid = connman_network_get_bssid(network); + + for (; bssid_list; bssid_list = bssid_list->next) { + struct g_connman_bssids *bssid = bssid_list->data; + + if (memcmp(cur_bssid, bssid->bssid, WIFI_BSSID_LEN_MAX) == 0) + continue; + + if (check_bss_condition( + bssid->frequency, bssid->strength, bssid->est_throughput, + cur_freq, cur_strength, cur_est_throughput)) { + roaming_ap_found = true; + + char bssid_buff[WIFI_BSSID_STR_LEN] = {0,}; + char *bssid_str = bssid_buff; + + snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid->bssid)); + connman_network_set_string(network, + "WiFi.RoamingDstBSSID", bssid_str); + break; + } + } + + if (roaming_ap_found) { + char bssid_buff[WIFI_BSSID_STR_LEN] = {0,}; + char *bssid_str = bssid_buff; + unsigned char *bssid; + + bssid = connman_network_get_bssid(network); + snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid)); + connman_network_set_string(network, + "WiFi.RoamingCurBSSID", bssid_str); + + network_disconnect(network); + wifi->pending_network = network; + connman_network_set_bool(network, "WiFi.Roaming", true); + } +} #endif static void scan_callback(int result, GSupplicantInterface *interface, @@ -2186,10 +2347,7 @@ static void scan_callback(int result, GSupplicantInterface *interface, 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; @@ -2306,46 +2464,8 @@ static void scan_callback(int result, GSupplicantInterface *interface, 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); - - if (g_slist_length(bssid_list) <= 1) - goto done; - - if (!connman_network_get_connected(wifi->network)) - goto done; - - if (connman_network_get_bool(wifi->network, "WiFi.Roaming")) - goto done; - - if (!need_bss_transition( - connman_network_get_frequency(wifi->network), - connman_network_get_snr(wifi->network), - connman_network_get_strength(wifi->network))) - goto done; - - for (bssid_list; bssid_list; bssid_list = bssid_list->next) { - struct g_connman_bssids *bssid = bssid_list->data; - - if (check_bss_condition(bssid->frequency, - bssid->score_snr, bssid->strength)) - roaming_ap_found = true; - } - - if (roaming_ap_found) { - char bssid_buff[WIFI_BSSID_STR_LEN] = {0,}; - char *bssid_str = bssid_buff; - unsigned char *bssid; - - 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); - } + } else { + start_roaming(wifi); } done: @@ -2613,7 +2733,20 @@ static void interface_create_callback(int result, wifi->interface = interface; g_supplicant_interface_set_data(interface, wifi); +#ifdef TIZEN_EXT + if (!interface) + return; + + if (wifi->device && + !connman_device_get_wifi_5ghz_supported(wifi->device) && + !connman_device_get_wifi_6ghz_supported(wifi->device)) { + bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface); + bool is_6_0_ghz_supported = g_supplicant_interface_get_is_6_0_ghz_supported(interface); + connman_device_set_wifi_5ghz_supported(wifi->device, is_5_0_ghz_supported); + connman_device_set_wifi_6ghz_supported(wifi->device, is_6_0_ghz_supported); + } +#endif if (g_supplicant_interface_get_ready(interface)) { wifi->interface_ready = true; finalize_interface_creation(wifi); @@ -2787,7 +2920,12 @@ static int get_latest_connections(int max_ssids, g_key_file_free(keyfile); continue; } +#if defined TIZEN_EXT + + util_iso8601_to_timeval(str, (struct timeval *)&modified); +#else util_iso8601_to_timeval(str, &modified); +#endif g_free(str); ssid = g_key_file_get_string(keyfile, @@ -2957,7 +3095,7 @@ static void specific_scan_callback(int result, GSupplicantInterface *interface, struct wifi_data *wifi = connman_device_get_data(device); bool scanning; - DBG("result %d wifi %p", result, wifi); + DBG("result %d device %p wifi %p", result, device, wifi); if (wifi && wifi->scan_params) { g_supplicant_free_scan_params(wifi->scan_params); @@ -2971,6 +3109,8 @@ static void specific_scan_callback(int result, GSupplicantInterface *interface, CONNMAN_SERVICE_TYPE_WIFI, false); connman_device_unref(device); } + + start_roaming(wifi); } static int wifi_specific_scan(enum connman_service_type type, @@ -3052,7 +3192,7 @@ static int wifi_specific_scan(enum connman_service_type type, count = 0; for (list = specific_scan_list; list; list = list->next) { - freq = (int)list->data; + freq = GPOINTER_TO_INT(list->data); scan_params->freqs[count] = freq; DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]); @@ -3633,6 +3773,11 @@ static void network_remove(struct connman_network *network) { struct connman_device *device = connman_network_get_device(network); struct wifi_data *wifi; +#if defined TIZEN_EXT + GSupplicantSSID *ssid; + const void *ssid_data; + const char *security; +#endif DBG("network %p", network); @@ -3653,6 +3798,35 @@ static void network_remove(struct connman_network *network) if (wifi->scan_pending_network == network) wifi->scan_pending_network = NULL; + + /* + * If this remove network is for the same network + * for which wpa_supplicant already has a profile + * then need to remove that profile. + */ + ssid = g_try_malloc0(sizeof(GSupplicantSSID)); + if (!ssid) + return; + + ssid_data = connman_network_get_blob(network, "WiFi.SSID", + &ssid->ssid_len); + + ssid->ssid = g_try_malloc0(ssid->ssid_len); + + if (!ssid->ssid) { + g_free(ssid); + return; + } else { + memcpy(ssid->ssid, ssid_data, ssid->ssid_len); + } + + security = connman_network_get_string(network, "WiFi.Security"); + ssid->security = network_security(security); + + g_supplicant_interface_remove_network(wifi->interface, ssid); + + g_free(ssid->ssid); + g_free(ssid); #endif } @@ -3751,6 +3925,8 @@ static GSupplicantSecurity network_security(const char *security) return G_SUPPLICANT_SECURITY_OWE; else if (g_str_equal(security, "dpp")) return G_SUPPLICANT_SECURITY_DPP; + else if (g_str_equal(security, "psk_sha256") == TRUE) + return G_SUPPLICANT_SECURITY_PSK_SHA256; #endif return G_SUPPLICANT_SECURITY_UNKNOWN; @@ -3773,6 +3949,7 @@ static GSupplicantEapKeymgmt network_eap_keymgmt(const char *security) static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network) { + struct wifi_network *network_data = connman_network_get_data(network); const char *security; #if defined TIZEN_EXT const void *ssid_data; @@ -3795,10 +3972,14 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network) #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; + if (connman_network_get_psk_sha256(network)) + security = "psk_sha256"; #endif + ssid->security = network_security(security); + + ssid->keymgmt = network_data->keymgmt; + ssid->ieee80211w = G_SUPPLICANT_MFP_OPTIONAL; ssid->passphrase = connman_network_get_string(network, "WiFi.Passphrase"); @@ -3880,14 +4061,24 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network) } GSList *list; - char buff[MAC_ADDRESS_LENGTH]; + char buff[WIFI_BSSID_STR_LEN]; + const char *dst_bssid = connman_network_get_string(network, + "WiFi.RoamingDstBSSID"); 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'; + g_snprintf(buff, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssids->bssid)); + buff[WIFI_BSSID_STR_LEN - 1] = '\0'; + + if (dst_bssid) { + if (g_strcmp0(dst_bssid, (const gchar *)buff) == 0) { + memcpy(buff_bssid, bssids->bssid, WIFI_BSSID_LEN_MAX); + ssid->bssid = buff_bssid; + ssid->freq = (unsigned int)bssids->frequency; + break; + } + continue; + } gchar *curr_bssid = g_strdup((const gchar *)buff); @@ -3905,6 +4096,9 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network) } } + if (dst_bssid) + connman_network_set_string(network, "WiFi.RoamingDstBSSID", NULL); + if (!list) { ssid->bssid = connman_network_get_bssid(network); g_hash_table_remove_all(failed_bssids); @@ -3917,7 +4111,7 @@ done: connman_network_get_string(network, "WiFi.KeymgmtType")); ssid->phase1 = connman_network_get_string(network, "WiFi.Phase1"); - if(g_strcmp0(ssid->eap, "fast") == 0) + if (g_strcmp0(ssid->eap, "fast") == 0) ssid->pac_file = g_strdup(WIFI_EAP_FAST_PAC_FILE); ssid->keymgmt = connman_network_get_keymgmt(network); @@ -3978,7 +4172,7 @@ static void disconnect_callback(int result, GSupplicantInterface *interface, struct connman_network *network = dd->network; #if defined TIZEN_EXT GList *list; - struct wifi_data *wifi; + struct wifi_data *wifi = NULL; g_free(dd); DBG("network %p result %d", network, result); @@ -3986,6 +4180,9 @@ static void disconnect_callback(int result, GSupplicantInterface *interface, for (list = iface_list; list; list = list->next) { wifi = list->data; + if (!wifi) + continue; + if (wifi->network == NULL && wifi->disconnecting == true) wifi->disconnecting = false; @@ -3993,6 +4190,9 @@ static void disconnect_callback(int result, GSupplicantInterface *interface, goto found; } + if (wifi && network == wifi->pending_network) + wifi->pending_network = NULL; + /* wifi_data may be invalid because wifi is already disabled */ return; @@ -4012,9 +4212,8 @@ found: } #if defined TIZEN_EXT - if (wifi->network && - (wifi->network != wifi->pending_network || - connman_network_get_bool(wifi->network, "WiFi.Roaming"))) + if (g_slist_find(wifi->networks, network) && + wifi->network != wifi->pending_network) #else if (g_slist_find(wifi->networks, network)) #endif @@ -4174,7 +4373,7 @@ static void set_connection_mode(struct connman_network *network, } static void signalpoll_callback(int result, int maxspeed, int strength, - int snr, void *user_data) + int snr, void *user_data, unsigned int est_throughput) { char bssid_buff[WIFI_BSSID_STR_LEN] = {0,}; char *bssid_str = bssid_buff; @@ -4184,7 +4383,10 @@ static void signalpoll_callback(int result, int maxspeed, int strength, const char *interface = NULL; struct connman_device *device; struct connman_network *network = user_data; + GSupplicantNetwork *supplicant_network; + struct wifi_data *wifi = NULL; uint16_t freq = connman_network_get_frequency(network); + const char *group = connman_network_get_group(network); if (result != 0) { DBG("Failed to get maxspeed from signalpoll !"); @@ -4192,30 +4394,45 @@ static void signalpoll_callback(int result, int maxspeed, int strength, return; } + device = connman_network_get_device(network); + if (device) + wifi = connman_device_get_data(device); + + if (group && wifi) { + supplicant_network = g_supplicant_interface_get_network(wifi->interface, group); + if (supplicant_network) { + g_supplicant_network_set_signal(supplicant_network, strength); + g_supplicant_network_set_bss_signal(supplicant_network, strength, snr); + } + } + strength += 120; if (strength > 100) strength = 100; - DBG("freq = %u, maxspeed = %d, strength = %d, snr = %d", freq, maxspeed, strength, snr); + bssid = connman_network_get_bssid(network); + snprintf(bssid_str, WIFI_BSSID_STR_LEN, MACSTR, MAC2STR(bssid)); + + DBG("network %p, bssid %s, freq %u, maxspeed %d, strength %d, snr %d, est_throughput %u", + network, bssid_str, freq, maxspeed, strength, snr, est_throughput); connman_network_set_strength(network, (uint8_t)strength); connman_network_set_snr(network, snr); + connman_network_set_est_throughput(network, est_throughput); connman_network_set_maxspeed(network, maxspeed); set_connection_mode(network, maxspeed); + if (connman_network_get_max_bssid_count(network) <= 1) + goto done; + 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; + if (device && need_bss_transition(freq, snr, strength)) { 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) @@ -4296,6 +4513,7 @@ static void interface_added(GSupplicantInterface *interface) #if defined TIZEN_EXT bool is_5_0_ghz_supported = g_supplicant_interface_get_is_5_0_ghz_supported(interface); + bool is_6_0_ghz_supported = g_supplicant_interface_get_is_6_0_ghz_supported(interface); #endif struct wifi_data *wifi; @@ -4323,6 +4541,7 @@ static void interface_added(GSupplicantInterface *interface) connman_device_set_powered(wifi->device, true); #if defined TIZEN_EXT connman_device_set_wifi_5ghz_supported(wifi->device, is_5_0_ghz_supported); + connman_device_set_wifi_6ghz_supported(wifi->device, is_6_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); @@ -4458,10 +4677,12 @@ static bool handle_wps_completion(GSupplicantInterface *interface, static bool handle_assoc_status_code(GSupplicantInterface *interface, struct wifi_data *wifi) { - if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING && #if defined TIZEN_EXT - wifi->assoc_code > 0 && + if ((wifi->state == G_SUPPLICANT_STATE_ASSOCIATING || + wifi->state == G_SUPPLICANT_STATE_AUTHENTICATING || + wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) && #else + if (wifi->state == G_SUPPLICANT_STATE_ASSOCIATING && wifi->assoc_code == ASSOC_STATUS_NO_CLIENT && #endif wifi->load_shaping_retries < LOAD_SHAPING_MAX_RETRIES) { @@ -4548,6 +4769,9 @@ static bool handle_wifi_assoc_retry(struct connman_network *network, return false; } + if (wifi->state > assoc_last_state) + assoc_last_state = wifi->state; + if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) { wifi->assoc_retry_count = 0; @@ -4555,7 +4779,7 @@ static bool handle_wifi_assoc_retry(struct connman_network *network, * however QA team recommends that the invalid-key error * might be better to display for user experience. */ - switch (wifi->state) { + switch (assoc_last_state) { case G_SUPPLICANT_STATE_AUTHENTICATING: connman_network_set_error(network, CONNMAN_NETWORK_ERROR_AUTHENTICATE_FAIL); break; @@ -4572,6 +4796,65 @@ static bool handle_wifi_assoc_retry(struct connman_network *network, return true; } + +static void handle_wifi_roaming_complete(struct connman_network *network) +{ + const char *cur_bssid; + const char *dst_bssid; + const char *ifname; + struct connman_device *device; + struct connman_service *service; + struct connman_ipconfig *ipconfig_ipv4; + enum connman_ipconfig_type type; + enum connman_ipconfig_method method; + + if (!connman_setting_get_bool("WifiRoaming") || + !connman_network_get_bool(network, "WiFi.Roaming")) + return; + + device = connman_network_get_device(network); + if (device) { + ifname = connman_device_get_string(device, "Interface"); + cur_bssid = connman_network_get_string(network, + "WiFi.RoamingCurBSSID"); + dst_bssid = connman_network_get_string(network, + "WiFi.RoamingDstBSSID"); + } + + if (device && ifname && cur_bssid && dst_bssid) { + __connman_technology_notify_roaming_state(ifname, + "success", cur_bssid, dst_bssid); + connman_network_set_bool(network, + "WiFi.Roaming", false); + connman_network_set_string(network, + "WiFi.RoamingCurBSSID", NULL); + connman_network_set_string(network, + "WiFi.RoamingDstBSSID", NULL); + + service = connman_service_lookup_from_network(network); + if (!service) + return; + + ipconfig_ipv4 = __connman_service_get_ip4config(service); + if (!ipconfig_ipv4) { + connman_error("Service has no IPv4 configuration"); + return; + } + + type = __connman_ipconfig_get_config_type(ipconfig_ipv4); + if (type != CONNMAN_IPCONFIG_TYPE_IPV4) + return; + + method = __connman_ipconfig_get_method(ipconfig_ipv4); + if (method != CONNMAN_IPCONFIG_METHOD_DHCP) + return; + + connman_network_set_bool(network, "WiFi.RoamingDHCP", true); + + if (set_connected_dhcp(network) != 0) + connman_network_set_bool(network, "WiFi.RoamingDHCP", false); + } +} #endif static void interface_state(GSupplicantInterface *interface) @@ -4632,6 +4915,8 @@ static void interface_state(GSupplicantInterface *interface) wifi->automaxspeed_timeout = 0; DBG("Remove signalpoll timer!!"); } + + if (!connman_network_get_bool(wifi->network, "WiFi.Roaming")) #endif if (wifi->connected) connman_network_set_connected(network, false); @@ -4645,7 +4930,9 @@ static void interface_state(GSupplicantInterface *interface) #else stop_autoscan(device); #endif - +#if defined TIZEN_EXT + if (!connman_network_get_bool(wifi->network, "WiFi.Roaming")) +#endif if (!wifi->connected) connman_network_set_associating(network, true); @@ -4679,6 +4966,7 @@ static void interface_state(GSupplicantInterface *interface) } g_hash_table_remove_all(failed_bssids); + handle_wifi_roaming_complete(network); #else /* though it should be already stopped: */ stop_autoscan(device); @@ -4720,19 +5008,22 @@ static void interface_state(GSupplicantInterface *interface) break; #if defined TIZEN_EXT - if (handle_assoc_status_code(interface, wifi)) { - const char *group = connman_network_get_group(network); - GSupplicantNetwork *supplicant_network; + if (!wifi->connected && handle_assoc_status_code(interface, wifi)) { GSList *bssid_list = NULL; guint bssid_length = 0; - if (group) { - supplicant_network = g_supplicant_interface_get_network(interface, group); + if (TIZEN_INS_ENABLED) { + const char *group = connman_network_get_group(network); + GSupplicantNetwork *supplicant_network; + + 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)); + connman_network_set_assoc_reject_table(network, + g_supplicant_network_clone_assoc_reject_table(supplicant_network)); - g_supplicant_network_update_assoc_reject(interface, supplicant_network); + g_supplicant_network_update_assoc_reject(interface, supplicant_network); + } } bssid_list = (GSList *)connman_network_get_bssid_list(network); @@ -4746,8 +5037,6 @@ static void interface_state(GSupplicantInterface *interface) wifi->load_shaping_retries = 0; } - - g_hash_table_remove_all(failed_bssids); #else if (handle_assoc_status_code(interface, wifi)) break; @@ -4777,6 +5066,9 @@ static void interface_state(GSupplicantInterface *interface) } #if defined TIZEN_EXT + if (wifi->assoc_retry_count == 0) + assoc_last_state = G_SUPPLICANT_STATE_UNKNOWN; + /* 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) { @@ -4785,7 +5077,7 @@ static void interface_state(GSupplicantInterface *interface) break; } - if(wifi->disconnect_code > 0){ + if (wifi->disconnect_code > 0){ DBG("Set disconnect reason code(%d)", wifi->disconnect_code); connman_network_set_disconnect_reason(network, wifi->disconnect_code); } @@ -5053,8 +5345,6 @@ static void ap_create_fail(GSupplicantInterface *interface) wifi->tethering = false; ret = tech_set_tethering(wifi->tethering_param->technology, - wifi->tethering_param->ssid->ssid, - wifi->tethering_param->ssid->passphrase, wifi->bridge, true); if ((ret == -EOPNOTSUPP) && (wifi_technology)) { @@ -5202,11 +5492,16 @@ static GSList *get_supported_security_list(unsigned int keymgmt, 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) + } + + 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_FT_SAE) + sec_list = g_slist_prepend (sec_list, "ft_sae"); + if (keymgmt & G_SUPPLICANT_KEYMGMT_OWE || owe_transition_mode) sec_list = g_slist_prepend (sec_list, "owe"); if (keymgmt & G_SUPPLICANT_KEYMGMT_DPP) @@ -5229,6 +5524,7 @@ static void network_added(GSupplicantNetwork *supplicant_network) struct connman_network *network; GSupplicantInterface *interface; struct wifi_data *wifi; + struct wifi_network *network_data; const char *name, *identifier, *security, *group, *mode; const unsigned char *ssid; unsigned int ssid_len; @@ -5307,8 +5603,15 @@ static void network_added(GSupplicantNetwork *supplicant_network) } wifi->networks = g_slist_prepend(wifi->networks, network); + + network_data = g_new0(struct wifi_network, 1); + connman_network_set_data(network, network_data); } + network_data = connman_network_get_data(network); + network_data->keymgmt = + g_supplicant_network_get_keymgmt(supplicant_network); + if (name && name[0] != '\0') connman_network_set_name(network, name); @@ -5324,6 +5627,11 @@ static void network_added(GSupplicantNetwork *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); + + if (g_strcmp0(security, "psk_sha256") == 0) { + connman_network_set_psk_sha256(network, true); + security = "psk"; + } #endif connman_network_set_string(network, "WiFi.Security", security); connman_network_set_strength(network, @@ -5378,11 +5686,15 @@ static void network_added(GSupplicantNetwork *supplicant_network) 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)); + + if (TIZEN_INS_ENABLED) { + 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_clone_assoc_reject_table(supplicant_network)); + } #endif + connman_network_set_available(network, true); connman_network_set_string(network, "WiFi.Mode", mode); @@ -5394,11 +5706,10 @@ static void network_added(GSupplicantNetwork *supplicant_network) 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 (TIZEN_INS_ENABLED) + g_supplicant_network_set_last_connected_bssid(supplicant_network, + connman_network_get_last_connected_bssid(network)); -#if defined TIZEN_EXT if (wifi_first_scan == true) found_with_first_scan = true; #endif @@ -5476,6 +5787,7 @@ static void network_removed(GSupplicantNetwork *network) wifi->networks = g_slist_remove(wifi->networks, connman_network); + g_free(connman_network_get_data(connman_network)); connman_device_remove_network(wifi->device, connman_network); connman_network_unref(connman_network); } @@ -5558,38 +5870,39 @@ static void network_changed(GSupplicantNetwork *network, const char *property) calculate_strength(network)); update_needed = true; } -#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); - } +#if defined TIZEN_EXT + else if (TIZEN_INS_ENABLED) { + 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, + 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; + update_needed = true; + } else if (g_str_equal(property, "UpdateAssocReject")) { + connman_network_set_assoc_reject_table(connman_network, + g_supplicant_network_clone_assoc_reject_table(network)); + update_needed = true; + } else { + update_needed = false; + } } -#endif +#endif /* defined TIZEN_EXT */ else update_needed = false; @@ -6167,14 +6480,27 @@ static void tech_remove(struct connman_technology *technology) wifi_technology = NULL; } -static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase) +static GSupplicantSSID *ssid_ap_init(const struct connman_technology *technology) { GSupplicantSSID *ap; + const char *ssid, *passphrase; + int freq; + bool ret; ap = g_try_malloc0(sizeof(GSupplicantSSID)); if (!ap) return NULL; + ret = connman_technology_get_wifi_tethering(technology, + &ssid, &passphrase, + &freq); + if (ret == false) { +#if defined TIZEN_EXT + g_free(ap); +#endif + return NULL; + } + ap->mode = G_SUPPLICANT_MODE_MASTER; #if defined TIZEN_EXT ap->ssid = (void *) ssid; @@ -6183,7 +6509,10 @@ static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase) #endif ap->ssid_len = strlen(ssid); ap->scan_ssid = 0; - ap->freq = 2412; + if (freq) + ap->freq = freq; + else + ap->freq = 2412; if (!passphrase || strlen(passphrase) == 0) { ap->security = G_SUPPLICANT_SECURITY_NONE; @@ -6296,8 +6625,7 @@ static void sta_remove_callback(int result, } static int enable_wifi_tethering(struct connman_technology *technology, - const char *bridge, const char *identifier, - const char *passphrase, bool available) + const char *bridge, bool available) { GList *list; GSupplicantInterface *interface; @@ -6350,14 +6678,14 @@ static int enable_wifi_tethering(struct connman_technology *technology, info->wifi = wifi; info->technology = technology; info->wifi->bridge = bridge; - info->ssid = ssid_ap_init(identifier, passphrase); + info->ssid = ssid_ap_init(technology); if (!info->ssid) goto failed; info->ifname = g_strdup(ifname); wifi->tethering_param->technology = technology; - wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase); + wifi->tethering_param->ssid = ssid_ap_init(technology); if (!wifi->tethering_param->ssid) goto failed; @@ -6399,7 +6727,6 @@ static int enable_wifi_tethering(struct connman_technology *technology, } static int tech_set_tethering(struct connman_technology *technology, - const char *identifier, const char *passphrase, const char *bridge, bool enabled) { GList *list; @@ -6427,13 +6754,11 @@ static int tech_set_tethering(struct connman_technology *technology, } DBG("trying tethering for available devices"); - err = enable_wifi_tethering(technology, bridge, identifier, passphrase, - true); + err = enable_wifi_tethering(technology, bridge, true); if (err < 0) { DBG("trying tethering for any device"); - err = enable_wifi_tethering(technology, bridge, identifier, - passphrase, false); + err = enable_wifi_tethering(technology, bridge, false); } return err; @@ -6457,7 +6782,7 @@ static int tech_set_regdom(struct connman_technology *technology, const char *al return g_supplicant_set_country(alpha2, regdom_callback, NULL); } -#if defined TIZEN_EXT && defined TIZEN_EXT_INS +#if defined TIZEN_EXT static void supp_ins_init(void) { const char *string; @@ -6479,10 +6804,10 @@ static void supp_ins_init(void) connman_setting_get_uint("INSLastConnectedBSSIDScore"), connman_setting_get_uint("INSAssocRejectScore"), connman_setting_get_int("INSSignalLevel3_5GHz"), - connman_setting_get_int("INSSignalLevel3_24GHz") + connman_setting_get_int("INSSignalLevel3_2_4GHz") ); } -#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ +#endif /* defined TIZEN_EXT */ static struct connman_technology_driver tech_driver = { .name = "wifi", @@ -6516,11 +6841,27 @@ static int wifi_init(void) #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 */ + min_snr = connman_setting_get_int("WifiRoamingMinSNR"); + + min_rssi_2_4GHz = connman_setting_get_int("WifiRoamingMinRSSI_2_4GHz"); + if (min_rssi_2_4GHz >= 0) + min_rssi_2_4GHz = RSSI_LEVEL_2_2_4G; + + min_rssi_5GHz = connman_setting_get_int("WifiRoamingMinRSSI_5GHz"); + if (min_rssi_5GHz >= 0) + min_rssi_5GHz = RSSI_LEVEL_2_5G; + + min_rssi_6GHz = connman_setting_get_int("WifiRoamingMinRSSI_6GHz"); + if (min_rssi_6GHz >= 0) + min_rssi_6GHz = RSSI_LEVEL_2_6G; + + DBG("Min SNR: %d, Min RSSI: %d(2.4GHz), %d(5GHz), %d(6GHz)", + min_snr, min_rssi_2_4GHz, min_rssi_5GHz, min_rssi_6GHz); + + if (TIZEN_INS_ENABLED) + supp_ins_init(); +#endif /* defined TIZEN_EXT */ return 0; } diff --git a/resources/var/lib/connman/settings b/resources/var/lib/connman/settings index ba476b5d..13684c9f 100644 --- a/resources/var/lib/connman/settings +++ b/resources/var/lib/connman/settings @@ -1,6 +1,7 @@ [global] OfflineMode=false +Timeservers=pool.ntp.org; [WiFi] Enable=false diff --git a/src/agent.c b/src/agent.c index d6113af7..d4f9add4 100755 --- a/src/agent.c +++ b/src/agent.c @@ -366,9 +366,9 @@ static void report_error_reply(DBusMessage *reply, void *user_data) retry = true; } +out: report_error->callback(report_error->user_context, retry, report_error->user_data); -out: g_free(report_error); } diff --git a/src/clock.c b/src/clock.c index 58a52c0e..54552cab 100755 --- a/src/clock.c +++ b/src/clock.c @@ -119,6 +119,17 @@ static void clock_properties_load(void) g_free(str); +#if defined TIZEN_EXT + str = g_key_file_get_string(keyfile, "global", "Timeservers", NULL); + + if (str && str[0] == ';') { + DBG("Set time_updates_config to MANUAL."); + time_updates_config = TIME_UPDATES_MANUAL; + } + + g_free(str); +#endif + g_key_file_free(keyfile); } @@ -387,6 +398,21 @@ static DBusMessage *set_property(DBusConnection *conn, __connman_timeserver_system_set(str); +#if defined TIZEN_EXT + if (str) { + if (str[0][0] == '\0') { + DBG("Set time_updates_config to MANUAL."); + time_updates_config = TIMEZONE_UPDATES_MANUAL; + } else { + DBG("Set time_updates_config to AUTO."); + time_updates_config = TIMEZONE_UPDATES_AUTO; + } + } else { + DBG("Set time_updates_config to MANUAL."); + time_updates_config = TIMEZONE_UPDATES_MANUAL; + } +#endif + if (str) g_strfreev(str); diff --git a/src/config.c b/src/config.c index 993f4f6b..afcb0cce 100644 --- a/src/config.c +++ b/src/config.c @@ -1167,8 +1167,7 @@ static char *config_pem_fsid(const char *pem_file) static void provision_service_wifi(struct connman_config_service *config, struct connman_service *service, - struct connman_network *network, - const void *ssid, unsigned int ssid_len) + struct connman_network *network) { if (config->eap) __connman_service_set_string(service, "EAP", config->eap); @@ -1541,8 +1540,7 @@ ipv4_out: config->timeservers); if (type == CONNMAN_SERVICE_TYPE_WIFI) { - provision_service_wifi(config, service, network, - ssid, ssid_len); + provision_service_wifi(config, service, network); } __connman_service_mark_dirty(); diff --git a/src/connman-robot.conf b/src/connman-robot.conf index b089f404..7a2e4caf 100644 --- a/src/connman-robot.conf +++ b/src/connman-robot.conf @@ -15,6 +15,7 @@ <allow send_destination="net.connman" send_type="signal"/> <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="GetScanState" /> <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="Get5GhzSupported" /> + <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="Get6GHzSupported" /> <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="GetMaxScanSsid" /> <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetTechnologies" /> @@ -27,6 +28,7 @@ <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetDisconnectedMeshPeers" /> <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="MeshAddPeer" /> <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="MeshRemovePeer" /> + <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetDhcpStatus" /> <allow send_destination="net.connman" send_interface="net.connman.Service" send_member="Connect" /> <allow send_destination="net.connman" send_interface="net.connman.Service" send_member="Disconnect" /> <allow send_destination="net.connman" send_interface="net.connman.Service" send_member="SetProperty" /> @@ -40,5 +42,6 @@ <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="SetBSSID" /> <allow send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetInterfaces" /> <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="MeshCommands" /> + <allow send_destination="net.connman" send_interface="net.connman.Clock" send_member="GetProperties" /> </policy> </busconfig> diff --git a/src/connman.conf b/src/connman.conf index 267a4fcd..7cc819e2 100644 --- a/src/connman.conf +++ b/src/connman.conf @@ -15,9 +15,11 @@ <allow send_destination="net.connman" send_type="signal"/> <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="GetScanState" /> <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="Get5GhzSupported" /> + <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="Get6GHzSupported" /> <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="GetMaxScanSsid" /> <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetTechnologies" privilege="http://tizen.org/privilege/network.get" /> + <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="SetProperty" privilege="http://tizen.org/privilege/network.set" /> <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetProperties" privilege="http://tizen.org/privilege/network.get" /> <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetServices" privilege="http://tizen.org/privilege/network.get" /> <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetDefaultService" privilege="http://tizen.org/privilege/network.get" /> @@ -27,12 +29,15 @@ <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetDisconnectedMeshPeers" privilege="http://tizen.org/privilege/network.get" /> <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="MeshAddPeer" privilege="http://tizen.org/privilege/network.set" /> <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="MeshRemovePeer" privilege="http://tizen.org/privilege/network.set" /> + <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetDhcpStatus" privilege="http://tizen.org/privilege/network.get" /> <check send_destination="net.connman" send_interface="net.connman.Service" send_member="Connect" privilege="http://tizen.org/privilege/network.set" /> <check send_destination="net.connman" send_interface="net.connman.Service" send_member="Disconnect" privilege="http://tizen.org/privilege/network.set" /> <check send_destination="net.connman" send_interface="net.connman.Service" send_member="SetProperty" privilege="http://tizen.org/privilege/network.profile" /> <check send_destination="net.connman" send_interface="net.connman.Service" send_member="GetProperties" privilege="http://tizen.org/privilege/network.get" /> <check send_destination="net.connman" send_interface="net.connman.Service" send_member="Remove" privilege="http://tizen.org/privilege/network.profile" /> <check send_destination="net.connman" send_interface="net.connman.Service" send_member="PropertyChanged" privilege="http://tizen.org/privilege/network.get" /> + <check send_destination="net.connman" send_interface="net.connman.Technology" send_member="GetProperties" privilege="http://tizen.org/privilege/network.get" /> + <check send_destination="net.connman" send_interface="net.connman.Technology" send_member="SetProperty" privilege="http://tizen.org/privilege/network.set" /> <check send_destination="net.connman" send_interface="net.connman.Technology" send_member="Scan" privilege="http://tizen.org/privilege/network.set" /> <check send_destination="net.connman" send_interface="net.connman.Technology" send_member="SpecificScan" privilege="http://tizen.org/privilege/network.set" /> <check send_destination="net.connman" send_interface="net.connman.Technology" send_member="ScanDevice" privilege="http://tizen.org/privilege/network.set" /> @@ -40,5 +45,6 @@ <check send_destination="net.connman" send_interface="net.connman.Technology" send_member="SetBSSID" privilege="http://tizen.org/privilege/network.set" /> <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetInterfaces" privilege="http://tizen.org/privilege/network.get" /> <check send_destination="net.connman" send_interface="net.connman.Technology" send_member="MeshCommands" privilege="http://tizen.org/privilege/network.set" /> + <check send_destination="net.connman" send_interface="net.connman.Clock" send_member="GetProperties" privilege="http://tizen.org/privilege/network.get" /> </policy> </busconfig> diff --git a/src/connman.h b/src/connman.h index 18c4fe0e..e6e16d11 100755 --- a/src/connman.h +++ b/src/connman.h @@ -598,6 +598,13 @@ void __connman_technology_notify_regdom_by_device(struct connman_device *device, int result, const char *alpha2); #if defined TIZEN_EXT +void __connman_technology_notify_mac_policy_by_device(struct connman_device *device, + int result, unsigned int policy); +void __connman_technology_notify_preassoc_mac_policy_by_device(struct connman_device *device, + int result, unsigned int policy); +void __connman_technology_notify_random_mac_lifetime_by_device(struct connman_device *device, + int result, unsigned int lifetime); + enum bssid_type { CHECK_BSSID = 0, GET_BSSID = 1, @@ -677,6 +684,12 @@ 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); +#if defined TIZEN_EXT +char *__connman_network_get_dhcp_status(const char *ifname); +dbus_bool_t __connman_network_notify_dhcp_changed(const char *key, const char *val); +bool connman_network_get_psk_sha256(struct connman_network *network); +void connman_network_set_psk_sha256(struct connman_network *network, bool is_psk_sha256); +#endif int __connman_config_init(); void __connman_config_cleanup(void); @@ -745,11 +758,9 @@ int __connman_service_move(struct connman_service *service, int __connman_service_load_modifiable(struct connman_service *service); void __connman_service_list_struct(DBusMessageIter *iter); -#if defined TIZEN_EXT_INS +#if defined TIZEN_EXT 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, @@ -687,7 +687,7 @@ int __connman_dbus_init(DBusConnection *conn) connection = conn; - return 0; + return g_dbus_attach_object_manager(conn); } void __connman_dbus_cleanup(void) diff --git a/src/device.c b/src/device.c index 51169001..da86084f 100755 --- a/src/device.c +++ b/src/device.c @@ -82,6 +82,7 @@ struct connman_device { */ int max_scan_ssids; bool is_5_0_ghz_supported; + bool is_6_0_ghz_supported; unsigned int mac_policy; unsigned int preassoc_mac_policy; unsigned int random_mac_lifetime; @@ -387,6 +388,10 @@ static void remove_device(struct connman_device *device) if (device->driver->remove) device->driver->remove(device); +#if defined TIZEN_EXT + __connman_technology_notify_device_detected_by_device(device, "", false); +#endif + device->driver = NULL; } @@ -882,7 +887,7 @@ const char *connman_device_get_last_connected_ident(struct connman_device *devic } #endif -#if defined TIZEN_EXT && defined TIZEN_EXT_INS +#if defined TIZEN_EXT void connman_device_save_last_user_selection(struct connman_device *device) { GKeyFile *keyfile; @@ -1016,7 +1021,7 @@ void connman_device_load_last_connected(struct connman_device *device) g_key_file_free(keyfile); } -#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ +#endif /* defined TIZEN_EXT */ static void mark_network_available(gpointer key, gpointer value, gpointer user_data) @@ -1281,10 +1286,21 @@ void connman_device_set_wifi_5ghz_supported(struct connman_device *device, device->is_5_0_ghz_supported = is_5_0_ghz_supported; } +void connman_device_set_wifi_6ghz_supported(struct connman_device *device, + bool is_6_0_ghz_supported) +{ + device->is_6_0_ghz_supported = is_6_0_ghz_supported; +} + bool connman_device_get_wifi_5ghz_supported(struct connman_device *device) { return device->is_5_0_ghz_supported; } + +bool connman_device_get_wifi_6ghz_supported(struct connman_device *device) +{ + return device->is_6_0_ghz_supported; +} #endif /** @@ -2050,10 +2066,12 @@ struct connman_device *connman_device_create_from_index(int index) connman_device_set_index(device, index); connman_device_set_interface(device, devname); -#if defined TIZEN_EXT && defined TIZEN_EXT_INS - connman_device_load_last_connected(device); - connman_device_load_last_user_selection(device); -#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ +#if defined TIZEN_EXT + if (TIZEN_INS_ENABLED) { + connman_device_load_last_connected(device); + connman_device_load_last_user_selection(device); + } +#endif /* defined TIZEN_EXT */ if (ident) { connman_device_set_ident(device, ident); @@ -43,6 +43,12 @@ #define RATE_LIMIT_INTERVAL 60 /* delay between successive attempts */ +#if defined TIZEN_EXT +#define DHCP_SUCCESS "DHCP_SUCCESS" +#define DHCP_FAIL "DHCP_FAIL" +#define DHCP_STARTED "DHCP_STARTED" +#endif + struct connman_dhcp { struct connman_ipconfig *ipconfig; struct connman_network *network; @@ -285,10 +291,26 @@ static void no_lease_cb(GDHCPClient *dhcp_client, gpointer user_data) dhcp->ipv4ll_client); #if defined TIZEN_EXT + if (dhcp->network && + connman_network_get_bool(dhcp->network, "WiFi.RoamingDHCP")) { + + connman_network_set_bool(dhcp->network, "WiFi.RoamingDHCP", false); + __connman_network_enable_ipconfig(dhcp->network, dhcp->ipconfig); + __connman_network_notify_dhcp_changed(DHCP_FAIL, + g_dhcp_client_get_interface(dhcp_client)); + + return; + } + if (connman_setting_get_bool("EnableAutoIp") == false) { DBG("link-local address autoconfiguration is disabled."); - if (dhcp->network) - __connman_network_disconnect(dhcp->network); + + if (dhcp->network) { + DBG("[DHCP-C] auto ip is not used, set dhcp-fail error and disconnect"); + __connman_network_notify_dhcp_changed(DHCP_FAIL, + g_dhcp_client_get_interface(dhcp_client)); + connman_network_set_error(dhcp->network, CONNMAN_NETWORK_ERROR_DHCP_FAIL); + } return; } #endif @@ -547,6 +569,8 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data) #if defined TIZEN_EXT __connman_ipconfig_set_dhcp_lease_duration(dhcp->ipconfig, dhcp_lease_duration); + __connman_network_notify_dhcp_changed(DHCP_SUCCESS, + g_dhcp_client_get_interface(dhcp_client)); #endif /* @@ -563,6 +587,17 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data) __connman_service_notify_ipv4_configuration(service); } +#if defined TIZEN_EXT + if (connman_network_get_bool(dhcp->network, "WiFi.RoamingDHCP")) { + + if (ip_change) + connman_service_notify_reconnection_roaming( + connman_service_lookup_from_network(dhcp->network)); + + connman_network_set_bool(dhcp->network, "WiFi.RoamingDHCP", false); + } +#endif + if (ip_change) { __connman_ipconfig_set_local(dhcp->ipconfig, address); __connman_ipconfig_set_prefixlen(dhcp->ipconfig, prefixlen); @@ -622,6 +657,11 @@ static void ipv4ll_available_cb(GDHCPClient *ipv4ll_client, gpointer user_data) g_free(address); g_free(netmask); + +#if defined TIZEN_EXT + __connman_network_notify_dhcp_changed(DHCP_FAIL, + g_dhcp_client_get_interface(ipv4ll_client)); +#endif } static int dhcp_initialize(struct connman_dhcp *dhcp) @@ -829,9 +869,18 @@ int __connman_dhcp_start(struct connman_ipconfig *ipconfig, dhcp->user_data = user_data; #if defined TIZEN_EXT - DBG("Start DHCP with DHCPDISCOVER request"); + __connman_network_notify_dhcp_changed(DHCP_STARTED, + g_dhcp_client_get_interface(dhcp->dhcp_client)); - return g_dhcp_client_start(dhcp->dhcp_client, NULL); + if (network && connman_network_get_bool(network, "WiFi.RoamingDHCP")) { + const char *last_addr = __connman_ipconfig_get_dhcp_address(ipconfig); + + DBG("Start DHCP with last address request"); + return g_dhcp_client_start(dhcp->dhcp_client, last_addr); + } else { + 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 diff --git a/src/dnsproxy.c b/src/dnsproxy.c index 18dc6480..8e3ce973 100755 --- a/src/dnsproxy.c +++ b/src/dnsproxy.c @@ -1843,7 +1843,8 @@ static char *uncompress(int16_t field_count, char *start, char *end, ulen = strlen(name) + 1; if ((uptr + ulen) > uncomp_end) goto out; - strncpy(uptr, name, ulen); + + memcpy(uptr, name, ulen); debug("pos %d ulen %d left %d name %s", pos, ulen, (int)(uncomp_end - (uptr + ulen)), uptr); @@ -2003,6 +2004,12 @@ static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol, if (offset < 0) return offset; + if (reply_len < 0) + return -EINVAL; + if (reply_len < offset + 1) + return -EINVAL; + if ((size_t)reply_len < sizeof(struct domain_hdr)) + return -EINVAL; hdr = (void *)(reply + offset); dns_id = reply[offset] | reply[offset + 1] << 8; @@ -2038,23 +2045,31 @@ static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol, */ if (req->append_domain && ntohs(hdr->qdcount) == 1) { uint16_t domain_len = 0; - uint16_t header_len; + uint16_t header_len, payload_len; uint16_t dns_type, dns_class; uint8_t host_len, dns_type_pos; char uncompressed[NS_MAXDNAME], *uptr; char *ptr, *eom = (char *)reply + reply_len; + char *domain; /* * ptr points to the first char of the hostname. * ->hostname.domain.net */ header_len = offset + sizeof(struct domain_hdr); + if (reply_len < header_len) + return -EINVAL; + payload_len = reply_len - header_len; + ptr = (char *)reply + header_len; host_len = *ptr; + domain = ptr + 1 + host_len; + if (domain > eom) + return -EINVAL; + if (host_len > 0) - domain_len = strnlen(ptr + 1 + host_len, - reply_len - header_len); + domain_len = strnlen(domain, eom - domain); /* * If the query type is anything other than A or AAAA, @@ -2063,6 +2078,8 @@ static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol, */ dns_type_pos = host_len + 1 + domain_len + 1; + if (ptr + (dns_type_pos + 3) > eom) + return -EINVAL; dns_type = ptr[dns_type_pos] << 8 | ptr[dns_type_pos + 1]; dns_class = ptr[dns_type_pos + 2] << 8 | @@ -2092,6 +2109,8 @@ static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol, int new_len, fixed_len; char *answers; + if (len > payload_len) + return -EINVAL; /* * First copy host (without domain name) into * tmp buffer. @@ -2106,6 +2125,8 @@ static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol, * Copy type and class fields of the question. */ ptr += len + domain_len + 1; + if (ptr + NS_QFIXEDSZ > eom) + return -EINVAL; memcpy(uptr, ptr, NS_QFIXEDSZ); /* @@ -2115,6 +2136,8 @@ static int forward_dns_reply(unsigned char *reply, int reply_len, int protocol, uptr += NS_QFIXEDSZ; answers = uptr; fixed_len = answers - uncompressed; + if (ptr + offset > eom) + return -EINVAL; /* * We then uncompress the result to buffer @@ -2225,6 +2248,9 @@ out: err = sendto(sk, req->resp, req->resplen, 0, &req->sa, req->sa_len); } else { + uint16_t tcp_len = htons(req->resplen - 2); + /* correct TCP message length */ + memcpy(req->resp, &tcp_len, sizeof(tcp_len)); sk = req->client_sk; err = send(sk, req->resp, req->resplen, MSG_NOSIGNAL); } @@ -2313,14 +2339,15 @@ static gboolean udp_server_event(GIOChannel *channel, GIOCondition condition, len = recv(sk, buf, sizeof(buf), 0); - if (len >= 12) - forward_dns_reply(buf, len, IPPROTO_UDP, data); + forward_dns_reply(buf, len, IPPROTO_UDP, data); #if defined TIZEN_EXT GSList *list; - for (list = server_list_sec; list; list = list->next) { + list = server_list_sec; + while (list) { struct server_data *new_data = list->data; + list = list->next; if (new_data == data) { destroy_server_sec(data); @@ -2408,14 +2435,21 @@ hangup: } } + /* + * Remove the G_IO_OUT flag from the watch, otherwise we end + * up in a busy loop, because the socket is constantly writable. + * + * There seems to be no better way in g_io to do that than + * re-adding the watch. + */ + g_source_remove(server->watch); + server->watch = g_io_add_watch(server->channel, + G_IO_IN | G_IO_HUP | G_IO_NVAL | G_IO_ERR, + tcp_server_event, server); + server->connected = true; server_list = g_slist_append(server_list, server); - if (server->timeout > 0) { - g_source_remove(server->timeout); - server->timeout = 0; - } - for (list = request_list; list; ) { struct request_data *req = list->data; int status; @@ -2693,8 +2727,10 @@ static void destroy_all_server_sec() DBG("remove all dns server"); - for (list = server_list_sec; list; list = list->next) { + list = server_list_sec; + while (list) { struct server_data *server = list->data; + list = list->next; destroy_server_sec(server); } server_list_sec = NULL; @@ -2950,7 +2986,7 @@ static void update_domain(int index, const char *domain, bool append) for (list = server_list; list; list = list->next) { struct server_data *data = list->data; GList *dom_list; - char *dom; + char *dom = NULL; bool dom_found = false; if (data->index < 0) @@ -1984,13 +1984,6 @@ int __connman_inet_ipv6_send_rs(int index, int timeout, return 0; } -static inline void ipv6_addr_advert_mult(const struct in6_addr *addr, - struct in6_addr *advert) -{ - ipv6_addr_set(advert, htonl(0xFF020000), 0, htonl(0x2), - htonl(0xFF000000) | addr->s6_addr32[3]); -} - #define MSG_SIZE_SEND 1452 static int inc_len(int len, int inc) @@ -2454,7 +2447,7 @@ int connman_inet_get_dest_addr(int index, char **dest) int connman_inet_ipv6_get_dest_addr(int index, char **dest) { struct interface_address if_addr = { 0 }; - struct in_addr dstaddr = { 0 }; + struct in6_addr dstaddr = { 0 }; char buf[INET6_ADDRSTRLEN] = { 0 }; int err; @@ -3516,6 +3509,10 @@ static int get_nfs_server_ip(const char *cmdline_file, const char *pnp_file, for (pp = args; *pp; pp++) { if (!strcmp(*pp, "root=/dev/nfs")) break; + if (!strncmp(*pp, "root=/dev/nbd", strlen("root=/dev/nbd"))) + break; + if (!strncmp(*pp, "nbddev=", strlen("nbddev="))) + break; } /* no rootnfs found */ if (!*pp) @@ -3525,6 +3522,8 @@ static int get_nfs_server_ip(const char *cmdline_file, const char *pnp_file, for (pp = args; *pp; pp++) { if (!strncmp(*pp, "nfsroot=", strlen("nfsroot="))) break; + if (!strncmp(*pp, "nbdroot=", strlen("nbdroot="))) + break; } /* no nfsroot argument found */ if (!*pp) diff --git a/src/ipconfig.c b/src/ipconfig.c index 4a0e4ad0..9765ca14 100755 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -1638,6 +1638,9 @@ static void disable_ipv6(struct connman_ipconfig *ipconfig) ifname = connman_inet_ifname(ipconfig->index); + if (!ifname) + return; + set_ipv6_state(ifname, false); g_free(ifname); @@ -1657,6 +1660,9 @@ static void enable_ipv6(struct connman_ipconfig *ipconfig) ifname = connman_inet_ifname(ipconfig->index); + if (!ifname) + return; + if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_AUTO) set_ipv6_privacy(ifname, ipconfig->ipv6_privacy_config); @@ -46,6 +46,9 @@ #define DEFAULT_INPUT_REQUEST_TIMEOUT (120 * 1000) #define DEFAULT_BROWSER_LAUNCH_TIMEOUT (300 * 1000) +#define DEFAULT_ONLINE_CHECK_IPV4_URL "http://ipv4.connman.net/online/status.html" +#define DEFAULT_ONLINE_CHECK_IPV6_URL "http://ipv6.connman.net/online/status.html" + /* * We set the integer to 1 sec so that we have a chance to get * necessary IPv6 router advertisement messages that might have @@ -104,6 +107,8 @@ static struct { char *vendor_class_id; bool enable_online_check; bool enable_online_to_ready_transition; + char *online_check_ipv4_url; + char *online_check_ipv6_url; unsigned int online_check_initial_interval; unsigned int online_check_max_interval; bool auto_connect_roaming_services; @@ -121,6 +126,11 @@ static struct { bool simple_log; bool wifi_roam_scan; bool wifi_roam; + int wifi_roam_min_snr; + int wifi_roam_min_rssi_2_4GHz; + int wifi_roam_min_rssi_5GHz; + int wifi_roam_min_rssi_6GHz; + int wifi_ap_selection_method; #endif } connman_settings = { .bg_scan = true, @@ -142,6 +152,8 @@ static struct { .vendor_class_id = NULL, .enable_online_check = true, .enable_online_to_ready_transition = false, + .online_check_ipv4_url = NULL, + .online_check_ipv6_url = NULL, .online_check_initial_interval = DEFAULT_ONLINE_CHECK_INITIAL_INTERVAL, .online_check_max_interval = DEFAULT_ONLINE_CHECK_MAX_INTERVAL, .auto_connect_roaming_services = false, @@ -159,6 +171,11 @@ static struct { .simple_log = true, .wifi_roam_scan = false, .wifi_roam = false, + .wifi_roam_min_snr = 0, + .wifi_roam_min_rssi_2_4GHz = 0, + .wifi_roam_min_rssi_5GHz = 0, + .wifi_roam_min_rssi_6GHz = 0, + .wifi_ap_selection_method = AP_SELECTION_METHOD_NORMAL, #endif }; @@ -237,6 +254,8 @@ static struct { #define CONF_VENDOR_CLASS_ID "VendorClassID" #define CONF_ENABLE_ONLINE_CHECK "EnableOnlineCheck" #define CONF_ENABLE_ONLINE_TO_READY_TRANSITION "EnableOnlineToReadyTransition" +#define CONF_ONLINE_CHECK_IPV4_URL "OnlineCheckIPv4URL" +#define CONF_ONLINE_CHECK_IPV6_URL "OnlineCheckIPv6URL" #define CONF_ONLINE_CHECK_INITIAL_INTERVAL "OnlineCheckInitialInterval" #define CONF_ONLINE_CHECK_MAX_INTERVAL "OnlineCheckMaxInterval" #define CONF_AUTO_CONNECT_ROAMING_SERVICES "AutoConnectRoamingServices" @@ -247,13 +266,18 @@ static struct { #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" +#define CONF_SUPPLICANT_DEBUG "ConnmanSupplicantDebug" +#define CONF_WIFI_DEF_IFNAME "DefaultWifiInterface" +#define CONF_FILE_LOG "FileLogging" +#define CONF_DLOG_LOG "DlogLogging" +#define CONF_SIMPLIFIED_LOG "SimplifiedLog" +#define CONF_WIFI_ROAM_SCAN "WifiRoamingScan" +#define CONF_WIFI_ROAM "WifiRoaming" +#define CONF_WIFI_ROAM_MIN_SNR "WifiRoamingMinSNR" +#define CONF_WIFI_ROAM_MIN_RSSI_2_4 "WifiRoamingMinRSSI_2_4GHz" +#define CONF_WIFI_ROAM_MIN_RSSI_5 "WifiRoamingMinRSSI_5GHz" +#define CONF_WIFI_ROAM_MIN_RSSI_6 "WifiRoamingMinRSSI_6GHz" +#define CONF_WIFI_AP_SELECTION_METHOD "ApSelectionMethod" #endif #if defined TIZEN_EXT @@ -281,7 +305,7 @@ static struct { #define CONF_INS_INTERNET_SCORE "INSInternetScore" /* Common */ #define CONF_INS_SIGNAL_LEVEL3_5GHZ "INSSignalLevel3_5GHz" -#define CONF_INS_SIGNAL_LEVEL3_24GHZ "INSSignalLevel3_24GHz" +#define CONF_INS_SIGNAL_LEVEL3_2_4GHZ "INSSignalLevel3_2_4GHz" #endif static const char *supported_options[] = { @@ -304,6 +328,8 @@ static const char *supported_options[] = { CONF_VENDOR_CLASS_ID, CONF_ENABLE_ONLINE_CHECK, CONF_ENABLE_ONLINE_TO_READY_TRANSITION, + CONF_ONLINE_CHECK_IPV4_URL, + CONF_ONLINE_CHECK_IPV6_URL, CONF_ONLINE_CHECK_INITIAL_INTERVAL, CONF_ONLINE_CHECK_MAX_INTERVAL, CONF_AUTO_CONNECT_ROAMING_SERVICES, @@ -314,13 +340,18 @@ static const char *supported_options[] = { 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, + CONF_SUPPLICANT_DEBUG, + CONF_WIFI_DEF_IFNAME, + CONF_FILE_LOG, + CONF_DLOG_LOG, + CONF_SIMPLIFIED_LOG, + CONF_WIFI_ROAM_SCAN, + CONF_WIFI_ROAM, + CONF_WIFI_ROAM_MIN_SNR, + CONF_WIFI_ROAM_MIN_RSSI_2_4, + CONF_WIFI_ROAM_MIN_RSSI_5, + CONF_WIFI_ROAM_MIN_RSSI_6, + CONF_WIFI_AP_SELECTION_METHOD, #endif NULL }; @@ -351,7 +382,7 @@ static const char *supported_ins_options[] = { CONF_INS_INTERNET_SCORE, /* Common */ CONF_INS_SIGNAL_LEVEL3_5GHZ, - CONF_INS_SIGNAL_LEVEL3_24GHZ, + CONF_INS_SIGNAL_LEVEL3_2_4GHZ, NULL }; #endif @@ -495,7 +526,7 @@ static void check_config(GKeyFile *config) } #if defined TIZEN_EXT -static void check_Tizen_INS_configuration(GKeyFile *config) +static void check_tizen_ins_configuration(GKeyFile *config) { GError *error = NULL; char *ins_preferred_freq_bssid; @@ -649,20 +680,21 @@ static void check_Tizen_INS_configuration(GKeyFile *config) g_clear_error(&error); integer = g_key_file_get_integer(config, "INS", - CONF_INS_SIGNAL_LEVEL3_24GHZ, &error); + CONF_INS_SIGNAL_LEVEL3_2_4GHZ, &error); if (!error) connman_ins_settings.ins_signal_level3_24ghz = integer; g_clear_error(&error); } -static void check_Tizen_configuration(GKeyFile *config) +static void check_tizen_configuration(GKeyFile *config) { GError *error = NULL; char **cellular_interfaces; char *global_nameserver; char *default_wifi_ifname; bool boolean; + int integer; gsize len; cellular_interfaces = g_key_file_get_string_list(config, "General", @@ -695,51 +727,90 @@ static void check_Tizen_configuration(GKeyFile *config) g_clear_error(&error); boolean = __connman_config_get_bool(config, "General", - CONF_CONNMAN_SUPPLICANT_DEBUG, &error); + CONF_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); + CONF_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); + CONF_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); + CONF_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); + CONF_SIMPLIFIED_LOG, &error); if (!error) connman_settings.simple_log = boolean; + g_clear_error(&error); + boolean = __connman_config_get_bool(config, "General", - CONF_CONNMAN_WIFI_ROAM_SCAN, &error); + CONF_WIFI_ROAM_SCAN, &error); if (!error) connman_settings.wifi_roam_scan = boolean; + g_clear_error(&error); + boolean = __connman_config_get_bool(config, "General", - CONF_CONNMAN_WIFI_ROAM, &error); + CONF_WIFI_ROAM, &error); if (!error) connman_settings.wifi_roam = boolean; g_clear_error(&error); - check_Tizen_INS_configuration(config); + integer = g_key_file_get_integer(config, "General", + CONF_WIFI_ROAM_MIN_SNR, &error); + if (!error && integer >= 0) + connman_settings.wifi_roam_min_snr = integer; + + g_clear_error(&error); + + integer = g_key_file_get_integer(config, "General", + CONF_WIFI_ROAM_MIN_RSSI_2_4, &error); + if (!error) + connman_settings.wifi_roam_min_rssi_2_4GHz = integer; + + g_clear_error(&error); + + integer = g_key_file_get_integer(config, "General", + CONF_WIFI_ROAM_MIN_RSSI_5, &error); + if (!error) + connman_settings.wifi_roam_min_rssi_5GHz = integer; + + g_clear_error(&error); + + integer = g_key_file_get_integer(config, "General", + CONF_WIFI_ROAM_MIN_RSSI_6, &error); + if (!error) + connman_settings.wifi_roam_min_rssi_6GHz = integer; + + g_clear_error(&error); + + integer = g_key_file_get_integer(config, "General", + CONF_WIFI_AP_SELECTION_METHOD, &error); + if (!error) + connman_settings.wifi_ap_selection_method = integer; + + g_clear_error(&error); + + check_tizen_ins_configuration(config); } static void set_nofile_inc(void) @@ -953,6 +1024,27 @@ static void parse_config(GKeyFile *config) g_clear_error(&error); + string = __connman_config_get_string(config, "General", + CONF_ONLINE_CHECK_IPV4_URL, &error); + if (!error) + connman_settings.online_check_ipv4_url = string; + else + connman_settings.online_check_ipv4_url = + g_strdup(DEFAULT_ONLINE_CHECK_IPV4_URL); + + g_clear_error(&error); + + string = __connman_config_get_string(config, "General", + CONF_ONLINE_CHECK_IPV6_URL, &error); + if (!error) + connman_settings.online_check_ipv6_url = string; + else + connman_settings.online_check_ipv6_url = + g_strdup(DEFAULT_ONLINE_CHECK_IPV6_URL); + + + g_clear_error(&error); + integer = g_key_file_get_integer(config, "General", CONF_ONLINE_CHECK_INITIAL_INTERVAL, &error); if (!error && integer >= 0) @@ -1000,7 +1092,7 @@ static void parse_config(GKeyFile *config) g_clear_error(&error); #if defined TIZEN_EXT - check_Tizen_configuration(config); + check_tizen_configuration(config); #endif } @@ -1187,6 +1279,12 @@ char *connman_setting_get_string(const char *key) if (g_str_equal(key, CONF_VENDOR_CLASS_ID)) return connman_settings.vendor_class_id; + if (g_str_equal(key, CONF_ONLINE_CHECK_IPV4_URL)) + return connman_settings.online_check_ipv4_url; + + if (g_str_equal(key, CONF_ONLINE_CHECK_IPV6_URL)) + return connman_settings.online_check_ipv6_url; + if (g_strcmp0(key, "wifi") == 0) { if (!option_wifi) return "nl80211,wext"; @@ -1204,7 +1302,7 @@ char *connman_setting_get_string(const char *key) 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)) + if (g_str_equal(key, CONF_WIFI_DEF_IFNAME)) return connman_settings.def_wifi_ifname; #endif return NULL; @@ -1249,22 +1347,22 @@ bool connman_setting_get_bool(const char *key) if (g_str_equal(key, CONF_ENABLE_AUTO_IP)) return connman_settings.auto_ip; - if (g_str_equal(key, CONF_CONNMAN_SUPPLICANT_DEBUG)) + if (g_str_equal(key, CONF_SUPPLICANT_DEBUG)) return connman_settings.supplicant_debug; - if (g_str_equal(key, CONF_CONNMAN_FILE_LOG)) + if (g_str_equal(key, CONF_FILE_LOG)) return connman_settings.file_log; - if (g_str_equal(key, CONF_CONNMAN_DLOG_LOG)) + if (g_str_equal(key, CONF_DLOG_LOG)) return connman_settings.dlog_log; - if (g_str_equal(key, CONF_CONNMAN_SIMPLIFIED_LOG)) + if (g_str_equal(key, CONF_SIMPLIFIED_LOG)) return connman_settings.simple_log; - if (g_str_equal(key, CONF_CONNMAN_WIFI_ROAM_SCAN)) + if (g_str_equal(key, CONF_WIFI_ROAM_SCAN)) return connman_settings.wifi_roam_scan; - if (g_str_equal(key, CONF_CONNMAN_WIFI_ROAM)) + if (g_str_equal(key, CONF_WIFI_ROAM)) return connman_settings.wifi_roam; if (g_str_equal(key, CONF_INS_LAST_CONNECTED_BSSID)) @@ -1337,12 +1435,27 @@ unsigned int connman_setting_get_uint(const char *key) #if defined TIZEN_EXT int connman_setting_get_int(const char *key) { + if (g_str_equal(key, CONF_WIFI_AP_SELECTION_METHOD)) + return connman_settings.wifi_ap_selection_method; + 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)) + if (g_str_equal(key, CONF_INS_SIGNAL_LEVEL3_2_4GHZ)) return connman_ins_settings.ins_signal_level3_24ghz; + if (g_str_equal(key, CONF_WIFI_ROAM_MIN_SNR)) + return connman_settings.wifi_roam_min_snr; + + if (g_str_equal(key, CONF_WIFI_ROAM_MIN_RSSI_2_4)) + return connman_settings.wifi_roam_min_rssi_2_4GHz; + + if (g_str_equal(key, CONF_WIFI_ROAM_MIN_RSSI_5)) + return connman_settings.wifi_roam_min_rssi_5GHz; + + if (g_str_equal(key, CONF_WIFI_ROAM_MIN_RSSI_6)) + return connman_settings.wifi_roam_min_rssi_6GHz; + return 0; } #endif @@ -1608,6 +1721,8 @@ int main(int argc, char *argv[]) g_strfreev(connman_settings.blacklisted_interfaces); g_strfreev(connman_settings.tethering_technologies); g_free(connman_settings.vendor_class_id); + g_free(connman_settings.online_check_ipv4_url); + g_free(connman_settings.online_check_ipv6_url); #if defined TIZEN_EXT g_free(connman_ins_settings.ins_preferred_freq_bssid); diff --git a/src/main.conf b/src/main.conf index e734ecfe..9905e3e2 100755 --- a/src/main.conf +++ b/src/main.conf @@ -130,12 +130,16 @@ SingleConnectedTechnology = true # Default value is true. # EnableOnlineCheck = false +# Urls (IPv4 and IPv6 respectively) used during the online status check. +# Please refer to the README for more detailed information. +# Default values are http://ipv4.connman.net/online/status.html and +# http://ipv6.connman.net/online/status.html respectively. +# OnlineCheckIPv4URL= http://ipv4.connman.net/online/status.html +# OnlineCheckIPv6URL= http://ipv6.connman.net/online/status.html + # 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. +# Please refer to the README for more detailed information. +# Default values are 1 and 12 respectively. # OnlineCheckInitialInterval = 1 # OnlineCheckMaxInterval = 12 @@ -215,6 +219,20 @@ DefaultWifiInterface = wlan0 # Default value is false. # WifiRoaming = true +# Determine if the SNR and signal have weakened +# based on the following conditions. +# - SNR is less than WifiRoamingMinSNR or RSSI is less than +# WifiRoamingMinRSSI_2_4GHz, WifiRoamingMinRSSI_5GHz or WifiRoamingMinRSSI_6GHz. +# - If the WifiRoamingMinSNR value is 0, the SNR check will be skipped. +WifiRoamingMinSNR = 20 +WifiRoamingMinRSSI_2_4GHz = -75 +WifiRoamingMinRSSI_5GHz = -77 +WifiRoamingMinRSSI_6GHz = -78 + +# This value indicates which AP selection method to be used. +# 0: Normal(Signal strength) +# 1: INS +ApSelectionMethod = 0 [INS] # INS(Intelligent Network Selection) configuration: BSSID Selection. @@ -245,4 +263,4 @@ INSInternetScore = 30 # INS(Intelligent Network Selection) configuration: Common. INSSignalLevel3_5GHz = -76 -INSSignalLevel3_24GHz = -74 +INSSignalLevel3_2_4GHz = -74 diff --git a/src/main_robot.conf b/src/main_robot.conf index f2b84b55..5b72cd98 100755 --- a/src/main_robot.conf +++ b/src/main_robot.conf @@ -215,6 +215,20 @@ DefaultWifiInterface = wlan0 # Default value is false. # WifiRoaming = true +# Determine if the SNR and signal have weakened +# based on the following conditions. +# - SNR is less than WifiRoamingMinSNR or RSSI is less than +# WifiRoamingMinRSSI_2_4GHz, WifiRoamingMinRSSI_5GHz or WifiRoamingMinRSSI_6GHz. +# - If the WifiRoamingMinSNR value is 0, the SNR check will be skipped. +WifiRoamingMinSNR = 20 +WifiRoamingMinRSSI_2_4GHz = -75 +WifiRoamingMinRSSI_5GHz = -77 +WifiRoamingMinRSSI_6GHz = -78 + +# This value indicates which AP selection method to be used. +# 0: Normal(Signal strength) +# 1: INS +ApSelectionMethod = 0 [INS] # INS(Intelligent Network Selection) configuration: BSSID Selection. @@ -245,4 +259,4 @@ INSInternetScore = 30 # INS(Intelligent Network Selection) configuration: Common. INSSignalLevel3_5GHz = -76 -INSSignalLevel3_24GHz = -74 +INSSignalLevel3_2_4GHz = -74 diff --git a/src/main_tv.conf b/src/main_tv.conf index c7b8e112..b40394c0 100755 --- a/src/main_tv.conf +++ b/src/main_tv.conf @@ -120,6 +120,11 @@ TizenTVExtension = true # Default value is wlan0. DefaultWifiInterface = wlan0 +# This value indicates which AP selection method to be used. +# 0: Normal(Signal strength) +# 1: INS +ApSelectionMethod = 0 + [INS] # INS(Intelligent Network Selection) configuration: BSSID Selection. INSPreferredFreqBSSID = 5GHz @@ -149,4 +154,4 @@ INSInternetScore = 30 # INS(Intelligent Network Selection) configuration: Common. INSSignalLevel3_5GHz = -76 -INSSignalLevel3_24GHz = -74 +INSSignalLevel3_2_4GHz = -74 diff --git a/src/manager.c b/src/manager.c index 0000f784..9fea4e0e 100755 --- a/src/manager.c +++ b/src/manager.c @@ -266,9 +266,30 @@ static DBusMessage *get_connected_service(DBusConnection *conn, return connman_service_create_dbus_service_reply(msg, service); } -#endif -#if defined TIZEN_EXT_INS +static DBusMessage *get_dhcp_status(DBusConnection *conn, DBusMessage *msg, void *data) +{ + const char *ifname; + const char *dhcp_status; + DBusMessage *reply; + DBusMessageIter iter; + + dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &ifname, DBUS_TYPE_INVALID); + dhcp_status = __connman_network_get_dhcp_status(ifname); + + reply = dbus_message_new_method_return(msg); + if (!reply) + return NULL; + + if (!dhcp_status) + dhcp_status = "Unknown"; + + dbus_message_iter_init_append(reply, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &dhcp_status); + + return reply; +} + static void append_ins_structs(DBusMessageIter *iter, void *user_data) { __connman_ins_list_struct(iter); @@ -283,8 +304,9 @@ static DBusMessage *get_ins(DBusConnection *conn, if (!reply) return NULL; - __connman_dbus_append_objpath_dict_array(reply, - append_ins_structs, NULL); + if (TIZEN_INS_ENABLED) + __connman_dbus_append_objpath_dict_array(reply, + append_ins_structs, NULL); return reply; } @@ -751,8 +773,10 @@ static const GDBusMethodTable manager_methods[] = { GDBUS_ARGS({ "ifname", "s" }), GDBUS_ARGS({ "service", "oa{sv}" }), get_connected_service) }, -#endif -#if defined TIZEN_EXT_INS + { GDBUS_METHOD("GetDhcpStatus", + GDBUS_ARGS({ "ifname", "s" }), + GDBUS_ARGS({ "status", "s" }), + get_dhcp_status) }, { GDBUS_METHOD("GetINS", NULL, GDBUS_ARGS({ "services", "a(oa{sv})" }), get_ins) }, @@ -835,6 +859,9 @@ static const GDBusSignalTable manager_signals[] = { { GDBUS_SIGNAL("PeersChanged", GDBUS_ARGS({ "changed", "a(oa{sv})" }, { "removed", "ao" })) }, + { GDBUS_SIGNAL("TetheringClientsChanged", + GDBUS_ARGS({ "registered", "as" }, + { "removed", "as" })) }, { }, }; diff --git a/src/network.c b/src/network.c index 70461370..69816999 100755 --- a/src/network.c +++ b/src/network.c @@ -30,6 +30,12 @@ #include <connman/acd.h> #include "src/shared/arp.h" +#if defined TIZEN_EXT +#include <gdbus.h> + +static DBusConnection *connection; +#endif + /* * How many times to send RS with the purpose of * refreshing RDNSS entries before they actually expire. @@ -56,6 +62,8 @@ static unsigned char invalid_bssid[WIFI_BSSID_LEN_MAX] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +static GHashTable *dhcp_status_list = NULL; #endif static GSList *network_list = NULL; @@ -138,8 +146,7 @@ struct connman_network { 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; @@ -147,16 +154,20 @@ struct connman_network { int transition_mode_ssid_len; unsigned char transition_mode_bssid[WIFI_BSSID_LEN_MAX]; bool roaming_progress; + bool roaming_dhcp; char *roaming_cur_bssid; char *roaming_dst_bssid; __time_t roam_scan_time; + unsigned int max_bssid_count; int snr; + unsigned int est_throughput; #endif } wifi; #if defined TIZEN_EXT /* Multiple APN services and a default APN which a user selected */ bool default_internet; + bool is_psk_sha256; #endif }; @@ -600,7 +611,11 @@ static void remove_dhcp_timeout(struct connman_network *network) } } +#if defined TIZEN_EXT +int set_connected_dhcp(struct connman_network *network) +#else static int set_connected_dhcp(struct connman_network *network) +#endif { struct connman_service *service; struct connman_ipconfig *ipconfig_ipv4; @@ -1350,6 +1365,9 @@ static void network_destruct(struct connman_network *network) #if defined TIZEN_EXT g_slist_free_full(network->wifi.vsie_list, g_free); g_slist_free_full(network->wifi.bssid_list, g_free); + + if (TIZEN_INS_ENABLED) + g_hash_table_destroy(network->wifi.assoc_reject_table); #endif g_free(network->path); g_free(network->group); @@ -1414,6 +1432,9 @@ struct connman_network * connman_network_ref_debug(struct connman_network *network, const char *file, int line, const char *caller) { +#if defined TIZEN_EXT + if (!simplified_log) +#endif DBG("%p name %s ref %d by %s:%d:%s()", network, network->name, network->refcount + 1, file, line, caller); @@ -1431,6 +1452,9 @@ connman_network_ref_debug(struct connman_network *network, void connman_network_unref_debug(struct connman_network *network, const char *file, int line, const char *caller) { +#if defined TIZEN_EXT + if (!simplified_log) +#endif DBG("%p name %s ref %d by %s:%d:%s()", network, network->name, network->refcount - 1, file, line, caller); @@ -1808,6 +1832,10 @@ static void set_authenticate_error(struct connman_network *network) if (!service) return; + if (connman_service_get_favorite(service)) { + __connman_service_set_ignore(service, true); + } + __connman_service_indicate_error(service, CONNMAN_SERVICE_ERROR_AUTH_FAILED); } @@ -1824,6 +1852,9 @@ static void set_associate_error(struct connman_network *network) if (!service) return; + if (connman_service_get_favorite(service)) + __connman_service_set_ignore(service, true); + __connman_service_indicate_error(service, CONNMAN_SERVICE_ERROR_ASSOC_FAILED); #else @@ -2006,6 +2037,18 @@ bool connman_network_get_connected(struct connman_network *network) return network->connected; } +#if defined TIZEN_EXT +bool connman_network_get_psk_sha256(struct connman_network *network) +{ + return network->is_psk_sha256; +} + +void connman_network_set_psk_sha256(struct connman_network *network, bool is_psk_sha256) +{ + network->is_psk_sha256 = is_psk_sha256; +} +#endif + /** * connman_network_get_associating: * @network: network structure @@ -2068,6 +2111,63 @@ out: return err; } +#if defined TIZEN_EXT +char *__connman_network_get_dhcp_status(const char *ifname) +{ + char *status = NULL; + + if (!ifname) + return NULL; + + status = g_hash_table_lookup(dhcp_status_list, ifname); + DBG("ifname: %s, DHCP status: %s", ifname, status); + + return status; +} + +static void __connman_network_update_dhcp_status( + const char *ifname, const char *status) +{ + if (!ifname || !status) + return; + + g_hash_table_replace(dhcp_status_list, g_strdup(ifname), g_strdup(status)); +} + +dbus_bool_t __connman_network_notify_dhcp_changed(const char *key, const char *val) +{ + DBusMessage *signal; + DBusMessageIter iter; + dbus_bool_t result = FALSE; + + if (val) + DBG("key %s, val %s", key, val); + else + DBG("key %s, val NULL", key); + + signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH, + CONNMAN_MANAGER_INTERFACE, "DhcpChanged"); + + if (!signal) + return result; + + dbus_message_iter_init_append(signal, &iter); + connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_STRING, &val); + + result = dbus_connection_send(connection, signal, NULL); + if (result) + DBG("Successfuly sent signal"); + else + DBG("Fail to send signal"); + + dbus_message_unref(signal); + + __connman_network_update_dhcp_status(val, key); + + return result; +} +#endif + /** * __connman_network_connect: * @network: network structure @@ -2379,9 +2479,6 @@ int connman_network_set_bssid(struct connman_network *network, 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], @@ -2600,9 +2697,15 @@ unsigned char *connman_network_get_countrycode(struct connman_network *network) int connman_network_set_bssid_list(struct connman_network *network, GSList *bssids) { + unsigned int max_bssid_count; + g_slist_free_full(network->wifi.bssid_list, g_free); network->wifi.bssid_list = bssids; + max_bssid_count = g_slist_length(bssids); + if (network->wifi.max_bssid_count < max_bssid_count) + network->wifi.max_bssid_count = max_bssid_count; + return 0; } @@ -2640,6 +2743,11 @@ void *connman_network_get_bssid_list(struct connman_network *network) return network->wifi.bssid_list; } +unsigned int connman_network_get_max_bssid_count(struct connman_network *network) +{ + return network->wifi.max_bssid_count; +} + int connman_network_set_last_connected_bssid(struct connman_network *network, const unsigned char *bssid) { @@ -2668,6 +2776,8 @@ void connman_network_set_assoc_reject_table(struct connman_network *network, if (!assoc_reject_table) return; + g_hash_table_destroy(network->wifi.assoc_reject_table); + network->wifi.assoc_reject_table = assoc_reject_table; } @@ -2699,6 +2809,17 @@ void connman_network_set_snr(struct connman_network *network, int snr) { network->wifi.snr = snr; } + +unsigned int connman_network_get_est_throughput(struct connman_network *network) +{ + return network->wifi.est_throughput; +} + +void connman_network_set_est_throughput(struct connman_network *network, + unsigned int est_throughput) +{ + network->wifi.est_throughput = est_throughput; +} #endif int connman_network_set_nameservers(struct connman_network *network, @@ -3031,6 +3152,8 @@ int connman_network_set_bool(struct connman_network *network, 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.RoamingDHCP") == 0) + network->wifi.roaming_dhcp = value; else if (g_strcmp0(key, "WiFi.PMFRequired") == 0) network->wifi.pmf_required = value; #endif @@ -3065,6 +3188,8 @@ bool connman_network_get_bool(struct connman_network *network, 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.RoamingDHCP")) + return network->wifi.roaming_dhcp; else if (g_str_equal(key, "WiFi.PMFRequired")) return network->wifi.pmf_required; #endif @@ -3232,6 +3357,11 @@ void connman_network_update(struct connman_network *network) int __connman_network_init(void) { DBG(""); +#if defined TIZEN_EXT + connection = connman_dbus_get_connection(); + dhcp_status_list = g_hash_table_new_full(g_str_hash, + g_str_equal, g_free, g_free); +#endif return 0; } @@ -3239,4 +3369,9 @@ int __connman_network_init(void) void __connman_network_cleanup(void) { DBG(""); +#if defined TIZEN_EXT + dbus_connection_unref(connection); + if (dhcp_status_list) + g_hash_table_destroy(dhcp_status_list); +#endif } @@ -370,6 +370,7 @@ static void decode_msg(struct ntp_data *nd, void *base, size_t len, connection = connman_dbus_get_connection(); if(!connection){ DBG("dbus connection does not exist"); + nd->cb(false, nd->user_data); return; } @@ -397,6 +398,7 @@ static void decode_msg(struct ntp_data *nd, void *base, size_t len, } dbus_connection_unref(connection); dbus_message_unref(msg); + nd->cb(false, nd->user_data); return; } @@ -409,6 +411,7 @@ static void decode_msg(struct ntp_data *nd, void *base, size_t len, DBG("setting time"); __connman_clock_set_time_updated(true); + nd->cb(true, nd->user_data); } #else if (offset < STEPTIME_MIN_OFFSET && offset > -STEPTIME_MIN_OFFSET) { @@ -527,6 +530,13 @@ static gboolean received_data(GIOChannel *channel, GIOCondition condition, } } +#if defined TIZEN_EXT + if (__connman_clock_timeupdates() == TIME_UPDATES_MANUAL) { + DBG("Skip time update."); + return TRUE; + } +#endif + decode_msg(nd, iov.iov_base, iov.iov_len, tv, &mrx_time); return TRUE; @@ -1456,75 +1456,71 @@ static const char *type2string(uint16_t type) static GIOChannel *channel = NULL; static guint channel_watch = 0; -struct rtnl_request { - struct nlmsghdr hdr; - struct rtgenmsg msg; -}; -#define RTNL_REQUEST_SIZE (sizeof(struct nlmsghdr) + sizeof(struct rtgenmsg)) +#define RTNL_REQUEST_SIZE (NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(struct rtgenmsg))) static GSList *request_list = NULL; static guint32 request_seq = 0; -static struct rtnl_request *find_request(guint32 seq) +static struct nlmsghdr *find_request(guint32 seq) { GSList *list; for (list = request_list; list; list = list->next) { - struct rtnl_request *req = list->data; + struct nlmsghdr *hdr = list->data; - if (req->hdr.nlmsg_seq == seq) - return req; + if (hdr->nlmsg_seq == seq) + return hdr; } return NULL; } -static int send_request(struct rtnl_request *req) +static int send_request(struct nlmsghdr *hdr) { struct sockaddr_nl addr; int sk; DBG("%s len %d type %d flags 0x%04x seq %d", - type2string(req->hdr.nlmsg_type), - req->hdr.nlmsg_len, req->hdr.nlmsg_type, - req->hdr.nlmsg_flags, req->hdr.nlmsg_seq); + type2string(hdr->nlmsg_type), + hdr->nlmsg_len, hdr->nlmsg_type, + hdr->nlmsg_flags, hdr->nlmsg_seq); sk = g_io_channel_unix_get_fd(channel); memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; - return sendto(sk, req, req->hdr.nlmsg_len, 0, + return sendto(sk, hdr, hdr->nlmsg_len, 0, (struct sockaddr *) &addr, sizeof(addr)); } -static int queue_request(struct rtnl_request *req) +static int queue_request(struct nlmsghdr *hdr) { - request_list = g_slist_append(request_list, req); + request_list = g_slist_append(request_list, hdr); if (g_slist_length(request_list) > 1) return 0; - return send_request(req); + return send_request(hdr); } static int process_response(guint32 seq) { - struct rtnl_request *req; + struct nlmsghdr *hdr; DBG("seq %d", seq); - req = find_request(seq); - if (req) { - request_list = g_slist_remove(request_list, req); - g_free(req); + hdr = find_request(seq); + if (hdr) { + request_list = g_slist_remove(request_list, hdr); + g_free(hdr); } - req = g_slist_nth_data(request_list, 0); - if (!req) + hdr = g_slist_nth_data(request_list, 0); + if (!hdr) return 0; - return send_request(req); + return send_request(hdr); } static void rtnl_message(void *buf, size_t len) @@ -1639,62 +1635,65 @@ static gboolean netlink_event(GIOChannel *chan, GIOCondition cond, gpointer data static int send_getlink(void) { - struct rtnl_request *req; + struct nlmsghdr *hdr; + struct rtgenmsg *msg; DBG(""); - req = g_try_malloc0(RTNL_REQUEST_SIZE); - if (!req) - return -ENOMEM; + hdr = g_malloc0(RTNL_REQUEST_SIZE); + + hdr->nlmsg_len = RTNL_REQUEST_SIZE; + hdr->nlmsg_type = RTM_GETLINK; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; + hdr->nlmsg_pid = 0; + hdr->nlmsg_seq = request_seq++; - req->hdr.nlmsg_len = RTNL_REQUEST_SIZE; - req->hdr.nlmsg_type = RTM_GETLINK; - req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; - req->hdr.nlmsg_pid = 0; - req->hdr.nlmsg_seq = request_seq++; - req->msg.rtgen_family = AF_INET; + msg = (struct rtgenmsg *) NLMSG_DATA(hdr); + msg->rtgen_family = AF_INET; - return queue_request(req); + return queue_request(hdr); } static int send_getaddr(void) { - struct rtnl_request *req; + struct nlmsghdr *hdr; + struct rtgenmsg *msg; DBG(""); - req = g_try_malloc0(RTNL_REQUEST_SIZE); - if (!req) - return -ENOMEM; + hdr = g_malloc0(RTNL_REQUEST_SIZE); - req->hdr.nlmsg_len = RTNL_REQUEST_SIZE; - req->hdr.nlmsg_type = RTM_GETADDR; - req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; - req->hdr.nlmsg_pid = 0; - req->hdr.nlmsg_seq = request_seq++; - req->msg.rtgen_family = AF_INET; + hdr->nlmsg_len = RTNL_REQUEST_SIZE; + hdr->nlmsg_type = RTM_GETADDR; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; + hdr->nlmsg_pid = 0; + hdr->nlmsg_seq = request_seq++; - return queue_request(req); + msg = (struct rtgenmsg *) NLMSG_DATA(hdr); + msg->rtgen_family = AF_INET; + + return queue_request(hdr); } static int send_getroute(void) { - struct rtnl_request *req; + struct nlmsghdr *hdr; + struct rtgenmsg *msg; DBG(""); - req = g_try_malloc0(RTNL_REQUEST_SIZE); - if (!req) - return -ENOMEM; + hdr = g_malloc0(RTNL_REQUEST_SIZE); + + hdr->nlmsg_len = RTNL_REQUEST_SIZE; + hdr->nlmsg_type = RTM_GETROUTE; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; + hdr->nlmsg_pid = 0; + hdr->nlmsg_seq = request_seq++; - req->hdr.nlmsg_len = RTNL_REQUEST_SIZE; - req->hdr.nlmsg_type = RTM_GETROUTE; - req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; - req->hdr.nlmsg_pid = 0; - req->hdr.nlmsg_seq = request_seq++; - req->msg.rtgen_family = AF_INET; + msg = (struct rtgenmsg *) NLMSG_DATA(hdr); + msg->rtgen_family = AF_INET; - return queue_request(req); + return queue_request(hdr); } static gboolean update_timeout_cb(gpointer user_data) @@ -1857,14 +1856,14 @@ void __connman_rtnl_cleanup(void) update_list = NULL; for (list = request_list; list; list = list->next) { - struct rtnl_request *req = list->data; + struct nlmsghdr *hdr= list->data; DBG("%s len %d type %d flags 0x%04x seq %d", - type2string(req->hdr.nlmsg_type), - req->hdr.nlmsg_len, req->hdr.nlmsg_type, - req->hdr.nlmsg_flags, req->hdr.nlmsg_seq); + type2string(hdr->nlmsg_type), + hdr->nlmsg_len, hdr->nlmsg_type, + hdr->nlmsg_flags, hdr->nlmsg_seq); - g_free(req); + g_free(hdr); list->data = NULL; } diff --git a/src/service.c b/src/service.c index 794555ea..9f7c4690 100755 --- a/src/service.c +++ b/src/service.c @@ -31,6 +31,10 @@ #include <ctype.h> #include <stdint.h> +#if defined TIZEN_EXT +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + #include <connman/storage.h> #include <connman/setting.h> #include <connman/agent.h> @@ -61,6 +65,7 @@ static DBusConnection *connection = NULL; static GList *service_list = NULL; static GHashTable *service_hash = NULL; +static GHashTable *passphrase_requested = NULL; static GSList *counter_list = NULL; static unsigned int autoconnect_id = 0; static unsigned int vpn_autoconnect_id = 0; @@ -81,9 +86,7 @@ struct saved_profiles { 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, @@ -109,7 +112,7 @@ struct connman_ins_settings { }; static struct connman_ins_settings ins_settings; -#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ +#endif /* defined TIZEN_EXT */ struct connman_stats { bool valid; @@ -231,22 +234,19 @@ struct connman_service { 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 @@ -475,6 +475,10 @@ static const char *security2string(enum connman_service_security security) #endif case CONNMAN_SERVICE_SECURITY_8021X: return "ieee8021x"; +#if defined TIZEN_EXT + default: + break; +#endif } return NULL; @@ -828,6 +832,9 @@ static void save_assoc_reject(gpointer key, gpointer value, gpointer user_data) GSList *list; char *val_str; + if (!assoc_rd) + return; + if (g_slist_length(assoc_rd->reject_time_list) < 1) return; @@ -866,10 +873,10 @@ static bool update_assoc_reject(struct connman_service *service) 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; @@ -956,9 +963,7 @@ static int service_ext_load(struct connman_service *service) 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); } @@ -987,7 +992,8 @@ static int service_ext_save(struct connman_service *service) if (service->type != CONNMAN_SERVICE_TYPE_WIFI) return -EINVAL; - keyfile = g_key_file_new(); + keyfile = connman_storage_load_service(service->identifier); + if (!keyfile) return -EIO; @@ -1013,9 +1019,7 @@ static int service_ext_save(struct connman_service *service) 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); } @@ -1039,9 +1043,7 @@ next: 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); @@ -1055,7 +1057,7 @@ done: g_key_file_free(keyfile); return err; } -#endif +#endif /* defined TIZEN_EXT */ static int service_load(struct connman_service *service) { @@ -1157,44 +1159,46 @@ static int service_load(struct connman_service *service) } #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; + if (TIZEN_INS_ENABLED) { + /* 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); + bssid_str = g_key_file_get_string(keyfile, + service->identifier, "LastConnectedBSSID", NULL); - if (bssid_str) { - str_list = g_strsplit(bssid_str, ":", 0); + 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); + 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); + memcpy(service->last_connected_bssid, + last_connected_bssid, WIFI_BSSID_LEN_MAX); - connman_network_set_last_connected_bssid(service->network, - last_connected_bssid); + connman_network_set_last_connected_bssid(service->network, + last_connected_bssid); - g_strfreev(str_list); - } + g_strfreev(str_list); + } - g_free(bssid_str); + 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; + /* 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 + g_clear_error(&error); + } +#endif /* defined TIZEN_EXT */ /* fall through */ case CONNMAN_SERVICE_TYPE_GADGET: @@ -1504,72 +1508,69 @@ static int service_save(struct connman_service *service) "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; + if (TIZEN_INS_ENABLED) { + /* 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; - } + 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, ":"); - } + 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, + 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 + DBG("last connected bssid[%s]", bssid_str->str); - g_string_free(bssid_str, TRUE); - } + 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 */ + 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; - } + 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); + 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); + 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); + 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 + DBG("assoc reject table [%d]", assoc_reject_len); - g_strfreev(assoc_reject_list); - g_string_free(assoc_reject_str, TRUE); - } else - g_key_file_remove_key(keyfile, service->identifier, "AssocReject", NULL); + 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 + /* Internet connection */ + g_key_file_set_boolean(keyfile, service->identifier, + "InternetConnection", service->is_internet_connection); + + DBG("internet connection [%s]", service->is_internet_connection ? "true" : "false"); + } +#endif /* defined TIZEN_EXT */ } /* fall through */ @@ -3028,6 +3029,25 @@ bool __connman_service_index_is_default(int index) return __connman_service_get_index(service) == index; } +static void start_wispr_when_connected(struct connman_service *service) +{ + if (!connman_setting_get_bool("EnableOnlineCheck")) { + connman_info("Online check disabled. " + "Default service remains in READY state."); + return; + } + + 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); +} + static void default_changed(void) { #if defined TIZEN_EXT @@ -3062,15 +3082,7 @@ static void default_changed(void) 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); + start_wispr_when_connected(service); /* * Connect VPN automatically when new default service @@ -3140,33 +3152,32 @@ static void state_changed(struct connman_service *service) #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; + if (TIZEN_INS_ENABLED) { + 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)); + 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)); + 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); + if (need_save) + connman_device_save_last_user_selection(device); + } } } -#endif connman_dbus_property_changed_basic(service->path, CONNMAN_SERVICE_INTERFACE, @@ -3174,9 +3185,7 @@ static void connect_reason_changed(struct connman_service *service) 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; @@ -3196,7 +3205,7 @@ static void disconnection_requested_changed(struct connman_service *service) } void connman_service_set_disconnection_requested(struct connman_service *service, - bool disconnection_requested) + bool disconnection_requested) { if (service == NULL) return; @@ -3204,6 +3213,47 @@ void connman_service_set_disconnection_requested(struct connman_service *service service->disconnection_requested = disconnection_requested; disconnection_requested_changed(service); } + +static void connman_service_emit_state(struct connman_service *service, + enum connman_service_state state) +{ + const char *str; + enum connman_service_state cur_state = service->state; + + if (service->state != state) + service->state = state; + + str = state2string(service->state); + if (!str) { + service->state = cur_state; + return; + } + + DBG(" %s, %s", str, service->path); + + connman_dbus_property_changed_basic(service->path, + CONNMAN_SERVICE_INTERFACE, "State", + DBUS_TYPE_STRING, &str); + + emit_state_changed_with_properties(service); + service->state = cur_state; +} + +void connman_service_notify_reconnection_roaming(struct connman_service *service) +{ + if (!service) + return; + + if (service->state != CONNMAN_SERVICE_STATE_READY && + service->state != CONNMAN_SERVICE_STATE_ONLINE) + return; + + connman_service_emit_state(service, CONNMAN_SERVICE_STATE_CONFIGURATION); + connman_service_emit_state(service, CONNMAN_SERVICE_STATE_READY); + + if (service->state == CONNMAN_SERVICE_STATE_ONLINE) + connman_service_emit_state(service, CONNMAN_SERVICE_STATE_ONLINE); +} #endif static void strength_changed(struct connman_service *service) @@ -3347,12 +3397,17 @@ static void append_security(DBusMessageIter *iter, void *user_data) break; #if defined TIZEN_EXT case CONNMAN_SERVICE_SECURITY_OWE: + case CONNMAN_SERVICE_SECURITY_DPP: #endif case CONNMAN_SERVICE_SECURITY_UNKNOWN: case CONNMAN_SERVICE_SECURITY_NONE: case CONNMAN_SERVICE_SECURITY_WEP: case CONNMAN_SERVICE_SECURITY_8021X: break; +#if defined TIZEN_EXT + default: + break; +#endif } if (service->wps_advertizing) { @@ -4650,7 +4705,7 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, connman_network_append_acddbus(dict, service->network); } -#if defined TIZEN_EXT && defined TIZEN_EXT_INS +#if defined TIZEN_EXT static void append_ins_bssid_info(DBusMessageIter *iter, void *user_data) { GSList *bssid_list = NULL; @@ -4741,7 +4796,7 @@ static void append_ins_properties(DBusMessageIter *dict, append_ins_bssid_info, service->network); } } -#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ +#endif /* defined TIZEN_EXT */ static void append_struct_service(DBusMessageIter *iter, connman_dbus_append_cb_t function, @@ -4780,7 +4835,7 @@ static void append_struct(gpointer value, gpointer user_data) append_struct_service(iter, append_dict_properties, service); } -#if defined TIZEN_EXT && defined TIZEN_EXT_INS +#if defined TIZEN_EXT static void append_dict_ins_properties(DBusMessageIter *dict, void *user_data) { struct connman_service *service = user_data; @@ -4806,7 +4861,7 @@ void __connman_ins_list_struct(DBusMessageIter *iter) { g_list_foreach(service_list, append_ins_struct, iter); } -#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ +#endif /* defined TIZEN_EXT */ void __connman_service_list_struct(DBusMessageIter *iter) { @@ -5071,7 +5126,7 @@ void connman_service_set_internet_connection(struct connman_service *service, if (service->is_internet_connection != internet_connection) { service->is_internet_connection = internet_connection; - g_get_current_time(&service->modified); + g_get_current_time((GTimeVal *)&service->modified); service_save(service); } } @@ -5465,6 +5520,7 @@ int __connman_service_check_passphrase(enum connman_service_security security, #if defined TIZEN_EXT case CONNMAN_SERVICE_SECURITY_OWE: case CONNMAN_SERVICE_SECURITY_DPP: + default: #endif break; } @@ -6081,13 +6137,7 @@ static DBusMessage *set_property(DBusConnection *conn, #endif dns_configuration_changed(service); - 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); + start_wispr_when_connected(service); service_save(service); } else if (g_str_equal(name, "Timeservers.Configuration")) { @@ -6307,8 +6357,10 @@ static void set_error(struct connman_service *service, { const char *str; +#if !defined TIZEN_EXT if (service->error == error) return; +#endif service->error = error; @@ -6611,6 +6663,7 @@ static bool auto_connect_service(GList *services, #if defined TIZEN_EXT GSList *wifi_ignore = NULL; #endif + int index; DBG("preferred %d sessions %d reason %s", preferred, active_count, reason2string(reason)); @@ -6659,6 +6712,11 @@ static bool auto_connect_service(GList *services, continue; } + index = __connman_service_get_index(service); + if (g_hash_table_lookup(passphrase_requested, + GINT_TO_POINTER(index))) + return true; + if (service->pending || is_connecting(service->state) || is_connected(service->state)) { @@ -7286,13 +7344,90 @@ bool __connman_service_remove(struct connman_service *service) return true; } +#if defined TIZEN_EXT +static char *__connman_service_get_wpa_id_to_remove(struct connman_service *service) +{ + char *identifier; + char *ptr; + + if (service->type != CONNMAN_SERVICE_TYPE_WIFI) + return NULL; + + if (service->security != CONNMAN_SERVICE_SECURITY_SAE && + service->security != CONNMAN_SERVICE_SECURITY_PSK) + return NULL; + + identifier = g_strdup(service->identifier); + if (!identifier) + return NULL; + + if (service->security == CONNMAN_SERVICE_SECURITY_SAE) { + ptr = strstr(identifier, "_sae"); + if (!ptr) { + g_free(identifier); + return NULL; + } + + memcpy(ptr, "_psk", strlen("_psk")); + } else if (service->security == CONNMAN_SERVICE_SECURITY_PSK) { + ptr = strstr(identifier, "_psk"); + if (!ptr) { + g_free(identifier); + return NULL; + } + + memcpy(ptr, "_sae", strlen("_sae")); + } + + return identifier; +} + + +static void __connman_service_remove_wpa_service(struct connman_service *service) +{ + gchar *dir; + GList *list; + char *identifier = __connman_service_get_wpa_id_to_remove(service); + + if (!identifier) + return; + + dir = g_strdup_printf("%s/%s", STORAGEDIR, identifier); + if (!dir) + goto done; + + if (g_file_test(dir, G_FILE_TEST_EXISTS) != TRUE) + goto done; + + for (list = service_list; list; list = list->next) { + struct connman_service *dst_service = list->data; + + if (dst_service->type != CONNMAN_SERVICE_TYPE_WIFI) + continue; + + if (g_strcmp0(dst_service->identifier, identifier) == 0) { + __connman_service_remove(dst_service); + goto done; + } + } + + __connman_storage_remove_service(identifier); + +done: + g_free(identifier); + g_free(dir); +} +#endif + static DBusMessage *remove_service(DBusConnection *conn, DBusMessage *msg, void *user_data) { struct connman_service *service = user_data; DBG("service %p", service); - +#if defined TIZEN_EXT + __connman_service_remove_wpa_service(service); +#endif if (!__connman_service_remove(service)) return __connman_error_not_supported(msg); @@ -7339,15 +7474,11 @@ static void apply_relevant_default_downgrade(struct connman_service *service) struct connman_service *def_service; def_service = connman_service_get_default(); - if (!def_service) + if (!def_service || def_service != service || + def_service->state != CONNMAN_SERVICE_STATE_ONLINE) return; - if (def_service == service && - def_service->state == CONNMAN_SERVICE_STATE_ONLINE) { - def_service->state = CONNMAN_SERVICE_STATE_READY; - __connman_notifier_leave_online(def_service->type); - state_changed(def_service); - } + downgrade_state(def_service); } static void switch_default_service(struct connman_service *default_service, @@ -7893,7 +8024,6 @@ static void service_initialize(struct connman_service *service) 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; /* @@ -7993,7 +8123,7 @@ void connman_service_unref_debug(struct connman_service *service, g_hash_table_remove(service_hash, service->identifier); } -#if defined TIZEN_EXT && defined TIZEN_EXT_INS +#if defined TIZEN_EXT static int calculate_score_last_user_selection(struct connman_service *service) { int score = 0; @@ -8171,7 +8301,7 @@ static int calculate_score(struct connman_service *service) service->ins_score = score; return score; } -#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ +#endif /* defined TIZEN_EXT */ static gint service_compare(gconstpointer a, gconstpointer b); @@ -8207,18 +8337,38 @@ static gint service_compare_vpn(struct connman_service *a, return service_compare(transport, service); } +static gint service_compare_preferred(struct connman_service *service_a, + struct connman_service *service_b) +{ + unsigned int *tech_array; + int i; + + tech_array = connman_setting_get_uint_list("PreferredTechnologies"); + if (tech_array) { + for (i = 0; tech_array[i]; i++) { + if (tech_array[i] == service_a->type) + return -1; + + if (tech_array[i] == service_b->type) + return 1; + } + } + return 0; +} + 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 +#if defined TIZEN_EXT int score_a; int score_b; -#else /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ + gint strength = 0; +#else /* defined TIZEN_EXT */ gint strength; -#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ +#endif /* defined TIZEN_EXT */ state_a = service_a->state; state_b = service_b->state; @@ -8261,6 +8411,10 @@ static gint service_compare(gconstpointer a, gconstpointer b) if (service_a->order < service_b->order) return 1; + + rval = service_compare_preferred(service_a, service_b); + if (rval) + return rval; } if (state_a != state_b) { @@ -8291,20 +8445,11 @@ static gint service_compare(gconstpointer a, gconstpointer b) return 1; if (service_a->type != service_b->type) { - unsigned int *tech_array; - int i; - - tech_array = connman_setting_get_uint_list( - "PreferredTechnologies"); - if (tech_array) { - for (i = 0; tech_array[i]; i++) { - if (tech_array[i] == service_a->type) - return -1; + int rval; - if (tech_array[i] == service_b->type) - return 1; - } - } + rval = service_compare_preferred(service_a, service_b); + if (rval) + return rval; if (service_a->type == CONNMAN_SERVICE_TYPE_ETHERNET) return -1; @@ -8337,44 +8482,32 @@ static gint service_compare(gconstpointer a, gconstpointer b) return 1; } -#if defined TIZEN_EXT && defined TIZEN_EXT_INS - score_a = calculate_score(service_a); - score_b = calculate_score(service_b); - if (score_b != score_a) - return score_b - score_a; -#else /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ +#if defined TIZEN_EXT + if (TIZEN_INS_ENABLED) { + score_a = calculate_score(service_a); + score_b = calculate_score(service_b); + + if (score_b != score_a) + return score_b - score_a; + else if (score_b == score_a) { + strength = (gint) service_b->strength - (gint) service_a->strength; + if (strength) + return strength; + } + } +#else /* defined TIZEN_EXT */ strength = (gint) service_b->strength - (gint) service_a->strength; if (strength) return strength; -#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ +#endif /* defined TIZEN_EXT */ 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(); } } @@ -8803,6 +8936,7 @@ static void request_input_cb(struct connman_service *service, struct connman_device *device; const char *security; int err = 0; + int index; DBG("RequestInput return, %p", service); @@ -8865,6 +8999,10 @@ static void request_input_cb(struct connman_service *service, err = __connman_service_set_passphrase(service, passphrase); done: + index = __connman_service_get_index(service); + g_hash_table_remove(passphrase_requested, + GINT_TO_POINTER(index)); + if (err >= 0) { /* We forget any previous error. */ set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN); @@ -8918,27 +9056,14 @@ static int service_update_preferred_order(struct connman_service *default_servic struct connman_service *new_service, enum connman_service_state new_state) { - unsigned int *tech_array; - int i; - - if (!default_service || default_service == new_service || - default_service->state != new_state) + if (!default_service || default_service == new_service) return 0; - 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; - - if (new_service->type == tech_array[i]) { - switch_default_service(default_service, - new_service); - __connman_connection_update_gateway(); - return 0; - } - } + if (service_compare_preferred(default_service, new_service) > 0) { + switch_default_service(default_service, + new_service); + __connman_connection_update_gateway(); + return 0; } return -EALREADY; @@ -9147,6 +9272,50 @@ static void set_priority_connected_service(void) #endif } } + +static void emit_wifi_roaming_failure(struct connman_service *service, + enum connman_service_state new_state) +{ + 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: + case CONNMAN_SERVICE_STATE_READY: + case CONNMAN_SERVICE_STATE_ONLINE: + 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 static const char *get_dbus_sender(struct connman_service *service) @@ -9215,6 +9384,15 @@ static int service_indicate_state(struct connman_service *service) break; case CONNMAN_SERVICE_STATE_IDLE: + if (old_state == CONNMAN_SERVICE_STATE_FAILURE && + service->connect_reason == + CONNMAN_SERVICE_CONNECT_REASON_NATIVE && + service->error == + CONNMAN_SERVICE_ERROR_INVALID_KEY) { + __connman_service_clear_error(service); + service_complete(service); + } + if (old_state != CONNMAN_SERVICE_STATE_DISCONNECT) __connman_service_disconnect(service); @@ -9257,12 +9435,12 @@ static int service_indicate_state(struct connman_service *service) service->new_service = false; - default_changed(); - def_service = connman_service_get_default(); service_update_preferred_order(def_service, service, new_state); + default_changed(); + __connman_service_set_favorite(service, true); reply_pending(service, 0); @@ -9324,7 +9502,7 @@ static int service_indicate_state(struct connman_service *service) #endif #if defined TIZEN_EXT - if (service->type == CONNMAN_SERVICE_TYPE_WIFI) + if (TIZEN_INS_ENABLED && service->type == CONNMAN_SERVICE_TYPE_WIFI) connman_service_set_internet_connection(service, true); #endif break; @@ -9353,6 +9531,8 @@ static int service_indicate_state(struct connman_service *service) proxy_changed(service); #if defined TIZEN_EXT } + + emit_wifi_roaming_failure(service, new_state); #endif /* @@ -9371,7 +9551,8 @@ static int service_indicate_state(struct connman_service *service) service->order = 5; __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO); #endif - if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) { + if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER || + service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_NATIVE) { connman_agent_report_error(service, service->path, error2string(service->error), report_error_cb, @@ -9393,55 +9574,7 @@ static int service_indicate_state(struct connman_service *service) #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; - } - } - } + emit_wifi_roaming_failure(service, new_state); #endif __connman_connection_update_gateway(); @@ -9475,6 +9608,20 @@ int __connman_service_indicate_error(struct connman_service *service, if (service->state == CONNMAN_SERVICE_STATE_FAILURE) return -EALREADY; +#if defined TIZEN_EXT + /* + * change connman_service_error type + * from CONNMAN_SERVICE_ERROR_AUTH_FAILED to CONNMAN_SERVICE_ERROR_INVALID_KEY + * in case of SAE security type. + */ + if (error == CONNMAN_SERVICE_ERROR_AUTH_FAILED && + service->security == CONNMAN_SERVICE_SECURITY_SAE) { + DBG("SAE security auth failed, set error to invalid-key and ignore the service"); + error = CONNMAN_SERVICE_ERROR_INVALID_KEY; + __connman_service_set_ignore(service, true); + } +#endif + set_error(service, error); /* default internet service: fix not cleared if pdp activation*/ @@ -10124,6 +10271,10 @@ static int service_connect(struct connman_service *service) return -ENOKEY; break; +#if defined TIZEN_EXT + default: + break; +#endif } break; } @@ -10150,6 +10301,10 @@ static int service_connect(struct connman_service *service) case CONNMAN_SERVICE_SECURITY_8021X: prepare_8021x(service); break; +#if defined TIZEN_EXT + default: + break; +#endif } if (__connman_stats_service_register(service) == 0) { @@ -10185,6 +10340,7 @@ static int service_connect(struct connman_service *service) int __connman_service_connect(struct connman_service *service, enum connman_service_connect_reason reason) { + int index; int err; DBG("service %p state %s connect reason %s -> %s", @@ -10254,7 +10410,8 @@ int __connman_service_connect(struct connman_service *service, service->provider) connman_provider_disconnect(service->provider); - if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER) { + if (reason == CONNMAN_SERVICE_CONNECT_REASON_USER || + reason == CONNMAN_SERVICE_CONNECT_REASON_NATIVE) { if (err == -ENOKEY || err == -EPERM) { DBusMessage *pending = NULL; const char *dbus_sender = get_dbus_sender(service); @@ -10277,6 +10434,13 @@ int __connman_service_connect(struct connman_service *service, if (service->hidden && err != -EINPROGRESS) service->pending = pending; + if (err == -EINPROGRESS) { + index = __connman_service_get_index(service); + g_hash_table_replace(passphrase_requested, + GINT_TO_POINTER(index), + GINT_TO_POINTER(true)); + } + return err; } } @@ -10475,6 +10639,63 @@ static struct connman_service *service_get(const char *identifier) return service; } +#if defined TIZEN_EXT +static void service_load_wpa_passphrase(struct connman_service *service) +{ + char *identifier; + char *ptr; + GKeyFile *keyfile; + bool favorite; + bool autoconnect; + char *passphrase; + + if (service->security != CONNMAN_SERVICE_SECURITY_SAE) + return; + + if (service->passphrase) + return; + + if (!service->identifier) + return; + + identifier = g_strdup(service->identifier); + if (!identifier) + return; + + ptr = strstr(identifier, "_sae"); + if (!ptr) { + g_free(identifier); + return; + } + + memcpy(ptr, "_psk", strlen("_psk")); + + keyfile = connman_storage_load_service(identifier); + if (!keyfile) { + g_free(identifier); + return; + } + + favorite = g_key_file_get_boolean(keyfile, identifier, "Favorite", NULL); + autoconnect = g_key_file_get_boolean(keyfile, identifier, "AutoConnect", NULL); + + if (!favorite || !autoconnect) { + g_free(identifier); + return; + } + + passphrase = g_key_file_get_string(keyfile, identifier, "Passphrase", NULL); + if (passphrase) { + service->passphrase = g_strdup(passphrase); + service->favorite = favorite; + service->autoconnect = autoconnect; + } + + g_free(identifier); + g_free(passphrase); +} +#endif + static int service_register(struct connman_service *service) { #if defined TIZEN_EXT @@ -10493,16 +10714,21 @@ static int service_register(struct connman_service *service) #if defined TIZEN_EXT int ret; service_load(service); - ret = service_ext_load(service); - if (ret == -ERANGE) - service_ext_save(service); + service_load_wpa_passphrase(service); + + if (TIZEN_INS_ENABLED) { + 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 +#endif /* defined TIZEN_EXT */ g_dbus_register_interface(connection, service->path, CONNMAN_SERVICE_INTERFACE, @@ -11061,8 +11287,19 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne if (__connman_network_get_weakness(network)) return service; + index = connman_network_get_index(network); + if (service->path) { update_from_network(service, network); + + if (service->ipconfig_ipv4) + __connman_ipconfig_set_index(service->ipconfig_ipv4, + index); + + if (service->ipconfig_ipv6) + __connman_ipconfig_set_index(service->ipconfig_ipv6, + index); + __connman_connection_update_gateway(); return service; } @@ -11093,14 +11330,16 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne update_from_network(service, network); - index = connman_network_get_index(network); - if (!service->ipconfig_ipv4) service->ipconfig_ipv4 = create_ip4config(service, index, CONNMAN_IPCONFIG_METHOD_DHCP); + else + __connman_ipconfig_set_index(service->ipconfig_ipv4, index); if (!service->ipconfig_ipv6) service->ipconfig_ipv6 = create_ip6config(service, index); + else + __connman_ipconfig_set_index(service->ipconfig_ipv6, index); service_register(service); service_schedule_added(service); @@ -11145,9 +11384,6 @@ void __connman_service_update_from_network(struct connman_network *network) bool roaming; const char *name; bool stats_enable; -#if defined TIZEN_EXT - bool need_save = false; -#endif service = connman_service_lookup_from_network(network); if (!service) @@ -11205,12 +11441,17 @@ roaming: 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; + if (TIZEN_INS_ENABLED) { + bool need_save = false; + + need_save |= update_last_connected_bssid(service); + need_save |= update_assoc_reject(service); + + if (need_save) { + g_get_current_time((GTimeVal *)&service->modified); + service_ext_save(service); + need_sort = true; + } } #endif @@ -11396,7 +11637,7 @@ static struct connman_agent_driver agent_driver = { .context_unref = agent_context_unref, }; -#if defined TIZEN_EXT && defined TIZEN_EXT_INS +#if defined TIZEN_EXT static void ins_setting_init(void) { int i; @@ -11459,7 +11700,7 @@ static void ins_setting_init(void) * 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; + ins_settings.signal_level3_24ghz = connman_setting_get_int("INSSignalLevel3_2_4GHz") + 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); @@ -11487,7 +11728,7 @@ static void ins_setting_init(void) 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 */ +#endif /* defined TIZEN_EXT */ int __connman_service_init(void) { @@ -11509,6 +11750,8 @@ int __connman_service_init(void) service_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, service_free); + passphrase_requested = g_hash_table_new(g_direct_hash, g_direct_equal); + services_notify = g_new0(struct _services_notify, 1); services_notify->remove = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL); @@ -11516,9 +11759,10 @@ int __connman_service_init(void) remove_unprovisioned_services(); -#if defined TIZEN_EXT && defined TIZEN_EXT_INS - ins_setting_init(); -#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ +#if defined TIZEN_EXT + if (TIZEN_INS_ENABLED) + ins_setting_init(); +#endif /* defined TIZEN_EXT */ return 0; } @@ -11545,6 +11789,9 @@ void __connman_service_cleanup(void) g_hash_table_destroy(service_hash); service_hash = NULL; + g_hash_table_destroy(passphrase_requested); + passphrase_requested = NULL; + g_slist_free(counter_list); counter_list = NULL; diff --git a/src/storage.c b/src/storage.c index fb6dc149..67f6036b 100755 --- a/src/storage.c +++ b/src/storage.c @@ -35,9 +35,9 @@ #define SETTINGS "settings" #define DEFAULT "default.profile" -#if defined TIZEN_EXT && defined TIZEN_EXT_INS +#if defined TIZEN_EXT #define INS_SETTINGS "settings.ins" -#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ +#endif /* defined TIZEN_EXT */ #define MODE (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | \ S_IXGRP | S_IROTH | S_IXOTH) @@ -133,7 +133,7 @@ int __connman_storage_save_global(GKeyFile *keyfile) return ret; } -#if defined TIZEN_EXT && defined TIZEN_EXT_INS +#if defined TIZEN_EXT GKeyFile *__connman_storage_load_ins(void) { gchar *pathname; @@ -165,7 +165,7 @@ int __connman_storage_save_ins(GKeyFile *keyfile) return ret; } -#endif /* defined TIZEN_EXT && defined TIZEN_EXT_INS */ +#endif /* defined TIZEN_EXT */ void __connman_storage_delete_global(void) { diff --git a/src/technology.c b/src/technology.c index 2ba02e2d..d21d790f 100644 --- a/src/technology.c +++ b/src/technology.c @@ -84,6 +84,7 @@ struct connman_technology { */ char *tethering_ident; char *tethering_passphrase; + int tethering_freq; bool enable_persistent; /* Save the tech state */ @@ -235,6 +236,12 @@ static void technology_save(struct connman_technology *technology) technology->random_mac_lifetime); } #endif /* TIZEN_EXT */ + if (technology->tethering_freq == 0) + technology->tethering_freq = 2412; + + g_key_file_set_integer(keyfile, identifier, + "Tethering.Freq", + technology->tethering_freq); done: g_free(identifier); @@ -308,8 +315,7 @@ static int set_tethering(struct connman_technology *technology, if (!driver || !driver->set_tethering) continue; - err = driver->set_tethering(technology, ident, passphrase, - bridge, enabled); + err = driver->set_tethering(technology, bridge, enabled); if (result == -EINPROGRESS) continue; @@ -400,25 +406,32 @@ enum connman_service_type connman_technology_get_type return technology->type; } -bool connman_technology_get_wifi_tethering(const char **ssid, - const char **psk) +bool connman_technology_get_wifi_tethering(const struct connman_technology *technology, + const char **ssid, const char **psk, + int *freq) { - struct connman_technology *technology; + bool force = true; if (!ssid || !psk) return false; *ssid = *psk = NULL; - technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI); + /* Workaround for the neard plugin */ + if (!technology) { + technology = technology_find(CONNMAN_SERVICE_TYPE_WIFI); + force = false; + } + if (!technology) return false; - if (!technology->tethering) + if (!force && !technology->tethering) return false; *ssid = technology->tethering_ident; *psk = technology->tethering_passphrase; + *freq = technology->tethering_freq; return true; } @@ -540,6 +553,9 @@ static void technology_load(struct connman_technology *technology) } #endif /* TIZEN_EXT */ + technology->tethering_freq = g_key_file_get_integer(keyfile, + identifier, "Tethering.Freq", NULL); + done: g_free(identifier); @@ -743,6 +759,9 @@ static void append_properties(DBusMessageIter *iter, DBUS_TYPE_STRING, &technology->regdom); #endif + connman_dbus_dict_append_basic(&dict, "TetheringFreq", + DBUS_TYPE_INT32, + &technology->tethering_freq); connman_dbus_dict_close(iter, &dict); } @@ -1440,6 +1459,27 @@ static DBusMessage *set_property(DBusConnection *conn, DBUS_TYPE_STRING, &technology->tethering_passphrase); } + } else if (g_str_equal(name, "TetheringFreq")) { + dbus_int32_t freq; + + if (type != DBUS_TYPE_INT32) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value, &freq); + + if (technology->type != CONNMAN_SERVICE_TYPE_WIFI) + return __connman_error_not_supported(msg); + + if (freq >= 0) { + technology->tethering_freq = freq; + technology_save(technology); + + connman_dbus_property_changed_basic(technology->path, + CONNMAN_TECHNOLOGY_INTERFACE, + "TetheringFreq", + DBUS_TYPE_INT32, + &technology->tethering_freq); + } } else if (g_str_equal(name, "Powered")) { dbus_bool_t enable; @@ -1675,6 +1715,19 @@ static void __connman_technology_notify_device_detected( DBG("Successfuly sent DeviceDetected signal"); } +void __connman_technology_notify_device_detected_by_device( + struct connman_device *device, const char *ifname, bool val) +{ + struct connman_technology *technology; + enum connman_service_type type; + + type = __connman_device_get_service_type(device); + + technology = technology_find(type); + if (technology) + __connman_technology_notify_device_detected(technology, ifname, val); +} + void __connman_technology_notify_roaming_state(const char *ifname, const char *state, const char *cur_bssid, const char *dst_bssid) { @@ -2064,6 +2117,41 @@ static DBusMessage *get_5ghz_supported(DBusConnection *conn, DBusMessage *msg, v return reply; } +static DBusMessage *get_6ghz_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_6ghz_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; @@ -2842,6 +2930,8 @@ static const GDBusMethodTable technology_methods[] = { get_scan_state) }, { GDBUS_METHOD("Get5GhzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }), get_5ghz_supported) }, + { GDBUS_METHOD("Get6GHzSupported", NULL, GDBUS_ARGS({ "supported", "a{sv}" }), + get_6ghz_supported) }, { GDBUS_METHOD("GetMaxScanSsid", NULL, GDBUS_ARGS({ "maxscanssid", "a{sv}" }), get_max_scan_ssid) }, { GDBUS_ASYNC_METHOD("SetDevicePower", @@ -2925,7 +3015,9 @@ static void technology_put(struct connman_technology *technology) g_slist_delete_link(technology->driver_list, technology->driver_list); } - +#ifdef TIZEN_EXT + __connman_technology_notify_device_detected(technology, "", false); +#endif technology_list = g_slist_remove(technology_list, technology); technology_dbus_unregister(technology); @@ -3345,9 +3437,6 @@ int __connman_technology_remove_device(struct connman_device *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) diff --git a/src/timeserver.c b/src/timeserver.c index b2707fad..2df609f3 100755 --- a/src/timeserver.c +++ b/src/timeserver.c @@ -206,7 +206,12 @@ static void sync_next(void) return; } #if defined TIZEN_EXT - if (!simplified_log) + if (ts_current[0] == '\0') { + DBG("current time server is empty. ignore next time server.."); + return; + } + + if (!simplified_log) #endif DBG("Resolving timeserver %s", ts_current); #if defined TIZEN_EXT diff --git a/src/wispr.c b/src/wispr.c index fb101a1d..f4dcb73e 100755 --- a/src/wispr.c +++ b/src/wispr.c @@ -30,9 +30,6 @@ #include "connman.h" -#define STATUS_URL_IPV4 "http://ipv4.connman.net/online/status.html" -#define STATUS_URL_IPV6 "http://ipv6.connman.net/online/status.html" - struct connman_wispr_message { bool has_error; const char *current_element; @@ -96,6 +93,8 @@ static bool wispr_portal_web_result(GWebResult *result, gpointer user_data); static GHashTable *wispr_portal_list = NULL; +static char *online_check_ipv4_url = NULL; +static char *online_check_ipv6_url = NULL; static bool enable_online_to_ready_transition = false; static void connman_wispr_message_init(struct connman_wispr_message *msg) @@ -426,7 +425,8 @@ static void wispr_portal_error(struct connman_wispr_portal_context *wp_context) wp_context->wispr_result = CONNMAN_WISPR_RESULT_FAILED; #if defined TIZEN_EXT - connman_service_set_internet_connection(wp_context->service, false); + if (TIZEN_INS_ENABLED) + connman_service_set_internet_connection(wp_context->service, false); #endif } @@ -937,10 +937,10 @@ static int wispr_portal_detect(struct connman_wispr_portal_context *wp_context) if (wp_context->type == CONNMAN_IPCONFIG_TYPE_IPV4) { g_web_set_address_family(wp_context->web, AF_INET); - wp_context->status_url = STATUS_URL_IPV4; + wp_context->status_url = online_check_ipv4_url; } else { g_web_set_address_family(wp_context->web, AF_INET6); - wp_context->status_url = STATUS_URL_IPV6; + wp_context->status_url = online_check_ipv6_url; } for (i = 0; nameservers[i]; i++) @@ -1047,17 +1047,11 @@ void __connman_wispr_stop(struct connman_service *service) 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)); - } + if ((wispr_portal->ipv4_context && + service == wispr_portal->ipv4_context->service) || + (wispr_portal->ipv6_context && + service == wispr_portal->ipv6_context->service)) + g_hash_table_remove(wispr_portal_list, GINT_TO_POINTER(index)); } int __connman_wispr_init(void) @@ -1068,6 +1062,11 @@ int __connman_wispr_init(void) g_direct_equal, NULL, free_connman_wispr_portal); + online_check_ipv4_url = + connman_setting_get_string("OnlineCheckIPv4URL"); + online_check_ipv6_url = + connman_setting_get_string("OnlineCheckIPv6URL"); + enable_online_to_ready_transition = connman_setting_get_bool("EnableOnlineToReadyTransition"); diff --git a/tools/ip6tables-test.c b/tools/ip6tables-test.c index 41e842dd..a52f4af0 100644 --- a/tools/ip6tables-test.c +++ b/tools/ip6tables-test.c @@ -45,7 +45,7 @@ int main(int argc, char *argv[]) { enum iptables_command cmd = IPTABLES_COMMAND_UNKNOWN; char *table = NULL, *chain = NULL, *rule = NULL, *tmp; - int err, c, i; + int err = -EINVAL, c, i; opterr = 0; diff --git a/tools/iptables-test.c b/tools/iptables-test.c index e9b7cb22..f9d091eb 100755 --- a/tools/iptables-test.c +++ b/tools/iptables-test.c @@ -44,7 +44,7 @@ int main(int argc, char *argv[]) { enum iptables_command cmd = IPTABLES_COMMAND_UNKNOWN; char *table = NULL, *chain = NULL, *rule = NULL, *tmp; - int err, c, i; + int err = -EINVAL, c, i; opterr = 0; diff --git a/unit/test-iptables.c b/unit/test-iptables.c index cd261d05..f08736ea 100644 --- a/unit/test-iptables.c +++ b/unit/test-iptables.c @@ -69,13 +69,13 @@ static void set_test_config(enum configtype type) #define IP6T_SO_GET_INFO (IP6T_BASE_CTL) #define IP6T_SO_GET_ENTRIES (IP6T_BASE_CTL + 1) -int xt_match_parse(int c, char **argv, int invert, unsigned int *flags, +int static xt_match_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { return 0; } -int xt_target_parse(int c, char **argv, int invert, unsigned int *flags, +int static xt_target_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_target **targetinfo) { return 0; diff --git a/vpn/plugins/l2tp.c b/vpn/plugins/l2tp.c index 1e4fcd1f..ee40dd72 100755 --- a/vpn/plugins/l2tp.c +++ b/vpn/plugins/l2tp.c @@ -4,6 +4,7 @@ * * Copyright (C) 2010,2013 BMW Car IT GmbH. * Copyright (C) 2012-2013 Intel Corporation. All rights reserved. + * Copyright (C) 2019-2021 Jolla Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -121,12 +122,40 @@ struct { static DBusConnection *connection; struct l2tp_private_data { + struct vpn_provider *provider; struct connman_task *task; char *if_name; vpn_provider_connect_cb_t cb; void *user_data; }; +static void l2tp_connect_done(struct l2tp_private_data *data, int err) +{ + vpn_provider_connect_cb_t cb; + void *user_data; + + if (!data || !data->cb) + return; + + /* Ensure that callback is called only once */ + cb = data->cb; + user_data = data->user_data; + data->cb = NULL; + data->user_data = NULL; + cb(data->provider, user_data, err); +} + +static void free_private_data(struct l2tp_private_data *data) +{ + if (vpn_provider_get_plugin_data(data->provider) == data) + vpn_provider_set_plugin_data(data->provider, NULL); + + l2tp_connect_done(data, EIO); + vpn_provider_unref(data->provider); + g_free(data->if_name); + g_free(data); +} + static DBusMessage *l2tp_get_sec(struct connman_task *task, DBusMessage *msg, void *user_data) { @@ -164,6 +193,9 @@ static int l2tp_notify(DBusMessage *msg, struct vpn_provider *provider) char *addressv4 = NULL, *netmask = NULL, *gateway = NULL; char *ifname = NULL, *nameservers = NULL; struct connman_ipaddress *ipaddress = NULL; + struct l2tp_private_data *data; + + data = vpn_provider_get_plugin_data(provider); dbus_message_iter_init(msg, &iter); @@ -182,11 +214,22 @@ static int l2tp_notify(DBusMessage *msg, struct vpn_provider *provider) vpn_provider_set_string_hide_value(provider, "L2TP.Password", NULL); + l2tp_connect_done(data, EACCES); return VPN_STATE_AUTH_FAILURE; } - if (strcmp(reason, "connect")) + if (strcmp(reason, "connect")) { + l2tp_connect_done(data, EIO); + + /* + * Stop the task to avoid potential looping of this state when + * authentication fails. + */ + if (data && data->task) + connman_task_stop(data->task); + return VPN_STATE_DISCONNECT; + } dbus_message_iter_recurse(&iter, &dict); @@ -257,6 +300,8 @@ static int l2tp_notify(DBusMessage *msg, struct vpn_provider *provider) g_free(nameservers); connman_ipaddress_free(ipaddress); + l2tp_connect_done(data, 0); + return VPN_STATE_CONNECT; } @@ -476,9 +521,10 @@ static int l2tp_write_config(struct vpn_provider *provider, static void l2tp_died(struct connman_task *task, int exit_code, void *user_data) { + struct l2tp_private_data *data = user_data; char *conf_file; - vpn_died(task, exit_code, user_data); + vpn_died(task, exit_code, data->provider); conf_file = g_strdup_printf(VPN_STATEDIR "/connman-xl2tpd.conf"); unlink(conf_file); @@ -487,6 +533,8 @@ static void l2tp_died(struct connman_task *task, int exit_code, void *user_data) conf_file = g_strdup_printf(VPN_STATEDIR "/connman-ppp-option.conf"); unlink(conf_file); g_free(conf_file); + + free_private_data(data); } struct request_input_reply { @@ -646,12 +694,12 @@ static int request_input(struct vpn_provider *provider, return -EINPROGRESS; } -static int run_connect(struct vpn_provider *provider, - struct connman_task *task, const char *if_name, - vpn_provider_connect_cb_t cb, void *user_data, +static int run_connect(struct l2tp_private_data *data, const char *username, const char *password) { - char *l2tp_name, *pppd_name; + struct vpn_provider *provider = data->provider; + struct connman_task *task = data->task; + char *l2tp_name, *ctrl_name, *pppd_name; int l2tp_fd, pppd_fd; int err; @@ -674,12 +722,24 @@ static int run_connect(struct vpn_provider *provider, goto done; } - pppd_name = g_strdup_printf(VPN_STATEDIR "/connman-ppp-option.conf"); + ctrl_name = g_strconcat(VPN_STATEDIR, "/connman-xl2tpd-control", NULL); + + if (mkfifo(ctrl_name, S_IRUSR|S_IWUSR) != 0 && errno != EEXIST) { + connman_error("Error creating xl2tp control pipe"); + g_free(l2tp_name); + g_free(ctrl_name); + close(l2tp_fd); + err = -EIO; + goto done; + } + + pppd_name = g_strconcat(VPN_STATEDIR, "/connman-ppp-option.conf", NULL); pppd_fd = open(pppd_name, O_RDWR|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR); if (pppd_fd < 0) { connman_error("Error writing pppd config"); g_free(l2tp_name); + g_free(ctrl_name); g_free(pppd_name); close(l2tp_fd); err = -EIO; @@ -691,34 +751,28 @@ static int run_connect(struct vpn_provider *provider, write_pppd_option(provider, pppd_fd); connman_task_add_argument(task, "-D", NULL); + connman_task_add_argument(task, "-C", ctrl_name); connman_task_add_argument(task, "-c", l2tp_name); g_free(l2tp_name); + g_free(ctrl_name); g_free(pppd_name); close(l2tp_fd); close(pppd_fd); - err = connman_task_run(task, l2tp_died, provider, - NULL, NULL, NULL); + err = connman_task_run(task, l2tp_died, data, NULL, NULL, NULL); if (err < 0) { connman_error("l2tp failed to start"); err = -EIO; - goto done; } done: - if (cb) - cb(provider, user_data, err); + if (err) + l2tp_connect_done(data, -err); return err; } -static void free_private_data(struct l2tp_private_data *data) -{ - g_free(data->if_name); - g_free(data); -} - static void request_input_cb(struct vpn_provider *provider, const char *username, const char *password, @@ -736,10 +790,7 @@ static void request_input_cb(struct vpn_provider *provider, vpn_provider_set_string_hide_value(provider, "L2TP.Password", password); - run_connect(provider, data->task, data->if_name, data->cb, - data->user_data, username, password); - - free_private_data(data); + run_connect(data, username, password); } static int l2tp_connect(struct vpn_provider *provider, @@ -747,9 +798,21 @@ static int l2tp_connect(struct vpn_provider *provider, vpn_provider_connect_cb_t cb, const char *dbus_sender, void *user_data) { + struct l2tp_private_data *data; const char *username, *password; int err; + data = g_try_new0(struct l2tp_private_data, 1); + if (!data) + return -ENOMEM; + + data->provider = vpn_provider_ref(provider); + data->task = task; + data->if_name = g_strdup(if_name); + data->cb = cb; + data->user_data = user_data; + vpn_provider_set_plugin_data(provider, data); + if (connman_task_set_notify(task, "getsec", l2tp_get_sec, provider) != 0) { err = -ENOMEM; @@ -762,33 +825,19 @@ static int l2tp_connect(struct vpn_provider *provider, DBG("user %s password %p", username, password); if (!username || !*username || !password || !*password) { - struct l2tp_private_data *data; - - data = g_try_new0(struct l2tp_private_data, 1); - if (!data) - return -ENOMEM; - - data->task = task; - data->if_name = g_strdup(if_name); - data->cb = cb; - data->user_data = user_data; - err = request_input(provider, request_input_cb, dbus_sender, data); - if (err != -EINPROGRESS) { - free_private_data(data); - goto done; - } + if (err != -EINPROGRESS) + goto error; + return err; } -done: - return run_connect(provider, task, if_name, cb, user_data, - username, password); + return run_connect(data, username, password); error: - if (cb) - cb(provider, user_data, err); + l2tp_connect_done(data, -err); + free_private_data(data); return err; } diff --git a/vpn/plugins/openconnect.c b/vpn/plugins/openconnect.c index fc6ceff0..fb63a1a3 100755 --- a/vpn/plugins/openconnect.c +++ b/vpn/plugins/openconnect.c @@ -110,6 +110,7 @@ struct oc_private_data { GIOChannel *err_ch; enum oc_connect_type connect_type; bool tried_passphrase; + bool group_set; }; typedef void (*request_input_reply_cb_t) (DBusMessage *reply, @@ -473,6 +474,7 @@ static void clear_provider_credentials(struct vpn_provider *provider, const char *keys[] = { "OpenConnect.PKCSPassword", "OpenConnect.Username", "OpenConnect.Password", + "OpenConnect.SecondPassword", "OpenConnect.Cookie", NULL }; @@ -794,13 +796,46 @@ static gboolean process_auth_form(void *user_data) { struct process_form_data *form_data = user_data; struct oc_private_data *data = form_data->data; + struct oc_form_opt_select *authgroup_opt; struct oc_form_opt *opt; const char *password; + const char *group; + int i; g_mutex_lock(&form_data->mutex); DBG(""); + /* + * Special handling for "GROUP:" field, if present. + * Different group selections can make other fields disappear/appear + */ + if (form_data->form->authgroup_opt) { + group = vpn_provider_get_string(data->provider, "OpenConnect.Group"); + authgroup_opt = form_data->form->authgroup_opt; + + if (group && !data->group_set) { + for (i = 0; i < authgroup_opt->nr_choices; i++) { + struct oc_choice *choice = authgroup_opt->choices[i]; + + if (!strcmp(group, choice->label)) { + DBG("Switching to auth group: %s", group); + openconnect_set_option_value(&authgroup_opt->form, + choice->name); + data->group_set = true; + form_data->status = OC_FORM_RESULT_NEWGROUP; + goto out; + } + } + + connman_warn("Group choice %s not present", group); + data->err = -EACCES; + clear_provider_credentials(data->provider, true); + form_data->status = OC_FORM_RESULT_ERR; + goto out; + } + } + switch (data->connect_type) { case OC_CONNECT_USERPASS: case OC_CONNECT_COOKIE_WITH_USERPASS: @@ -872,12 +907,21 @@ static gboolean process_auth_form(void *user_data) "OpenConnect.Username"); if (user) opt->_value = strdup(user); - } else if (opt->type == OC_FORM_OPT_PASSWORD) { + } else if (opt->type == OC_FORM_OPT_PASSWORD && + g_str_has_prefix(opt->name, "password")) { + const char *pass = vpn_provider_get_string( data->provider, "OpenConnect.Password"); if (pass) opt->_value = strdup(pass); + } else if (opt->type == OC_FORM_OPT_PASSWORD && + g_str_has_prefix(opt->name, "secondary_password")) { + const char *pass = vpn_provider_get_string( + data->provider, + "OpenConnect.SecondPassword"); + if (pass) + opt->_value = strdup(pass); } } @@ -1201,6 +1245,7 @@ static void request_input_credentials_reply(DBusMessage *reply, void *user_data) const char *vpnhost = NULL; const char *username = NULL; const char *password = NULL; + const char *second_password = NULL; const char *pkcspassword = NULL; const char *key; DBusMessageIter iter, dict; @@ -1298,6 +1343,19 @@ static void request_input_credentials_reply(DBusMessage *reply, void *user_data) dbus_message_iter_get_basic(&value, &password); vpn_provider_set_string_hide_value(data->provider, "OpenConnect.Password", password); + } else if (g_str_equal(key, "OpenConnect.SecondPassword")) { + dbus_message_iter_next(&entry); + if (dbus_message_iter_get_arg_type(&entry) + != DBUS_TYPE_VARIANT) + break; + dbus_message_iter_recurse(&entry, &value); + if (dbus_message_iter_get_arg_type(&value) + != DBUS_TYPE_STRING) + break; + dbus_message_iter_get_basic(&value, &second_password); + vpn_provider_set_string_hide_value(data->provider, + "OpenConnect.SecondPassword", + second_password); } else if (g_str_equal(key, "OpenConnect.PKCSPassword")) { dbus_message_iter_next(&entry); if (dbus_message_iter_get_arg_type(&entry) @@ -1374,6 +1432,7 @@ static int request_input_credentials_full( DBusMessageIter dict; int err; void *agent; + bool use_second_password = false; if (!data || !cb) return -ESRCH; @@ -1440,6 +1499,16 @@ static int request_input_credentials_full( username = vpn_provider_get_string(data->provider, "OpenConnect.Username"); vpn_agent_append_user_info(&dict, data->provider, username); + + use_second_password = vpn_provider_get_boolean(data->provider, + "OpenConnect.UseSecondPassword", + false); + + if (use_second_password) + request_input_append_to_dict(data->provider, &dict, + request_input_append_password, + "OpenConnect.SecondPassword"); + break; case OC_CONNECT_PUBLICKEY: return -EINVAL; @@ -1520,8 +1589,10 @@ static int oc_connect(struct vpn_provider *provider, const char *certificate; const char *username; const char *password; + const char *second_password = NULL; const char *private_key; int err; + bool use_second_password = false; connman_info("provider %p task %p", provider, task); @@ -1551,8 +1622,18 @@ static int oc_connect(struct vpn_provider *provider, "OpenConnect.Username"); password = vpn_provider_get_string(provider, "OpenConnect.Password"); + + use_second_password = vpn_provider_get_boolean(provider, + "OpenConnect.UseSecondPassword", + false); + + if (use_second_password) + second_password = vpn_provider_get_string(provider, + "OpenConnect.SecondPassword"); + if (!username || !password || !g_strcmp0(username, "-") || - !g_strcmp0(password, "-")) + !g_strcmp0(password, "-") || + (use_second_password && !second_password)) goto request_input; break; diff --git a/vpn/plugins/openvpn.c b/vpn/plugins/openvpn.c index 8c8d3162..5ab5c5c4 100755 --- a/vpn/plugins/openvpn.c +++ b/vpn/plugins/openvpn.c @@ -56,36 +56,48 @@ static DBusConnection *connection; +enum opt_type { + OPT_NONE = 0, + OPT_STRING = 1, + OPT_BOOL = 2, +}; + struct { - const char *cm_opt; - const char *ov_opt; - char has_value; + const char *cm_opt; + const char *ov_opt; + const char *ov_opt_to_null; + enum opt_type opt_type; } ov_options[] = { - { "Host", "--remote", 1 }, - { "OpenVPN.CACert", "--ca", 1 }, - { "OpenVPN.Cert", "--cert", 1 }, - { "OpenVPN.Key", "--key", 1 }, - { "OpenVPN.MTU", "--tun-mtu", 1 }, - { "OpenVPN.NSCertType", "--ns-cert-type", 1 }, - { "OpenVPN.Proto", "--proto", 1 }, - { "OpenVPN.Port", "--port", 1 }, - { "OpenVPN.AuthUserPass", "--auth-user-pass", 1 }, - { "OpenVPN.AskPass", "--askpass", 1 }, - { "OpenVPN.AuthNoCache", "--auth-nocache", 0 }, - { "OpenVPN.TLSRemote", "--tls-remote", 1 }, - { "OpenVPN.TLSAuth", NULL, 1 }, - { "OpenVPN.TLSAuthDir", NULL, 1 }, - { "OpenVPN.TLSCipher", "--tls-cipher", 1}, - { "OpenVPN.Cipher", "--cipher", 1 }, - { "OpenVPN.Auth", "--auth", 1 }, - { "OpenVPN.CompLZO", "--comp-lzo", 0 }, - { "OpenVPN.RemoteCertTls", "--remote-cert-tls", 1 }, - { "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}, + { "Host", "--remote", NULL, OPT_STRING}, + { "OpenVPN.CACert", "--ca", NULL, OPT_STRING}, + { "OpenVPN.Cert", "--cert", NULL, OPT_STRING}, + { "OpenVPN.Key", "--key", NULL, OPT_STRING}, + { "OpenVPN.MTU", "--tun-mtu", NULL, OPT_STRING}, + { "OpenVPN.NSCertType", "--ns-cert-type", NULL, OPT_STRING}, + { "OpenVPN.Proto", "--proto", NULL, OPT_STRING}, + { "OpenVPN.Port", "--port", NULL, OPT_STRING}, + /* + * If the AuthUserPass option is "-", provide the input via management + * interface. To facilitate this set the option as NULL. + */ + { "OpenVPN.AuthUserPass", "--auth-user-pass", "-", OPT_STRING}, + { "OpenVPN.AskPass", "--askpass", NULL, OPT_STRING}, + { "OpenVPN.AuthNoCache", "--auth-nocache", NULL, OPT_BOOL}, + { "OpenVPN.TLSRemote", "--tls-remote", NULL, OPT_STRING}, + { "OpenVPN.TLSAuth", NULL, NULL, OPT_NONE}, + { "OpenVPN.TLSCipher", "--tls-cipher", NULL, OPT_STRING}, + { "OpenVPN.TLSAuthDir", NULL, NULL, OPT_NONE}, + { "OpenVPN.Cipher", "--cipher", NULL, OPT_STRING}, + { "OpenVPN.Auth", "--auth", NULL, OPT_STRING}, + /* Is set to adaptive by default if value is omitted */ + { "OpenVPN.CompLZO", "--comp-lzo", NULL, OPT_STRING}, + { "OpenVPN.RemoteCertTls", "--remote-cert-tls", NULL, OPT_STRING}, + { "OpenVPN.ConfigFile", "--config", NULL, OPT_STRING}, + { "OpenVPN.DeviceType", NULL, NULL, OPT_NONE}, + { "OpenVPN.Verb", "--verb", NULL, OPT_STRING}, + { "OpenVPN.Ping", "--ping", NULL, OPT_STRING}, + { "OpenVPN.PingExit", "--ping-exit", NULL, OPT_STRING}, + { "OpenVPN.RemapUsr1", "--remap-usr1", NULL, OPT_STRING}, }; struct ov_private_data { @@ -362,29 +374,49 @@ static int ov_save(struct vpn_provider *provider, GKeyFile *keyfile) static int task_append_config_data(struct vpn_provider *provider, struct connman_task *task) { - const char *option; int i; for (i = 0; i < (int)ARRAY_SIZE(ov_options); i++) { - if (!ov_options[i].ov_opt) - continue; + const char *ov_opt = ov_options[i].ov_opt; + const char *cm_opt = ov_options[i].cm_opt; + const char *option = NULL; + const char *opt_to_null; - option = vpn_provider_get_string(provider, - ov_options[i].cm_opt); - if (!option) + switch (ov_options[i].opt_type) { + case OPT_NONE: continue; - /* - * If the AuthUserPass option is "-", provide the input - * via management interface - */ - if (!strcmp(ov_options[i].cm_opt, "OpenVPN.AuthUserPass") && - !strcmp(option, "-")) - option = NULL; + case OPT_STRING: + if (!ov_opt) + continue; + + option = vpn_provider_get_string(provider, cm_opt); + /* + * A string option may be used alone without a value + * in which case the default value is used by OpenVPN. + */ + if (!option && !vpn_provider_setting_key_exists( + provider, ov_opt)) + continue; - if (connman_task_add_argument(task, - ov_options[i].ov_opt, - ov_options[i].has_value ? option : NULL) < 0) + opt_to_null = ov_options[i].ov_opt_to_null; + if (opt_to_null && !g_strcmp0(option, opt_to_null)) + option = NULL; + + break; + + case OPT_BOOL: + if (!ov_opt) + continue; + + /* Ignore the boolean toggle if option is disabled. */ + if (!vpn_provider_get_boolean(provider, cm_opt, false)) + continue; + + break; + } + + if (connman_task_add_argument(task, ov_opt, option)) return -EIO; } @@ -1108,6 +1140,15 @@ static int ov_connect(struct vpn_provider *provider, const char *tmpdir; struct ov_private_data *data; + /* + * Explicitly set limit of 10 for authentication errors. This defines + * the authentication error message limit from the server before VPN + * agent is instructed to clear the credentials. This is effective only + * after a successful connection has been made within CONNECT_OK_DIFF + * time. User defined value for "AuthErrorLimit" overrides this. + */ + vpn_provider_set_auth_error_limit(provider, 10); + data = g_try_new0(struct ov_private_data, 1); if (!data) return -ENOMEM; diff --git a/vpn/plugins/pptp.c b/vpn/plugins/pptp.c index 4a704bb1..7274376f 100755 --- a/vpn/plugins/pptp.c +++ b/vpn/plugins/pptp.c @@ -4,6 +4,7 @@ * * Copyright (C) 2010,2013-2014 BMW Car IT GmbH. * Copyright (C) 2012-2013 Intel Corporation. All rights reserved. + * Copyright (C) 2019-2021 Jolla Ltd. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -86,12 +87,40 @@ struct { static DBusConnection *connection; struct pptp_private_data { + struct vpn_provider *provider; struct connman_task *task; char *if_name; vpn_provider_connect_cb_t cb; void *user_data; }; +static void pptp_connect_done(struct pptp_private_data *data, int err) +{ + vpn_provider_connect_cb_t cb; + void *user_data; + + if (!data || !data->cb) + return; + + /* Ensure that callback is called only once */ + cb = data->cb; + user_data = data->user_data; + data->cb = NULL; + data->user_data = NULL; + cb(data->provider, user_data, err); +} + +static void free_private_data(struct pptp_private_data *data) +{ + if (vpn_provider_get_plugin_data(data->provider) == data) + vpn_provider_set_plugin_data(data->provider, NULL); + + pptp_connect_done(data, EIO); + vpn_provider_unref(data->provider); + g_free(data->if_name); + g_free(data); +} + static DBusMessage *pptp_get_sec(struct connman_task *task, DBusMessage *msg, void *user_data) { @@ -125,6 +154,9 @@ static int pptp_notify(DBusMessage *msg, struct vpn_provider *provider) char *addressv4 = NULL, *netmask = NULL, *gateway = NULL; char *ifname = NULL, *nameservers = NULL; struct connman_ipaddress *ipaddress = NULL; + struct pptp_private_data *data; + + data = vpn_provider_get_plugin_data(provider); dbus_message_iter_init(msg, &iter); @@ -143,11 +175,22 @@ static int pptp_notify(DBusMessage *msg, struct vpn_provider *provider) vpn_provider_set_string_hide_value(provider, "PPTP.Password", NULL); + pptp_connect_done(data, EACCES); return VPN_STATE_AUTH_FAILURE; } - if (strcmp(reason, "connect")) + if (strcmp(reason, "connect")) { + pptp_connect_done(data, EIO); + + /* + * Stop the task to avoid potential looping of this state when + * authentication fails. + */ + if (data && data->task) + connman_task_stop(data->task); + return VPN_STATE_DISCONNECT; + } dbus_message_iter_recurse(&iter, &dict); @@ -217,6 +260,7 @@ static int pptp_notify(DBusMessage *msg, struct vpn_provider *provider) g_free(nameservers); connman_ipaddress_free(ipaddress); + pptp_connect_done(data, 0); return VPN_STATE_CONNECT; } @@ -278,6 +322,16 @@ static void pptp_write_bool_option(struct connman_task *task, } } +static void pptp_died(struct connman_task *task, int exit_code, + void *user_data) +{ + struct pptp_private_data *data = user_data; + + vpn_died(task, exit_code, data->provider); + + free_private_data(data); +} + struct request_input_reply { struct vpn_provider *provider; vpn_provider_password_cb_t callback; @@ -435,18 +489,18 @@ static int request_input(struct vpn_provider *provider, return -EINPROGRESS; } -static int run_connect(struct vpn_provider *provider, - struct connman_task *task, const char *if_name, - vpn_provider_connect_cb_t cb, void *user_data, - const char *username, const char *password) +static int run_connect(struct pptp_private_data *data, const char *username, + const char *password) { + struct vpn_provider *provider = data->provider; + struct connman_task *task = data->task; GString *pptp_opt_s; const char *opt_s; const char *host; char *str; int err, i; - if (!username || !password) { + if (!username || !*username || !password || !*password) { DBG("Cannot connect username %s password %p", username, password); err = -EINVAL; @@ -498,27 +552,19 @@ static int run_connect(struct vpn_provider *provider, connman_task_add_argument(task, "plugin", SCRIPTDIR "/libppp-plugin.so"); - err = connman_task_run(task, vpn_died, provider, - NULL, NULL, NULL); + err = connman_task_run(task, pptp_died, data, NULL, NULL, NULL); if (err < 0) { connman_error("pptp failed to start"); err = -EIO; - goto done; } done: - if (cb) - cb(provider, user_data, err); + if (err) + pptp_connect_done(data, -err); return err; } -static void free_private_data(struct pptp_private_data *data) -{ - g_free(data->if_name); - g_free(data); -} - static void request_input_cb(struct vpn_provider *provider, const char *username, const char *password, @@ -526,7 +572,7 @@ static void request_input_cb(struct vpn_provider *provider, { struct pptp_private_data *data = user_data; - if (!username || !password) + if (!username || !*username || !password || !*password) DBG("Requesting username %s or password failed, error %s", username, error); else if (error) @@ -536,10 +582,7 @@ static void request_input_cb(struct vpn_provider *provider, vpn_provider_set_string_hide_value(provider, "PPTP.Password", password); - run_connect(provider, data->task, data->if_name, data->cb, - data->user_data, username, password); - - free_private_data(data); + run_connect(data, username, password); } static int pptp_connect(struct vpn_provider *provider, @@ -547,9 +590,21 @@ static int pptp_connect(struct vpn_provider *provider, vpn_provider_connect_cb_t cb, const char *dbus_sender, void *user_data) { + struct pptp_private_data *data; const char *username, *password; int err; + data = g_try_new0(struct pptp_private_data, 1); + if (!data) + return -ENOMEM; + + data->provider = vpn_provider_ref(provider); + data->task = task; + data->if_name = g_strdup(if_name); + data->cb = cb; + data->user_data = user_data; + vpn_provider_set_plugin_data(provider, data); + DBG("iface %s provider %p user %p", if_name, provider, user_data); if (connman_task_set_notify(task, "getsec", @@ -563,34 +618,20 @@ static int pptp_connect(struct vpn_provider *provider, DBG("user %s password %p", username, password); - if (!username || !password) { - struct pptp_private_data *data; - - data = g_try_new0(struct pptp_private_data, 1); - if (!data) - return -ENOMEM; - - data->task = task; - data->if_name = g_strdup(if_name); - data->cb = cb; - data->user_data = user_data; - + if (!username || !*username || !password || !*password) { err = request_input(provider, request_input_cb, dbus_sender, data); - if (err != -EINPROGRESS) { - free_private_data(data); - goto done; - } + if (err != -EINPROGRESS) + goto error; + return err; } -done: - return run_connect(provider, task, if_name, cb, user_data, - username, password); + return run_connect(data, username, password); error: - if (cb) - cb(provider, user_data, err); + pptp_connect_done(data, -err); + free_private_data(data); return err; } diff --git a/vpn/vpn-provider.c b/vpn/vpn-provider.c index 8092b5d6..6defbf27 100755 --- a/vpn/vpn-provider.c +++ b/vpn/vpn-provider.c @@ -3,7 +3,7 @@ * ConnMan VPN daemon * * Copyright (C) 2012-2013 Intel Corporation. All rights reserved. - * Copyright (C) 2019 Jolla Ltd. All rights reserved. + * Copyright (C) 2019-2021 Jolla Ltd. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -24,6 +24,21 @@ #include <config.h> #endif +/* + * One hour difference in seconds between connections for checking whether to + * treat the authentication error as a real error or as a result of rapid + * transport change. + */ +#define CONNECT_OK_DIFF ((time_t)60*60) +#define AUTH_ERROR_LIMIT_DEFAULT 1 + +#define STATE_INTERVAL_DEFAULT 0 + +#define CONNMAN_STATE_ONLINE "online" +#define CONNMAN_STATE_OFFLINE "offline" +#define CONNMAN_STATE_READY "ready" +#define CONNMAN_STATE_IDLE "idle" + #include <errno.h> #include <stdio.h> #include <string.h> @@ -32,6 +47,7 @@ #include <connman/log.h> #include <gweb/gresolv.h> #include <netdb.h> +#include <time.h> #include "../src/connman.h" #include "connman/agent.h" @@ -89,15 +105,57 @@ struct vpn_provider { struct connman_ipaddress *prev_ipv4_addr; struct connman_ipaddress *prev_ipv6_addr; void *plugin_data; + unsigned int do_connect_timeout; unsigned int auth_error_counter; unsigned int conn_error_counter; unsigned int signal_watch; + unsigned int auth_error_limit; + time_t previous_connect_time; +}; + +struct vpn_provider_connect_data { + DBusConnection *conn; + DBusMessage *msg; + struct vpn_provider *provider; }; +static unsigned int get_connman_state_timeout; + +static guint connman_signal_watch; +static guint connman_service_watch; + +static bool connman_online; +static bool state_query_completed; + static void append_properties(DBusMessageIter *iter, struct vpn_provider *provider); static int vpn_provider_save(struct vpn_provider *provider); +static void get_connman_state(void); + +static void set_state(const char *new_state) +{ + if (!new_state || !*new_state) + return; + + DBG("old state %s new state %s", + connman_online ? + CONNMAN_STATE_ONLINE "/" CONNMAN_STATE_READY : + CONNMAN_STATE_OFFLINE "/" CONNMAN_STATE_IDLE, + new_state); + + /* States "online" and "ready" mean connman is online */ + if (!g_ascii_strcasecmp(new_state, CONNMAN_STATE_ONLINE) || + !g_ascii_strcasecmp(new_state, CONNMAN_STATE_READY)) + connman_online = true; + /* Everything else means connman is offline */ + else + connman_online = false; + + DBG("set state %s connman_online=%s ", new_state, + connman_online ? "true" : "false"); +} + static void free_route(gpointer data) { struct vpn_route *route = data; @@ -740,6 +798,61 @@ static DBusMessage *clear_property(DBusConnection *conn, DBusMessage *msg, return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } +static gboolean do_connect_timeout_function(gpointer data) +{ + struct vpn_provider_connect_data *cdata = data; + struct vpn_provider *provider = cdata->provider; + int err; + + DBG(""); + + /* Keep in main loop if connman is not online. */ + if (!connman_online) + return G_SOURCE_CONTINUE; + + provider->do_connect_timeout = 0; + err = __vpn_provider_connect(provider, cdata->msg); + + if (err < 0 && err != -EINPROGRESS) { + g_dbus_send_message(cdata->conn, + __connman_error_failed(cdata->msg, -err)); + cdata->msg = NULL; + } + + return G_SOURCE_REMOVE; +} + +static void do_connect_timeout_free(gpointer data) +{ + struct vpn_provider_connect_data *cdata = data; + + if (cdata->msg) + g_dbus_send_message(cdata->conn, + __connman_error_operation_aborted(cdata->msg)); + + dbus_connection_unref(cdata->conn); + g_free(data); +} + +static void do_connect_later(struct vpn_provider *provider, + DBusConnection *conn, DBusMessage *msg) +{ + struct vpn_provider_connect_data *cdata = + g_new0(struct vpn_provider_connect_data, 1); + + cdata->conn = dbus_connection_ref(conn); + cdata->msg = dbus_message_ref(msg); + cdata->provider = provider; + + if (provider->do_connect_timeout) + g_source_remove(provider->do_connect_timeout); + + provider->do_connect_timeout = + g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, 1, + do_connect_timeout_function, cdata, + do_connect_timeout_free); +} + static DBusMessage *do_connect(DBusConnection *conn, DBusMessage *msg, void *data) { @@ -748,6 +861,25 @@ static DBusMessage *do_connect(DBusConnection *conn, DBusMessage *msg, DBG("conn %p provider %p", conn, provider); + if (!connman_online) { + if (state_query_completed) { + DBG("%s not started - ConnMan not online/ready", + provider->identifier); + return __connman_error_failed(msg, ENOLINK); + } + + DBG("%s start delayed - ConnMan state not queried", + provider->identifier); + do_connect_later(provider, conn, msg); + return NULL; + } + + /* Cancel delayed connection if connmand is online. */ + if (provider->do_connect_timeout) { + g_source_remove(provider->do_connect_timeout); + provider->do_connect_timeout = 0; + } + err = __vpn_provider_connect(provider, msg); if (err < 0 && err != -EINPROGRESS) return __connman_error_failed(msg, -err); @@ -1117,12 +1249,15 @@ static void reset_error_counters(struct vpn_provider *provider) if (!provider) return; + DBG("provider %p", provider); + provider->auth_error_counter = provider->conn_error_counter = 0; } static int vpn_provider_save(struct vpn_provider *provider) { GKeyFile *keyfile; + const char *value; DBG("provider %p immutable %s", provider, provider->immutable ? "yes" : "no"); @@ -1153,6 +1288,11 @@ static int vpn_provider_save(struct vpn_provider *provider) g_key_file_set_string(keyfile, provider->identifier, "VPN.Domain", provider->domain); + value = vpn_provider_get_string(provider, "AuthErrorLimit"); + if (value) + g_key_file_set_string(keyfile, provider->identifier, + "AuthErrorLimit", value); + if (provider->user_networks) { gchar **networks; gsize network_count; @@ -1269,6 +1409,9 @@ static void provider_destruct(struct vpn_provider *provider) { DBG("provider %p", provider); + if (provider->do_connect_timeout) + g_source_remove(provider->do_connect_timeout); + if (provider->notify_id != 0) g_source_remove(provider->notify_id); @@ -1658,6 +1801,18 @@ static void append_dns(DBusMessageIter *iter, void *user_data) append_nameservers(iter, provider->nameservers); } +static time_t get_uptime(void) +{ + struct timespec t = { 0 }; + + if (clock_gettime(CLOCK_BOOTTIME, &t) == -1) { + connman_warn("clock_gettime() error %d, uptime failed", errno); + return 0; + } + + return t.tv_sec; +} + static int provider_indicate_state(struct vpn_provider *provider, enum vpn_provider_state state) { @@ -1673,6 +1828,8 @@ static int provider_indicate_state(struct vpn_provider *provider, provider->state = state; if (state == VPN_PROVIDER_STATE_READY) { + provider->previous_connect_time = get_uptime(); + connman_dbus_property_changed_basic(provider->path, VPN_CONNECTION_INTERFACE, "Index", DBUS_TYPE_INT32, &provider->index); @@ -1885,8 +2042,10 @@ void vpn_provider_add_error(struct vpn_provider *provider, { switch (error) { case VPN_PROVIDER_ERROR_UNKNOWN: + provider->previous_connect_time = 0; break; case VPN_PROVIDER_ERROR_CONNECT_FAILED: + provider->previous_connect_time = 0; ++provider->conn_error_counter; break; case VPN_PROVIDER_ERROR_LOGIN_FAILED: @@ -1894,6 +2053,10 @@ void vpn_provider_add_error(struct vpn_provider *provider, ++provider->auth_error_counter; break; } + + DBG("%p connect errors %d auth errors %d", provider, + provider->conn_error_counter, + provider->auth_error_counter); } int vpn_provider_indicate_error(struct vpn_provider *provider, @@ -1902,6 +2065,21 @@ int vpn_provider_indicate_error(struct vpn_provider *provider, DBG("provider %p id %s error %d", provider, provider->identifier, error); + /* + * Ignore adding of errors when the VPN is idle or not set. Calls may + * happen in a case when networks are rapidly changed and the call to + * vpn_died() is done before executing the connect_cb() from the + * plugin. Then vpn.c:vpn_died() executes the plugin specific died() + * function which may free the plugin private data, containing also + * the callback which hasn't yet been called. As a result the provider + * might already been reset to idle state when the callback is executed + * resulting in unnecessary reset of the previous successful connect + * timer and adding of an error for already disconnected VPN. + */ + if (provider->state == VPN_PROVIDER_STATE_IDLE || + provider->state == VPN_PROVIDER_STATE_UNKNOWN) + return 0; + vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE); vpn_provider_add_error(provider, error); @@ -2053,6 +2231,7 @@ static void provider_initialize(struct vpn_provider *provider) g_free, free_route); provider->setting_strings = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_setting); + provider->auth_error_limit = AUTH_ERROR_LIMIT_DEFAULT; } static struct vpn_provider *vpn_provider_new(void) @@ -2788,6 +2967,21 @@ bool vpn_provider_get_string_immutable(struct vpn_provider *provider, return setting->immutable; } +bool vpn_provider_setting_key_exists(struct vpn_provider *provider, + const char *key) +{ + return g_hash_table_contains(provider->setting_strings, key); +} + +void vpn_provider_set_auth_error_limit(struct vpn_provider *provider, + unsigned int limit) +{ + if (!provider) + return; + + provider->auth_error_limit = limit; +} + bool __vpn_provider_check_routes(struct vpn_provider *provider) { if (!provider) @@ -3100,9 +3294,70 @@ const char *vpn_provider_get_path(struct vpn_provider *provider) return provider->path; } +/* + * This crude heuristic is meant to mitigate an issue with certain VPN + * providers that allow only one authentication per account at a time. These + * providers require the VPN client shuts down cleanly by sending an exit + * notification. In many cases this is not possible as the transport may + * already be gone and there is no route to the VPN server. In such case server + * may return authentication error to indicate that an other client is active + * and reserves the slot. + * + * By allowing the VPN client to try again with the following conditons the + * unnecessary credential resets done by VPN agent can be avoided. VPN client + * is allowed to retry if 1) there was a successful connection to the server + * within the specified CONNECT_OK_DIFF time and 2) the provider specific + * limit for auth errors is not reached the unnecessary credential resets in + * this case are avoided. + * + * This feature is controlled by the provider specific value for + * "AuthErrorLimit". Setting the value to 0 feature is disabled. User defined + * value is preferred if set, otherwise plugin default set with + * vpn_provider_set_auth_error_limit() is used, which defaults to + * AUTH_ERROR_LIMIT_DEFAULT. + */ +static bool ignore_authentication_errors(struct vpn_provider *provider) +{ + const char *val; + unsigned int limit; + time_t uptime; + time_t diff; + + val = vpn_provider_get_string(provider, "AuthErrorLimit"); + if (val) + limit = g_ascii_strtoull(val, NULL, 10); + else + limit = provider->auth_error_limit; + + if (!limit || !provider->previous_connect_time) { + DBG("%p errors %u %s", provider, provider->auth_error_counter, + !limit ? + "disabled by 0 limit" : + "no previous ok conn"); + return false; + } + + uptime = get_uptime(); + diff = uptime - provider->previous_connect_time; + + DBG("%p errors %u limit %u uptime %jd time diff %jd", provider, + provider->auth_error_counter, limit, + (intmax_t)uptime, (intmax_t)diff); + + if (diff <= CONNECT_OK_DIFF && provider->auth_error_counter <= limit) { + DBG("ignore auth errors"); + return true; + } + + return false; +} + unsigned int vpn_provider_get_authentication_errors( struct vpn_provider *provider) { + if (ignore_authentication_errors(provider)) + return 0; + return provider->auth_error_counter; } @@ -3248,6 +3503,215 @@ static void remove_unprovisioned_providers(void) g_strfreev(providers); } +static gboolean connman_property_changed(DBusConnection *conn, + DBusMessage *message, + void *user_data) +{ + DBusMessageIter iter, value; + const char *key; + const char *signature = DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING; + + if (!dbus_message_has_signature(message, signature)) { + connman_error("vpn connman property signature \"%s\" " + "does not match expected \"%s\"", + dbus_message_get_signature(message), + signature); + return TRUE; + } + + 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("key %s", key); + + if (g_str_equal(key, "State")) { + const char *str; + + if (dbus_message_iter_get_arg_type(&value) != DBUS_TYPE_STRING) + return TRUE; + + dbus_message_iter_get_basic(&value, &str); + set_state(str); + } + + return TRUE; +} + +static void get_connman_state_reply(DBusPendingCall *call, void *user_data) +{ + DBusMessage *reply = NULL; + DBusError error; + DBusMessageIter iter, array, dict, value; + + const char *signature = 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; + + const char *key; + const char *str; + + DBG(""); + + if (!dbus_pending_call_get_completed(call)) + goto done; + + reply = dbus_pending_call_steal_reply(call); + + dbus_error_init(&error); + + if (dbus_set_error_from_message(&error, reply)) { + connman_error("%s", error.message); + + /* + * In case of timeout re-add the state function to main + * event loop. + */ + if (g_ascii_strcasecmp(error.name, DBUS_ERROR_TIMEOUT) == 0) { + DBG("D-Bus timeout, re-add get_connman_state()"); + get_connman_state(); + } else { + dbus_error_free(&error); + goto done; + } + } + + if (!dbus_message_has_signature(reply, signature)) { + connman_error("vpnd signature \"%s\" does not match " + "expected \"%s\"", + dbus_message_get_signature(reply), + signature); + + goto done; + } + + if (!dbus_message_iter_init(reply, &array)) + goto done; + + dbus_message_iter_recurse(&array, &dict); + + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + dbus_message_iter_recurse(&dict, &iter); + + dbus_message_iter_get_basic(&iter, &key); + + dbus_message_iter_next(&iter); + dbus_message_iter_recurse(&iter, &value); + + if (g_ascii_strcasecmp(key, "State") == 0 && + dbus_message_iter_get_arg_type(&value) == + DBUS_TYPE_STRING) { + dbus_message_iter_get_basic(&value, &str); + + DBG("Got initial state %s", str); + + set_state(str); + + /* No need to process further */ + break; + } + + dbus_message_iter_next(&dict); + } + + state_query_completed = true; + +done: + if (reply) + dbus_message_unref(reply); + + if (call) + dbus_pending_call_unref(call); +} + +static gboolean run_get_connman_state(gpointer user_data) +{ + const char *path = "/"; + const char *method = "GetProperties"; + gboolean rval = FALSE; + + DBusMessage *msg = NULL; + DBusPendingCall *call = NULL; + + DBG(""); + + msg = dbus_message_new_method_call(CONNMAN_SERVICE, path, + CONNMAN_MANAGER_INTERFACE, method); + if (!msg) + goto out; + + rval = g_dbus_send_message_with_reply(connection, msg, &call, -1); + if (!rval) { + connman_error("Cannot call %s on %s", method, + CONNMAN_MANAGER_INTERFACE); + goto out; + } + + if (!call) { + connman_error("set pending call failed"); + rval = FALSE; + goto out; + } + + if (!dbus_pending_call_set_notify(call, get_connman_state_reply, + NULL, NULL)) { + connman_error("set notify to pending call failed"); + + if (call) + dbus_pending_call_unref(call); + + rval = FALSE; + } + +out: + if (msg) + dbus_message_unref(msg); + + /* In case sending was success, unset timeout function id */ + if (rval) { + DBG("unsetting get_connman_state_timeout id"); + get_connman_state_timeout = 0; + } + + /* Return FALSE in case of success to remove from main event loop */ + return !rval; +} + +static void get_connman_state(void) +{ + if (get_connman_state_timeout) + return; + + get_connman_state_timeout = g_timeout_add(STATE_INTERVAL_DEFAULT, + run_get_connman_state, NULL); +} + +static void connman_service_watch_connected(DBusConnection *conn, + void *user_data) +{ + DBG(""); + + get_connman_state(); +} + +static void connman_service_watch_disconnected(DBusConnection *conn, + void *user_data) +{ + DBG(""); + + set_state(CONNMAN_STATE_IDLE); + + /* Set state query variable to initial state */ + state_query_completed = false; +} + int __vpn_provider_init(void) { int err; @@ -3267,6 +3731,20 @@ int __vpn_provider_init(void) provider_hash = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, unregister_provider); + + connman_service_watch = g_dbus_add_service_watch(connection, + CONNMAN_SERVICE, + connman_service_watch_connected, + connman_service_watch_disconnected, + NULL, NULL); + + connman_signal_watch = g_dbus_add_signal_watch(connection, + CONNMAN_SERVICE, NULL, + CONNMAN_MANAGER_INTERFACE, + PROPERTY_CHANGED, + connman_property_changed, + NULL, NULL); + return 0; } @@ -3281,5 +3759,13 @@ void __vpn_provider_cleanup(void) g_hash_table_destroy(provider_hash); provider_hash = NULL; + if (get_connman_state_timeout) { + if (!g_source_remove(get_connman_state_timeout)) + connman_error("connman state timeout not removed"); + } + + g_dbus_remove_watch(connection, connman_service_watch); + g_dbus_remove_watch(connection, connman_signal_watch); + dbus_connection_unref(connection); } diff --git a/vpn/vpn-provider.h b/vpn/vpn-provider.h index f7fa8591..5d1455da 100755 --- a/vpn/vpn-provider.h +++ b/vpn/vpn-provider.h @@ -88,6 +88,10 @@ int vpn_provider_set_boolean(struct vpn_provider *provider, const char *key, bool force_change); bool vpn_provider_get_boolean(struct vpn_provider *provider, const char *key, bool default_value); +bool vpn_provider_setting_key_exists(struct vpn_provider *provider, + const char *key); +void vpn_provider_set_auth_error_limit(struct vpn_provider *provider, + unsigned int limit); int vpn_provider_set_state(struct vpn_provider *provider, enum vpn_provider_state state); diff --git a/vpn/vpn-rtnl.c b/vpn/vpn-rtnl.c index 295c05ce..5a02d779 100755 --- a/vpn/vpn-rtnl.c +++ b/vpn/vpn-rtnl.c @@ -797,75 +797,71 @@ static const char *type2string(uint16_t type) static GIOChannel *channel = NULL; -struct rtnl_request { - struct nlmsghdr hdr; - struct rtgenmsg msg; -}; -#define RTNL_REQUEST_SIZE (sizeof(struct nlmsghdr) + sizeof(struct rtgenmsg)) +#define RTNL_REQUEST_SIZE (NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(struct rtgenmsg))) static GSList *request_list = NULL; static guint32 request_seq = 0; -static struct rtnl_request *find_request(guint32 seq) +static struct nlmsghdr *find_request(guint32 seq) { GSList *list; for (list = request_list; list; list = list->next) { - struct rtnl_request *req = list->data; + struct nlmsghdr *hdr = list->data; - if (req->hdr.nlmsg_seq == seq) - return req; + if (hdr->nlmsg_seq == seq) + return hdr; } return NULL; } -static int send_request(struct rtnl_request *req) +static int send_request(struct nlmsghdr *hdr) { struct sockaddr_nl addr; int sk; debug("%s len %d type %d flags 0x%04x seq %d", - type2string(req->hdr.nlmsg_type), - req->hdr.nlmsg_len, req->hdr.nlmsg_type, - req->hdr.nlmsg_flags, req->hdr.nlmsg_seq); + type2string(hdr->nlmsg_type), + hdr->nlmsg_len, hdr->nlmsg_type, + hdr->nlmsg_flags, hdr->nlmsg_seq); sk = g_io_channel_unix_get_fd(channel); memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; - return sendto(sk, req, req->hdr.nlmsg_len, 0, + return sendto(sk, hdr, hdr->nlmsg_len, 0, (struct sockaddr *) &addr, sizeof(addr)); } -static int queue_request(struct rtnl_request *req) +static int queue_request(struct nlmsghdr *hdr) { - request_list = g_slist_append(request_list, req); + request_list = g_slist_append(request_list, hdr); if (g_slist_length(request_list) > 1) return 0; - return send_request(req); + return send_request(hdr); } static int process_response(guint32 seq) { - struct rtnl_request *req; + struct nlmsghdr *hdr; debug("seq %d", seq); - req = find_request(seq); - if (req) { - request_list = g_slist_remove(request_list, req); - g_free(req); + hdr = find_request(seq); + if (hdr) { + request_list = g_slist_remove(request_list, hdr); + g_free(hdr); } - req = g_slist_nth_data(request_list, 0); - if (!req) + hdr = g_slist_nth_data(request_list, 0); + if (!hdr) return 0; - return send_request(req); + return send_request(hdr); } static void rtnl_message(void *buf, size_t len) @@ -960,62 +956,65 @@ static gboolean netlink_event(GIOChannel *chan, GIOCondition cond, gpointer data static int send_getlink(void) { - struct rtnl_request *req; + struct nlmsghdr *hdr; + struct rtgenmsg *msg; debug(""); - req = g_try_malloc0(RTNL_REQUEST_SIZE); - if (!req) - return -ENOMEM; + hdr = g_malloc0(RTNL_REQUEST_SIZE); + + hdr->nlmsg_len = RTNL_REQUEST_SIZE; + hdr->nlmsg_type = RTM_GETLINK; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; + hdr->nlmsg_pid = 0; + hdr->nlmsg_seq = request_seq++; - req->hdr.nlmsg_len = RTNL_REQUEST_SIZE; - req->hdr.nlmsg_type = RTM_GETLINK; - req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; - req->hdr.nlmsg_pid = 0; - req->hdr.nlmsg_seq = request_seq++; - req->msg.rtgen_family = AF_INET; + msg = (struct rtgenmsg *) NLMSG_DATA(hdr); + msg->rtgen_family = AF_INET; - return queue_request(req); + return queue_request(hdr); } static int send_getaddr(void) { - struct rtnl_request *req; + struct nlmsghdr *hdr; + struct rtgenmsg *msg; debug(""); - req = g_try_malloc0(RTNL_REQUEST_SIZE); - if (!req) - return -ENOMEM; + hdr = g_malloc0(RTNL_REQUEST_SIZE); - req->hdr.nlmsg_len = RTNL_REQUEST_SIZE; - req->hdr.nlmsg_type = RTM_GETADDR; - req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; - req->hdr.nlmsg_pid = 0; - req->hdr.nlmsg_seq = request_seq++; - req->msg.rtgen_family = AF_INET; + hdr->nlmsg_len = RTNL_REQUEST_SIZE; + hdr->nlmsg_type = RTM_GETADDR; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; + hdr->nlmsg_pid = 0; + hdr->nlmsg_seq = request_seq++; - return queue_request(req); + msg = (struct rtgenmsg *) NLMSG_DATA(hdr); + msg->rtgen_family = AF_INET; + + return queue_request(hdr); } static int send_getroute(void) { - struct rtnl_request *req; + struct nlmsghdr *hdr; + struct rtgenmsg *msg; debug(""); - req = g_try_malloc0(RTNL_REQUEST_SIZE); - if (!req) - return -ENOMEM; + hdr = g_malloc0(RTNL_REQUEST_SIZE); + + hdr->nlmsg_len = RTNL_REQUEST_SIZE; + hdr->nlmsg_type = RTM_GETROUTE; + hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; + hdr->nlmsg_pid = 0; + hdr->nlmsg_seq = request_seq++; - req->hdr.nlmsg_len = RTNL_REQUEST_SIZE; - req->hdr.nlmsg_type = RTM_GETROUTE; - req->hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; - req->hdr.nlmsg_pid = 0; - req->hdr.nlmsg_seq = request_seq++; - req->msg.rtgen_family = AF_INET; + msg = (struct rtgenmsg *) NLMSG_DATA(hdr); + msg->rtgen_family = AF_INET; - return queue_request(req); + return queue_request(hdr); } static gboolean update_timeout_cb(gpointer user_data) @@ -1158,14 +1157,14 @@ void __vpn_rtnl_cleanup(void) update_list = NULL; for (list = request_list; list; list = list->next) { - struct rtnl_request *req = list->data; + struct nlmsghdr *hdr = list->data; debug("%s len %d type %d flags 0x%04x seq %d", - type2string(req->hdr.nlmsg_type), - req->hdr.nlmsg_len, req->hdr.nlmsg_type, - req->hdr.nlmsg_flags, req->hdr.nlmsg_seq); + type2string(hdr->nlmsg_type), + hdr->nlmsg_len, hdr->nlmsg_type, + hdr->nlmsg_flags, hdr->nlmsg_seq); - g_free(req); + g_free(hdr); list->data = NULL; } |