From: Kévin THIERRY Date: Tue, 2 Dec 2014 10:20:40 +0000 (+0100) Subject: connman: add Tizen patches X-Git-Tag: rev_0.7~13 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F90%2F31190%2F2;p=scm%2Fbb%2Fmeta-tizen.git connman: add Tizen patches Change-Id: I5b9f65476b2d08fb602b7365fdb8556665f7ec30 Signed-off-by: Kévin THIERRY --- diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0001-Add-bootstrap-files.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0001-Add-bootstrap-files.patch new file mode 100644 index 0000000..c0cec7f --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0001-Add-bootstrap-files.patch @@ -0,0 +1,55 @@ +From 79fe33b1a73f42592ac98c44b87dc15b52c7d791 Mon Sep 17 00:00:00 2001 +From: Zhang zhengguang +Date: Fri, 11 Jul 2014 09:34:05 +0800 +Subject: [PATCH 01/32] Add bootstrap files + +Change-Id: Ia3923cb1ff35e7bfbd4e45f13dd18af15ed89f56 +--- + bootstrap | 7 +++++++ + bootstrap-configure | 20 ++++++++++++++++++++ + 2 files changed, 27 insertions(+) + create mode 100755 bootstrap + create mode 100755 bootstrap-configure + +diff --git a/bootstrap b/bootstrap +new file mode 100755 +index 0000000..0dd71d9 +--- /dev/null ++++ b/bootstrap +@@ -0,0 +1,7 @@ ++#!/bin/sh ++ ++aclocal && \ ++ autoheader && \ ++ libtoolize --automake --copy --force && \ ++ automake --add-missing --copy && \ ++ autoconf +diff --git a/bootstrap-configure b/bootstrap-configure +new file mode 100755 +index 0000000..070c676 +--- /dev/null ++++ b/bootstrap-configure +@@ -0,0 +1,20 @@ ++#!/bin/sh ++ ++if [ -f config.status ]; then ++ make maintainer-clean ++fi ++ ++./bootstrap && \ ++ ./configure --enable-maintainer-mode \ ++ --enable-debug \ ++ --prefix=/usr \ ++ --mandir=/usr/share/man \ ++ --localstatedir=/var \ ++ --sysconfdir=/etc \ ++ --disable-datafiles \ ++ --enable-openconnect=builtin \ ++ --enable-openvpn=builtin \ ++ --enable-vpnc=builtin \ ++ --enable-session-policy-local=builtin \ ++ --enable-nmcompat \ ++ --enable-polkit $* +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0002-Add-package-build-spec-file.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0002-Add-package-build-spec-file.patch new file mode 100644 index 0000000..7c29ad5 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0002-Add-package-build-spec-file.patch @@ -0,0 +1,117 @@ +From 88ec373b61d46ef46dcab48fe14d02ab7254763c Mon Sep 17 00:00:00 2001 +From: Zhang zhengguang +Date: Fri, 4 Jul 2014 13:45:07 +0800 +Subject: [PATCH 02/32] Add package build spec file + +Change-Id: Ia8c78e122998da70565700d895dbf54688e7c8b9 +--- + packaging/connman.spec | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 97 insertions(+) + create mode 100644 packaging/connman.spec + +diff --git a/packaging/connman.spec b/packaging/connman.spec +new file mode 100644 +index 0000000..7da9ddd +--- /dev/null ++++ b/packaging/connman.spec +@@ -0,0 +1,97 @@ ++Name: connman ++Version: 1.26 ++Release: 1 ++License: GPL-2.0 ++Summary: Connection Manager ++Url: http://connman.net ++Group: Network & Connectivity/Connection Management ++Source0: %{name}-%{version}.tar.gz ++BuildRequires: systemd ++BuildRequires: pkgconfig(dbus-1) ++BuildRequires: pkgconfig(glib-2.0) ++BuildRequires: pkgconfig(libiptc) ++BuildRequires: pkgconfig(xtables) ++BuildRequires: pkgconfig(gnutls) ++BuildRequires: readline-devel ++%systemd_requires ++Requires: iptables ++ ++%description ++Connection Manager provides a daemon for managing Internet connections ++within embedded devices running the Linux operating system. ++ ++%package test ++Summary: Test Scripts for Connection Manager ++Requires: %{name} = %{version} ++Requires: dbus-python ++Requires: pygobject ++Requires: python-xml ++ ++%description test ++Scripts for testing Connman and its functionality ++ ++%package devel ++Summary: Development Files for connman ++Requires: %{name} = %{version} ++ ++%description devel ++Header files and development files for connman. ++ ++%prep ++%setup -q ++ ++%build ++CFLAGS+=" -DTIZEN_EXT" ++ ++chmod +x bootstrap ++./bootstrap ++%configure \ ++ --enable-threads \ ++ --enable-client \ ++ --enable-pacrunner \ ++ --enable-wifi=builtin \ ++ --enable-test \ ++ --enable-loopback \ ++ --enable-ethernet \ ++ --with-systemdunitdir=%{_unitdir} ++ ++make %{?_smp_mflags} ++ ++%install ++%make_install ++ ++mkdir -p %{buildroot}%{_sysconfdir}/connman ++cp src/main.conf %{buildroot}%{_sysconfdir}/connman/main.conf ++ ++%install_service network.target.wants connman.service ++%install_service multi-user.target.wants connman.service ++ ++%post ++systemctl daemon-reload ++systemctl restart connman.service ++ ++%preun ++systemctl stop connman.service ++ ++%postun ++systemctl daemon-reload ++ ++%docs_package ++ ++%files ++%license COPYING ++%{_sbindir}/* ++%config %{_sysconfdir}/connman/main.conf ++%config %{_sysconfdir}/dbus-1/system.d/* ++%{_unitdir}/connman.service ++%{_unitdir}/network.target.wants/connman.service ++%{_unitdir}/multi-user.target.wants/connman.service ++ ++%files test ++%{_libdir}/%{name}/test/* ++ ++%files devel ++%{_includedir}/connman/*.h ++%{_libdir}/pkgconfig/*.pc ++ ++%changelog +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0003-Add-systemd-service-to-manager-ConnMan-NTP.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0003-Add-systemd-service-to-manager-ConnMan-NTP.patch new file mode 100644 index 0000000..f12ba95 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0003-Add-systemd-service-to-manager-ConnMan-NTP.patch @@ -0,0 +1,41 @@ +From cdc8865c44bb77e9b7fa664a3669f84f7305718d Mon Sep 17 00:00:00 2001 +From: Zhang zhengguang +Date: Fri, 4 Jul 2014 14:12:08 +0800 +Subject: [PATCH 03/32] Add systemd service to manager ConnMan NTP + +--- + packaging/40-connman-ntp.list | 1 + + packaging/connman-ntp.service | 13 +++++++++++++ + 2 files changed, 14 insertions(+) + create mode 100644 packaging/40-connman-ntp.list + create mode 100644 packaging/connman-ntp.service + +diff --git a/packaging/40-connman-ntp.list b/packaging/40-connman-ntp.list +new file mode 100644 +index 0000000..9b84282 +--- /dev/null ++++ b/packaging/40-connman-ntp.list +@@ -0,0 +1 @@ ++connman-ntp.service +diff --git a/packaging/connman-ntp.service b/packaging/connman-ntp.service +new file mode 100644 +index 0000000..6ca46e2 +--- /dev/null ++++ b/packaging/connman-ntp.service +@@ -0,0 +1,13 @@ ++[Unit] ++Description=Connman NTP service ++Requires=connman.service ++After=connman.service ++ ++[Service] ++Type=oneshot ++ExecStart=/bin/bash -c "dbus-send --system --type=method_call --print-reply --dest=net.connman / net.connman.Clock.SetProperty string:'TimeUpdates' variant:string:'auto'" ++ExecStop=/bin/bash -c "dbus-send --system --type=method_call --print-reply --dest=net.connman / net.connman.Clock.SetProperty string:'TimeUpdates' variant:string:'manual'" ++RemainAfterExit=yes ++ ++[Install] ++WantedBy=multi-user.target +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0004-Set-manifest-request-domain-to-floor.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0004-Set-manifest-request-domain-to-floor.patch new file mode 100644 index 0000000..ffb90f7 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0004-Set-manifest-request-domain-to-floor.patch @@ -0,0 +1,65 @@ +From 7923d6ca6ccb144a5b036b03a015a182c3622a92 Mon Sep 17 00:00:00 2001 +From: Zhang zhengguang +Date: Fri, 4 Jul 2014 13:50:49 +0800 +Subject: [PATCH 04/32] Set manifest request domain to floor + +--- + packaging/connman.manifest | 5 +++++ + packaging/connman.spec | 5 +++++ + 2 files changed, 10 insertions(+) + create mode 100644 packaging/connman.manifest + +diff --git a/packaging/connman.manifest b/packaging/connman.manifest +new file mode 100644 +index 0000000..017d22d +--- /dev/null ++++ b/packaging/connman.manifest +@@ -0,0 +1,5 @@ ++ ++ ++ ++ ++ +diff --git a/packaging/connman.spec b/packaging/connman.spec +index 7da9ddd..c43deaa 100644 +--- a/packaging/connman.spec ++++ b/packaging/connman.spec +@@ -6,6 +6,7 @@ Summary: Connection Manager + Url: http://connman.net + Group: Network & Connectivity/Connection Management + Source0: %{name}-%{version}.tar.gz ++Source1001: connman.manifest + BuildRequires: systemd + BuildRequires: pkgconfig(dbus-1) + BuildRequires: pkgconfig(glib-2.0) +@@ -39,6 +40,7 @@ Header files and development files for connman. + + %prep + %setup -q ++cp %{SOURCE1001} . + + %build + CFLAGS+=" -DTIZEN_EXT" +@@ -79,6 +81,7 @@ systemctl daemon-reload + %docs_package + + %files ++%manifest %{name}.manifest + %license COPYING + %{_sbindir}/* + %config %{_sysconfdir}/connman/main.conf +@@ -88,9 +91,11 @@ systemctl daemon-reload + %{_unitdir}/multi-user.target.wants/connman.service + + %files test ++%manifest %{name}.manifest + %{_libdir}/%{name}/test/* + + %files devel ++%manifest %{name}.manifest + %{_includedir}/connman/*.h + %{_libdir}/pkgconfig/*.pc + +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0005-Set-ConnMan-default-settings-in-config-files.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0005-Set-ConnMan-default-settings-in-config-files.patch new file mode 100644 index 0000000..8c37f11 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0005-Set-ConnMan-default-settings-in-config-files.patch @@ -0,0 +1,66 @@ +From 85053773dfe482c81ca1ac87dc6baf2ff6b29df0 Mon Sep 17 00:00:00 2001 +From: Zhang zhengguang +Date: Fri, 4 Jul 2014 14:49:18 +0800 +Subject: [PATCH 05/32] Set ConnMan default settings in config files + +--- + src/connman.service.in | 3 ++- + src/main.conf | 4 ++++ + 2 files changed, 6 insertions(+), 1 deletion(-) + +diff --git a/src/connman.service.in b/src/connman.service.in +index 7b6195e..67d051d 100644 +--- a/src/connman.service.in ++++ b/src/connman.service.in +@@ -5,10 +5,11 @@ After=dbus.socket + Before=remote-fs.target + + [Service] ++EnvironmentFile=-/etc/sysconfig/connman + Type=dbus + BusName=net.connman + Restart=on-failure +-ExecStart=@prefix@/sbin/connmand -n ++ExecStart=@prefix@/sbin/connmand -n $OPTIONS + StandardOutput=null + + [Install] +diff --git a/src/main.conf b/src/main.conf +index 93c7a50..c979553 100644 +--- a/src/main.conf ++++ b/src/main.conf +@@ -19,6 +19,7 @@ + # the scan list is empty. In that case, a simple backoff + # mechanism starting from 10s up to 5 minutes will run. + # BackgroundScanning = true ++BackgroundScanning = false + + # List of Fallback timeservers separated by ",". + # These timeservers are used for NTP sync when there are +@@ -26,6 +27,7 @@ + # These can contain mixed combination of fully qualified + # domain names, IPv4 and IPv6 addresses. + # FallbackTimeservers = ++FallbackTimeservers = pool.ntp.org + + # List of fallback nameservers separated by "," used if no + # nameservers are otherwise provided by the service. The +@@ -52,6 +54,7 @@ + # the default route when compared to either a non-preferred + # type or a preferred type further down in the list. + # PreferredTechnologies = ++PreferredTechnologies = ethernet,wifi + + # List of blacklisted network interfaces separated by ",". + # Found interfaces will be compared to the list and will +@@ -59,6 +62,7 @@ + # match any of the list entries. Default value is + # vmnet,vboxnet,virbr,ifb. + # NetworkInterfaceBlacklist = vmnet,vboxnet,virbr,ifb ++NetworkInterfaceBlacklist = vmnet,vboxnet,virbr + + # Allow connman to change the system hostname. This can + # happen for example if we receive DHCP hostname option. +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0006-Enable-ConnMan-NTP-configurable-in-spec-file.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0006-Enable-ConnMan-NTP-configurable-in-spec-file.patch new file mode 100644 index 0000000..46074fb --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0006-Enable-ConnMan-NTP-configurable-in-spec-file.patch @@ -0,0 +1,60 @@ +From 346988b0c78109cce94fec48f8eeb16719426fa3 Mon Sep 17 00:00:00 2001 +From: Zhang zhengguang +Date: Fri, 4 Jul 2014 14:33:55 +0800 +Subject: [PATCH 06/32] Enable ConnMan NTP configurable in spec file + +--- + packaging/connman.spec | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/packaging/connman.spec b/packaging/connman.spec +index c43deaa..5438f4c 100644 +--- a/packaging/connman.spec ++++ b/packaging/connman.spec +@@ -1,3 +1,5 @@ ++%bcond_with connman_ntp ++ + Name: connman + Version: 1.26 + Release: 1 +@@ -6,6 +8,8 @@ Summary: Connection Manager + Url: http://connman.net + Group: Network & Connectivity/Connection Management + Source0: %{name}-%{version}.tar.gz ++Source10: 40-connman-ntp.list ++Source11: connman-ntp.service + Source1001: connman.manifest + BuildRequires: systemd + BuildRequires: pkgconfig(dbus-1) +@@ -62,6 +66,14 @@ make %{?_smp_mflags} + %install + %make_install + ++%if %{with connman_ntp} ++mkdir -p %{buildroot}/usr/lib/systemd/ntp-units.d ++install -m644 %{SOURCE10} %{buildroot}/usr/lib/systemd/ntp-units.d ++install -m644 %{SOURCE11} %{buildroot}%{_unitdir} ++%install_service network.target.wants connman-ntp.service ++%install_service multi-user.target.wants connman-ntp.service ++%endif ++ + mkdir -p %{buildroot}%{_sysconfdir}/connman + cp src/main.conf %{buildroot}%{_sysconfdir}/connman/main.conf + +@@ -89,6 +101,13 @@ systemctl daemon-reload + %{_unitdir}/connman.service + %{_unitdir}/network.target.wants/connman.service + %{_unitdir}/multi-user.target.wants/connman.service ++%if %{with connman_ntp} ++%dir /usr/lib/systemd/ntp-units.d ++%{_unitdir}/connman-ntp.service ++%{_unitdir}/multi-user.target.wants/connman-ntp.service ++%{_unitdir}/network.target.wants/connman-ntp.service ++/usr/lib/systemd/ntp-units.d/40-connman-ntp.list ++%endif + + %files test + %manifest %{name}.manifest +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0007-Enable-ConnMan-VPND-OpenVPN-OpenConnect-configurable.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0007-Enable-ConnMan-VPND-OpenVPN-OpenConnect-configurable.patch new file mode 100644 index 0000000..2ab8b28 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0007-Enable-ConnMan-VPND-OpenVPN-OpenConnect-configurable.patch @@ -0,0 +1,148 @@ +From 509d88ad3a5d229a5df0e7f349ac70e02148396e Mon Sep 17 00:00:00 2001 +From: Zhang zhengguang +Date: Fri, 4 Jul 2014 14:37:58 +0800 +Subject: [PATCH 07/32] Enable ConnMan VPND/OpenVPN/OpenConnect configurable in + spec file + +--- + packaging/connman.spec | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 88 insertions(+) + +diff --git a/packaging/connman.spec b/packaging/connman.spec +index 5438f4c..edc1d53 100644 +--- a/packaging/connman.spec ++++ b/packaging/connman.spec +@@ -1,3 +1,6 @@ ++%bcond_with connman_openconnect ++%bcond_with connman_openvpn ++%bcond_with connman_vpnd + %bcond_with connman_ntp + + Name: connman +@@ -17,6 +20,12 @@ BuildRequires: pkgconfig(glib-2.0) + BuildRequires: pkgconfig(libiptc) + BuildRequires: pkgconfig(xtables) + BuildRequires: pkgconfig(gnutls) ++%if %{with connman_openconnect} ++BuildRequires: openconnect ++%endif ++%if %{with connman_openvpn} ++BuildRequires: openvpn ++%endif + BuildRequires: readline-devel + %systemd_requires + Requires: iptables +@@ -25,6 +34,36 @@ Requires: iptables + Connection Manager provides a daemon for managing Internet connections + within embedded devices running the Linux operating system. + ++%if %{with connman_openconnect} ++%package plugin-openconnect ++Summary: Openconnect Support for Connman ++Requires: %{name} = %{version} ++Requires: openconnect ++ ++%description plugin-openconnect ++Openconnect Support for Connman. ++%endif ++ ++%if %{with connman_openvpn} ++%package plugin-openvpn ++Summary: Openvpn Support for Connman ++Requires: %{name} = %{version} ++Requires: openvpn ++ ++%description plugin-openvpn ++OpenVPN support for Connman. ++%endif ++ ++%if %{with connman_vpnd} ++%package connman-vpnd ++Summary: VPN Support for Connman ++BuildRequires: %{name} = %{version} ++Requires: %{name} = %{version} ++ ++%description connman-vpnd ++Provides VPN support for Connman ++%endif ++ + %package test + Summary: Test Scripts for Connection Manager + Requires: %{name} = %{version} +@@ -56,6 +95,12 @@ chmod +x bootstrap + --enable-client \ + --enable-pacrunner \ + --enable-wifi=builtin \ ++%if %{with connman_openconnect} ++ --enable-openconnect \ ++%endif ++%if %{with connman_openvpn} ++ --enable-openvpn \ ++%endif + --enable-test \ + --enable-loopback \ + --enable-ethernet \ +@@ -80,12 +125,23 @@ cp src/main.conf %{buildroot}%{_sysconfdir}/connman/main.conf + %install_service network.target.wants connman.service + %install_service multi-user.target.wants connman.service + ++%if %{with connman_vpnd} ++%install_service network.target.wants connman-vpn.service ++%install_service multi-user.target.wants connman-vpn.service ++%endif ++ + %post + systemctl daemon-reload + systemctl restart connman.service ++%if %{with connman_vpnd} ++systemctl restart connman-vpn.service ++%endif + + %preun + systemctl stop connman.service ++%if %{with connman_vpnd} ++systemctl stop connman-vpn.service ++%endif + + %postun + systemctl daemon-reload +@@ -118,4 +174,36 @@ systemctl daemon-reload + %{_includedir}/connman/*.h + %{_libdir}/pkgconfig/*.pc + ++%if %{with connman_openconnect} ++%files plugin-openconnect ++%manifest %{name}.manifest ++%{_unitdir}/connman-vpn.service ++%{_libdir}/connman/plugins-vpn/openconnect.so ++%{_libdir}/connman/scripts/openconnect-script ++%{_datadir}/dbus-1/system-services/net.connman.vpn.service ++%endif ++ ++%if %{with connman_openvpn} ++%files plugin-openvpn ++%manifest %{name}.manifest ++%{_unitdir}/connman-vpn.service ++%{_libdir}/%{name}/plugins-vpn/openvpn.so ++%{_libdir}/%{name}/scripts/openvpn-script ++%{_datadir}/dbus-1/system-services/net.connman.vpn.service ++%endif ++ ++%if %{with connman_vpnd} ++%files connman-vpnd ++%manifest %{name}.manifest ++%{_sbindir}/connman-vpnd ++%{_unitdir}/connman-vpn.service ++%{_unitdir}/network.target.wants/connman-vpn.service ++%{_unitdir}/multi-user.target.wants/connman-vpn.service ++%dir %{_libdir}/%{name} ++%dir %{_libdir}/%{name}/scripts ++%dir %{_libdir}/%{name}/plugins-vpn ++%config %{_sysconfdir}/dbus-1/system.d/connman-vpn-dbus.conf ++%{_datadir}/dbus-1/system-services/net.connman.vpn.service ++%endif ++ + %changelog +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0008-Add-connmanctl-to-the-built-rpm.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0008-Add-connmanctl-to-the-built-rpm.patch new file mode 100644 index 0000000..dd89415 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0008-Add-connmanctl-to-the-built-rpm.patch @@ -0,0 +1,26 @@ +From 8b828d775adb413be2e02a5377d83af9ecb979ed Mon Sep 17 00:00:00 2001 +From: Zhang zhengguang +Date: Tue, 19 Aug 2014 09:41:09 +0800 +Subject: [PATCH 08/32] Add connmanctl to the built rpm + +Change-Id: I84fb13ea9224985ad9e15b5c3c5f616bcf7431a4 +--- + Makefile.am | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile.am b/Makefile.am +index a574170..76863cf 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -237,7 +237,7 @@ script_LTLIBRARIES = + include Makefile.plugins + + if CLIENT +-noinst_PROGRAMS += client/connmanctl ++sbin_PROGRAMS += client/connmanctl + + noinst_MANUAL_PAGES = doc/connmanctl.1 + +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0009-Tizen-Export-more-wifi-info-in-ConnMan-network-API.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0009-Tizen-Export-more-wifi-info-in-ConnMan-network-API.patch new file mode 100644 index 0000000..cd3eafd --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0009-Tizen-Export-more-wifi-info-in-ConnMan-network-API.patch @@ -0,0 +1,283 @@ +From 98894f533f23fe532a4449ddaafaa69d39441980 Mon Sep 17 00:00:00 2001 +From: Arron Wang +Date: Mon, 24 Sep 2012 14:18:07 +0800 +Subject: [PATCH 09/32] Tizen: Export more wifi info in ConnMan network API + +Network client requires additional wifi specific info + +Export the BSSID property +Export the MaxRate property +Export the detailed info for encryption mode(mixed,aes,tkip,wep,none) + +Export the connman_network get/set method for bssid, maxrate, +encryption_mode property + +Change-Id: Ic5744978282e49cb2f70165aaadc7822dc718dfb +--- + gsupplicant/gsupplicant.h | 10 +++++++ + gsupplicant/supplicant.c | 49 +++++++++++++++++++++++++++++++ + include/network.h | 17 +++++++++++ + plugins/wifi.c | 25 +++++++++++++++- + src/network.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 173 insertions(+), 1 deletion(-) + +diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h +index e49aaa6..27826dc 100644 +--- a/gsupplicant/gsupplicant.h ++++ b/gsupplicant/gsupplicant.h +@@ -336,6 +336,16 @@ GSupplicantInterface *g_supplicant_peer_get_group_interface(GSupplicantPeer *pee + bool g_supplicant_peer_is_client(GSupplicantPeer *peer); + bool g_supplicant_peer_has_requested_connection(GSupplicantPeer *peer); + ++#if defined TIZEN_EXT ++/* ++* Description: Network client requires additional wifi specific info ++*/ ++const unsigned char *g_supplicant_network_get_bssid( ++ GSupplicantNetwork *network); ++unsigned int g_supplicant_network_get_maxrate(GSupplicantNetwork *network); ++const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network); ++#endif ++ + struct _GSupplicantCallbacks { + void (*system_ready) (void); + void (*system_killed) (void); +diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c +index 909a617..d2e4a64 100644 +--- a/gsupplicant/supplicant.c ++++ b/gsupplicant/supplicant.c +@@ -1169,6 +1169,55 @@ bool g_supplicant_peer_has_requested_connection(GSupplicantPeer *peer) + return peer->connection_requested; + } + ++#if defined TIZEN_EXT ++/* ++ * Description: Network client requires additional wifi specific info ++ */ ++const unsigned char *g_supplicant_network_get_bssid(GSupplicantNetwork *network) ++{ ++ if (network == NULL || network->best_bss == NULL) ++ return NULL; ++ ++ return (const unsigned char *)network->best_bss->bssid; ++} ++ ++unsigned int g_supplicant_network_get_maxrate(GSupplicantNetwork *network) ++{ ++ if (network == NULL || network->best_bss == NULL) ++ return 0; ++ ++ return network->best_bss->maxrate; ++} ++ ++const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network) ++{ ++ if (network == NULL || network->best_bss == NULL) ++ return NULL; ++ ++ if (network->best_bss->security == G_SUPPLICANT_SECURITY_PSK || ++ network->best_bss->security == G_SUPPLICANT_SECURITY_IEEE8021X) { ++ unsigned int pairwise; ++ ++ pairwise = network->best_bss->rsn_pairwise | ++ network->best_bss->wpa_pairwise; ++ ++ if ((pairwise & G_SUPPLICANT_PAIRWISE_CCMP) && ++ (pairwise & G_SUPPLICANT_PAIRWISE_TKIP)) ++ return "mixed"; ++ else if (pairwise & G_SUPPLICANT_PAIRWISE_CCMP) ++ return "aes"; ++ else if (pairwise & G_SUPPLICANT_PAIRWISE_TKIP) ++ return "tkip"; ++ ++ } else if (network->best_bss->security == G_SUPPLICANT_SECURITY_WEP) ++ return "wep"; ++ else if (network->best_bss->security == G_SUPPLICANT_SECURITY_NONE) ++ return "none"; ++ ++ return NULL; ++} ++#endif ++ + static void merge_network(GSupplicantNetwork *network) + { + GString *str; +diff --git a/include/network.h b/include/network.h +index d772699..180f2a2 100644 +--- a/include/network.h ++++ b/include/network.h +@@ -116,6 +116,23 @@ int connman_network_set_nameservers(struct connman_network *network, + const char *nameservers); + int connman_network_set_domain(struct connman_network *network, + const char *domain); ++#if defined TIZEN_EXT ++/* ++ * Description: Network client requires additional wifi specific info ++ */ ++int connman_network_set_bssid(struct connman_network *network, ++ const unsigned char *bssid); ++unsigned char *connman_network_get_bssid(struct connman_network *network); ++ ++int connman_network_set_maxrate(struct connman_network *network, ++ unsigned int maxrate); ++unsigned int connman_network_get_maxrate(struct connman_network *network); ++ ++int connman_network_set_enc_mode(struct connman_network *network, ++ const char *encryption_mode); ++const char *connman_network_get_enc_mode(struct connman_network *network); ++#endif ++ + int connman_network_set_name(struct connman_network *network, + const char *name); + int connman_network_set_strength(struct connman_network *network, +diff --git a/plugins/wifi.c b/plugins/wifi.c +index 5f2ebf1..69a0e23 100644 +--- a/plugins/wifi.c ++++ b/plugins/wifi.c +@@ -2602,7 +2602,14 @@ static void network_added(GSupplicantNetwork *supplicant_network) + + connman_network_set_frequency(network, + g_supplicant_network_get_frequency(supplicant_network)); +- ++#if defined TIZEN_EXT ++ connman_network_set_bssid(network, ++ g_supplicant_network_get_bssid(supplicant_network)); ++ connman_network_set_maxrate(network, ++ g_supplicant_network_get_maxrate(supplicant_network)); ++ connman_network_set_enc_mode(network, ++ g_supplicant_network_get_enc_mode(supplicant_network)); ++#endif + connman_network_set_available(network, true); + connman_network_set_string(network, "WiFi.Mode", mode); + +@@ -2658,6 +2665,12 @@ static void network_changed(GSupplicantNetwork *network, const char *property) + const char *name, *identifier; + struct connman_network *connman_network; + ++#if defined TIZEN_EXT ++ const unsigned char *bssid; ++ unsigned int maxrate; ++ uint16_t frequency; ++#endif ++ + interface = g_supplicant_network_get_interface(network); + wifi = g_supplicant_interface_get_data(interface); + identifier = g_supplicant_network_get_identifier(network); +@@ -2677,6 +2690,16 @@ static void network_changed(GSupplicantNetwork *network, const char *property) + calculate_strength(network)); + connman_network_update(connman_network); + } ++ ++#if defined TIZEN_EXT ++ bssid = g_supplicant_network_get_bssid(network); ++ maxrate = g_supplicant_network_get_maxrate(network); ++ frequency = g_supplicant_network_get_frequency(network); ++ ++ connman_network_set_bssid(connman_network, bssid); ++ connman_network_set_maxrate(connman_network, maxrate); ++ connman_network_set_frequency(connman_network, frequency); ++#endif + } + + static void apply_peer_services(GSupplicantPeer *peer, +diff --git a/src/network.c b/src/network.c +index b388995..c40a079 100644 +--- a/src/network.c ++++ b/src/network.c +@@ -41,6 +41,11 @@ + */ + #define RS_REFRESH_TIMEOUT 3 + ++#if defined TIZEN_EXT ++#define WIFI_ENCYPTION_MODE_LEN_MAX 6 ++#define WIFI_BSSID_LEN_MAX 6 ++#endif ++ + static GSList *network_list = NULL; + static GSList *driver_list = NULL; + +@@ -87,6 +92,11 @@ struct connman_network { + bool wps; + bool use_wps; + char *pin_wps; ++#if defined TIZEN_EXT ++ char encryption_mode[WIFI_ENCYPTION_MODE_LEN_MAX]; ++ unsigned char bssid[WIFI_BSSID_LEN_MAX]; ++ unsigned int maxrate; ++#endif + } wifi; + + }; +@@ -1737,6 +1747,69 @@ int connman_network_set_ipaddress(struct connman_network *network, + return 0; + } + ++#if defined TIZEN_EXT ++/* ++ * Description: Network client requires additional wifi specific info ++ */ ++int connman_network_set_bssid(struct connman_network *network, ++ const unsigned char *bssid) ++{ ++ int i = 0; ++ ++ if (bssid == NULL) ++ return -EINVAL; ++ ++ DBG("network %p bssid %02x:%02x:%02x:%02x:%02x:%02x", network, ++ bssid[0], bssid[1], bssid[2], ++ bssid[3], bssid[4], bssid[5]); ++ ++ for (;i < WIFI_BSSID_LEN_MAX;i++) ++ network->wifi.bssid[i] = bssid[i]; ++ ++ return 0; ++} ++ ++unsigned char *connman_network_get_bssid(struct connman_network *network) ++{ ++ return (unsigned char *)network->wifi.bssid; ++} ++ ++int connman_network_set_maxrate(struct connman_network *network, ++ unsigned int maxrate) ++{ ++ DBG("network %p maxrate %d", network, maxrate); ++ ++ network->wifi.maxrate = maxrate; ++ ++ return 0; ++} ++ ++unsigned int connman_network_get_maxrate(struct connman_network *network) ++{ ++ return network->wifi.maxrate; ++} ++ ++int connman_network_set_enc_mode(struct connman_network *network, ++ const char *encryption_mode) ++{ ++ if (encryption_mode == NULL) ++ return -EINVAL; ++ ++ DBG("network %p encryption mode %s", network, encryption_mode); ++ ++ g_strlcpy(network->wifi.encryption_mode, encryption_mode, ++ WIFI_ENCYPTION_MODE_LEN_MAX); ++ ++ return 0; ++} ++ ++const char *connman_network_get_enc_mode(struct connman_network *network) ++{ ++ return (const char *)network->wifi.encryption_mode; ++} ++ ++#endif ++ + int connman_network_set_nameservers(struct connman_network *network, + const char *nameservers) + { +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0010-Tizen-Append-extra-wifi-service-property.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0010-Tizen-Append-extra-wifi-service-property.patch new file mode 100644 index 0000000..cb17315 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0010-Tizen-Append-extra-wifi-service-property.patch @@ -0,0 +1,122 @@ +From d9c8d2e9c9b3d0b7c8c884e74b124895a627d148 Mon Sep 17 00:00:00 2001 +From: Arron Wang +Date: Mon, 24 Sep 2012 14:42:02 +0800 +Subject: [PATCH 10/32] Tizen: Append extra wifi service property + +Append wifi property bssid, maxrate, frequency, encryptionmode to wifi +service + +Change-Id: I1d5987334ab288fc04ff931fda5108f4afe864f0 +--- + doc/service-api.txt | 26 ++++++++++++++++++++++++++ + src/service.c | 43 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 69 insertions(+) + +diff --git a/doc/service-api.txt b/doc/service-api.txt +index c9dd7e2..74c8345 100644 +--- a/doc/service-api.txt ++++ b/doc/service-api.txt +@@ -191,6 +191,32 @@ Properties string State [readonly] + This property might be only present for WiFi + services. + ++ string BSSID [readonly] ++ ++ If the service type is WiFi, then this property ++ indicates the BSSID of the service. ++ ++ uint32 MaxRate [readonly] ++ ++ If the service type is WiFi, then this property ++ indicates the Maximum speed(bps) of the service. ++ ++ uint16 Frequency [readonly] ++ ++ If the service type is WiFi, then this property ++ indicates the frequency band(MHz) of the service. ++ ++ string EncryptionMode [readonly] ++ ++ If the service type is WiFi, then this property ++ indicates the key encryption mode. ++ ++ Possible values are "none", "wep", "tkip", "aes" ++ and "mixed". ++ ++ This property might be only present for WiFi ++ services. ++ + uint8 Strength [readonly] + + Indicates the signal strength of the service. This +diff --git a/src/service.c b/src/service.c +index 87a2f2c..d3b219f 100644 +--- a/src/service.c ++++ b/src/service.c +@@ -39,6 +39,10 @@ + + #define CONNECT_TIMEOUT 120 + ++#if defined TIZEN_EXT ++#define WIFI_BSSID_STR_LEN 18 ++#endif ++ + static DBusConnection *connection = NULL; + + static GList *service_list = NULL; +@@ -2252,6 +2256,37 @@ int __connman_service_iterate_services(service_iterate_cb cb, void *user_data) + return 0; + } + ++#if defined TIZEN_EXT ++static void append_wifi_ext_info(DBusMessageIter *dict, ++ struct connman_network *network) ++{ ++ char bssid_buff[WIFI_BSSID_STR_LEN] = {0,}; ++ char *bssid_str = bssid_buff; ++ unsigned char *bssid; ++ unsigned int maxrate; ++ uint16_t frequency; ++ const char *enc_mode; ++ ++ bssid = connman_network_get_bssid(network); ++ maxrate = connman_network_get_maxrate(network); ++ frequency = connman_network_get_frequency(network); ++ enc_mode = connman_network_get_enc_mode(network); ++ ++ snprintf(bssid_str, WIFI_BSSID_STR_LEN, "%02x:%02x:%02x:%02x:%02x:%02x", ++ bssid[0], bssid[1], bssid[2], ++ bssid[3], bssid[4], bssid[5]); ++ ++ connman_dbus_dict_append_basic(dict, "BSSID", ++ DBUS_TYPE_STRING, &bssid_str); ++ connman_dbus_dict_append_basic(dict, "MaxRate", ++ DBUS_TYPE_UINT32, &maxrate); ++ connman_dbus_dict_append_basic(dict, "Frequency", ++ DBUS_TYPE_UINT16, &frequency); ++ connman_dbus_dict_append_basic(dict, "EncryptionMode", ++ DBUS_TYPE_STRING, &enc_mode); ++} ++#endif ++ + static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, + struct connman_service *service) + { +@@ -2317,6 +2352,14 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, + append_ethernet, service); + break; + case CONNMAN_SERVICE_TYPE_WIFI: ++#if defined TIZEN_EXT ++ if (service->network != NULL) ++ append_wifi_ext_info(dict, service->network); ++ ++ connman_dbus_dict_append_dict(dict, "Ethernet", ++ append_ethernet, service); ++ break; ++#endif + case CONNMAN_SERVICE_TYPE_ETHERNET: + case CONNMAN_SERVICE_TYPE_BLUETOOTH: + case CONNMAN_SERVICE_TYPE_GADGET: +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0011-Tizen-Export-network-proxy-API-for-telephony-plugin.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0011-Tizen-Export-network-proxy-API-for-telephony-plugin.patch new file mode 100644 index 0000000..78bf825 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0011-Tizen-Export-network-proxy-API-for-telephony-plugin.patch @@ -0,0 +1,104 @@ +From 2bbc2b500806c808f54b459615ea4daddef1cf4e Mon Sep 17 00:00:00 2001 +From: Arron Wang +Date: Tue, 9 Oct 2012 16:20:45 +0800 +Subject: [PATCH 11/32] Tizen: Export network proxy API for telephony plugin + +Telephony plug-in requires manual PROXY setting function +Telephony stack provides proxy address (3G profile). + +Change-Id: Iaa02f59465a687961c303667ee09051b419507d2 +--- + include/network.h | 3 +++ + src/connman.h | 4 ++++ + src/network.c | 18 ++++++++++++++++++ + src/service.c | 16 ++++++++++++++++ + 4 files changed, 41 insertions(+) + +diff --git a/include/network.h b/include/network.h +index 180f2a2..e433c22 100644 +--- a/include/network.h ++++ b/include/network.h +@@ -131,6 +131,9 @@ unsigned int connman_network_get_maxrate(struct connman_network *network); + int connman_network_set_enc_mode(struct connman_network *network, + const char *encryption_mode); + const char *connman_network_get_enc_mode(struct connman_network *network); ++ ++int connman_network_set_proxy(struct connman_network *network, ++ const char *proxies); + #endif + + int connman_network_set_name(struct connman_network *network, +diff --git a/src/connman.h b/src/connman.h +index da01215..4d78eab 100644 +--- a/src/connman.h ++++ b/src/connman.h +@@ -756,6 +756,10 @@ void __connman_service_timeserver_changed(struct connman_service *service, + GSList *ts_list); + void __connman_service_set_pac(struct connman_service *service, + const char *pac); ++#if defined TIZEN_EXT ++void __connman_service_set_proxy(struct connman_service *service, ++ const char *proxies); ++#endif + bool __connman_service_is_hidden(struct connman_service *service); + bool __connman_service_is_split_routing(struct connman_service *service); + bool __connman_service_index_is_split_routing(int index); +diff --git a/src/network.c b/src/network.c +index c40a079..8c9fdcb 100644 +--- a/src/network.c ++++ b/src/network.c +@@ -1808,6 +1808,24 @@ const char *connman_network_get_enc_mode(struct connman_network *network) + return (const char *)network->wifi.encryption_mode; + } + ++int connman_network_set_proxy(struct connman_network *network, ++ const char *proxies) ++{ ++ struct connman_service *service; ++ ++ DBG("network %p proxies %s", network, proxies); ++ ++ service = connman_service_lookup_from_network(network); ++ if (service == NULL) ++ return -EINVAL; ++ ++ __connman_service_set_proxy(service, proxies); ++ ++ connman_service_set_proxy_method(service, ++ CONNMAN_SERVICE_PROXY_METHOD_MANUAL); ++ ++ return 0; ++} + #endif + + int connman_network_set_nameservers(struct connman_network *network, +diff --git a/src/service.c b/src/service.c +index d3b219f..8d3c619 100644 +--- a/src/service.c ++++ b/src/service.c +@@ -2806,6 +2806,22 @@ void __connman_service_set_pac(struct connman_service *service, + proxy_changed(service); + } + ++#if defined TIZEN_EXT ++void __connman_service_set_proxy(struct connman_service *service, ++ const char *proxies) ++{ ++ char **proxies_array = NULL; ++ ++ g_strfreev(service->proxies); ++ service->proxies = NULL; ++ ++ if (proxies != NULL) ++ proxies_array = g_strsplit(proxies, " ", 0); ++ ++ service->proxies = proxies_array; ++} ++#endif ++ + void __connman_service_set_identity(struct connman_service *service, + const char *identity) + { +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0012-Tizen-Integrate-telephony-plugin.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0012-Tizen-Integrate-telephony-plugin.patch new file mode 100644 index 0000000..88613f2 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0012-Tizen-Integrate-telephony-plugin.patch @@ -0,0 +1,1833 @@ +From f5af9712213cb0da9e5066e0a2fcf8fbedccc075 Mon Sep 17 00:00:00 2001 +From: Arron Wang +Date: Wed, 10 Oct 2012 09:56:13 +0800 +Subject: [PATCH 12/32] Tizen: Integrate telephony plugin + +Change-Id: Ia178f5de981501296573bf3f48e329d5a1355af6 +--- + Makefile.plugins | 12 + + configure.ac | 6 + + packaging/connman.spec | 2 + + plugins/telephony.c | 1757 ++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 1777 insertions(+) + create mode 100644 plugins/telephony.c + +diff --git a/Makefile.plugins b/Makefile.plugins +index e90ad19..83ad8fb 100644 +--- a/Makefile.plugins ++++ b/Makefile.plugins +@@ -55,6 +55,18 @@ builtin_modules += dundee + builtin_sources += plugins/dundee.c + endif + ++if TELEPHONY ++if TELEPHONY_BUILTIN ++builtin_modules += telephony ++builtin_sources += plugins/telephony.c ++else ++plugin_LTLIBRARIES += plugins/telephony.la ++plugin_objects += $(plugins_telephony_la_OBJECTS) ++plugins_telephony_la_CFLAGS = $(plugin_cflags) ++plugins_telephony_la_LDFLAGS = $(plugin_ldflags) ++endif ++endif ++ + if VPN + builtin_modules += vpn + builtin_sources += plugins/vpn.c +diff --git a/configure.ac b/configure.ac +index 6f35c78..dee2dcb 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -61,6 +61,12 @@ AC_ARG_ENABLE(hh2serial-gps, + AM_CONDITIONAL(HH2SERIAL_GPS, test "${enable_hh2serial_gps}" != "no") + AM_CONDITIONAL(HH2SERIAL_GPS_BUILTIN, test "${enable_hh2serial_gps}" = "builtin") + ++AC_ARG_ENABLE(telephony, ++ AC_HELP_STRING([--enable-telephony], [enable Telephony support]), ++ [enable_telephony=${enableval}], [enable_telephony="yes"]) ++AM_CONDITIONAL(TELEPHONY, test "${enable_telephony}" != "no") ++AM_CONDITIONAL(TELEPHONY_BUILTIN, test "${enable_telephony}" = "builtin") ++ + AC_ARG_WITH(openconnect, AC_HELP_STRING([--with-openconnect=PROGRAM], + [specify location of openconnect binary]), [path_openconnect=${withval}]) + +diff --git a/packaging/connman.spec b/packaging/connman.spec +index edc1d53..f4faf92 100644 +--- a/packaging/connman.spec ++++ b/packaging/connman.spec +@@ -152,6 +152,8 @@ systemctl daemon-reload + %manifest %{name}.manifest + %license COPYING + %{_sbindir}/* ++%{_libdir}/connman/plugins/*.so ++%{_datadir}/man/* + %config %{_sysconfdir}/connman/main.conf + %config %{_sysconfdir}/dbus-1/system.d/* + %{_unitdir}/connman.service +diff --git a/plugins/telephony.c b/plugins/telephony.c +new file mode 100644 +index 0000000..63e7f6e +--- /dev/null ++++ b/plugins/telephony.c +@@ -0,0 +1,1757 @@ ++/* ++ * ++ * Connection Manager ++ * ++ * Copyright (C) 2011-2013 Samsung Electronics Co., 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 ++ * published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++ ++#include ++#include ++ ++#include ++#include ++ ++#define CONNMAN_API_SUBJECT_TO_CHANGE ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define PS_DBUS_SERVICE "com.tcore.ps" ++ ++#define PS_MASTER_INTERFACE PS_DBUS_SERVICE ".master" ++#define PS_MODEM_INTERFACE PS_DBUS_SERVICE ".modem" ++#define PS_SERVICE_INTERFACE PS_DBUS_SERVICE ".service" ++#define PS_CONTEXT_INTERFACE PS_DBUS_SERVICE ".context" ++ ++/* methods */ ++#define GET_MODEMS "GetModems" ++#define GET_SERVICES "GetServices" ++#define GET_CONTEXTS "GetContexts" ++#define ACTIVATE_CONTEXT "Activate" ++#define DEACTIVATE_CONTEXT "Deactivate" ++#define GET_PROPERTIES "GetProperties" ++#define SET_PROPERTY "SetProperties" ++ ++/* signals */ ++#define MODEM_ADDED "ModemAdded" ++#define MODEM_REMOVED "ModemRemoved" ++#define SERVICE_ADDED "ServiceAdded" ++#define SERVICE_REMOVED "ServiceRemoved" ++#define CONTEXT_ADDED "ContextAdded" ++#define CONTEXT_REMOVED "ContextRemoved" ++#define PROPERTY_CHANGED "PropertyChanged" ++ ++#define TIMEOUT 40000 ++ ++#define STRING2BOOL(a) ((g_str_equal(a, "TRUE")) ? (TRUE):(FALSE)) ++ ++static DBusConnection *connection; ++static GHashTable *modem_hash; ++static GHashTable *service_hash; ++static GHashTable *network_hash; ++ ++struct telephony_service { ++ char *path; ++ ++ gpointer p_modem; ++ char *act; ++ gboolean roaming; /* global roaming state */ ++ gboolean ps_attached; /* packet service is available */ ++}; ++ ++struct telephony_modem { ++ char *path; ++ ++ char *operator; ++ gboolean powered; ++ gboolean sim_init; ++ gboolean flight_mode; ++ gboolean data_allowed; ++ gboolean roaming_allowed; ++ ++ struct connman_device *device; ++ struct telephony_service *s_service; ++}; ++ ++struct telephony_network { ++ char *path; ++ struct connman_network *network; ++ ++ enum connman_ipconfig_method ipv4_method; ++ struct connman_ipaddress *ipv4_address; ++ ++ enum connman_ipconfig_method ipv6_method; ++ struct connman_ipaddress *ipv6_address; ++}; ++ ++/* function prototype */ ++static void telephony_connect(DBusConnection *connection, void *user_data); ++static void telephony_disconnect(DBusConnection *connection, void *user_data); ++static void __remove_modem(gpointer data); ++static void __remove_service(gpointer data); ++static void __remove_network(gpointer data); ++ ++static int __modem_probe(struct connman_device *device); ++static void __modem_remove(struct connman_device *device); ++static int __modem_enable(struct connman_device *device); ++static int __modem_disable(struct connman_device *device); ++ ++static int __network_probe(struct connman_network *network); ++static void __network_remove(struct connman_network *network); ++static int __network_connect(struct connman_network *network); ++static int __network_disconnect(struct connman_network *network); ++ ++ ++/* dbus request and reply */ ++static int __dbus_request(const char *path, const char *interface, ++ const char *method, ++ DBusPendingCallNotifyFunction notify, void *user_data, ++ DBusFreeFunction free_function, int type, ...); ++ ++static int __request_get_modems(void); ++static void __response_get_modems(DBusPendingCall *call, void *user_data); ++static int __request_get_services(const char *path); ++static void __response_get_services(DBusPendingCall *call, void *user_data); ++static int __request_get_contexts(struct telephony_modem *modem); ++static void __response_get_contexts(DBusPendingCall *call, void *user_data); ++static int __request_network_activate(struct connman_network *network); ++static void __response_network_activate(DBusPendingCall *call, void *user_data); ++static int __request_network_deactivate(struct connman_network *network); ++ ++/* telephony internal function */ ++static void __add_modem(const char *path, DBusMessageIter *prop); ++static void __add_service(struct telephony_modem *modem, ++ const char *service_path, DBusMessageIter *prop); ++static void __add_connman_device(const char *modem_path, const char *operator); ++static void __remove_connman_device(struct telephony_modem *modem); ++static void __remove_connman_networks(struct connman_device *device); ++static void __set_device_powered(struct telephony_modem *modem, ++ gboolean powered); ++static int __check_device_powered(const char *path, gboolean online); ++static gboolean __check_network_available(struct connman_network *network); ++static void __create_service(struct connman_network *network); ++static int __add_context(struct connman_device *device, const char *path, ++ DBusMessageIter *prop); ++static gboolean __set_network_ipconfig(struct telephony_network *network, ++ DBusMessageIter *dict); ++static void __set_network_connected(struct telephony_network *network, ++ gboolean connected); ++static char *__get_ident(const char *path); ++ ++/* signal handler */ ++static gboolean __changed_modem(DBusConnection *connection, ++ DBusMessage *message, void *user_data); ++static gboolean __added_modem(DBusConnection *connection, ++ DBusMessage *message, void *user_data); ++static gboolean __removed_modem(DBusConnection *connection, ++ DBusMessage *message, void *user_data); ++static gboolean __changed_service(DBusConnection *connection, ++ DBusMessage *message, void *user_data); ++static gboolean __added_service(DBusConnection *connection, ++ DBusMessage *message, void *user_data); ++static gboolean __removed_service(DBusConnection *connection, ++ DBusMessage *message, void *user_data); ++static gboolean __changed_context(DBusConnection *connection, ++ DBusMessage *message, void *user_data); ++static gboolean __added_context(DBusConnection *connection, ++ DBusMessage *message, void *user_data); ++static gboolean __removed_context(DBusConnection *connection, ++ DBusMessage *message, void *user_data); ++ ++/* device driver */ ++static struct connman_device_driver modem_driver = { ++ .name = "device", ++ .type = CONNMAN_DEVICE_TYPE_CELLULAR, ++ .probe = __modem_probe, ++ .remove = __modem_remove, ++ .enable = __modem_enable, ++ .disable = __modem_disable, ++}; ++ ++/* network driver */ ++static struct connman_network_driver network_driver = { ++ .name = "network", ++ .type = CONNMAN_NETWORK_TYPE_CELLULAR, ++ .probe = __network_probe, ++ .remove = __network_remove, ++ .connect = __network_connect, ++ .disconnect = __network_disconnect, ++}; ++ ++static int tech_probe(struct connman_technology *technology) ++{ ++ return 0; ++} ++ ++static void tech_remove(struct connman_technology *technology) ++{ ++} ++ ++static struct connman_technology_driver tech_driver = { ++ .name = "cellular", ++ .type = CONNMAN_SERVICE_TYPE_CELLULAR, ++ .probe = tech_probe, ++ .remove = tech_remove, ++}; ++ ++/* local function */ ++static void telephony_connect(DBusConnection *connection, void *user_data) ++{ ++ DBG("connection %p", connection); ++ modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal, ++ g_free, __remove_modem); ++ service_hash = g_hash_table_new_full(g_str_hash, g_str_equal, ++ g_free, __remove_service); ++ network_hash = g_hash_table_new_full(g_str_hash, g_str_equal, ++ g_free, __remove_network); ++ __request_get_modems(); ++ return; ++} ++ ++static void telephony_disconnect(DBusConnection *connection, void *user_data) ++{ ++ DBG("connection %p", connection); ++ ++ if (modem_hash != NULL) { ++ g_hash_table_destroy(modem_hash); ++ modem_hash = NULL; ++ } ++ ++ if (network_hash != NULL) { ++ g_hash_table_destroy(network_hash); ++ network_hash = NULL; ++ } ++ ++ return; ++} ++ ++static void __remove_modem(gpointer data) ++{ ++ struct telephony_modem *modem = data; ++ ++ __remove_connman_device(modem); ++ ++ g_free(modem->path); ++ g_free(modem->operator); ++ g_free(modem); ++} ++ ++static void __remove_service(gpointer data) ++{ ++ struct telephony_service *service = data; ++ ++ g_free(service->path); ++ g_free(service->act); ++ g_free(service); ++} ++ ++static void __remove_network(gpointer data) ++{ ++ struct telephony_network *info = data; ++ struct connman_device *device; ++ ++ device = connman_network_get_device(info->network); ++ if (device != NULL) ++ connman_device_remove_network(device, info->network); ++ ++ connman_network_unref(info->network); ++ ++ g_free(info->path); ++ connman_ipaddress_free(info->ipv4_address); ++ connman_ipaddress_free(info->ipv6_address); ++ g_free(info); ++} ++ ++static int __modem_probe(struct connman_device *device) ++{ ++ DBG("device %p", device); ++ return 0; ++} ++ ++static void __modem_remove(struct connman_device *device) ++{ ++ DBG("device %p", device); ++} ++ ++static int __modem_enable(struct connman_device *device) ++{ ++ const char *path = connman_device_get_string(device, "Path"); ++ DBG("device %p, path, %s", device, path); ++ ++ return __check_device_powered(path, TRUE); ++} ++ ++static int __modem_disable(struct connman_device *device) ++{ ++ const char *path = connman_device_get_string(device, "Path"); ++ DBG("device %p, path, %s", device, path); ++ ++ return __check_device_powered(path, FALSE); ++} ++ ++static int __network_probe(struct connman_network *network) ++{ ++ DBG("network_prove network(%p)", network); ++ return 0; ++} ++ ++static int __network_connect(struct connman_network *network) ++{ ++ struct connman_device *device; ++ struct telephony_modem *modem; ++ ++ DBG("network %p", network); ++ ++ device = connman_network_get_device(network); ++ if (device == NULL) ++ return -ENODEV; ++ ++ modem = connman_device_get_data(device); ++ if (modem == NULL) ++ return -ENODEV; ++ ++ if (modem->powered == FALSE) ++ return -ENOLINK; ++ ++ return __request_network_activate(network); ++} ++ ++static int __network_disconnect(struct connman_network *network) ++{ ++ DBG("network %p", network); ++ ++ if (connman_network_get_index(network) < 0) ++ return -ENOTCONN; ++ ++ connman_network_set_associating(network, FALSE); ++ ++ return __request_network_deactivate(network); ++} ++ ++static void __network_remove(struct connman_network *network) ++{ ++ char const *path = connman_network_get_string(network, "Path"); ++ DBG("network %p path %s", network, path); ++ ++ g_hash_table_remove(network_hash, path); ++ return; ++} ++ ++static int __dbus_request(const char *path, const char *interface, ++ const char *method, ++ DBusPendingCallNotifyFunction notify, void *user_data, ++ DBusFreeFunction free_function, int type, ...) ++{ ++ DBusMessage *message; ++ DBusPendingCall *call; ++ dbus_bool_t ok; ++ va_list va; ++ ++ DBG("Telephony request path %s %s.%s", path, interface, method); ++ ++ if (path == NULL) ++ return -EINVAL; ++ ++ message = dbus_message_new_method_call(PS_DBUS_SERVICE, path, ++ interface, method); ++ if (message == NULL) ++ return -ENOMEM; ++ ++ dbus_message_set_auto_start(message, FALSE); ++ ++ va_start(va, type); ++ ok = dbus_message_append_args_valist(message, type, va); ++ va_end(va); ++ ++ if (!ok) ++ return -ENOMEM; ++ ++ if (dbus_connection_send_with_reply(connection, message, ++ &call, TIMEOUT) == FALSE) { ++ connman_error("Failed to call %s.%s", interface, method); ++ dbus_message_unref(message); ++ return -EINVAL; ++ } ++ ++ if (call == NULL) { ++ connman_error("D-Bus connection not available"); ++ dbus_message_unref(message); ++ return -EINVAL; ++ } ++ ++ dbus_pending_call_set_notify(call, notify, user_data, free_function); ++ ++ dbus_message_unref(message); ++ ++ return -EINPROGRESS; ++} ++ ++static int __request_get_modems(void) ++{ ++ DBG("request get modem"); ++ /* call connect master */ ++ return __dbus_request("/", PS_MASTER_INTERFACE, GET_MODEMS, ++ __response_get_modems, NULL, NULL, DBUS_TYPE_INVALID); ++} ++ ++static void __response_get_modems(DBusPendingCall *call, void *user_data) ++{ ++ DBusMessage *reply; ++ DBusError error; ++ DBusMessageIter args, dict; ++ ++ DBG(""); ++ ++ reply = dbus_pending_call_steal_reply(call); ++ ++ dbus_error_init(&error); ++ ++ if (dbus_set_error_from_message(&error, reply)) { ++ connman_error("GetModems() %s %s", error.name, error.message); ++ dbus_error_free(&error); ++ goto done; ++ } ++ ++ DBG("message signature (%s)", dbus_message_get_signature(reply)); ++ ++ if (dbus_message_iter_init(reply, &args) == FALSE) ++ goto done; ++ ++ dbus_message_iter_recurse(&args, &dict); ++ ++ while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) { ++ DBusMessageIter entry, property; ++ const char *modem_path; ++ ++ dbus_message_iter_recurse(&dict, &entry); ++ dbus_message_iter_get_basic(&entry, &modem_path); ++ DBG("modem path (%s)", modem_path); ++ ++ dbus_message_iter_next(&entry); ++ dbus_message_iter_recurse(&entry, &property); ++ ++ __add_modem(modem_path, &property); ++ ++ dbus_message_iter_next(&dict); ++ } ++ ++done: ++ dbus_message_unref(reply); ++ dbus_pending_call_unref(call); ++ return; ++} ++ ++static int __request_get_services(const char *path) ++{ ++ DBG("request get service"); ++ return __dbus_request(path, PS_MODEM_INTERFACE, GET_SERVICES, ++ __response_get_services, g_strdup(path), ++ g_free, DBUS_TYPE_INVALID); ++} ++ ++static void __response_get_services(DBusPendingCall *call, void *user_data) ++{ ++ DBusMessage *reply; ++ DBusError error; ++ DBusMessageIter args, dict; ++ ++ const char *path = user_data; ++ struct telephony_modem *modem; ++ ++ modem = g_hash_table_lookup(modem_hash, path); ++ if (modem == NULL) ++ return; ++ if (modem->device == NULL) ++ return; ++ ++ DBG(""); ++ ++ reply = dbus_pending_call_steal_reply(call); ++ ++ dbus_error_init(&error); ++ ++ if (dbus_set_error_from_message(&error, reply)) { ++ connman_error("GetServices() %s %s", error.name, error.message); ++ dbus_error_free(&error); ++ goto done; ++ } ++ ++ DBG("message signature (%s)", dbus_message_get_signature(reply)); ++ ++ if (dbus_message_iter_init(reply, &args) == FALSE) ++ goto done; ++ ++ dbus_message_iter_recurse(&args, &dict); ++ ++ while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) { ++ DBusMessageIter entry, property; ++ const char *service_path; ++ ++ dbus_message_iter_recurse(&dict, &entry); ++ dbus_message_iter_get_basic(&entry, &service_path); ++ DBG("service path (%s)", service_path); ++ ++ dbus_message_iter_next(&entry); ++ dbus_message_iter_recurse(&entry, &property); ++ ++ __add_service(modem, service_path, &property); ++ ++ dbus_message_iter_next(&dict); ++ } ++ ++done: ++ dbus_message_unref(reply); ++ dbus_pending_call_unref(call); ++ return; ++} ++ ++static int __request_get_contexts(struct telephony_modem *modem) ++{ ++ DBG("request get contexts"); ++ return __dbus_request(modem->s_service->path, ++ PS_SERVICE_INTERFACE, GET_CONTEXTS, ++ __response_get_contexts, g_strdup(modem->path), ++ g_free, DBUS_TYPE_INVALID); ++} ++ ++static void __response_get_contexts(DBusPendingCall *call, void *user_data) ++{ ++ DBusError error; ++ DBusMessage *reply; ++ DBusMessageIter args, dict; ++ ++ const char *path = user_data; ++ struct telephony_modem *modem; ++ ++ DBG(""); ++ ++ modem = g_hash_table_lookup(modem_hash, path); ++ if (modem == NULL) ++ return; ++ if (modem->s_service == NULL) ++ return; ++ if (modem->device == NULL) ++ return; ++ ++ reply = dbus_pending_call_steal_reply(call); ++ ++ dbus_error_init(&error); ++ ++ if (dbus_set_error_from_message(&error, reply)) { ++ connman_error("GetContexts() %s %s", error.name, error.message); ++ dbus_error_free(&error); ++ goto done; ++ } ++ ++ DBG("message signature (%s)", dbus_message_get_signature(reply)); ++ ++ if (dbus_message_iter_init(reply, &args) == FALSE) ++ goto done; ++ ++ dbus_message_iter_recurse(&args, &dict); ++ ++ while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) { ++ DBusMessageIter entry, property; ++ const char *context_path; ++ ++ dbus_message_iter_recurse(&dict, &entry); ++ dbus_message_iter_get_basic(&entry, &context_path); ++ DBG("context path (%s)", context_path); ++ ++ dbus_message_iter_next(&entry); ++ dbus_message_iter_recurse(&entry, &property); ++ ++ __add_context(modem->device, context_path, &property); ++ ++ dbus_message_iter_next(&dict); ++ } ++ ++done: ++ dbus_message_unref(reply); ++ dbus_pending_call_unref(call); ++ return; ++} ++ ++static int __request_network_activate(struct connman_network *network) ++{ ++ DBG("request network activate"); ++ ++ const char *path = connman_network_get_string(network, "Path"); ++ DBG("network %p, path %s", network, path); ++ ++ return __dbus_request(path, PS_CONTEXT_INTERFACE, ACTIVATE_CONTEXT, ++ __response_network_activate, ++ g_strdup(path), NULL, DBUS_TYPE_INVALID); ++} ++ ++static void __response_network_activate(DBusPendingCall *call, void *user_data) ++{ ++ DBG("network activation response"); ++ ++ DBusError error; ++ DBusMessage *reply; ++ ++ struct telephony_network *info; ++ const char *path = user_data; ++ ++ info = g_hash_table_lookup(network_hash, path); ++ reply = dbus_pending_call_steal_reply(call); ++ ++ if (info == NULL) ++ goto done; ++ ++ if (!__check_network_available(info->network)) { ++ g_hash_table_remove(network_hash, path); ++ goto done; ++ } ++ ++ dbus_error_init(&error); ++ if (dbus_set_error_from_message(&error, reply)) { ++ connman_error("connection activate() %s %s", ++ error.name, error.message); ++ ++ if (connman_network_get_index(info->network) < 0) ++ connman_network_set_error(info->network, ++ CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); ++ ++ dbus_error_free(&error); ++ goto done; ++ } ++ ++done: ++ dbus_message_unref(reply); ++ dbus_pending_call_unref(call); ++ return; ++} ++ ++static int __request_network_deactivate(struct connman_network *network) ++{ ++ DBG("request network deactivate"); ++ ++ const char *path = connman_network_get_string(network, "Path"); ++ DBG("network %p, path %s", network, path); ++ ++ return __dbus_request(path, PS_CONTEXT_INTERFACE, DEACTIVATE_CONTEXT, ++ NULL, NULL, NULL, DBUS_TYPE_INVALID); ++} ++ ++static void __add_modem(const char *path, DBusMessageIter *prop) ++{ ++ struct telephony_modem *modem; ++ ++ modem = g_hash_table_lookup(modem_hash, path); ++ if (modem != NULL) ++ return; ++ ++ modem = (struct telephony_modem *)malloc( ++ sizeof(struct telephony_modem)); ++ memset(modem, 0, sizeof(struct telephony_modem)); ++ ++ modem->path = g_strdup(path); ++ modem->device = NULL; ++ modem->s_service = NULL; ++ ++ g_hash_table_insert(modem_hash, g_strdup(path), modem); ++ ++ while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) { ++ DBusMessageIter entry; ++ const char *key, *tmp; ++ ++ dbus_message_iter_recurse(prop, &entry); ++ dbus_message_iter_get_basic(&entry, &key); ++ ++ dbus_message_iter_next(&entry); ++ dbus_message_iter_get_basic(&entry, &tmp); ++ ++ DBG("key (%s) value(%s)", key, tmp); ++ ++ if (g_str_equal(key, "powered") == TRUE) { ++ modem->powered = STRING2BOOL(tmp); ++ } else if (g_str_equal(key, "operator") == TRUE) { ++ modem->operator = g_strdup(tmp); ++ } else if (g_str_equal(key, "sim_init") == TRUE) { ++ modem->sim_init = STRING2BOOL(tmp); ++ } else if (g_str_equal(key, "flight_mode") == TRUE) { ++ modem->flight_mode = STRING2BOOL(tmp); ++ } else if (g_str_equal(key, "roaming_allowed") == TRUE) { ++ modem->roaming_allowed = STRING2BOOL(tmp); ++ } else if (g_str_equal(key, "data_allowed") == TRUE) { ++ modem->data_allowed = STRING2BOOL(tmp); ++ } ++ dbus_message_iter_next(prop); ++ } ++ ++ __add_connman_device(path, modem->operator); ++ __set_device_powered(modem, modem->powered); ++ ++ if (modem->powered != TRUE) { ++ DBG("modem is not powered"); ++ return; ++ } ++ ++ __request_get_services(modem->path); ++ ++ return; ++} ++ ++static void __add_service(struct telephony_modem *modem, ++ const char *service_path, DBusMessageIter *prop) ++{ ++ struct telephony_service *service; ++ ++ if (modem->s_service != NULL) ++ return; ++ ++ service = (struct telephony_service *)g_try_malloc( ++ sizeof(struct telephony_service)); ++ if (service == NULL) ++ return; ++ ++ memset(service, 0, sizeof(struct telephony_service)); ++ ++ service->path = g_strdup(service_path); ++ service->p_modem = modem; ++ g_hash_table_insert(service_hash, g_strdup(service_path), service); ++ ++ while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) { ++ DBusMessageIter entry; ++ const char *key, *tmp; ++ ++ dbus_message_iter_recurse(prop, &entry); ++ dbus_message_iter_get_basic(&entry, &key); ++ ++ dbus_message_iter_next(&entry); ++ dbus_message_iter_get_basic(&entry, &tmp); ++ ++ DBG("key (%s) value(%s)", key, tmp); ++ ++ if (g_str_equal(key, "roaming") == TRUE) { ++ service->roaming = STRING2BOOL(tmp); ++ } else if (g_str_equal(key, "act") == TRUE) { ++ service->act = g_strdup(tmp); ++ } else if (g_str_equal(key, "ps_attached") == TRUE) { ++ service->ps_attached = STRING2BOOL(tmp); ++ } ++ ++ dbus_message_iter_next(prop); ++ } ++ ++ modem->s_service = service; ++ __request_get_contexts(modem); ++ ++ return; ++} ++ ++static void __add_connman_device(const char *modem_path, const char *operator) ++{ ++ struct telephony_modem *modem; ++ struct connman_device *device; ++ ++ DBG("path %s operator %s", modem_path, operator); ++ ++ if (modem_path == NULL) ++ return; ++ ++ if (operator == NULL) ++ return; ++ ++ modem = g_hash_table_lookup(modem_hash, modem_path); ++ if (modem == NULL) ++ return; ++ ++ if (modem->device) { ++ if (!g_strcmp0(operator, ++ connman_device_get_ident(modem->device))) ++ return; ++ ++ __remove_connman_device(modem); ++ } ++ ++ if (strlen(operator) == 0) ++ return; ++ ++ device = connman_device_create(operator, CONNMAN_DEVICE_TYPE_CELLULAR); ++ if (device == NULL) ++ return; ++ ++ connman_device_set_ident(device, operator); ++ connman_device_set_string(device, "Path", modem_path); ++ connman_device_set_data(device, modem); ++ ++ if (connman_device_register(device) < 0) { ++ connman_error("Failed to register cellular device"); ++ connman_device_unref(device); ++ return; ++ } ++ ++ modem->device = device; ++ ++ return; ++} ++ ++static void __remove_connman_device(struct telephony_modem *modem) ++{ ++ DBG("modem %p path %s device %p", modem, modem->path, modem->device); ++ ++ if (modem->device == NULL) ++ return; ++ ++ __remove_connman_networks(modem->device); ++ ++ connman_device_unregister(modem->device); ++ connman_device_unref(modem->device); ++ ++ modem->device = NULL; ++ ++ return; ++} ++ ++static void __remove_connman_networks(struct connman_device *device) ++{ ++ GHashTableIter iter; ++ gpointer key, value; ++ GSList *info_list = NULL; ++ GSList *list; ++ ++ if (network_hash == NULL) ++ return; ++ ++ g_hash_table_iter_init(&iter, network_hash); ++ ++ while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { ++ struct telephony_network *info = value; ++ ++ if (connman_network_get_device(info->network) != device) ++ continue; ++ ++ info_list = g_slist_append(info_list, info); ++ } ++ ++ for (list = info_list; list != NULL; list = list->next) { ++ struct telephony_network *info = list->data; ++ connman_device_remove_network(device, info->network); ++ } ++ ++ g_slist_free(info_list); ++} ++ ++static void __set_device_powered(struct telephony_modem *modem, ++ gboolean powered) ++{ ++ DBG("set modem(%s) powered(%d)", modem->path, powered); ++ ++ if (modem->device) ++ connman_device_set_powered(modem->device, powered); ++ ++ return; ++} ++ ++static int __check_device_powered(const char *path, gboolean powered) ++{ ++ struct telephony_modem *modem = g_hash_table_lookup(modem_hash, path); ++ ++ if (modem == NULL) ++ return -ENODEV; ++ ++ DBG("check modem (%s) powered (%d)", modem->path, modem->powered); ++ ++ if (modem->powered == powered) ++ return -EALREADY; ++ ++ return 0; ++} ++ ++static gboolean __check_network_available(struct connman_network *network) ++{ ++ if (network == NULL || connman_network_get_device(network) == NULL) { ++ DBG("Modem or network was removed"); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++static int __add_context(struct connman_device *device, const char *path, ++ DBusMessageIter *prop) ++{ ++ char *ident; ++ gboolean active = FALSE; ++ ++ struct telephony_modem *modem = connman_device_get_data(device); ++ struct connman_network *network; ++ struct telephony_network *info; ++ ++ DBG("modem %p device %p path %s", modem, device, path); ++ ++ ident = __get_ident(path); ++ ++ network = connman_device_get_network(device, ident); ++ if (network != NULL) ++ return -EALREADY; ++ ++ info = g_hash_table_lookup(network_hash, path); ++ if (info != NULL) { ++ DBG("path %p already exists with device %p", path, ++ connman_network_get_device(info->network)); ++ ++ if (connman_network_get_device(info->network)) ++ return -EALREADY; ++ ++ g_hash_table_remove(network_hash, path); ++ } ++ ++ network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR); ++ if (network == NULL) ++ return -ENOMEM; ++ ++ info = (struct telephony_network *)g_try_malloc( ++ sizeof(struct telephony_network)); ++ if (info == NULL) { ++ connman_network_unref(network); ++ return -ENOMEM; ++ } ++ ++ memset(info, 0, sizeof(struct telephony_network)); ++ ++ info->path = g_strdup(path); ++ ++ connman_ipaddress_clear(info->ipv4_address); ++ connman_ipaddress_clear(info->ipv6_address); ++ info->network = network; ++ ++ connman_network_set_string(network, "Path", path); ++ connman_network_set_name(network, path); ++ ++ __create_service(network); ++ ++ g_hash_table_insert(network_hash, g_strdup(path), info); ++ ++ connman_network_set_available(network, TRUE); ++ connman_network_set_index(network, -1); ++ connman_network_set_bool(network, "Roaming", modem->s_service->roaming); ++ ++ if (connman_device_add_network(device, network) != 0) { ++ g_hash_table_remove(network_hash, path); ++ return -EIO; ++ } ++ ++ active = __set_network_ipconfig(info, prop); ++ ++ if (active && (connman_network_get_connecting(network) || ++ connman_network_get_associating(network))) ++ __set_network_connected(info, active); ++ ++ return 0; ++} ++ ++static void __create_service(struct connman_network *network) ++{ ++ const char *path; ++ char *group; ++ ++ DBG(""); ++ ++ path = connman_network_get_string(network, "Path"); ++ ++ group = __get_ident(path); ++ ++ connman_network_set_group(network, group); ++} ++ ++static gboolean __set_network_ipconfig(struct telephony_network *network, ++ DBusMessageIter *dict) ++{ ++ DBG("set network info"); ++ ++ gboolean active = FALSE; ++ char *dev_name = NULL, *proxy_addr = NULL; ++ char *ipv4_addr = NULL, *ipv4_gw = NULL, *ipv4_netmask = NULL, ++ *ipv4_dns1 = NULL, *ipv4_dns2 = NULL; ++ char *ipv6_addr = NULL, *ipv6_gw = NULL, *ipv6_netmask = NULL, ++ *ipv6_dns1 = NULL, *ipv6_dns2 = NULL; ++ int index; ++ int dns_flag = 0; ++ ++ while (dbus_message_iter_get_arg_type(dict) != DBUS_TYPE_INVALID) { ++ DBusMessageIter entry; ++ const char *key, *tmp; ++ ++ dbus_message_iter_recurse(dict, &entry); ++ dbus_message_iter_get_basic(&entry, &key); ++ ++ dbus_message_iter_next(&entry); ++ ++ DBG("key (%s)", key); ++ ++ if (g_str_equal(key, "dev_name") == TRUE) { ++ dbus_message_iter_get_basic(&entry, &dev_name); ++ DBG("dev_name (%s)", dev_name); ++ } else if (g_str_equal(key, "proxy") == TRUE) { ++ dbus_message_iter_get_basic(&entry, &proxy_addr); ++ } else if (g_str_equal(key, "ipv4_address") == TRUE) { ++ dbus_message_iter_get_basic(&entry, &ipv4_addr); ++ DBG("ipv4 address (%s)", ipv4_addr); ++ } else if (g_str_equal(key, "ipv4_gateway") == TRUE) { ++ dbus_message_iter_get_basic(&entry, &ipv4_gw); ++ } else if (g_str_equal(key, "ipv4_netmask") == TRUE) { ++ dbus_message_iter_get_basic(&entry, &ipv4_netmask); ++ } else if (g_str_equal(key, "ipv4_dns1") == TRUE) { ++ dbus_message_iter_get_basic(&entry, &ipv4_dns1); ++ } else if (g_str_equal(key, "ipv4_dns2") == TRUE) { ++ dbus_message_iter_get_basic(&entry, &ipv4_dns2); ++ } else if (g_str_equal(key, "ipv6_address") == TRUE) { ++ dbus_message_iter_get_basic(&entry, &ipv6_addr); ++ DBG("ipv6 address (%s)", ipv6_addr); ++ } else if (g_str_equal(key, "ipv6_gateway") == TRUE) { ++ dbus_message_iter_get_basic(&entry, &ipv6_gw); ++ } else if (g_str_equal(key, "ipv6_netmask") == TRUE) { ++ dbus_message_iter_get_basic(&entry, &ipv6_netmask); ++ } else if (g_str_equal(key, "ipv6_dns1") == TRUE) { ++ dbus_message_iter_get_basic(&entry, &ipv6_dns1); ++ } else if (g_str_equal(key, "ipv6_dns2") == TRUE) { ++ dbus_message_iter_get_basic(&entry, &ipv6_dns2); ++ } else if (g_str_equal(key, "active") == TRUE) { ++ dbus_message_iter_get_basic(&entry, &tmp); ++ DBG("active (%s)", tmp); ++ active = STRING2BOOL(tmp); ++ } ++ ++ dbus_message_iter_next(dict); ++ } ++ ++ /* interface index set */ ++ if (dev_name == NULL) ++ dev_name = ""; ++ ++ if (!g_str_equal(dev_name, "")) { ++ index = connman_inet_ifindex(dev_name); ++ DBG("interface %s, index %d", dev_name, index); ++ connman_network_set_index(network->network, index); ++ } ++ ++ /* proxy set */ ++ if (proxy_addr == NULL) ++ proxy_addr = ""; ++ ++ DBG("proxy (%s) is set", proxy_addr); ++ connman_network_set_proxy(network->network, proxy_addr); ++ ++ /* ipv4 set */ ++ if (ipv4_addr == NULL) ++ ipv4_addr = "0.0.0.0"; ++ ++ if (g_str_equal(ipv4_addr, "0.0.0.0")) { ++ network->ipv4_method = CONNMAN_IPCONFIG_METHOD_OFF; ++ } else { ++ network->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED; ++ network->ipv4_address = ++ connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4); ++ if (network->ipv4_address == NULL) ++ return FALSE; ++ ++ connman_ipaddress_set_ipv4(network->ipv4_address, ipv4_addr, ++ ipv4_netmask, ipv4_gw); ++ ++ if (ipv4_dns1 == NULL) ++ ipv4_dns1 = "0.0.0.0"; ++ if (ipv4_dns2 == NULL) ++ ipv4_dns2 = "0.0.0.0"; ++ ++ if (g_str_equal(ipv4_dns1, "0.0.0.0")) ++ dns_flag += 1; ++ ++ if (g_str_equal(ipv4_dns2, "0.0.0.0")) ++ dns_flag += 2; ++ ++ gchar *nameservers = NULL; ++ ++ switch (dns_flag) { ++ case 0: ++ nameservers = g_strdup_printf("%s %s", ipv4_dns1, ++ ipv4_dns2); ++ break; ++ case 1: ++ nameservers = g_strdup_printf("%s", ipv4_dns2); ++ break; ++ case 2: ++ nameservers = g_strdup_printf("%s", ipv4_dns1); ++ } ++ ++ connman_network_set_nameservers(network->network, nameservers); ++ g_free(nameservers); ++ } ++ ++ /* ipv6 set */ ++ if (ipv6_addr == NULL) ++ ipv6_addr = "::"; ++ ++ if (g_str_equal(ipv6_addr, "::")) { ++ network->ipv6_method = CONNMAN_IPCONFIG_METHOD_OFF; ++ } else { ++ network->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED; ++ unsigned char prefix_length = 64; ++ network->ipv6_address = ++ connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6); ++ if (network->ipv6_address == NULL) ++ return FALSE; ++ ++ connman_ipaddress_set_ipv6(network->ipv6_address, ipv6_addr, ++ prefix_length, ipv6_gw); ++ ++ dns_flag = 0; ++ ++ if (ipv6_dns1 == NULL) ++ ipv6_dns1 = "::"; ++ if (ipv6_dns2 == NULL) ++ ipv6_dns2 = "::"; ++ ++ if (g_str_equal(ipv6_dns1, "::")) ++ dns_flag += 1; ++ ++ if (g_str_equal(ipv6_dns2, "::")) ++ dns_flag += 2; ++ ++ gchar *nameservers = NULL; ++ ++ switch (dns_flag) { ++ case 0: ++ nameservers = g_strdup_printf("%s %s", ipv6_dns1, ++ ipv6_dns2); ++ break; ++ case 1: ++ nameservers = g_strdup_printf("%s", ipv6_dns2); ++ break; ++ case 2: ++ nameservers = g_strdup_printf("%s", ipv6_dns1); ++ } ++ ++ connman_network_set_nameservers(network->network, nameservers); ++ g_free(nameservers); ++ } ++ ++ if (active) ++ connman_network_set_associating(network->network, TRUE); ++ ++ return active; ++} ++ ++static void __set_network_connected(struct telephony_network *network, ++ gboolean connected) ++{ ++ gboolean setip = FALSE; ++ ++ DBG("network %p connected %d", network, connected); ++ ++ switch (network->ipv4_method) { ++ case CONNMAN_IPCONFIG_METHOD_UNKNOWN: ++ case CONNMAN_IPCONFIG_METHOD_OFF: ++ case CONNMAN_IPCONFIG_METHOD_MANUAL: ++ case CONNMAN_IPCONFIG_METHOD_AUTO: ++ setip = TRUE; ++ break; ++ ++ case CONNMAN_IPCONFIG_METHOD_FIXED: ++ connman_network_set_ipv4_method(network->network, ++ network->ipv4_method); ++ connman_network_set_ipaddress(network->network, ++ network->ipv4_address); ++ setip = TRUE; ++ break; ++ ++ case CONNMAN_IPCONFIG_METHOD_DHCP: ++ connman_network_set_ipv4_method(network->network, ++ network->ipv4_method); ++ setip = TRUE; ++ break; ++ } ++ ++ switch (network->ipv6_method) { ++ case CONNMAN_IPCONFIG_METHOD_UNKNOWN: ++ case CONNMAN_IPCONFIG_METHOD_OFF: ++ case CONNMAN_IPCONFIG_METHOD_MANUAL: ++ case CONNMAN_IPCONFIG_METHOD_DHCP: ++ case CONNMAN_IPCONFIG_METHOD_AUTO: ++ DBG("ipv6 not supported"); ++ break; ++ ++ case CONNMAN_IPCONFIG_METHOD_FIXED: ++ connman_network_set_ipv6_method(network->network, ++ network->ipv6_method); ++ connman_network_set_ipaddress(network->network, ++ network->ipv6_address); ++ setip = TRUE; ++ break; ++ } ++ ++ if (setip == TRUE) ++ connman_network_set_connected(network->network, connected); ++ ++ return; ++} ++ ++static char *__get_ident(const char *path) ++{ ++ char *pos; ++ ++ if (*path != '/') ++ return NULL; ++ ++ pos = strrchr(path, '/'); ++ if (pos == NULL) ++ return NULL; ++ ++ return pos + 1; ++} ++ ++static gboolean __changed_modem(DBusConnection *connection, ++ DBusMessage *message, void *user_data) ++{ ++ DBG("modem changed signal"); ++ ++ DBusMessageIter args, dict; ++ const char *path = dbus_message_get_path(message); ++ struct telephony_modem *modem; ++ ++ DBG("modem path %s", path); ++ ++ modem = g_hash_table_lookup(modem_hash, path); ++ if (modem == NULL) { ++ DBG("modem object does not exists"); ++ return TRUE; ++ } ++ ++ DBG("message signature (%s)", dbus_message_get_signature(message)); ++ ++ if (dbus_message_iter_init(message, &args) == FALSE) { ++ DBG("error to read message"); ++ return TRUE; ++ } ++ ++ dbus_message_iter_recurse(&args, &dict); ++ ++ while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) { ++ DBusMessageIter entry; ++ const char *key, *tmp; ++ ++ dbus_message_iter_recurse(&dict, &entry); ++ dbus_message_iter_get_basic(&entry, &key); ++ ++ dbus_message_iter_next(&entry); ++ dbus_message_iter_get_basic(&entry, &tmp); ++ ++ DBG("key(%s), value(%s)", key, tmp); ++ ++ if (g_str_equal(key, "powered") == TRUE) { ++ modem->powered = STRING2BOOL(tmp); ++ } else if (g_str_equal(key, "operator") == TRUE) { ++ modem->operator = g_strdup(tmp); ++ } else if (g_str_equal(key, "sim_init") == TRUE) { ++ modem->sim_init = STRING2BOOL(tmp); ++ } else if (g_str_equal(key, "flight_mode") == TRUE) { ++ modem->flight_mode = STRING2BOOL(tmp); ++ } else if (g_str_equal(key, "roaming_allowed") == TRUE) { ++ modem->roaming_allowed = STRING2BOOL(tmp); ++ } else if (g_str_equal(key, "data_allowed") == TRUE) { ++ modem->data_allowed = STRING2BOOL(tmp); ++ } ++ ++ dbus_message_iter_next(&dict); ++ } ++ ++ if (modem->device == NULL) ++ __add_connman_device(path, modem->operator); ++ ++ __set_device_powered(modem, modem->powered); ++ ++ if (modem->powered != TRUE) { ++ DBG("modem is not powered"); ++ return TRUE; ++ } ++ ++ if (!modem->s_service) { ++ __request_get_services(modem->path); ++ return TRUE; ++ } ++ ++ if (modem->flight_mode || !modem->data_allowed) { ++ DBG("modem(%s) flight mode(%d) data allowed(%d)", ++ modem->path, modem->flight_mode, modem->data_allowed); ++ return TRUE; ++ } ++ ++ return TRUE; ++} ++ ++static gboolean __added_modem(DBusConnection *connection, ++ DBusMessage *message, void *user_data) ++{ ++ DBG("modem added signal"); ++ ++ const char *modem_path = NULL; ++ DBusMessageIter args, dict, tmp; ++ ++ DBG("message signature (%s)", dbus_message_get_signature(message)); ++ if (dbus_message_iter_init(message, &args) == FALSE) { ++ DBG("error to read message"); ++ return TRUE; ++ } ++ ++ dbus_message_iter_recurse(&args, &dict); ++ memcpy(&tmp, &dict, sizeof(struct DBusMessageIter)); ++ ++ while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) { ++ DBusMessageIter entry; ++ const char *key, *value; ++ ++ dbus_message_iter_recurse(&tmp, &entry); ++ dbus_message_iter_get_basic(&entry, &key); ++ ++ dbus_message_iter_next(&entry); ++ dbus_message_iter_get_basic(&entry, &value); ++ ++ DBG("key (%s) value(%s)", key, value); ++ ++ if (g_str_equal(key, "path") == TRUE) ++ modem_path = g_strdup(value); ++ ++ dbus_message_iter_next(&tmp); ++ } ++ ++ if (modem_path != NULL) ++ __add_modem(modem_path, &dict); ++ ++ return TRUE; ++} ++ ++static gboolean __removed_modem(DBusConnection *connection, ++ DBusMessage *message, void *user_data) ++{ ++ DBG("modem removed signal"); ++ ++ DBusMessageIter iter; ++ const char *modem_path; ++ ++ if (dbus_message_iter_init(message, &iter) == FALSE) { ++ DBG("error to read message"); ++ return TRUE; ++ } ++ ++ dbus_message_iter_get_basic(&iter, &modem_path); ++ g_hash_table_remove(modem_hash, modem_path); ++ ++ return TRUE; ++} ++ ++static gboolean __changed_service(DBusConnection *connection, ++ DBusMessage *message, void *user_data) ++{ ++ DBG("service changed signal"); ++ ++ DBusMessageIter args, dict; ++ const char *service_path = dbus_message_get_path(message); ++ struct telephony_modem *modem; ++ struct telephony_service *s_service; ++ gboolean roaming_option = TRUE; ++ ++ DBG("service path %s", service_path); ++ ++ s_service = g_hash_table_lookup(service_hash, service_path); ++ if (s_service == NULL) { ++ DBG("service object does not exists"); ++ return TRUE; ++ } ++ ++ modem = s_service->p_modem; ++ if (modem == NULL) { ++ DBG("modem object does not exists"); ++ return TRUE; ++ } ++ ++ DBG("message signature (%s)", dbus_message_get_signature(message)); ++ ++ if (dbus_message_iter_init(message, &args) == FALSE) { ++ DBG("error to read message"); ++ return TRUE; ++ } ++ ++ dbus_message_iter_recurse(&args, &dict); ++ ++ while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) { ++ DBusMessageIter entry; ++ const char *key, *tmp; ++ ++ dbus_message_iter_recurse(&dict, &entry); ++ dbus_message_iter_get_basic(&entry, &key); ++ ++ dbus_message_iter_next(&entry); ++ dbus_message_iter_get_basic(&entry, &tmp); ++ ++ DBG("key(%s), value(%s)", key, tmp); ++ ++ if (g_str_equal(key, "roaming") == TRUE) { ++ s_service->roaming = STRING2BOOL(tmp); ++ } else if (g_str_equal(key, "act") == TRUE) { ++ s_service->act = g_strdup(tmp); ++ } else if (g_str_equal(key, "ps_attached") == TRUE) { ++ s_service->ps_attached = STRING2BOOL(tmp); ++ } ++ ++ dbus_message_iter_next(&dict); ++ } ++ ++ roaming_option &= (!s_service->roaming && !modem->roaming_allowed) ++ || modem->roaming_allowed; ++ ++ return TRUE; ++} ++ ++ ++static gboolean __added_service(DBusConnection *connection, ++ DBusMessage *message, void *user_data) ++{ ++ DBG("service added signal"); ++ ++ const char *path = dbus_message_get_path(message); ++ const char *service_path = NULL; ++ DBusMessageIter args, dict, tmp; ++ struct telephony_modem *modem; ++ ++ modem = g_hash_table_lookup(modem_hash, path); ++ if (modem == NULL || modem->device == NULL) ++ return TRUE; ++ ++ DBG("message signature (%s)", dbus_message_get_signature(message)); ++ if (dbus_message_iter_init(message, &args) == FALSE) { ++ DBG("error to read message"); ++ return TRUE; ++ } ++ ++ dbus_message_iter_recurse(&args, &dict); ++ memcpy(&tmp, &dict, sizeof(struct DBusMessageIter)); ++ ++ while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) { ++ DBusMessageIter entry; ++ const char *key, *value; ++ ++ dbus_message_iter_recurse(&tmp, &entry); ++ dbus_message_iter_get_basic(&entry, &key); ++ ++ dbus_message_iter_next(&entry); ++ dbus_message_iter_get_basic(&entry, &value); ++ ++ DBG("key (%s) value(%s)", key, value); ++ ++ if (g_str_equal(key, "path") == TRUE) { ++ service_path = g_strdup(value); ++ } ++ ++ dbus_message_iter_next(&tmp); ++ } ++ ++ if (service_path != NULL) ++ __add_service(modem, service_path, &dict); ++ ++ return TRUE; ++} ++ ++static gboolean __removed_service(DBusConnection *connection, ++ DBusMessage *message, void *user_data) ++{ ++ DBG("service removed signal"); ++ ++ DBusMessageIter iter; ++ const char *service_path; ++ ++ if (dbus_message_iter_init(message, &iter) == FALSE) { ++ DBG("error to read message"); ++ return TRUE; ++ } ++ ++ dbus_message_iter_get_basic(&iter, &service_path); ++ g_hash_table_remove(service_hash, service_path); ++ ++ return TRUE; ++} ++ ++static gboolean __changed_context(DBusConnection *connection, ++ DBusMessage *message, void *user_data) ++{ ++ DBG("network changed signal"); ++ ++ gboolean active = FALSE; ++ const char *path = dbus_message_get_path(message); ++ struct telephony_network *info; ++ DBusMessageIter args, dict; ++ ++ DBG("path %s", path); ++ info = g_hash_table_lookup(network_hash, path); ++ if (info == NULL) ++ return TRUE; ++ ++ if (!__check_network_available(info->network)) { ++ g_hash_table_remove(network_hash, path); ++ return TRUE; ++ } ++ ++ if (dbus_message_iter_init(message, &args) == FALSE) { ++ DBG("error to read message"); ++ return TRUE; ++ } ++ ++ dbus_message_iter_recurse(&args, &dict); ++ ++ active = __set_network_ipconfig(info, &dict); ++ ++ if (active == FALSE) ++ __set_network_connected(info, active); ++ else if ((connman_network_get_connecting(info->network) || ++ connman_network_get_associating(info->network))) ++ __set_network_connected(info, active); ++ ++ return TRUE; ++} ++ ++static gboolean __added_context(DBusConnection *connection, ++ DBusMessage *message, void *user_data) ++{ ++ DBG("network added signal"); ++ ++ DBusMessageIter args, dict, tmp; ++ const char *path = dbus_message_get_path(message); ++ const char *network_path = NULL; ++ struct telephony_service *service = NULL; ++ struct telephony_modem *modem = NULL; ++ ++ service = g_hash_table_lookup(service_hash, path); ++ if (service == NULL || service->p_modem == NULL) ++ return TRUE; ++ ++ modem = service->p_modem; ++ if (modem == NULL || modem->device == NULL) ++ return TRUE; ++ ++ DBG("message signature (%s)", dbus_message_get_signature(message)); ++ if (dbus_message_iter_init(message, &args) == FALSE) { ++ DBG("error to read message"); ++ return TRUE; ++ } ++ ++ dbus_message_iter_recurse(&args, &dict); ++ memcpy(&tmp, &dict, sizeof(struct DBusMessageIter)); ++ ++ while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) { ++ DBusMessageIter entry; ++ const char *key, *value; ++ ++ dbus_message_iter_recurse(&tmp, &entry); ++ dbus_message_iter_get_basic(&entry, &key); ++ ++ dbus_message_iter_next(&entry); ++ dbus_message_iter_get_basic(&entry, &value); ++ ++ DBG("key (%s) value(%s)", key, value); ++ ++ if (g_str_equal(key, "path") == TRUE) ++ network_path = g_strdup(value); ++ ++ dbus_message_iter_next(&tmp); ++ } ++ ++ if (network_path != NULL) ++ __add_context(modem->device, network_path, &dict); ++ ++ return TRUE; ++} ++ ++static gboolean __removed_context(DBusConnection *connection, ++ DBusMessage *message, void *user_data) ++{ ++ DBG("network removed signal"); ++ ++ DBusMessageIter iter; ++ const char *path = dbus_message_get_path(message); ++ const char *network_path = NULL; ++ struct telephony_service *service = NULL; ++ ++ service = g_hash_table_lookup(service_hash, path); ++ if (service == NULL || service->p_modem == NULL) ++ return TRUE; ++ ++ if (dbus_message_iter_init(message, &iter) == FALSE) { ++ DBG("error to read message"); ++ return TRUE; ++ } ++ ++ dbus_message_iter_get_basic(&iter, &network_path); ++ g_hash_table_remove(network_hash, network_path); ++ ++ return TRUE; ++} ++ ++/* telephony initialization */ ++static guint watch; ++static guint modem_watch; ++static guint modem_added_watch; ++static guint modem_removed_watch; ++static guint service_watch; ++static guint service_added_watch; ++static guint service_removed_watch; ++static guint context_watch; ++static guint context_added_watch; ++static guint context_removed_watch; ++ ++static int telephony_init(void) ++{ ++ DBG("telephony plugin"); ++ int err; ++ ++ connection = connman_dbus_get_connection(); ++ if (connection == NULL) ++ return -EIO; ++ ++ /* telephony watch */ ++ watch = g_dbus_add_service_watch(connection, PS_DBUS_SERVICE, ++ telephony_connect, telephony_disconnect, ++ NULL, NULL); ++ ++ modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL, ++ PS_MODEM_INTERFACE, ++ PROPERTY_CHANGED, ++ __changed_modem, NULL, NULL); ++ ++ modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL, ++ PS_MASTER_INTERFACE, ++ MODEM_ADDED, __added_modem, ++ NULL, NULL); ++ ++ modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL, ++ PS_MASTER_INTERFACE, ++ MODEM_REMOVED, __removed_modem, ++ NULL, NULL); ++ ++ service_watch = g_dbus_add_signal_watch(connection, NULL, NULL, ++ PS_SERVICE_INTERFACE, ++ PROPERTY_CHANGED, ++ __changed_service, ++ NULL, NULL); ++ ++ service_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL, ++ PS_MODEM_INTERFACE, ++ SERVICE_ADDED, __added_service, ++ NULL, NULL); ++ ++ service_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL, ++ PS_MODEM_INTERFACE, ++ SERVICE_REMOVED, ++ __removed_service, ++ NULL, NULL); ++ ++ context_watch = g_dbus_add_signal_watch(connection, NULL, NULL, ++ PS_CONTEXT_INTERFACE, ++ PROPERTY_CHANGED, ++ __changed_context, ++ NULL, NULL); ++ ++ context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL, ++ PS_SERVICE_INTERFACE, ++ CONTEXT_ADDED, __added_context, ++ NULL, NULL); ++ ++ context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL, ++ PS_SERVICE_INTERFACE, ++ CONTEXT_REMOVED, ++ __removed_context, ++ NULL, NULL); ++ ++ if (watch == 0 || modem_watch == 0 || modem_added_watch == 0 ++ || modem_removed_watch == 0 || service_watch == 0 ++ || service_added_watch == 0 || context_watch == 0 ++ || service_removed_watch == 0 ++ || context_added_watch == 0 ++ || context_removed_watch == 0) { ++ err = -EIO; ++ goto remove; ++ } ++ ++ err = connman_network_driver_register(&network_driver); ++ if (err < 0) ++ goto remove; ++ ++ err = connman_device_driver_register(&modem_driver); ++ if (err < 0) { ++ connman_network_driver_unregister(&network_driver); ++ goto remove; ++ } ++ ++ err = connman_technology_driver_register(&tech_driver); ++ if (err < 0) { ++ connman_device_driver_unregister(&modem_driver); ++ connman_network_driver_unregister(&network_driver); ++ goto remove; ++ } ++ ++ return 0; ++ ++remove: ++ g_dbus_remove_watch(connection, watch); ++ g_dbus_remove_watch(connection, modem_watch); ++ g_dbus_remove_watch(connection, modem_added_watch); ++ g_dbus_remove_watch(connection, modem_removed_watch); ++ g_dbus_remove_watch(connection, service_watch); ++ g_dbus_remove_watch(connection, service_added_watch); ++ g_dbus_remove_watch(connection, service_removed_watch); ++ g_dbus_remove_watch(connection, context_watch); ++ g_dbus_remove_watch(connection, context_added_watch); ++ g_dbus_remove_watch(connection, context_removed_watch); ++ ++ dbus_connection_unref(connection); ++ return err; ++} ++ ++static void telephony_exit(void) ++{ ++ g_dbus_remove_watch(connection, watch); ++ g_dbus_remove_watch(connection, modem_watch); ++ g_dbus_remove_watch(connection, modem_added_watch); ++ g_dbus_remove_watch(connection, modem_removed_watch); ++ g_dbus_remove_watch(connection, service_watch); ++ g_dbus_remove_watch(connection, service_added_watch); ++ g_dbus_remove_watch(connection, service_removed_watch); ++ g_dbus_remove_watch(connection, context_watch); ++ g_dbus_remove_watch(connection, context_added_watch); ++ g_dbus_remove_watch(connection, context_removed_watch); ++ ++ telephony_disconnect(connection, NULL); ++ ++ connman_device_driver_unregister(&modem_driver); ++ connman_network_driver_unregister(&network_driver); ++ ++ dbus_connection_unref(connection); ++} ++ ++CONNMAN_PLUGIN_DEFINE(telephony, "Samsung Telephony Framework plug-in", VERSION, ++ CONNMAN_PLUGIN_PRIORITY_DEFAULT, telephony_init, telephony_exit) +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0013-Tizen-Fix-wifi-enterprise-to-support-SIM-and-AKA.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0013-Tizen-Fix-wifi-enterprise-to-support-SIM-and-AKA.patch new file mode 100644 index 0000000..17cf362 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0013-Tizen-Fix-wifi-enterprise-to-support-SIM-and-AKA.patch @@ -0,0 +1,96 @@ +From ede27f8e832d3ce5dc6bf2a8be78f34abddcc885 Mon Sep 17 00:00:00 2001 +From: Arron Wang +Date: Fri, 12 Oct 2012 10:10:28 +0800 +Subject: [PATCH 13/32] Tizen: Fix wifi enterprise to support SIM and AKA + +Revise Wi-Fi enterprise to enable PEAP, TLS, TTLS +Fix wifi enterprise to support SIM and AKA + +Change-Id: Ib9c10615fd0668b2ebca57eac9285bf8a3564427 +--- + gsupplicant/supplicant.c | 20 ++++++++++++++++++++ + src/service.c | 13 ++++++++++++- + 2 files changed, 32 insertions(+), 1 deletion(-) + +diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c +index d2e4a64..58a8c9f 100644 +--- a/gsupplicant/supplicant.c ++++ b/gsupplicant/supplicant.c +@@ -4392,14 +4392,27 @@ static void add_network_security_eap(DBusMessageIter *dict, + { + char *eap_value; + ++#if defined TIZEN_EXT ++ if (!ssid->eap) ++#else + if (!ssid->eap || !ssid->identity) ++#endif + return; + + if (g_strcmp0(ssid->eap, "tls") == 0) { + add_network_security_tls(dict, ssid); + } else if (g_strcmp0(ssid->eap, "peap") == 0 || + g_strcmp0(ssid->eap, "ttls") == 0) { ++#if defined TIZEN_EXT ++ if (!ssid->identity) ++ return; ++#endif + add_network_security_peap(dict, ssid); ++ ++#if defined TIZEN_EXT ++ } else if (g_strcmp0(ssid->eap, "sim") == 0 || ++ g_strcmp0(ssid->eap, "aka") == 0) { ++#endif + } else + return; + +@@ -4408,9 +4421,16 @@ static void add_network_security_eap(DBusMessageIter *dict, + supplicant_dbus_dict_append_basic(dict, "eap", + DBUS_TYPE_STRING, + &eap_value); ++#if defined TIZEN_EXT ++ if (ssid->identity != NULL) ++ supplicant_dbus_dict_append_basic(dict, "identity", ++ DBUS_TYPE_STRING, ++ &ssid->identity); ++#else + supplicant_dbus_dict_append_basic(dict, "identity", + DBUS_TYPE_STRING, + &ssid->identity); ++#endif + + g_free(eap_value); + } +diff --git a/src/service.c b/src/service.c +index 8d3c619..99bb35d 100644 +--- a/src/service.c ++++ b/src/service.c +@@ -5912,13 +5912,24 @@ static int service_connect(struct connman_service *service) + if (!service->eap) + return -EINVAL; + ++#if defined TIZEN_EXT ++ /* ++ * never request credentials if using EAP-TLS, EAP-SIM ++ * or EAP-AKA (EAP-TLS, EAP-SIM and EAP-AKA networks ++ * need to be fully provisioned) ++ */ ++ if (g_str_equal(service->eap, "tls") || ++ g_str_equal(service->eap, "sim") || ++ g_str_equal(service->eap, "aka")) ++ break; ++#else + /* + * never request credentials if using EAP-TLS + * (EAP-TLS networks need to be fully provisioned) + */ + if (g_str_equal(service->eap, "tls")) + break; +- ++#endif + /* + * Return -ENOKEY if either identity or passphrase is + * missing. Agent provided credentials can be used as +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0014-Tizen-Check-some-telephony-flags-before-active-conte.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0014-Tizen-Check-some-telephony-flags-before-active-conte.patch new file mode 100644 index 0000000..c2349e1 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0014-Tizen-Check-some-telephony-flags-before-active-conte.patch @@ -0,0 +1,50 @@ +From 1eb2741818fb2d2ec09ab055c8e4d1df1f2fb481 Mon Sep 17 00:00:00 2001 +From: "guoqiang.liu" +Date: Fri, 27 Dec 2013 14:22:52 +0800 +Subject: [PATCH 14/32] Tizen: Check some telephony flags before active context + +Telephony active maybe fail if data_allowed or ps_attached is false, +so check it before actived. + +When data_allowed is false, if connman starts to auto connect 3G +service, it will result in 3G service auto connected fail, which +leads to it will not be auto connected next time. + +Change-Id: Ibdd9c34fee7a612c1788a364c69550c4f7e79123 +Signed-off-by: guoqiang.liu +--- + plugins/telephony.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/plugins/telephony.c b/plugins/telephony.c +index 63e7f6e..ea0bf65 100644 +--- a/plugins/telephony.c ++++ b/plugins/telephony.c +@@ -323,6 +323,7 @@ static int __network_connect(struct connman_network *network) + { + struct connman_device *device; + struct telephony_modem *modem; ++ struct telephony_service *service; + + DBG("network %p", network); + +@@ -334,9 +335,16 @@ static int __network_connect(struct connman_network *network) + if (modem == NULL) + return -ENODEV; + ++ service = modem->s_service; ++ if (service == NULL) ++ return -ENOLINK; ++ + if (modem->powered == FALSE) + return -ENOLINK; + ++ if (modem->data_allowed == FALSE || service->ps_attached == FALSE) ++ return -ENOLINK; ++ + return __request_network_activate(network); + } + +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0015-Tizen-Unify-bluetooth-tethering-enable-logic.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0015-Tizen-Unify-bluetooth-tethering-enable-logic.patch new file mode 100644 index 0000000..069eaf7 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0015-Tizen-Unify-bluetooth-tethering-enable-logic.patch @@ -0,0 +1,32 @@ +From ee0652fae6fc8615408e0937f3f61ebd28f9c42c Mon Sep 17 00:00:00 2001 +From: Zhang zhengguang +Date: Tue, 25 Mar 2014 14:16:52 +0800 +Subject: [PATCH 15/32] Tizen: Unify bluetooth tethering enable logic + +In bluez 4.x plugin, when bluetooth tethering is enabled, +set_tethering() returns 0, while in bluez 5.x plugin, +it returns -EINPROGRESS, which is not compatiable for +ConnMan to handle both of them, this patch makes bluez +5.x tethering enable logic consistent with bluez 4.x. + +Change-Id: I618efd32b5f123fe9bdb58d10adb29c67a87796f +--- + plugins/bluetooth.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c +index 82217d0..28df406 100644 +--- a/plugins/bluetooth.c ++++ b/plugins/bluetooth.c +@@ -880,7 +880,7 @@ static int bluetooth_tech_set_tethering(struct connman_technology *technology, + if (i == 0) + return -ENODEV; + +- return -EINPROGRESS; ++ return 0; + } + + static struct connman_technology_driver tech_driver = { +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0016-Tethering-Add-handling-for-wpa_supplicant-authorized.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0016-Tethering-Add-handling-for-wpa_supplicant-authorized.patch new file mode 100644 index 0000000..721b649 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0016-Tethering-Add-handling-for-wpa_supplicant-authorized.patch @@ -0,0 +1,99 @@ +From 763bd791fc3a52dc6381b18da246b7c0656861fd Mon Sep 17 00:00:00 2001 +From: Chengyi Zhao +Date: Wed, 10 Jul 2013 15:37:50 +0800 +Subject: [PATCH 16/32] Tethering: Add handling for wpa_supplicant + authorized/deauthorized signals + +Change-Id: Iff022e257ee9d2c5227585bf0b84e726914cc62b +--- + gsupplicant/gsupplicant.h | 2 ++ + gsupplicant/supplicant.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 55 insertions(+) + +diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h +index 27826dc..1fab1ba 100644 +--- a/gsupplicant/gsupplicant.h ++++ b/gsupplicant/gsupplicant.h +@@ -359,6 +359,8 @@ struct _GSupplicantCallbacks { + void (*network_removed) (GSupplicantNetwork *network); + void (*network_changed) (GSupplicantNetwork *network, + const char *property); ++ void (*add_station) (const char *mac); ++ void (*remove_station) (const char *mac); + void (*peer_found) (GSupplicantPeer *peer); + void (*peer_lost) (GSupplicantPeer *peer); + void (*peer_changed) (GSupplicantPeer *peer, +diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c +index 58a8c9f..5ff9b3d 100644 +--- a/gsupplicant/supplicant.c ++++ b/gsupplicant/supplicant.c +@@ -2609,6 +2609,56 @@ static void signal_wps_event(const char *path, DBusMessageIter *iter) + supplicant_dbus_property_foreach(iter, wps_event_args, interface); + } + ++static void signal_station_connected(const char *path, DBusMessageIter *iter) ++{ ++ GSupplicantInterface *interface; ++ const char *sta_mac = NULL; ++ ++ SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH); ++ ++ if (callbacks_pointer->add_station == NULL) ++ return; ++ ++ if (g_strcmp0(path, "/") == 0) ++ return; ++ ++ interface = g_hash_table_lookup(interface_table, path); ++ if (interface == NULL) ++ return; ++ ++ dbus_message_iter_get_basic(iter, &sta_mac); ++ if (sta_mac == NULL) ++ return; ++ ++ SUPPLICANT_DBG("New station %s connected", sta_mac); ++ callbacks_pointer->add_station(sta_mac); ++} ++ ++static void signal_station_disconnected(const char *path, DBusMessageIter *iter) ++{ ++ GSupplicantInterface *interface; ++ const char *sta_mac = NULL; ++ ++ SUPPLICANT_DBG("path %s %s", path, SUPPLICANT_PATH); ++ ++ if (callbacks_pointer->remove_station == NULL) ++ return; ++ ++ if (g_strcmp0(path, "/") == 0) ++ return; ++ ++ interface = g_hash_table_lookup(interface_table, path); ++ if (interface == NULL) ++ return; ++ ++ dbus_message_iter_get_basic(iter, &sta_mac); ++ if (sta_mac == NULL) ++ return; ++ ++ SUPPLICANT_DBG("Station %s disconnected", sta_mac); ++ callbacks_pointer->remove_station(sta_mac); ++} ++ + static void create_peer_identifier(GSupplicantPeer *peer) + { + const unsigned char test[ETH_ALEN] = {}; +@@ -3171,6 +3221,9 @@ static struct { + { SUPPLICANT_INTERFACE ".Interface.WPS", "Credentials", signal_wps_credentials }, + { SUPPLICANT_INTERFACE ".Interface.WPS", "Event", signal_wps_event }, + ++ { SUPPLICANT_INTERFACE".Interface", "StaAuthorized", signal_station_connected }, ++ { SUPPLICANT_INTERFACE".Interface", "StaDeauthorized", signal_station_disconnected }, ++ + { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceFound", signal_peer_found }, + { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceLost", signal_peer_lost }, + +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0017-Tethering-Add-station-information-management-feature.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0017-Tethering-Add-station-information-management-feature.patch new file mode 100644 index 0000000..1aa4482 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0017-Tethering-Add-station-information-management-feature.patch @@ -0,0 +1,186 @@ +From c7d7214b511b0fa8b43f21b3b87416051fa9ef29 Mon Sep 17 00:00:00 2001 +From: Chengyi Zhao +Date: Wed, 10 Jul 2013 17:54:32 +0800 +Subject: [PATCH 17/32] Tethering: Add station information management feature + +Change-Id: I2f699e42ec5ce7f148b8c1d685b52ee32e2e236b +--- + include/technology.h | 4 +++ + plugins/wifi.c | 13 ++++++++ + src/tethering.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 104 insertions(+) + +diff --git a/include/technology.h b/include/technology.h +index d7fcdde..b13d4ec 100644 +--- a/include/technology.h ++++ b/include/technology.h +@@ -36,6 +36,10 @@ extern "C" { + + struct connman_technology; + ++int connman_technology_tethering_add_station(enum connman_service_type type, ++ const char *mac); ++int connman_technology_tethering_remove_station(const char *mac); ++ + void connman_technology_tethering_notify(struct connman_technology *technology, + bool enabled); + int connman_technology_set_regdom(const char *alpha2); +diff --git a/plugins/wifi.c b/plugins/wifi.c +index 69a0e23..b5bc3ba 100644 +--- a/plugins/wifi.c ++++ b/plugins/wifi.c +@@ -2719,6 +2719,17 @@ static void apply_peer_services(GSupplicantPeer *peer, + } + } + ++static void add_station(const char *mac) ++{ ++ connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_WIFI, ++ mac); ++} ++ ++static void remove_station(const char *mac) ++{ ++ connman_technology_tethering_remove_station(mac); ++} ++ + static void peer_found(GSupplicantPeer *peer) + { + GSupplicantInterface *iface = g_supplicant_peer_get_interface(peer); +@@ -2887,6 +2898,8 @@ static const GSupplicantCallbacks callbacks = { + .network_added = network_added, + .network_removed = network_removed, + .network_changed = network_changed, ++ .add_station = add_station, ++ .remove_station = remove_station, + .peer_found = peer_found, + .peer_lost = peer_lost, + .peer_changed = peer_changed, +diff --git a/src/tethering.c b/src/tethering.c +index ceeec74..0cbf06c 100644 +--- a/src/tethering.c ++++ b/src/tethering.c +@@ -52,6 +52,9 @@ + + #define DEFAULT_MTU 1500 + ++#define CONNMAN_STATION_STR_INFO_LEN 64 ++#define CONNMAN_STATION_MAC_INFO_LEN 32 ++ + static char *private_network_primary_dns = NULL; + static char *private_network_secondary_dns = NULL; + +@@ -60,6 +63,7 @@ static GDHCPServer *tethering_dhcp_server = NULL; + static struct connman_ippool *dhcp_ippool = NULL; + static DBusConnection *connection; + static GHashTable *pn_hash; ++static GHashTable *sta_hash; + + struct connman_private_network { + char *owner; +@@ -76,6 +80,84 @@ struct connman_private_network { + char *secondary_dns; + }; + ++struct connman_station_info { ++ bool is_connected; ++ char *path; ++ char *type; ++ char ip[CONNMAN_STATION_STR_INFO_LEN]; ++ char mac[CONNMAN_STATION_MAC_INFO_LEN]; ++ char hostname[CONNMAN_STATION_STR_INFO_LEN]; ++}; ++ ++static void destroy_station(gpointer key, gpointer value, gpointer user_data) ++{ ++ struct connman_station_info *station_info; ++ ++ __sync_synchronize(); ++ ++ station_info = value; ++ ++ g_free(station_info->path); ++ g_free(station_info->type); ++ g_free(station_info); ++} ++ ++int connman_technology_tethering_add_station(enum connman_service_type type, ++ const char *mac) ++{ ++ const char *str_type; ++ char *lower_mac; ++ char *path; ++ struct connman_station_info *station_info; ++ ++ __sync_synchronize(); ++ ++ DBG("type %d", type); ++ ++ str_type = __connman_service_type2string(type); ++ if (str_type == NULL) ++ return 0; ++ ++ path = g_strdup_printf("%s/technology/%s", CONNMAN_PATH, str_type); ++ ++ station_info = g_try_new0(struct connman_station_info, 1); ++ if (station_info == NULL) ++ return -ENOMEM; ++ ++ lower_mac = g_ascii_strdown(mac, -1); ++ ++ memcpy(station_info->mac, lower_mac, strlen(lower_mac) + 1); ++ station_info->path = path; ++ station_info->type = g_strdup(str_type); ++ ++ g_hash_table_insert(sta_hash, station_info->mac, station_info); ++ ++ g_free(lower_mac); ++ return 0; ++} ++ ++int connman_technology_tethering_remove_station(const char *mac) ++{ ++ char *lower_mac; ++ struct connman_station_info *info_found; ++ ++ __sync_synchronize(); ++ ++ lower_mac = g_ascii_strdown(mac, -1); ++ ++ info_found = g_hash_table_lookup(sta_hash, lower_mac); ++ if (info_found == NULL) ++ return -EACCES; ++ ++ g_free(lower_mac); ++ g_hash_table_remove(sta_hash, info_found->mac); ++ g_free(info_found->path); ++ g_free(info_found->type); ++ g_free(info_found); ++ ++ return 0; ++} ++ + const char *__connman_tethering_get_bridge(void) + { + int sk, err; +@@ -534,6 +616,9 @@ int __connman_tethering_init(void) + pn_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + NULL, remove_private_network); + ++ sta_hash = g_hash_table_new_full(g_str_hash, ++ g_str_equal, NULL, NULL); ++ + return 0; + } + +@@ -554,5 +639,7 @@ void __connman_tethering_cleanup(void) + return; + + g_hash_table_destroy(pn_hash); ++ g_hash_table_foreach(sta_hash, destroy_station, NULL); ++ g_hash_table_destroy(sta_hash); + dbus_connection_unref(connection); + } +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0018-Tethering-Add-interface-that-save-lease-in-DHCP-info.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0018-Tethering-Add-interface-that-save-lease-in-DHCP-info.patch new file mode 100644 index 0000000..04fb8cc --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0018-Tethering-Add-interface-that-save-lease-in-DHCP-info.patch @@ -0,0 +1,277 @@ +From 5bd77bc62bc47d5752a9060cb887883a9d1b9844 Mon Sep 17 00:00:00 2001 +From: Chengyi Zhao +Date: Wed, 10 Jul 2013 19:17:02 +0800 +Subject: [PATCH 18/32] Tethering: Add interface that save lease in DHCP + information + +Change-Id: Ia09c875954d8a20a3e6c39f87076780d8a6582e4 +--- + gdhcp/client.c | 65 ---------------------------------------------------------- + gdhcp/common.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + gdhcp/common.h | 1 + + gdhcp/gdhcp.h | 5 +++++ + gdhcp/server.c | 29 +++++++++++++++++++++++++- + 5 files changed, 99 insertions(+), 66 deletions(-) + +diff --git a/gdhcp/client.c b/gdhcp/client.c +index 66c3a90..a72efb4 100644 +--- a/gdhcp/client.c ++++ b/gdhcp/client.c +@@ -1808,71 +1808,6 @@ static char *get_ip(uint32_t ip) + return g_strdup(inet_ntoa(addr)); + } + +-/* get a rough idea of how long an option will be */ +-static const uint8_t len_of_option_as_string[] = { +- [OPTION_IP] = sizeof("255.255.255.255 "), +- [OPTION_STRING] = 1, +- [OPTION_U8] = sizeof("255 "), +- [OPTION_U16] = sizeof("65535 "), +- [OPTION_U32] = sizeof("4294967295 "), +-}; +- +-static int sprint_nip(char *dest, const char *pre, const uint8_t *ip) +-{ +- return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]); +-} +- +-/* Create "opt_value1 option_value2 ..." string */ +-static char *malloc_option_value_string(uint8_t *option, GDHCPOptionType type) +-{ +- unsigned upper_length; +- int len, optlen; +- char *dest, *ret; +- +- len = option[OPT_LEN - OPT_DATA]; +- type &= OPTION_TYPE_MASK; +- optlen = dhcp_option_lengths[type]; +- if (optlen == 0) +- return NULL; +- upper_length = len_of_option_as_string[type] * +- ((unsigned)len / (unsigned)optlen); +- dest = ret = g_malloc(upper_length + 1); +- if (!ret) +- return NULL; +- +- while (len >= optlen) { +- switch (type) { +- case OPTION_IP: +- dest += sprint_nip(dest, "", option); +- break; +- case OPTION_U16: { +- uint16_t val_u16 = get_be16(option); +- dest += sprintf(dest, "%u", val_u16); +- break; +- } +- case OPTION_U32: { +- uint32_t val_u32 = get_be32(option); +- dest += sprintf(dest, "%u", val_u32); +- break; +- } +- case OPTION_STRING: +- memcpy(dest, option, len); +- dest[len] = '\0'; +- return ret; +- default: +- break; +- } +- option += optlen; +- len -= optlen; +- if (len <= 0) +- break; +- *dest++ = ' '; +- *dest = '\0'; +- } +- +- return ret; +-} +- + static GList *get_option_value_list(char *value, GDHCPOptionType type) + { + char *pos = value; +diff --git a/gdhcp/common.c b/gdhcp/common.c +index 45278a8..ac6b125 100644 +--- a/gdhcp/common.c ++++ b/gdhcp/common.c +@@ -144,6 +144,71 @@ int dhcp_end_option(uint8_t *optionptr) + return i; + } + ++/* get a rough idea of how long an option will be */ ++static const uint8_t len_of_option_as_string[] = { ++ [OPTION_IP] = sizeof("255.255.255.255 "), ++ [OPTION_STRING] = 1, ++ [OPTION_U8] = sizeof("255 "), ++ [OPTION_U16] = sizeof("65535 "), ++ [OPTION_U32] = sizeof("4294967295 "), ++}; ++ ++static int sprint_nip(char *dest, const char *pre, const uint8_t *ip) ++{ ++ return sprintf(dest, "%s%u.%u.%u.%u", pre, ip[0], ip[1], ip[2], ip[3]); ++} ++ ++/* Create "opt_value1 option_value2 ..." string */ ++char *malloc_option_value_string(uint8_t *option, GDHCPOptionType type) ++{ ++ unsigned upper_length; ++ int len, optlen; ++ char *dest, *ret; ++ ++ len = option[OPT_LEN - OPT_DATA]; ++ type &= OPTION_TYPE_MASK; ++ optlen = dhcp_option_lengths[type]; ++ if (optlen == 0) ++ return NULL; ++ upper_length = len_of_option_as_string[type] * ++ ((unsigned)len / (unsigned)optlen); ++ dest = ret = g_malloc(upper_length + 1); ++ if (ret == NULL) ++ return NULL; ++ ++ while (len >= optlen) { ++ switch (type) { ++ case OPTION_IP: ++ dest += sprint_nip(dest, "", option); ++ break; ++ case OPTION_U16: { ++ uint16_t val_u16 = get_be16(option); ++ dest += sprintf(dest, "%u", val_u16); ++ break; ++ } ++ case OPTION_U32: { ++ uint32_t val_u32 = get_be32(option); ++ dest += sprintf(dest, "%u", val_u32); ++ break; ++ } ++ case OPTION_STRING: ++ memcpy(dest, option, len); ++ dest[len] = '\0'; ++ return ret; ++ default: ++ break; ++ } ++ option += optlen; ++ len -= optlen; ++ if (len <= 0) ++ break; ++ *dest++ = ' '; ++ *dest = '\0'; ++ } ++ ++ return ret; ++} ++ + uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len, + int code, uint16_t *option_len, int *option_count) + { +diff --git a/gdhcp/common.h b/gdhcp/common.h +index c692799..1ab9a7c 100644 +--- a/gdhcp/common.h ++++ b/gdhcp/common.h +@@ -170,6 +170,7 @@ static const uint8_t dhcp_option_lengths[] = { + [OPTION_U32] = 4, + }; + ++char *malloc_option_value_string(uint8_t *option, GDHCPOptionType type); + uint8_t *dhcp_get_option(struct dhcp_packet *packet, int code); + uint8_t *dhcpv6_get_option(struct dhcpv6_packet *packet, uint16_t pkt_len, + int code, uint16_t *option_len, int *option_count); +diff --git a/gdhcp/gdhcp.h b/gdhcp/gdhcp.h +index f3e47bf..f4ef292 100644 +--- a/gdhcp/gdhcp.h ++++ b/gdhcp/gdhcp.h +@@ -205,6 +205,9 @@ struct _GDHCPServer; + + typedef struct _GDHCPServer GDHCPServer; + ++typedef void (*GDHCPSaveACKLeaseFunc) (char *hostname, ++ unsigned char *mac, unsigned int nip); ++ + GDHCPServer *g_dhcp_server_new(GDHCPType type, + int ifindex, GDHCPServerError *error); + int g_dhcp_server_start(GDHCPServer *server); +@@ -223,6 +226,8 @@ void g_dhcp_server_set_lease_time(GDHCPServer *dhcp_server, + unsigned int lease_time); + void g_dhcp_server_set_save_lease(GDHCPServer *dhcp_server, + GDHCPSaveLeaseFunc func, gpointer user_data); ++void g_dhcp_server_set_save_ack_lease(GDHCPServer *dhcp_server, ++ GDHCPSaveACKLeaseFunc func, gpointer user_data); + #ifdef __cplusplus + } + #endif +diff --git a/gdhcp/server.c b/gdhcp/server.c +index aa40488..0171b5f 100644 +--- a/gdhcp/server.c ++++ b/gdhcp/server.c +@@ -65,6 +65,7 @@ struct _GDHCPServer { + GHashTable *nip_lease_hash; + GHashTable *option_hash; /* Options send to client */ + GDHCPSaveLeaseFunc save_lease_func; ++ GDHCPSaveACKLeaseFunc save_ack_lease_func; + GDHCPDebugFunc debug_func; + gpointer debug_data; + }; +@@ -398,6 +399,7 @@ GDHCPServer *g_dhcp_server_new(GDHCPType type, + dhcp_server->listener_watch = -1; + dhcp_server->listener_channel = NULL; + dhcp_server->save_lease_func = NULL; ++ dhcp_server->save_ack_lease_func = NULL; + dhcp_server->debug_func = NULL; + dhcp_server->debug_data = NULL; + +@@ -646,9 +648,12 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition, + struct dhcp_packet packet; + struct dhcp_lease *lease; + uint32_t requested_nip = 0; +- uint8_t type, *server_id_option, *request_ip_option; ++ uint8_t type, *server_id_option, *request_ip_option, *host_name; + int re; + ++ GDHCPOptionType option_type; ++ char *option_value; ++ + if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) { + dhcp_server->listener_watch = 0; + return FALSE; +@@ -693,8 +698,21 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition, + + if (lease && requested_nip == lease->lease_nip) { + debug(dhcp_server, "Sending ACK"); ++ ++ host_name = dhcp_get_option(&packet, DHCP_HOST_NAME); ++ option_type = dhcp_get_code_type(DHCP_HOST_NAME); ++ option_value = malloc_option_value_string(host_name, ++ option_type); + send_ACK(dhcp_server, &packet, + lease->lease_nip); ++ ++ if (dhcp_server->save_ack_lease_func) ++ dhcp_server->save_ack_lease_func( ++ option_value, ++ lease->lease_mac, ++ lease->lease_nip); ++ g_free(option_value); ++ + break; + } + +@@ -814,6 +832,15 @@ void g_dhcp_server_set_save_lease(GDHCPServer *dhcp_server, + dhcp_server->save_lease_func = func; + } + ++void g_dhcp_server_set_save_ack_lease(GDHCPServer *dhcp_server, ++ GDHCPSaveACKLeaseFunc func, gpointer user_data) ++{ ++ if (dhcp_server == NULL) ++ return; ++ ++ dhcp_server->save_ack_lease_func = func; ++} ++ + GDHCPServer *g_dhcp_server_ref(GDHCPServer *dhcp_server) + { + if (!dhcp_server) +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0019-Tethering-Notify-listeners-when-station-connection-c.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0019-Tethering-Notify-listeners-when-station-connection-c.patch new file mode 100644 index 0000000..20403c2 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0019-Tethering-Notify-listeners-when-station-connection-c.patch @@ -0,0 +1,160 @@ +From b846a12300fa054beb16e97add2d13cd8e2496ae Mon Sep 17 00:00:00 2001 +From: Chengyi Zhao +Date: Wed, 10 Jul 2013 20:00:36 +0800 +Subject: [PATCH 19/32] Tethering: Notify listeners when station connection + changes + +Change-Id: I048c1a8a348b6f862ca104ad2fbe971f580fe180 +--- + src/technology.c | 10 +++++++ + src/tethering.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 94 insertions(+), 1 deletion(-) + +diff --git a/src/technology.c b/src/technology.c +index d80d9e6..a06efd3 100644 +--- a/src/technology.c ++++ b/src/technology.c +@@ -1070,6 +1070,16 @@ static const GDBusMethodTable technology_methods[] = { + static const GDBusSignalTable technology_signals[] = { + { GDBUS_SIGNAL("PropertyChanged", + GDBUS_ARGS({ "name", "s" }, { "value", "v" })) }, ++ { GDBUS_SIGNAL("DhcpConnected", ++ GDBUS_ARGS({ "aptype", "s" }, ++ { "ipaddr", "s" }, ++ { "macaddr", "s" }, ++ { "hostname", "s" })) }, ++ { GDBUS_SIGNAL("DhcpLeaseDeleted", ++ GDBUS_ARGS({ "aptype", "s" }, ++ { "ipaddr", "s" }, ++ { "macaddr", "s" }, ++ { "hostname", "s" })) }, + { }, + }; + +diff --git a/src/tethering.c b/src/tethering.c +index 0cbf06c..c0c9743 100644 +--- a/src/tethering.c ++++ b/src/tethering.c +@@ -89,6 +89,32 @@ struct connman_station_info { + char hostname[CONNMAN_STATION_STR_INFO_LEN]; + }; + ++static void emit_station_signal(char *action_str, ++ const struct connman_station_info *station_info) ++{ ++ char *ip, *mac, *hostname; ++ ++ if (station_info->path == NULL || station_info->type == NULL ++ || station_info->ip == NULL || station_info->mac == NULL ++ || station_info->hostname == NULL) ++ return; ++ ++ ip = g_strdup(station_info->ip); ++ mac = g_strdup(station_info->mac); ++ hostname = g_strdup(station_info->hostname); ++ ++ g_dbus_emit_signal(connection, station_info->path, ++ CONNMAN_TECHNOLOGY_INTERFACE, action_str, ++ DBUS_TYPE_STRING, &station_info->type, ++ DBUS_TYPE_STRING, &ip, ++ DBUS_TYPE_STRING, &mac, ++ DBUS_TYPE_STRING, &hostname, ++ DBUS_TYPE_INVALID); ++ ++ g_free(ip); ++ g_free(mac); ++ g_free(hostname); ++} + static void destroy_station(gpointer key, gpointer value, gpointer user_data) + { + struct connman_station_info *station_info; +@@ -97,11 +123,59 @@ static void destroy_station(gpointer key, gpointer value, gpointer user_data) + + station_info = value; + ++ if (station_info->is_connected) { ++ station_info->is_connected = FALSE; ++ emit_station_signal("DhcpLeaseDeleted", station_info); ++ } ++ + g_free(station_info->path); + g_free(station_info->type); + g_free(station_info); + } + ++static void save_dhcp_ack_lease_info(char *hostname, ++ unsigned char *mac, unsigned int nip) ++{ ++ char *lower_mac; ++ const char *ip; ++ char sta_mac[CONNMAN_STATION_MAC_INFO_LEN]; ++ struct connman_station_info *info_found; ++ struct in_addr addr; ++ int str_len; ++ ++ __sync_synchronize(); ++ ++ snprintf(sta_mac, CONNMAN_STATION_MAC_INFO_LEN, ++ "%02x:%02x:%02x:%02x:%02x:%02x", ++ mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); ++ lower_mac = g_ascii_strdown(sta_mac, -1); ++ ++ info_found = g_hash_table_lookup(sta_hash, lower_mac); ++ if (info_found == NULL) { ++ g_free(lower_mac); ++ return; ++ } ++ ++ /* get the ip */ ++ addr.s_addr = nip; ++ ip = inet_ntoa(addr); ++ str_len = strlen(ip) + 1; ++ if (str_len > CONNMAN_STATION_STR_INFO_LEN) ++ str_len = CONNMAN_STATION_STR_INFO_LEN - 1; ++ memcpy(info_found->ip, ip, str_len); ++ ++ /* get hostname */ ++ str_len = strlen(hostname) + 1; ++ if (str_len > CONNMAN_STATION_STR_INFO_LEN) ++ str_len = CONNMAN_STATION_STR_INFO_LEN - 1; ++ memcpy(info_found->hostname, hostname, str_len); ++ ++ /* emit a signal */ ++ info_found->is_connected = TRUE; ++ emit_station_signal("DhcpConnected", info_found); ++ g_free(lower_mac); ++} ++ + int connman_technology_tethering_add_station(enum connman_service_type type, + const char *mac) + { +@@ -146,9 +220,15 @@ int connman_technology_tethering_remove_station(const char *mac) + lower_mac = g_ascii_strdown(mac, -1); + + info_found = g_hash_table_lookup(sta_hash, lower_mac); +- if (info_found == NULL) ++ if (info_found == NULL) { ++ g_free(lower_mac); + return -EACCES; ++ } + ++ if (info_found->is_connected) { ++ info_found->is_connected = FALSE; ++ emit_station_signal("DhcpLeaseDeleted", info_found); ++ } + g_free(lower_mac); + g_hash_table_remove(sta_hash, info_found->mac); + g_free(info_found->path); +@@ -243,6 +323,9 @@ static GDHCPServer *dhcp_server_start(const char *bridge, + g_dhcp_server_set_option(dhcp_server, G_DHCP_DNS_SERVER, dns); + g_dhcp_server_set_ip_range(dhcp_server, start_ip, end_ip); + ++ g_dhcp_server_set_save_ack_lease(dhcp_server, ++ save_dhcp_ack_lease_info, NULL); ++ + g_dhcp_server_start(dhcp_server); + + return dhcp_server; +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0020-Tethering-Add-open-access-point-support-in-technolog.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0020-Tethering-Add-open-access-point-support-in-technolog.patch new file mode 100644 index 0000000..2272504 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0020-Tethering-Add-open-access-point-support-in-technolog.patch @@ -0,0 +1,69 @@ +From d0fcec2219e62723f4ed4e67e1724b8dc2c1cd96 Mon Sep 17 00:00:00 2001 +From: Chengyi Zhao +Date: Thu, 11 Jul 2013 09:12:01 +0800 +Subject: [PATCH 20/32] Tethering: Add open access point support in technology + +Change-Id: I86f4a22567f5df2fbd5d0c0c03c6cc5b6fc24a2d +--- + src/technology.c | 36 +++++++++++++++++++++++------------- + 1 file changed, 23 insertions(+), 13 deletions(-) + +diff --git a/src/technology.c b/src/technology.c +index a06efd3..be66c3a 100644 +--- a/src/technology.c ++++ b/src/technology.c +@@ -245,8 +245,7 @@ static int set_tethering(struct connman_technology *technology, + if (!bridge) + return -EOPNOTSUPP; + +- if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && +- (!ident || !passphrase)) ++ if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && (!ident)) + return -EINVAL; + + for (tech_drivers = technology->driver_list; tech_drivers; +@@ -912,19 +911,30 @@ static DBusMessage *set_property(DBusConnection *conn, + if (technology->type != CONNMAN_SERVICE_TYPE_WIFI) + return __connman_error_not_supported(msg); + +- if (strlen(str) < 8 || strlen(str) > 63) +- return __connman_error_passphrase_required(msg); ++ if (strlen(str) < 8 || strlen(str) > 63) { ++ if (g_str_equal(str, "")) { ++ technology->tethering_passphrase = NULL; + +- if (g_strcmp0(technology->tethering_passphrase, str) != 0) { +- g_free(technology->tethering_passphrase); +- technology->tethering_passphrase = g_strdup(str); +- technology_save(technology); ++ connman_dbus_property_changed_basic(technology->path, ++ CONNMAN_TECHNOLOGY_INTERFACE, ++ "TetheringPassphrase", ++ DBUS_TYPE_STRING, ++ &str); ++ } ++ else ++ return __connman_error_passphrase_required(msg); ++ } else { ++ if (g_strcmp0(technology->tethering_passphrase, str) != 0) { ++ g_free(technology->tethering_passphrase); ++ technology->tethering_passphrase = g_strdup(str); ++ technology_save(technology); + +- connman_dbus_property_changed_basic(technology->path, +- CONNMAN_TECHNOLOGY_INTERFACE, +- "TetheringPassphrase", +- DBUS_TYPE_STRING, +- &technology->tethering_passphrase); ++ connman_dbus_property_changed_basic(technology->path, ++ CONNMAN_TECHNOLOGY_INTERFACE, ++ "TetheringPassphrase", ++ DBUS_TYPE_STRING, ++ &technology->tethering_passphrase); ++ } + } + } else if (g_str_equal(name, "Powered")) { + dbus_bool_t enable; +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0021-Tethering-Add-hidden-access-point-support-in-technol.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0021-Tethering-Add-hidden-access-point-support-in-technol.patch new file mode 100644 index 0000000..a12e98f --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0021-Tethering-Add-hidden-access-point-support-in-technol.patch @@ -0,0 +1,275 @@ +From cdc3af7c29f82b71c2ce76fb6aa28dd6b3d9e5cd Mon Sep 17 00:00:00 2001 +From: Chengyi Zhao +Date: Thu, 11 Jul 2013 10:00:31 +0800 +Subject: [PATCH 21/32] Tethering: Add hidden access point support in + technology + +Change-Id: I73fccf5f322ee2597f8f58d5e3d7f60ddeb0a641 +--- + doc/technology-api.txt | 5 +++++ + gsupplicant/gsupplicant.h | 7 +++++++ + gsupplicant/supplicant.c | 4 ++++ + include/technology.h | 2 +- + plugins/bluetooth.c | 2 +- + plugins/bluetooth_legacy.c | 2 +- + plugins/ethernet.c | 2 +- + plugins/gadget.c | 2 +- + plugins/wifi.c | 13 ++++++++++--- + src/technology.c | 33 ++++++++++++++++++++++++++++++++- + 10 files changed, 63 insertions(+), 9 deletions(-) + +diff --git a/doc/technology-api.txt b/doc/technology-api.txt +index f97eac0..2fbc876 100644 +--- a/doc/technology-api.txt ++++ b/doc/technology-api.txt +@@ -97,3 +97,8 @@ 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. ++ ++ boolean Hidden [readwrite] ++ ++ This option allows to enable or disable the support ++ for the hidden Wi-Fi tethering. +diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h +index 1fab1ba..c5dad72 100644 +--- a/gsupplicant/gsupplicant.h ++++ b/gsupplicant/gsupplicant.h +@@ -129,6 +129,12 @@ typedef enum { + G_SUPPLICANT_PEER_GROUP_FAILED, + } GSupplicantPeerState; + ++enum GSupplicantAPHiddenSSID { ++ G_SUPPLICANT_AP_NO_SSID_HIDING, ++ G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_LEN, ++ G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS, ++}; ++ + struct _GSupplicantSSID { + const void *ssid; + unsigned int ssid_len; +@@ -150,6 +156,7 @@ struct _GSupplicantSSID { + dbus_bool_t use_wps; + const char *pin_wps; + const char *bgscan; ++ int ignore_broadcast_ssid; + }; + + typedef struct _GSupplicantSSID GSupplicantSSID; +diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c +index 5ff9b3d..59bf279 100644 +--- a/gsupplicant/supplicant.c ++++ b/gsupplicant/supplicant.c +@@ -4659,6 +4659,10 @@ static void interface_add_network_params(DBusMessageIter *iter, void *user_data) + DBUS_TYPE_BYTE, &ssid->ssid, + ssid->ssid_len); + ++ supplicant_dbus_dict_append_basic(&dict, "ignore_broadcast_ssid", ++ DBUS_TYPE_INT32, ++ &ssid->ignore_broadcast_ssid); ++ + supplicant_dbus_dict_close(iter, &dict); + } + +diff --git a/include/technology.h b/include/technology.h +index b13d4ec..8efe9e7 100644 +--- a/include/technology.h ++++ b/include/technology.h +@@ -63,7 +63,7 @@ struct connman_technology_driver { + int index); + int (*set_tethering) (struct connman_technology *technology, + const char *identifier, const char *passphrase, +- const char *bridge, bool enabled); ++ const char *bridge, bool enabled, bool hidden); + int (*set_regdom) (struct connman_technology *technology, + const char *alpha2); + }; +diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c +index 28df406..f8abeac 100644 +--- a/plugins/bluetooth.c ++++ b/plugins/bluetooth.c +@@ -854,7 +854,7 @@ 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) ++ const char *bridge, bool enabled, bool hidden) + { + GHashTableIter hash_iter; + gpointer key, value; +diff --git a/plugins/bluetooth_legacy.c b/plugins/bluetooth_legacy.c +index 2d7a9e0..a9ff574 100644 +--- a/plugins/bluetooth_legacy.c ++++ b/plugins/bluetooth_legacy.c +@@ -1234,7 +1234,7 @@ static void disable_nap(gpointer key, gpointer value, gpointer user_data) + + static int tech_set_tethering(struct connman_technology *technology, + const char *identifier, const char *passphrase, +- const char *bridge, bool enabled) ++ const char *bridge, bool enabled, bool hidden) + { + struct tethering_info info = { + .technology = technology, +diff --git a/plugins/ethernet.c b/plugins/ethernet.c +index b8e52ce..4e71346 100644 +--- a/plugins/ethernet.c ++++ b/plugins/ethernet.c +@@ -309,7 +309,7 @@ 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) ++ const char *bridge, bool enabled, bool hidden) + { + if (!connman_technology_is_tethering_allowed( + CONNMAN_SERVICE_TYPE_ETHERNET)) +diff --git a/plugins/gadget.c b/plugins/gadget.c +index 94f6648..97807d8 100644 +--- a/plugins/gadget.c ++++ b/plugins/gadget.c +@@ -291,7 +291,7 @@ 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) ++ const char *bridge, bool enabled, bool hidden) + { + DBG("bridge %s enabled %d", bridge, enabled); + +diff --git a/plugins/wifi.c b/plugins/wifi.c +index b5bc3ba..21f9912 100644 +--- a/plugins/wifi.c ++++ b/plugins/wifi.c +@@ -2927,7 +2927,8 @@ struct wifi_tethering_info { + GSupplicantSSID *ssid; + }; + +-static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase) ++static GSupplicantSSID *ssid_ap_init(const char *ssid, ++ const char *passphrase, bool hidden) + { + GSupplicantSSID *ap; + +@@ -2952,6 +2953,12 @@ static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase) + ap->passphrase = passphrase; + } + ++ if (hidden) ++ ap->ignore_broadcast_ssid = ++ G_SUPPLICANT_AP_HIDDEN_SSID_ZERO_CONTENTS; ++ else ++ ap->ignore_broadcast_ssid = G_SUPPLICANT_AP_NO_SSID_HIDING; ++ + return ap; + } + +@@ -3032,7 +3039,7 @@ static void sta_remove_callback(int result, + + static int tech_set_tethering(struct connman_technology *technology, + const char *identifier, const char *passphrase, +- const char *bridge, bool enabled) ++ const char *bridge, bool enabled, bool hidden) + { + GList *list; + GSupplicantInterface *interface; +@@ -3085,7 +3092,7 @@ static int tech_set_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(identifier, passphrase, hidden); + if (!info->ssid) { + g_free(info); + continue; +diff --git a/src/technology.c b/src/technology.c +index be66c3a..679c779 100644 +--- a/src/technology.c ++++ b/src/technology.c +@@ -66,6 +66,7 @@ struct connman_technology { + */ + char *tethering_ident; + char *tethering_passphrase; ++ bool tethering_hidden; + + bool enable_persistent; /* Save the tech state */ + +@@ -177,6 +178,9 @@ static void technology_save(struct connman_technology *technology) + g_key_file_set_boolean(keyfile, identifier, "Tethering", + technology->tethering_persistent); + ++ g_key_file_set_boolean(keyfile, identifier, "Hidden", ++ technology->tethering_hidden); ++ + if (technology->tethering_ident) + g_key_file_set_string(keyfile, identifier, + "Tethering.Identifier", +@@ -233,9 +237,11 @@ static int set_tethering(struct connman_technology *technology, + int err; + const char *ident, *passphrase, *bridge; + GSList *tech_drivers; ++ bool hidden; + + ident = technology->tethering_ident; + passphrase = technology->tethering_passphrase; ++ hidden = technology->tethering_hidden; + + __sync_synchronize(); + if (!technology->enabled) +@@ -256,7 +262,7 @@ static int set_tethering(struct connman_technology *technology, + continue; + + err = driver->set_tethering(technology, ident, passphrase, +- bridge, enabled); ++ bridge, enabled, hidden); + + if (result == -EINPROGRESS) + continue; +@@ -523,6 +529,11 @@ static void append_properties(DBusMessageIter *iter, + DBUS_TYPE_STRING, + &technology->tethering_passphrase); + ++ val = technology->tethering_hidden; ++ connman_dbus_dict_append_basic(&dict, "Hidden", ++ DBUS_TYPE_BOOLEAN, ++ &val); ++ + connman_dbus_dict_close(iter, &dict); + } + +@@ -936,6 +947,25 @@ static DBusMessage *set_property(DBusConnection *conn, + &technology->tethering_passphrase); + } + } ++ } else if (g_str_equal(name, "Hidden")) { ++ dbus_bool_t hidden; ++ ++ if (type != DBUS_TYPE_BOOLEAN) ++ return __connman_error_invalid_arguments(msg); ++ ++ dbus_message_iter_get_basic(&value, &hidden); ++ ++ if (technology->type != CONNMAN_SERVICE_TYPE_WIFI) ++ return __connman_error_not_supported(msg); ++ ++ technology->tethering_hidden = hidden; ++ technology_save(technology); ++ ++ connman_dbus_property_changed_basic(technology->path, ++ CONNMAN_TECHNOLOGY_INTERFACE, ++ "Hidden", ++ DBUS_TYPE_BOOLEAN, ++ &hidden); + } else if (g_str_equal(name, "Powered")) { + dbus_bool_t enable; + +@@ -1204,6 +1234,7 @@ static struct connman_technology *technology_get(enum connman_service_type type) + + technology->refcount = 1; + technology->type = type; ++ technology->tethering_hidden = FALSE; + technology->path = g_strdup_printf("%s/technology/%s", + CONNMAN_PATH, str); + if (type == CONNMAN_SERVICE_TYPE_P2P) { +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0022-Tethering-Add-test-script-of-open-and-hidden-AP.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0022-Tethering-Add-test-script-of-open-and-hidden-AP.patch new file mode 100644 index 0000000..c2bf003 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0022-Tethering-Add-test-script-of-open-and-hidden-AP.patch @@ -0,0 +1,86 @@ +From 395d388931d37b6760d7b9f59a5710dfe42662c7 Mon Sep 17 00:00:00 2001 +From: Chengyi Zhao +Date: Thu, 11 Jul 2013 10:29:38 +0800 +Subject: [PATCH 22/32] Tethering: Add test script of open and hidden AP + +Change-Id: I8dbeaeba5848c8a8739422a93786b2ca6ed31b21 +--- + test/enable-tethering | 34 +++++++++++++++++++++++++++------- + 1 file changed, 27 insertions(+), 7 deletions(-) + mode change 100755 => 100644 test/enable-tethering + +diff --git a/test/enable-tethering b/test/enable-tethering +old mode 100755 +new mode 100644 +index cbcd4e7..674b3c9 +--- a/test/enable-tethering ++++ b/test/enable-tethering +@@ -3,8 +3,17 @@ + import sys + import dbus + +-if (len(sys.argv) >= 3 and len(sys.argv) != 4 and sys.argv[1] == "wifi"): +- print "Usage: %s wifi [SSID] [passphrase]" % (sys.argv[0]) ++if (len(sys.argv) >= 2 and len(sys.argv) < 4 and sys.argv[1] == "wifi"): ++ print "Usage: %s wifi [SSID] [passphrase] [hidden]" % (sys.argv[0]) ++ print "Example:" ++ print "Create the open system access point:" ++ print "%s wifi abcd \"\"" % (sys.argv[0]) ++ print "Create the security access point:" ++ print "%s wifi abcd 123456789" % (sys.argv[0]) ++ print "Create the hidden access point:" ++ print "%s wifi abcd 123456789 hidden" % (sys.argv[0]) ++ print "Create the open and hidden access point:" ++ print "%s wifi abcd \"\" hidden" % (sys.argv[0]) + sys.exit(1) + elif (len(sys.argv) < 2): + print "Usage: %s type" % (sys.argv[0]) +@@ -15,7 +24,7 @@ bus = dbus.SystemBus() + manager = dbus.Interface(bus.get_object('net.connman', "/"), + 'net.connman.Manager') + +-def technology_enable_tethering(path, tech_type, ssid, psk): ++def technology_enable_tethering(path, tech_type, ssid, psk, hidden): + tech = dbus.Interface(bus.get_object("net.connman", path), + "net.connman.Technology") + +@@ -27,9 +36,17 @@ def technology_enable_tethering(path, tech_type, ssid, psk): + if len(ssid) > 0: + tech.SetProperty("TetheringIdentifier", + ssid) +- if len(psk) > 0: + tech.SetProperty("TetheringPassphrase", + psk) ++ if tech_type == "wifi": ++ if len(hidden) > 0: ++ if hidden == "hidden": ++ tech.SetProperty("Hidden",dbus.Boolean(1)) ++ else: ++ tech.SetProperty("Hidden",dbus.Boolean(0)) ++ else: ++ tech.SetProperty("Hidden",dbus.Boolean(0)) ++ + print "Enabling %s tethering" % tech_type + tech.SetProperty("Tethering", dbus.Boolean(1)) + +@@ -41,11 +58,14 @@ technologies = manager.GetTechnologies() + tech = None + + for path,_ in technologies: +- if (len(sys.argv) == 4): ++ if (len(sys.argv) == 5): ++ tech = technology_enable_tethering(path, ++ sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4]) ++ elif (len(sys.argv) == 4): + tech = technology_enable_tethering(path, +- sys.argv[1], sys.argv[2], sys.argv[3]) ++ sys.argv[1], sys.argv[2], sys.argv[3], "") + else: +- tech = technology_enable_tethering(path, sys.argv[1], "", "") ++ tech = technology_enable_tethering(path, sys.argv[1], "", "", "") + + if tech != None: + break; +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0023-Tethering-Add-tethering-interfaces-description-to-te.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0023-Tethering-Add-tethering-interfaces-description-to-te.patch new file mode 100644 index 0000000..3049ae1 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0023-Tethering-Add-tethering-interfaces-description-to-te.patch @@ -0,0 +1,37 @@ +From 5eb028f4bdf85b35d8003f36ee95b15e48aa3fbc Mon Sep 17 00:00:00 2001 +From: Chengyi Zhao +Date: Fri, 26 Jul 2013 14:58:32 +0800 +Subject: [PATCH 23/32] Tethering: Add tethering interfaces description to + technology-api.txt + +Change-Id: I59768258d5f2515311ed3dad5db91618b1c459ec +--- + doc/technology-api.txt | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/doc/technology-api.txt b/doc/technology-api.txt +index 2fbc876..14245eb 100644 +--- a/doc/technology-api.txt ++++ b/doc/technology-api.txt +@@ -45,6 +45,18 @@ Signals PropertyChanged(string name, variant value) + This signal indicates a changed value of the given + property. + ++ DhcpConnected(string aptype, string ipaddr, ++ string macaddr, string hostname) ++ ++ This signal indicates a station information that ++ has connected to the AP(Access Point). ++ ++ DhcpLeaseDeleted(string aptype, string ipaddr, ++ string macaddr, string hostname) ++ ++ This signal indicates a station information that ++ has disconnected to the AP(Access Point). ++ + Properties boolean Powered [readwrite] + + Boolean representing the power state of the +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0024-Tethering-Watch-the-connection-and-disconnection-sig.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0024-Tethering-Watch-the-connection-and-disconnection-sig.patch new file mode 100644 index 0000000..7c86d21 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0024-Tethering-Watch-the-connection-and-disconnection-sig.patch @@ -0,0 +1,138 @@ +From 4f74881432eee7f368ae6827aa2453115749734e Mon Sep 17 00:00:00 2001 +From: Chengyi Zhao +Date: Sun, 22 Sep 2013 14:14:06 +0800 +Subject: [PATCH 24/32] Tethering: Watch the connection and disconnection + signal of Bluetooth + +Signed-off-by: Chengyi Zhao + +Change-Id: I38bb9b799c3e4c4c25acd9d264a4225bf59401dc +--- + plugins/bluetooth_legacy.c | 75 ++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 72 insertions(+), 3 deletions(-) + +diff --git a/plugins/bluetooth_legacy.c b/plugins/bluetooth_legacy.c +index a9ff574..5a9a395 100644 +--- a/plugins/bluetooth_legacy.c ++++ b/plugins/bluetooth_legacy.c +@@ -51,6 +51,9 @@ + #define ADAPTER_REMOVED "AdapterRemoved" + #define DEVICE_REMOVED "DeviceRemoved" + ++#define PEER_CONNECTED "PeerConnected" ++#define PEER_DISCONNECTED "PeerDisconnected" ++ + #define PROPERTY_CHANGED "PropertyChanged" + #define GET_PROPERTIES "GetProperties" + #define SET_PROPERTY "SetProperty" +@@ -334,6 +337,53 @@ static gboolean network_changed(DBusConnection *conn, + return TRUE; + } + ++static void parse_peer_device(DBusMessage *message, char **dev, ++ char **address) ++{ ++ const char *path = dbus_message_get_path(message); ++ DBusMessageIter iter; ++ ++ DBG("path %s", path); ++ ++ if (dbus_message_iter_init(message, &iter) == FALSE) ++ return; ++ ++ dbus_message_iter_get_basic(&iter, dev); ++ dbus_message_iter_next(&iter); ++ dbus_message_iter_get_basic(&iter, address); ++} ++ ++static gboolean peer_connected(DBusConnection *connection, ++ DBusMessage *message, void *user_data) ++{ ++ char *dev, *address; ++ ++ parse_peer_device(message, &dev, &address); ++ ++ DBG("connection device is %s", dev); ++ DBG("connection address is %s", address); ++ ++ connman_technology_tethering_add_station( ++ CONNMAN_SERVICE_TYPE_BLUETOOTH, address); ++ ++ return TRUE; ++} ++ ++static gboolean peer_disconnected(DBusConnection *connection, ++ DBusMessage *message, void *user_data) ++{ ++ char *dev, *address; ++ ++ parse_peer_device(message, &dev, &address); ++ ++ DBG("disconnection device is %s", dev); ++ DBG("disconnection address is %s", address); ++ ++ connman_technology_tethering_remove_station(address); ++ ++ return TRUE; ++} ++ + static void extract_properties(DBusMessage *reply, const char **parent, + const char **address, + const char **name, +@@ -1270,6 +1320,8 @@ static guint adapter_watch; + static guint device_watch; + static guint device_removed_watch; + static guint network_watch; ++static guint peerconnected_watch; ++static guint peerdisconnected_watch; + + static int bluetooth_init(void) + { +@@ -1313,10 +1365,23 @@ static int bluetooth_init(void) + PROPERTY_CHANGED, network_changed, + NULL, NULL); + ++ peerconnected_watch = g_dbus_add_signal_watch(connection, ++ BLUEZ_SERVICE, ++ NULL, BLUEZ_NETWORK_SERVER, ++ PEER_CONNECTED, peer_connected, ++ NULL, NULL); ++ ++ peerdisconnected_watch = g_dbus_add_signal_watch(connection, ++ BLUEZ_SERVICE, ++ NULL, BLUEZ_NETWORK_SERVER, ++ PEER_DISCONNECTED, ++ peer_disconnected, ++ NULL, NULL); ++ + if (watch == 0 || added_watch == 0 || removed_watch == 0 +- || adapter_watch == 0 || network_watch == 0 +- || device_watch == 0 +- || device_removed_watch == 0) { ++ || adapter_watch == 0 || network_watch == 0 || device_watch == 0 ++ || peerconnected_watch == 0 || peerdisconnected_watch == 0 ++ || device_removed_watch == 0) { + err = -EIO; + goto remove; + } +@@ -1348,6 +1413,8 @@ remove: + g_dbus_remove_watch(connection, device_removed_watch); + g_dbus_remove_watch(connection, device_watch); + g_dbus_remove_watch(connection, network_watch); ++ g_dbus_remove_watch(connection, peerconnected_watch); ++ g_dbus_remove_watch(connection, peerdisconnected_watch); + + dbus_connection_unref(connection); + +@@ -1363,6 +1430,8 @@ static void bluetooth_exit(void) + g_dbus_remove_watch(connection, device_removed_watch); + g_dbus_remove_watch(connection, device_watch); + g_dbus_remove_watch(connection, network_watch); ++ g_dbus_remove_watch(connection, peerconnected_watch); ++ g_dbus_remove_watch(connection, peerdisconnected_watch); + + /* + * We unset the disabling of the Bluetooth device when shutting down +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0025-Tethering-Get-the-client-mac-info-of-Gadget-tether.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0025-Tethering-Get-the-client-mac-info-of-Gadget-tether.patch new file mode 100644 index 0000000..6b5c090 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0025-Tethering-Get-the-client-mac-info-of-Gadget-tether.patch @@ -0,0 +1,154 @@ +From 58bd810c3a61593a3c7494f843fc5dfc1d411769 Mon Sep 17 00:00:00 2001 +From: "guoqiang.liu" +Date: Wed, 25 Sep 2013 16:36:21 +0800 +Subject: [PATCH 25/32] Tethering: Get the client mac info of Gadget tether + +Change-Id: Icfa6cd683c659e6728060d6201b90109c63fe56d +--- + plugins/gadget.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 87 insertions(+) + +diff --git a/plugins/gadget.c b/plugins/gadget.c +index 97807d8..6bc37a7 100644 +--- a/plugins/gadget.c ++++ b/plugins/gadget.c +@@ -25,6 +25,8 @@ + + #include + #include ++#include ++#include + + #ifndef IFF_LOWER_UP + #define IFF_LOWER_UP 0x10000 +@@ -226,6 +228,71 @@ static struct connman_device_driver gadget_dev_driver = { + }; + + static GList *cdc_interface_list = NULL; ++static GHashTable *cdc_mac_hash = NULL; ++ ++static void add_station(int index) ++{ ++ char *path, line[128] = {'\0'}; ++ char *ifname = connman_inet_ifname(index); ++ char *mac; ++ FILE *f; ++ ++ if (ifname == NULL) ++ return; ++ ++ path = g_strdup_printf("/sys/class/usb_mode/%s/f_rndis/ethaddr", ++ ifname); ++ ++ f = fopen(path, "re"); ++ ++ g_free(ifname); ++ g_free(path); ++ ++ if (f == NULL) ++ return; ++ ++ if (fgets(line, sizeof(line), f) == NULL) { ++ fclose(f); ++ return; ++ } ++ ++ fclose(f); ++ ++ mac = g_ascii_strdown(line, strlen(line) - 1); ++ DBG("Add station %s in Technology %d", mac, ++ CONNMAN_SERVICE_TYPE_GADGET); ++ ++ g_hash_table_insert(cdc_mac_hash, GINT_TO_POINTER(index), ++ mac); ++ ++ connman_technology_tethering_add_station(CONNMAN_SERVICE_TYPE_GADGET, ++ mac); ++} ++ ++static void remove_station(int index) ++{ ++ char *mac; ++ mac = g_hash_table_lookup(cdc_mac_hash, GINT_TO_POINTER(index)); ++ if (mac == NULL) ++ return; ++ ++ connman_technology_tethering_remove_station(mac); ++ ++ g_hash_table_remove(cdc_mac_hash, GINT_TO_POINTER(index)); ++} ++ ++static gboolean remove_all_station(gpointer key, gpointer value, gpointer user_data) ++{ ++ char *mac; ++ mac = value; ++ if (mac == NULL) ++ return TRUE; ++ ++ connman_technology_tethering_remove_station(mac); ++ ++ return TRUE; ++} ++ + + static void gadget_tech_add_interface(struct connman_technology *technology, + int index, const char *name, const char *ident) +@@ -246,6 +313,8 @@ static void gadget_tech_remove_interface(struct connman_technology *technology, + + cdc_interface_list = g_list_remove(cdc_interface_list, + GINT_TO_POINTER((int) index)); ++ ++ remove_station(index); + } + + static void gadget_tech_enable_tethering(struct connman_technology *technology, +@@ -270,6 +339,8 @@ static void gadget_tech_enable_tethering(struct connman_technology *technology, + connman_inet_ifup(index); + + connman_inet_add_to_bridge(index, bridge); ++ ++ add_station(index); + } + } + +@@ -283,6 +354,8 @@ static void gadget_tech_disable_tethering(struct connman_technology *technology, + + connman_inet_remove_from_bridge(index, bridge); + ++ remove_station(index); ++ + connman_inet_ifdown(index); + + connman_technology_tethering_notify(technology, false); +@@ -305,14 +378,28 @@ static int gadget_tech_set_tethering(struct connman_technology *technology, + + static int gadget_tech_probe(struct connman_technology *technology) + { ++ DBG("tech probe %p", technology); ++ ++ cdc_mac_hash = g_hash_table_new_full(g_direct_hash, ++ g_direct_equal, NULL, g_free); ++ + return 0; + } + + static void gadget_tech_remove(struct connman_technology *technology) + { ++ DBG("tech remove %p", technology); ++ + g_list_free(cdc_interface_list); + + cdc_interface_list = NULL; ++ ++ if (cdc_mac_hash) { ++ g_hash_table_foreach_remove(cdc_mac_hash, remove_all_station, ++ NULL); ++ g_hash_table_destroy(cdc_mac_hash); ++ cdc_mac_hash = NULL; ++ } + } + + static struct connman_technology_driver gadget_tech_driver = { +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0026-multi-user-Add-function-to-get-dbus-user-id-synchron.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0026-multi-user-Add-function-to-get-dbus-user-id-synchron.patch new file mode 100644 index 0000000..265e47c --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0026-multi-user-Add-function-to-get-dbus-user-id-synchron.patch @@ -0,0 +1,66 @@ +From 113ccd0ca92ab8fe8a6e6c2db190cbcbeebe912d Mon Sep 17 00:00:00 2001 +From: Zhang zhengguang +Date: Sat, 11 Oct 2014 15:06:14 +0800 +Subject: [PATCH 26/32] multi-user: Add function to get dbus user id + synchronously + +Change-Id: Ic41643e5f8b6e1a28ce00e0456d961fe2de7a7fb +--- + include/dbus.h | 4 ++++ + src/dbus.c | 25 +++++++++++++++++++++++++ + 2 files changed, 29 insertions(+) + +diff --git a/include/dbus.h b/include/dbus.h +index 26f94d6..3087fe4 100644 +--- a/include/dbus.h ++++ b/include/dbus.h +@@ -180,6 +180,10 @@ int connman_dbus_get_connection_unix_user(DBusConnection *connection, + connman_dbus_get_connection_unix_user_cb_t func, + void *user_data); + ++int connman_dbus_get_connection_unix_user_sync(DBusConnection *connection, ++ const char *bus_name, ++ unsigned int *user_id); ++ + typedef void (* connman_dbus_get_context_cb_t) (const unsigned char *context, + void *user_data, int err); + +diff --git a/src/dbus.c b/src/dbus.c +index d80a46c..260cec6 100644 +--- a/src/dbus.c ++++ b/src/dbus.c +@@ -524,6 +524,31 @@ err: + return err; + } + ++int connman_dbus_get_connection_unix_user_sync(DBusConnection *connection, ++ const char *bus_name, ++ unsigned int *user_id) ++{ ++ unsigned long uid; ++ DBusError err; ++ ++ dbus_error_init(&err); ++ ++ uid = dbus_bus_get_unix_user(connection, bus_name, &err); ++ ++ if (uid == (unsigned long)-1) { ++ DBG("Can not get unix user ID!"); ++ if (dbus_error_is_set(&err)) { ++ DBG("%s", err.message); ++ dbus_error_free(&err); ++ } ++ return -1; ++ } ++ ++ *user_id = (unsigned int)uid; ++ ++ return 0; ++} ++ + static unsigned char *parse_context(DBusMessage *msg) + { + DBusMessageIter iter, array; +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0027-multi-user-Add-multi-user-support-in-service.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0027-multi-user-Add-multi-user-support-in-service.patch new file mode 100644 index 0000000..d8e8092 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0027-multi-user-Add-multi-user-support-in-service.patch @@ -0,0 +1,302 @@ +From 44a0a44c579df0192ec33c291b2efdfabfe5c7eb Mon Sep 17 00:00:00 2001 +From: Zhang zhengguang +Date: Sat, 11 Oct 2014 15:08:18 +0800 +Subject: [PATCH 27/32] multi-user: Add multi-user support in service + +Use cases: + +Given 2 users: UserA and UserB + +1. If UserA is connected to a wifi service, then UserB is not allowed +to connect wifi service, and not allowed to disconnect the service +UserA connected. + +2. If UserA is connected to a wifi service, then UserB is allowed to +use the same connection, but he is not allowed to modify the connection. + +3. If UserA is connected to a wifi service with security wep/wpa/psk, +then UserA disconnects it, when UserB tries to connect the same wifi +service, it must input passphrase to connect it. + +Change-Id: Id686ebd7d1f3490875a9d8f877219bd004907227 +--- + src/connman.h | 3 ++ + src/service.c | 157 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- + 2 files changed, 159 insertions(+), 1 deletion(-) + +diff --git a/src/connman.h b/src/connman.h +index 4d78eab..386e8c8 100644 +--- a/src/connman.h ++++ b/src/connman.h +@@ -791,6 +791,9 @@ void __connman_service_notify(struct connman_service *service, + unsigned int rx_error, unsigned int tx_error, + unsigned int rx_dropped, unsigned int tx_dropped); + ++bool __connman_service_is_user_allowed(enum connman_service_type type, ++ uid_t uid); ++ + int __connman_service_counter_register(const char *counter); + void __connman_service_counter_unregister(const char *counter); + +diff --git a/src/service.c b/src/service.c +index 99bb35d..a1124ae 100644 +--- a/src/service.c ++++ b/src/service.c +@@ -39,6 +39,9 @@ + + #define CONNECT_TIMEOUT 120 + ++#define USER_ROOT 0 ++#define USER_NONE (uid_t)-1 ++ + #if defined TIZEN_EXT + #define WIFI_BSSID_STR_LEN 18 + #endif +@@ -67,6 +70,11 @@ struct connman_stats_counter { + struct connman_stats stats_roaming; + }; + ++struct connman_service_user { ++ uid_t favorite_user; ++ uid_t current_user; ++}; ++ + struct connman_service { + int refcount; + char *identifier; +@@ -89,6 +97,8 @@ struct connman_service { + char *name; + char *passphrase; + bool roaming; ++ bool request_passphrase_input; ++ struct connman_service_user user; + struct connman_ipconfig *ipconfig_ipv4; + struct connman_ipconfig *ipconfig_ipv6; + struct connman_network *network; +@@ -351,6 +361,24 @@ static enum connman_service_proxy_method string2proxymethod(const char *method) + return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN; + } + ++static bool ++connman_service_is_user_allowed(struct connman_service *service, uid_t uid) ++{ ++ uid_t favorite_user = service->user.favorite_user; ++ uid_t current_user = uid; ++ ++ DBG("Service favorite UID: %d, current UID: %d", favorite_user, current_user); ++ if (favorite_user == USER_NONE || current_user == USER_ROOT) ++ return true; ++ ++ if (favorite_user != current_user || current_user == USER_NONE) { ++ DBG("Current user is not a favorite user to this service!"); ++ return false; ++ } ++ ++ return true; ++} ++ + int __connman_service_load_modifiable(struct connman_service *service) + { + GKeyFile *keyfile; +@@ -574,6 +602,8 @@ static int service_load(struct connman_service *service) + service->hidden_service = g_key_file_get_boolean(keyfile, + service->identifier, "Hidden", NULL); + ++ service->user.favorite_user = g_key_file_get_integer(keyfile, ++ service->identifier, "UID", NULL); + done: + g_key_file_free(keyfile); + +@@ -619,6 +649,9 @@ static int service_save(struct connman_service *service) + const unsigned char *ssid; + unsigned int ssid_len = 0; + ++ g_key_file_set_integer(keyfile, service->identifier, ++ "UID", service->user.favorite_user); ++ + ssid = connman_network_get_blob(service->network, + "WiFi.SSID", &ssid_len); + +@@ -3236,6 +3269,21 @@ static DBusMessage *set_property(DBusConnection *conn, + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) + return __connman_error_invalid_arguments(msg); + ++ if (service->type == CONNMAN_SERVICE_TYPE_WIFI && is_connected(service)) { ++ uid_t uid; ++ if (connman_dbus_get_connection_unix_user_sync(conn, ++ dbus_message_get_sender(msg), ++ &uid) < 0) { ++ DBG("Can not get unix user id!"); ++ return __connman_error_permission_denied(msg); ++ } ++ ++ if (!connman_service_is_user_allowed(service, uid)) { ++ DBG("Not allow this user to operate this wifi service now!"); ++ return __connman_error_permission_denied(msg); ++ } ++ } ++ + dbus_message_iter_get_basic(&iter, &name); + dbus_message_iter_next(&iter); + +@@ -3997,6 +4045,26 @@ static DBusMessage *connect_service(DBusConnection *conn, + if (service->pending) + return __connman_error_in_progress(msg); + ++ if (service->type == CONNMAN_SERVICE_TYPE_WIFI) { ++ uid_t uid; ++ if (connman_dbus_get_connection_unix_user_sync(conn, ++ dbus_message_get_sender(msg), ++ &uid) < 0) { ++ DBG("Can not get unix user id!"); ++ return __connman_error_permission_denied(msg); ++ } ++ ++ if (!__connman_service_is_user_allowed(CONNMAN_SERVICE_TYPE_WIFI, uid)) { ++ DBG("Not allow this user to connect this wifi service now!"); ++ return __connman_error_permission_denied(msg); ++ } ++ ++ if (uid != USER_ROOT && uid != service->user.favorite_user) ++ service->request_passphrase_input = true; ++ ++ service->user.current_user = uid; ++ } ++ + index = __connman_service_get_index(service); + + for (list = service_list; list; list = list->next) { +@@ -4048,6 +4116,21 @@ static DBusMessage *disconnect_service(DBusConnection *conn, + + DBG("service %p", service); + ++ if (service->type == CONNMAN_SERVICE_TYPE_WIFI) { ++ uid_t uid; ++ if (connman_dbus_get_connection_unix_user_sync(conn, ++ dbus_message_get_sender(msg), ++ &uid) < 0) { ++ DBG("Can not get unix user id!"); ++ return __connman_error_permission_denied(msg); ++ } ++ ++ if (!connman_service_is_user_allowed(service, uid)) { ++ DBG("Not allow this user to disconnect this wifi service now!"); ++ return __connman_error_permission_denied(msg); ++ } ++ } ++ + service->ignore = true; + + err = __connman_service_disconnect(service); +@@ -4103,6 +4186,21 @@ static DBusMessage *remove_service(DBusConnection *conn, + + DBG("service %p", service); + ++ if (service->type == CONNMAN_SERVICE_TYPE_WIFI) { ++ uid_t uid; ++ if (connman_dbus_get_connection_unix_user_sync(conn, ++ dbus_message_get_sender(msg), ++ &uid) < 0) { ++ DBG("Can not get unix user id!"); ++ return __connman_error_permission_denied(msg); ++ } ++ ++ if (!connman_service_is_user_allowed(service, uid)) { ++ DBG("Not allow this user to remove this wifi service now!"); ++ return __connman_error_permission_denied(msg); ++ } ++ } ++ + if (!__connman_service_remove(service)) + return __connman_error_not_supported(msg); + +@@ -4583,6 +4681,11 @@ static void service_initialize(struct connman_service *service) + + service->ignore = false; + ++ service->user.favorite_user = USER_NONE; ++ service->user.current_user = USER_NONE; ++ ++ service->request_passphrase_input = false; ++ + service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_NONE; + + service->order = 0; +@@ -4809,6 +4912,40 @@ char *connman_service_get_interface(struct connman_service *service) + } + + /** ++ * __connman_service_is_user_allowed: ++ * @type: service type ++ * @uid: user id ++ * ++ * Check a user is allowed to operate a type of service ++ */ ++bool __connman_service_is_user_allowed(enum connman_service_type type, ++ uid_t uid) ++{ ++ GList *list; ++ uid_t owner_user = USER_NONE; ++ ++ for (list = service_list; list; list = list->next) { ++ struct connman_service *service = list->data; ++ ++ if (service->type != type) ++ continue; ++ ++ if (is_connected(service)) { ++ owner_user = service->user.favorite_user; ++ break; ++ } ++ } ++ ++ if (uid == USER_NONE || ++ (uid != USER_ROOT && ++ owner_user != USER_NONE && ++ owner_user != uid)) ++ return false; ++ ++ return true; ++} ++ ++/** + * connman_service_get_network: + * @service: service structure + * +@@ -5487,6 +5624,20 @@ static int service_indicate_state(struct connman_service *service) + default_changed(); + } + ++ if (service->type == CONNMAN_SERVICE_TYPE_WIFI && ++ service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER && ++ (new_state == CONNMAN_SERVICE_STATE_READY || ++ new_state == CONNMAN_SERVICE_STATE_ONLINE)) { ++ if (service->user.favorite_user != service->user.current_user) { ++ DBG("Now set service favorite user id from %d to %d", ++ service->user.favorite_user, service->user.current_user); ++ ++ service->user.favorite_user = service->user.current_user; ++ ++ service_save(service); ++ } ++ } ++ + return 0; + } + +@@ -5898,7 +6049,11 @@ static int service_connect(struct connman_service *service) + case CONNMAN_SERVICE_SECURITY_PSK: + case CONNMAN_SERVICE_SECURITY_WPA: + case CONNMAN_SERVICE_SECURITY_RSN: +- if (!service->passphrase) { ++ if (service->request_passphrase_input) { ++ DBG("Now try to connect other user's favorite service"); ++ service->request_passphrase_input = false; ++ return -ENOKEY; ++ } else if (!service->passphrase) { + if (!service->network) + return -EOPNOTSUPP; + +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0028-multi-user-Add-multi-user-support-in-technology.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0028-multi-user-Add-multi-user-support-in-technology.patch new file mode 100644 index 0000000..ebb04a0 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0028-multi-user-Add-multi-user-support-in-technology.patch @@ -0,0 +1,46 @@ +From 37cbead2d2cbea4b9bd9f7180caf26a4b653662d Mon Sep 17 00:00:00 2001 +From: Zhang zhengguang +Date: Sat, 11 Oct 2014 15:09:09 +0800 +Subject: [PATCH 28/32] multi-user: Add multi-user support in technology + +Use case: + +Given 2 users: UserA and UserB + +If UserA is connected to a wifi service, then UserB is not allowed +to set wifi technology properties. + +Change-Id: Ia783b22bc28e9e487ddfa3a4c249c9d1ea76bde8 +--- + src/technology.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/src/technology.c b/src/technology.c +index 679c779..70732f6 100644 +--- a/src/technology.c ++++ b/src/technology.c +@@ -862,6 +862,21 @@ static DBusMessage *set_property(DBusConnection *conn, + + DBG("property %s", name); + ++ if (technology->type == CONNMAN_SERVICE_TYPE_WIFI && technology->connected) { ++ uid_t uid; ++ if (connman_dbus_get_connection_unix_user_sync(conn, ++ dbus_message_get_sender(msg), ++ &uid) < 0) { ++ DBG("Can not get unix user id!"); ++ return __connman_error_permission_denied(msg); ++ } ++ ++ if (!__connman_service_is_user_allowed(CONNMAN_SERVICE_TYPE_WIFI, uid)) { ++ DBG("Not allow this user to operate wifi technology now!"); ++ return __connman_error_permission_denied(msg); ++ } ++ } ++ + if (g_str_equal(name, "Tethering")) { + dbus_bool_t tethering; + int err; +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0029-multi-user-Add-multi-user-support-in-manager.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0029-multi-user-Add-multi-user-support-in-manager.patch new file mode 100644 index 0000000..efcffd6 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0029-multi-user-Add-multi-user-support-in-manager.patch @@ -0,0 +1,45 @@ +From 9235632fd02062efa3a1af7eb1957fdd364f4a8c Mon Sep 17 00:00:00 2001 +From: Zhang zhengguang +Date: Fri, 17 Oct 2014 11:21:37 +0800 +Subject: [PATCH 29/32] multi-user: Add multi-user support in manager + +Use case: + +Given 2 users: UserA and UserB + +If UserA is connected to a wifi service, then UserB is not allowed +to turn on offline mode. + +Change-Id: I54b108beb580a805c7fa2d3ae9dac192b836ba77 +--- + src/manager.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/src/manager.c b/src/manager.c +index d15ce20..bd52f39 100644 +--- a/src/manager.c ++++ b/src/manager.c +@@ -102,6 +102,20 @@ static DBusMessage *set_property(DBusConnection *conn, + + dbus_message_iter_get_basic(&value, &offlinemode); + ++ if (offlinemode) { ++ uid_t uid; ++ if (connman_dbus_get_connection_unix_user_sync(conn, ++ dbus_message_get_sender(msg), ++ &uid) < 0) { ++ DBG("Can not get unix user id!"); ++ return __connman_error_permission_denied(msg); ++ } ++ ++ if (!__connman_service_is_user_allowed(CONNMAN_SERVICE_TYPE_WIFI, uid)) { ++ DBG("Not allow this user to turn on offlinemode now!"); ++ return __connman_error_permission_denied(msg); ++ } ++ } + __connman_technology_set_offlinemode(offlinemode); + } else if (g_str_equal(name, "SessionMode")) { + +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0030-multi-user-Add-multi-user-support-for-auto-connect-s.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0030-multi-user-Add-multi-user-support-for-auto-connect-s.patch new file mode 100644 index 0000000..c7d6817 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0030-multi-user-Add-multi-user-support-for-auto-connect-s.patch @@ -0,0 +1,106 @@ +From 96469b8ff2cd0e7dc77b7974c431f1dd97981356 Mon Sep 17 00:00:00 2001 +From: Zhang zhengguang +Date: Sat, 11 Oct 2014 16:46:50 +0800 +Subject: [PATCH 30/32] multi-user: Add multi-user support for auto connect + service + +Use case: + +For wifi auto connect mechamnism, only when the user who owns the +wifi service login, the service is allowed to be auto connected. + +Change-Id: I99135117facafda41532e0280c89194b27baac16 +--- + src/service.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 62 insertions(+) + +diff --git a/src/service.c b/src/service.c +index a1124ae..55cf02c 100644 +--- a/src/service.c ++++ b/src/service.c +@@ -30,6 +30,8 @@ + #include + #include + #include ++#include ++#include + + #include + #include +@@ -379,6 +381,61 @@ connman_service_is_user_allowed(struct connman_service *service, uid_t uid) + return true; + } + ++static GList *connman_service_get_login_users() ++{ ++ struct utmpx *utmp; ++ struct passwd *pwd; ++ GList *user_list = NULL; ++ ++ setutxent(); ++ ++ while ((utmp = getutxent()) != NULL) { ++ if (utmp->ut_user != USER_ROOT && utmp->ut_type != USER_PROCESS) ++ continue; ++ ++ pwd = getpwnam(utmp->ut_user); ++ ++ if (!g_list_find(user_list, GUINT_TO_POINTER(pwd->pw_uid))) ++ user_list = g_list_append(user_list, ++ GUINT_TO_POINTER(pwd->pw_uid)); ++ ++ DBG("User Name: %s, UID: %d", utmp->ut_user, pwd->pw_uid); ++ } ++ ++ endutxent(); ++ ++ return user_list; ++} ++ ++static bool is_service_owner_user_login(struct connman_service *service) ++{ ++ GList *list, *user_list; ++ bool ret = false; ++ ++ /* Here we only care about wifi service */ ++ if (service->type != CONNMAN_SERVICE_TYPE_WIFI) ++ return true; ++ ++ user_list = connman_service_get_login_users(); ++ ++ DBG("service favorite user id is: %d", service->user.favorite_user); ++ ++ for (list = user_list; list; list = list->next) { ++ uid_t uid = GPOINTER_TO_UINT(list->data); ++ ++ DBG("login user id is %d", uid); ++ ++ if (service->user.favorite_user == uid) { ++ ret = true; ++ break; ++ } ++ } ++ ++ g_list_free(user_list); ++ ++ return ret; ++} ++ + int __connman_service_load_modifiable(struct connman_service *service) + { + GKeyFile *keyfile; +@@ -3800,6 +3857,11 @@ static bool auto_connect_service(GList *services, + continue; + } + ++ if (!is_service_owner_user_login(service)) { ++ DBG("favorite user not login, wifi auto connect denied"); ++ continue; ++ } ++ + DBG("service %p %s %s", service, service->name, + (preferred) ? "preferred" : reason2string(reason)); + +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0031-multi-user-Expose-function-to-check-service-user-fav.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0031-multi-user-Expose-function-to-check-service-user-fav.patch new file mode 100644 index 0000000..4945b38 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0031-multi-user-Expose-function-to-check-service-user-fav.patch @@ -0,0 +1,81 @@ +From 9d476728838e2442d349adb679147581a963f8e9 Mon Sep 17 00:00:00 2001 +From: Zhang zhengguang +Date: Wed, 19 Nov 2014 09:50:45 +0800 +Subject: [PATCH 31/32] multi-user: Expose function to check service user + favorite + +Expose the function to check whether the service is favorite +to the current user. + +Change-Id: Ib232f16c652ec94ef2e10b199a638a98554a1066 +--- + doc/service-api.txt | 7 +++++++ + src/service.c | 27 +++++++++++++++++++++++++++ + 2 files changed, 34 insertions(+) + +diff --git a/doc/service-api.txt b/doc/service-api.txt +index 74c8345..0238d22 100644 +--- a/doc/service-api.txt ++++ b/doc/service-api.txt +@@ -122,6 +122,13 @@ Methods dict GetProperties() [deprecated] + + Possible Errors: None + ++ boolean GetUserFavorite() [experimental] ++ ++ This function is used to check whether this service ++ is favorite to the current user. ++ ++ Possible Errors: None ++ + Signals PropertyChanged(string name, variant value) + + This signal indicates a changed value of the given +diff --git a/src/service.c b/src/service.c +index 55cf02c..5eca970 100644 +--- a/src/service.c ++++ b/src/service.c +@@ -4472,6 +4472,30 @@ static DBusMessage *reset_counters(DBusConnection *conn, + return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); + } + ++static DBusMessage *get_user_favorite(DBusConnection *conn, ++ DBusMessage *msg, void *user_data) ++{ ++ DBusMessage *reply; ++ uid_t uid = USER_NONE; ++ dbus_bool_t user_favorite = false; ++ struct connman_service *service = user_data; ++ ++ connman_dbus_get_connection_unix_user_sync(conn, ++ dbus_message_get_sender(msg), ++ &uid); ++ if (uid == USER_ROOT) ++ user_favorite = service->favorite; ++ else if (uid != USER_NONE && uid == service->user.favorite_user) { ++ DBG("The service is favorite to this user!"); ++ user_favorite = true; ++ } ++ ++ reply = g_dbus_create_reply(msg, DBUS_TYPE_INVALID); ++ dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, ++ &user_favorite, DBUS_TYPE_INVALID); ++ return reply; ++} ++ + static struct _services_notify { + int id; + GHashTable *add; +@@ -4613,6 +4637,9 @@ static const GDBusMethodTable service_methods[] = { + GDBUS_ARGS({ "service", "o" }), NULL, + move_after) }, + { GDBUS_METHOD("ResetCounters", NULL, NULL, reset_counters) }, ++ { GDBUS_METHOD("GetUserFavorite", ++ NULL, GDBUS_ARGS({ "value", "v" }), ++ get_user_favorite) }, + { }, + }; + +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0032-multi-user-Fix-service-load-save-issues.patch b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0032-multi-user-Fix-service-load-save-issues.patch new file mode 100644 index 0000000..450580a --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman/0032-multi-user-Fix-service-load-save-issues.patch @@ -0,0 +1,109 @@ +From 7d48e7bfd2d9d371766ddb36bb3da99111dd3935 Mon Sep 17 00:00:00 2001 +From: Zhang zhengguang +Date: Fri, 21 Nov 2014 16:34:11 +0800 +Subject: [PATCH 32/32] multi-user: Fix service load/save issues + +Refine service load/save to be multi-user complicant. + +Change-Id: Icc8a0507826f4cae72319191e4fdbebe548434fc +--- + src/service.c | 47 +++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 39 insertions(+), 8 deletions(-) + +diff --git a/src/service.c b/src/service.c +index 5eca970..86dffaf 100644 +--- a/src/service.c ++++ b/src/service.c +@@ -484,6 +484,23 @@ int __connman_service_load_modifiable(struct connman_service *service) + return 0; + } + ++static int service_load_passphrase(struct connman_service *service) ++{ ++ GKeyFile *keyfile; ++ gchar *str; ++ ++ keyfile = connman_storage_load_service(service->identifier); ++ if (!keyfile) ++ return -EIO; ++ ++ str = g_key_file_get_string(keyfile, ++ service->identifier, "Passphrase", NULL); ++ if (str) ++ service->passphrase = str; ++ ++ return 0; ++} ++ + static int service_load(struct connman_service *service) + { + GKeyFile *keyfile; +@@ -659,7 +676,8 @@ static int service_load(struct connman_service *service) + service->hidden_service = g_key_file_get_boolean(keyfile, + service->identifier, "Hidden", NULL); + +- service->user.favorite_user = g_key_file_get_integer(keyfile, ++ if (g_key_file_has_key(keyfile, service->identifier, "UID", NULL)) ++ service->user.favorite_user = g_key_file_get_integer(keyfile, + service->identifier, "UID", NULL); + done: + g_key_file_free(keyfile); +@@ -706,8 +724,12 @@ static int service_save(struct connman_service *service) + const unsigned char *ssid; + unsigned int ssid_len = 0; + +- g_key_file_set_integer(keyfile, service->identifier, +- "UID", service->user.favorite_user); ++ if (service->user.favorite_user == USER_NONE) ++ g_key_file_remove_key(keyfile, service->identifier, ++ "UID", NULL); ++ else ++ g_key_file_set_integer(keyfile, service->identifier, ++ "UID", service->user.favorite_user); + + ssid = connman_network_get_blob(service->network, + "WiFi.SSID", &ssid_len); +@@ -764,12 +786,14 @@ static int service_save(struct connman_service *service) + g_free(str); + } + +- if (service->passphrase && strlen(service->passphrase) > 0) +- g_key_file_set_string(keyfile, service->identifier, ++ if (service->user.current_user == service->user.favorite_user) { ++ if (service->passphrase && strlen(service->passphrase) > 0) ++ g_key_file_set_string(keyfile, service->identifier, + "Passphrase", service->passphrase); +- else +- g_key_file_remove_key(keyfile, service->identifier, +- "Passphrase", NULL); ++ else ++ g_key_file_remove_key(keyfile, service->identifier, ++ "Passphrase", NULL); ++ } + + if (service->ipconfig_ipv4) + __connman_ipconfig_save(service->ipconfig_ipv4, keyfile, +@@ -4125,6 +4149,11 @@ static DBusMessage *connect_service(DBusConnection *conn, + service->request_passphrase_input = true; + + service->user.current_user = uid; ++ ++ if (!service->passphrase && uid == service->user.favorite_user) { ++ DBG("Now load this favorite user's passphrase."); ++ service_load_passphrase(service); ++ } + } + + index = __connman_service_get_index(service); +@@ -4232,6 +4261,8 @@ bool __connman_service_remove(struct connman_service *service) + + service->error = CONNMAN_SERVICE_ERROR_UNKNOWN; + ++ service->user.favorite_user = USER_NONE; ++ + __connman_service_set_favorite(service, false); + + __connman_ipconfig_ipv6_reset_privacy(service->ipconfig_ipv6); +-- +1.8.1.4 + diff --git a/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman_%.bbappend b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman_%.bbappend new file mode 100644 index 0000000..16d6828 --- /dev/null +++ b/meta-tizen-adaptation-oe-core/recipes-connectivity/connman/connman_%.bbappend @@ -0,0 +1,34 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +SRC_URI += "file://0001-Add-bootstrap-files.patch" +SRC_URI += "file://0002-Add-package-build-spec-file.patch" +SRC_URI += "file://0003-Add-systemd-service-to-manager-ConnMan-NTP.patch" +SRC_URI += "file://0004-Set-manifest-request-domain-to-floor.patch" +SRC_URI += "file://0005-Set-ConnMan-default-settings-in-config-files.patch" +SRC_URI += "file://0006-Enable-ConnMan-NTP-configurable-in-spec-file.patch" +SRC_URI += "file://0007-Enable-ConnMan-VPND-OpenVPN-OpenConnect-configurable.patch" +SRC_URI += "file://0008-Add-connmanctl-to-the-built-rpm.patch" +SRC_URI += "file://0009-Tizen-Export-more-wifi-info-in-ConnMan-network-API.patch" +SRC_URI += "file://0010-Tizen-Append-extra-wifi-service-property.patch" +SRC_URI += "file://0011-Tizen-Export-network-proxy-API-for-telephony-plugin.patch" +SRC_URI += "file://0012-Tizen-Integrate-telephony-plugin.patch" +SRC_URI += "file://0013-Tizen-Fix-wifi-enterprise-to-support-SIM-and-AKA.patch" +SRC_URI += "file://0014-Tizen-Check-some-telephony-flags-before-active-conte.patch" +SRC_URI += "file://0015-Tizen-Unify-bluetooth-tethering-enable-logic.patch" +SRC_URI += "file://0016-Tethering-Add-handling-for-wpa_supplicant-authorized.patch" +SRC_URI += "file://0017-Tethering-Add-station-information-management-feature.patch" +SRC_URI += "file://0018-Tethering-Add-interface-that-save-lease-in-DHCP-info.patch" +SRC_URI += "file://0019-Tethering-Notify-listeners-when-station-connection-c.patch" +SRC_URI += "file://0020-Tethering-Add-open-access-point-support-in-technolog.patch" +SRC_URI += "file://0021-Tethering-Add-hidden-access-point-support-in-technol.patch" +SRC_URI += "file://0022-Tethering-Add-test-script-of-open-and-hidden-AP.patch" +SRC_URI += "file://0023-Tethering-Add-tethering-interfaces-description-to-te.patch" +SRC_URI += "file://0024-Tethering-Watch-the-connection-and-disconnection-sig.patch" +SRC_URI += "file://0025-Tethering-Get-the-client-mac-info-of-Gadget-tether.patch" +SRC_URI += "file://0026-multi-user-Add-function-to-get-dbus-user-id-synchron.patch" +SRC_URI += "file://0027-multi-user-Add-multi-user-support-in-service.patch" +SRC_URI += "file://0028-multi-user-Add-multi-user-support-in-technology.patch" +SRC_URI += "file://0029-multi-user-Add-multi-user-support-in-manager.patch" +SRC_URI += "file://0030-multi-user-Add-multi-user-support-for-auto-connect-s.patch" +SRC_URI += "file://0031-multi-user-Expose-function-to-check-service-user-fav.patch" +SRC_URI += "file://0032-multi-user-Fix-service-load-save-issues.patch"