diff options
-rwxr-xr-x[-rw-r--r--] | AUTHORS | 0 | ||||
-rw-r--r-- | HACKING | 109 | ||||
-rwxr-xr-x[-rw-r--r--] | Makefile.am | 119 | ||||
-rwxr-xr-x[-rw-r--r--] | Makefile.plugins | 37 | ||||
-rwxr-xr-x[-rw-r--r--] | README | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | TODO | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | acinclude.m4 | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | client/agent.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | client/agent.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | client/commands.c | 24 | ||||
-rwxr-xr-x[-rw-r--r--] | client/commands.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | client/dbus_helpers.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | client/dbus_helpers.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | client/input.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | client/input.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | client/main.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | client/peers.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | client/peers.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | client/services.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | client/services.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | client/vpnconnections.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | client/vpnconnections.h | 0 | ||||
-rw-r--r-- | configure.ac | 75 | ||||
-rw-r--r-- | connman.manifest | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/advanced-configuration.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/agent-api.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/backtrace.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/behavior-api.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/clock-api.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/config-format.txt | 0 | ||||
-rw-r--r-- | doc/connman.conf.5.in | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/counter-api.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/ipconfig-api.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/manager-api.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/overview-api.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/peer-api.txt | 1 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/plugin-api.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/service-api.txt | 33 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/session-api.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/session-overview.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/session-policy-format.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/technology-api.txt | 17 | ||||
-rw-r--r-- | doc/valgrind.suppressions | 235 | ||||
-rw-r--r-- | doc/vpn-config-format.txt | 29 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/vpn-connection-api.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/vpn-manager-api.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/vpn-overview.txt | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | gdbus/client.c | 8 | ||||
-rwxr-xr-x[-rw-r--r--] | gdbus/gdbus.h | 6 | ||||
-rwxr-xr-x[-rw-r--r--] | gdbus/mainloop.c | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | gdbus/object.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | gdbus/polkit.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | gdbus/watch.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | gdhcp/client.c | 193 | ||||
-rwxr-xr-x[-rw-r--r--] | gdhcp/common.c | 65 | ||||
-rwxr-xr-x[-rw-r--r--] | gdhcp/common.h | 1 | ||||
-rwxr-xr-x[-rw-r--r--] | gdhcp/gdhcp.h | 14 | ||||
-rwxr-xr-x[-rw-r--r--] | gdhcp/ipv4ll.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | gdhcp/ipv4ll.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | gdhcp/server.c | 29 | ||||
-rwxr-xr-x[-rw-r--r--] | gsupplicant/dbus.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | gsupplicant/dbus.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | gsupplicant/gsupplicant.h | 58 | ||||
-rw-r--r-- | gsupplicant/supplicant.c | 779 | ||||
-rwxr-xr-x[-rw-r--r--] | gweb/giognutls.c | 1 | ||||
-rwxr-xr-x[-rw-r--r--] | gweb/giognutls.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | gweb/gionotls.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | gweb/gresolv.c | 8 | ||||
-rwxr-xr-x[-rw-r--r--] | gweb/gresolv.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | gweb/gweb.c | 14 | ||||
-rwxr-xr-x[-rw-r--r--] | gweb/gweb.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/agent.h | 0 | ||||
-rw-r--r-- | include/backtrace.h | 32 | ||||
-rwxr-xr-x[-rw-r--r--] | include/dbus.h | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | include/device.h | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | include/inet.h | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | include/inotify.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/ipaddress.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/ipconfig.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/log.h | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | include/machine.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/network.h | 47 | ||||
-rwxr-xr-x[-rw-r--r--] | include/notifier.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/option.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/peer.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/plugin.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/provider.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/provision.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/proxy.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/resolver.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/rtnl.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/service.h | 41 | ||||
-rwxr-xr-x[-rw-r--r--] | include/session.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/setting.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/storage.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/task.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/technology.h | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | include/timeserver.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/utsname.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/version.h.in | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | include/vpn-dbus.h | 0 | ||||
-rwxr-xr-x | packaging/connman.spec | 343 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/bluetooth.c | 36 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/connman-nmcompat.conf | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/dundee.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/ethernet.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/gadget.c | 87 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/hh2serial-gps.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/iospm.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/loopback.c | 53 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/mcc.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/neard.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/nmcompat.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/ofono.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/pacrunner.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/polkit.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/polkit.policy | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/session_policy_local.c | 0 | ||||
-rwxr-xr-x | plugins/telephony.c | 1934 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/tist.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/vpn.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | plugins/wifi.c | 902 | ||||
-rw-r--r-- | resources/usr/share/dbus-1/system-services/net.connman.service | 6 | ||||
-rw-r--r-- | resources/var/lib/connman/settings | 15 | ||||
-rw-r--r-- | scripts/500.connman_upgrade.sh | 9 | ||||
-rwxr-xr-x[-rw-r--r--] | scripts/connman.in | 2 | ||||
-rw-r--r-- | scripts/connman_resolvconf.conf.in | 2 | ||||
-rwxr-xr-x | scripts/ipsec-script.c | 146 | ||||
-rwxr-xr-x[-rw-r--r--] | scripts/libppp-plugin.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | scripts/openconnect-script.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | scripts/openvpn-script.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/6to4.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/agent-connman.c | 6 | ||||
-rwxr-xr-x[-rw-r--r--] | src/agent.c | 0 | ||||
-rw-r--r-- | src/backtrace.c | 138 | ||||
-rwxr-xr-x[-rw-r--r--] | src/bridge.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/clock.c | 6 | ||||
-rwxr-xr-x[-rw-r--r--] | src/config.c | 52 | ||||
-rwxr-xr-x[-rw-r--r--] | src/connection.c | 70 | ||||
-rwxr-xr-x[-rw-r--r--] | src/connman-dbus.conf | 13 | ||||
-rwxr-xr-x[-rw-r--r--] | src/connman-polkit.conf | 6 | ||||
-rw-r--r-- | src/connman-wait-online.service.in | 15 | ||||
-rw-r--r-- | src/connman.conf | 30 | ||||
-rwxr-xr-x[-rw-r--r--] | src/connman.h | 97 | ||||
-rwxr-xr-x[-rw-r--r--] | src/connman.service.in | 18 | ||||
-rw-r--r-- | src/connman.socket | 13 | ||||
-rw-r--r-- | src/connman_tv.service.in | 19 | ||||
-rwxr-xr-x[-rw-r--r--] | src/counter.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/dbus.c | 29 | ||||
-rwxr-xr-x[-rw-r--r--] | src/detect.c | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | src/device.c | 86 | ||||
-rwxr-xr-x[-rw-r--r--] | src/dhcp.c | 73 | ||||
-rwxr-xr-x[-rw-r--r--] | src/dhcpv6.c | 89 | ||||
-rwxr-xr-x[-rw-r--r--] | src/dnsproxy.c | 352 | ||||
-rwxr-xr-x[-rw-r--r--] | src/eduroam.config | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/error.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/inet.c | 95 | ||||
-rwxr-xr-x[-rw-r--r--] | src/inotify.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/ipaddress.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/ipconfig.c | 79 | ||||
-rwxr-xr-x[-rw-r--r--] | src/ippool.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/iptables.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | src/ipv6pd.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/log.c | 233 | ||||
-rwxr-xr-x[-rw-r--r--] | src/machine.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/main.c | 75 | ||||
-rwxr-xr-x[-rw-r--r--] | src/main.conf | 7 | ||||
-rwxr-xr-x | src/main_disable_eth.conf | 110 | ||||
-rwxr-xr-x | src/main_ivi.conf | 110 | ||||
-rwxr-xr-x | src/main_tv.conf | 116 | ||||
-rwxr-xr-x[-rw-r--r--] | src/manager.c | 39 | ||||
-rwxr-xr-x[-rw-r--r--] | src/nat.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/net.connman.service.in | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | src/network.c | 478 | ||||
-rwxr-xr-x[-rw-r--r--] | src/notifier.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/ntp.c | 66 | ||||
-rwxr-xr-x[-rw-r--r--] | src/peer.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/peer_service.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/plugin.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/provider.c | 10 | ||||
-rwxr-xr-x[-rw-r--r--] | src/proxy.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/resolver.c | 34 | ||||
-rwxr-xr-x[-rw-r--r--] | src/rfkill.c | 10 | ||||
-rwxr-xr-x[-rw-r--r--] | src/rtnl.c | 139 | ||||
-rwxr-xr-x[-rw-r--r--] | src/service.c | 1976 | ||||
-rwxr-xr-x[-rw-r--r--] | src/session.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/shared/netlink.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/shared/netlink.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/shared/util.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/shared/util.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/stats.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/storage.c | 14 | ||||
-rwxr-xr-x[-rw-r--r--] | src/task.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/technology.c | 284 | ||||
-rwxr-xr-x[-rw-r--r--] | src/tethering.c | 170 | ||||
-rwxr-xr-x[-rw-r--r--] | src/timeserver.c | 14 | ||||
-rwxr-xr-x[-rw-r--r--] | src/timezone.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/util.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/utsname.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | src/wispr.c | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | src/wpad.c | 2 | ||||
-rwxr-xr-x | test/enable-tethering | 34 | ||||
-rwxr-xr-x | test/set-timezone | 21 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/dbus-test.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/dhcp-server-test.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/dhcp-test.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/dnsproxy-test.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/iptables-test.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/iptables-unit.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/manager-api.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/netlink-test.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/polkit-test.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/private-network-test.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/resolv-test.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/session-api.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/session-test.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/session-test.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/session-utils.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/stats-tool.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/supplicant-dbus.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/supplicant-dbus.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/supplicant-test.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/supplicant.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/supplicant.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/tap-test.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/web-test.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/wispr.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | tools/wpad-test.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | unit/test-ippool.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/connman-task.te | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/connman-vpn.service.in | 10 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/main.c | 28 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/net.connman.vpn.service.in | 5 | ||||
-rw-r--r-- | vpn/plugins/ipsec.c | 925 | ||||
-rw-r--r-- | vpn/plugins/ipsec.h | 51 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/plugins/l2tp.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/plugins/openconnect.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/plugins/openvpn.c | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/plugins/pptp.c | 0 | ||||
-rw-r--r-- | vpn/plugins/vici-client.c | 1290 | ||||
-rw-r--r-- | vpn/plugins/vici-client.h | 84 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/plugins/vpn.c | 56 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/plugins/vpn.h | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/plugins/vpnc.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/vpn-agent.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/vpn-agent.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/vpn-config.c | 14 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/vpn-dbus.conf | 7 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/vpn-ipconfig.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/vpn-manager.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/vpn-polkit.conf | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/vpn-polkit.policy | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/vpn-provider.c | 23 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/vpn-provider.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/vpn-rtnl.c | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/vpn-rtnl.h | 0 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/vpn.h | 5 | ||||
-rwxr-xr-x[-rw-r--r--] | vpn/vpn.ver | 0 |
258 files changed, 12474 insertions, 838 deletions
diff --git a/HACKING b/HACKING deleted file mode 100644 index 80382ed4..00000000 --- a/HACKING +++ /dev/null @@ -1,109 +0,0 @@ -Hacking on Connection Manager -***************************** - - -Build tools requirements -======================== - -When building and testing directly from the repository it is important to -have at least automake version 1.10 or later installed. All modern -distributions should default to the latest version, but it seems that -Debian's default is still an earlier version: - - Check version - # dpkg -l '*automake*' - - Install new version - # apt-get install automake1.10 - # update-alternatives --config automake - - -Working with the source code repository -======================================= - -The repository contains two extra scripts that accomplish the bootstrap -process. One is called "bootstrap" which is the basic scripts that uses the -autotools scripts to create the needed files for building and installing. -It makes sure to call the right programs depending on the usage of shared or -static libraries or translations etc. - -The second program is called "bootstrap-configure". This program will make -sure to properly clean the repository, call the "bootstrap" script and then -call configure with proper settings for development. It will use the best -options and pass them over to configure. These options normally include -the enabling the maintainer mode and the debugging features. - -So while in a normal source project the call "./configure ..." is used to -configure the project with its settings like prefix and extra options. In -case of bare repositories call "./bootstrap-configure" and it will bootstrap -the repository and calls configure with all the correct options to make -development easier. - -In case of preparing for a release with "make distcheck", don't use -bootstrap-configure since it could export development specific settings. - -So the normal steps to checkout, build and install such a repository is -like this: - - Checkout repository - # git clone git://git.kernel.org/pub/scm/network/connman/connman.git - # cd connman - - Configure and build - # ./bootstrap-configure - # make - - Check installation - # make install DESTDIR=$PWD/x - # find x - # rm -rf x - - Check distribution - # make distcheck - - Final installation - # sudo make install - - Remove autogenerated files - # make maintainer-clean - - -Running from within the source code repository -============================================== - -When using "./configure --enable-maintainer-mode" the automake scripts will -use the plugins directly from within the repository. This removes the need -to use "make install" when testing "connmand". The "bootstrap-configure" -automatically includes this option. - - Run daemon in foreground with debugging - # sudo ./src/connmand -n -d 'plugins/*' - -The debugging option -d takes an argument. This argument can be a comma -separated list of file names like 'plugins/wifi.c,plugins/ethernet.c' to -enable debugs in these files. Simple glob style pattern matching is -supported in this list. - -For production installations or distribution packaging it is important that -the "--enable-maintainer-mode" option is NOT used. - -Some times it is important to restrict the available interfaces. For example -in cases where testing happens over a network connection. The "-i" command -line switch allows to specify a glob pattern for the interface names. - - Run daemon for wireless interfaces - # sudo ./src/connmand -n -i wlan* - - -Debugging the D-Bus interface during runtime -============================================ - -Running the daemon with debugging information in the foreground is quite -verbose and sometimes not really helpful. The "monitor-connman" script -allows to monitor "PropertyChanged" D-Bus signals from various interfaces. - -Every "PropertyChanged" signal will generate a line of output. Some of them -can get very complex. The first detail inside "{ ... }" is the interface -name (without its service name prefix). The second detail inside "[ ... ]" -is the object path. And after that it is followed by a key and value of -the property that changed. diff --git a/Makefile.am b/Makefile.am index e67a7a55..76c5419c 100644..100755 --- a/Makefile.am +++ b/Makefile.am @@ -19,8 +19,7 @@ noinst_HEADERS = include/rtnl.h include/task.h \ include/dbus.h include/option.h \ include/provider.h include/vpn-dbus.h \ include/utsname.h include/timeserver.h include/proxy.h \ - include/technology.h include/setting.h \ - include/backtrace.h + include/technology.h include/setting.h local_headers = $(foreach file,$(include_HEADERS) $(nodist_include_HEADERS) \ $(noinst_HEADERS), include/connman/$(notdir $(file))) @@ -43,10 +42,6 @@ else gweb_sources += gweb/giognutls.h gweb/gionotls.c endif -if BACKTRACE -backtrace_sources = src/backtrace.c -endif - shared_sources = src/shared/util.h src/shared/util.c \ src/shared/netlink.h src/shared/netlink.c @@ -64,29 +59,30 @@ if VPN dbusconf_DATA += vpn/connman-vpn-dbus.conf dbusservicedir = @DBUS_DATADIR@ dbusservice_DATA = vpn/net.connman.vpn.service -endif if SYSTEMD systemdunitdir = @SYSTEMD_UNITDIR@ -systemdunit_DATA = src/connman.service src/connman-wait-online.service +systemdunit_DATA = src/connman.service vpn/connman-vpn.service -tmpfilesdir = @SYSTEMD_TMPFILESDIR@ -nodist_tmpfiles_DATA = scripts/connman_resolvconf.conf - -if VPN -systemdunit_DATA += vpn/connman-vpn.service -endif -endif endif service_files_sources = src/connman.service.in src/net.connman.service.in \ - vpn/connman-vpn.service.in \ - vpn/net.connman.vpn.service.in \ - src/connman-wait-online.service.in + vpn/net.connman.vpn.service.in vpn/connman-vpn.service.in service_files = src/connman.service src/net.connman.service \ - vpn/connman-vpn.service \ - vpn/net.connman.vpn.service \ - src/connman-wait-online.service + vpn/net.connman.vpn.service vpn/connman-vpn.service + +else + +if SYSTEMD +systemdunitdir = @SYSTEMD_UNITDIR@ +systemdunit_DATA = src/connman.service + +endif + +service_files_sources = src/connman.service.in src/net.connman.service.in +service_files = src/connman.service src/net.connman.service +endif +endif plugin_LTLIBRARIES = @@ -98,15 +94,23 @@ builtin_libadd = builtin_cflags = noinst_PROGRAMS = +if TIZEN_EXT +bin_PROGRAMS = src/connmand +else bin_PROGRAMS = +endif unit_objects = MANUAL_PAGES = +if TIZEN_EXT +sbin_PROGRAMS = +else sbin_PROGRAMS = src/connmand src/connmand-wait-online +endif -src_connmand_SOURCES = $(gdhcp_sources) $(gweb_sources) $(backtrace_sources) \ +src_connmand_SOURCES = $(gdhcp_sources) $(gweb_sources) \ $(builtin_sources) $(shared_sources) src/connman.ver \ src/main.c src/connman.h src/log.c \ src/error.c src/plugin.c src/task.c \ @@ -126,10 +130,10 @@ src_connmand_SOURCES = $(gdhcp_sources) $(gweb_sources) $(backtrace_sources) \ src/peer_service.c src/machine.c src/util.c src_connmand_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \ - @GLIB_LIBS@ @DBUS_LIBS@ @GNUTLS_LIBS@ \ + @GLIB_LIBS@ @DBUS_LIBS@ @GNUTLS_LIBS@ @LIBSYSTEMD_LIBS@ \ -lresolv -ldl -lrt -src_connmand_LDFLAGS = -Wl,--export-dynamic \ +src_connmand_LDFLAGS = -Wl,--export-dynamic -pie \ -Wl,--version-script=$(srcdir)/src/connman.ver src_connmand_wait_online_SOURCES = src/connmand-wait-online.c @@ -157,28 +161,45 @@ builtin_vpn_sources = builtin_vpn_libadd = builtin_vpn_cflags = +if TIZEN_EXT +bin_PROGRAMS += vpn/connman-vpnd +else sbin_PROGRAMS += vpn/connman-vpnd +endif -vpn_connman_vpnd_SOURCES = $(builtin_vpn_sources) $(backtrace_sources) \ +vpn_connman_vpnd_SOURCES = $(gdhcp_sources) $(builtin_vpn_sources) \ $(gweb_sources) vpn/vpn.ver vpn/main.c vpn/vpn.h \ - src/log.c src/error.c src/plugin.c src/task.c \ vpn/vpn-manager.c vpn/vpn-provider.c \ vpn/vpn-provider.h vpn/vpn-rtnl.h \ vpn/vpn-ipconfig.c src/inet.c vpn/vpn-rtnl.c \ - src/dbus.c src/storage.c src/ipaddress.c src/agent.c \ - vpn/vpn-agent.c vpn/vpn-agent.h src/inotify.c \ + src/log.c src/error.c src/plugin.c src/task.c \ + src/device.c src/network.c src/connection.c \ + src/manager.c src/service.c \ + src/clock.c src/timezone.c src/agent-connman.c \ + src/agent.c src/notifier.c src/provider.c \ + src/resolver.c src/ipconfig.c src/detect.c \ + src/dhcp.c src/dhcpv6.c src/rtnl.c src/proxy.c \ + src/utsname.c src/timeserver.c src/rfkill.c \ + src/storage.c src/dbus.c src/config.c \ + src/technology.c src/counter.c src/ntp.c \ + src/session.c src/tethering.c src/wpad.c src/wispr.c \ + src/stats.c src/iptables.c src/dnsproxy.c src/6to4.c \ + src/ippool.c src/bridge.c src/nat.c src/ipaddress.c \ + src/inotify.c src/firewall-iptables.c src/ipv6pd.c src/peer.c \ + src/peer_service.c src/machine.c src/util.c \ + vpn/vpn-agent.c vpn/vpn-agent.h \ vpn/vpn-config.c vpn_connman_vpnd_LDADD = gdbus/libgdbus-internal.la $(builtin_vpn_libadd) \ - @GLIB_LIBS@ @DBUS_LIBS@ @GNUTLS_LIBS@ \ + @GLIB_LIBS@ @DBUS_LIBS@ @XTABLES_LIBS@ @GNUTLS_LIBS@ \ + @LIBSYSTEMD_LIBS@ \ -lresolv -ldl vpn_connman_vpnd_LDFLAGS = -Wl,--export-dynamic \ -Wl,--version-script=$(srcdir)/vpn/vpn.ver endif -BUILT_SOURCES = $(local_headers) src/builtin.h $(service_files) \ - scripts/connman scripts/connman_resolvconf.conf +BUILT_SOURCES = $(local_headers) src/builtin.h $(service_files) scripts/connman if VPN BUILT_SOURCES += vpn/builtin.h @@ -216,7 +237,7 @@ build_vpn_plugindir = $(vpn_plugindir) endif endif -AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ \ +AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @LIBSYSTEMD_CFLAGS@\ @GNUTLS_CFLAGS@ $(builtin_cflags) \ -DCONNMAN_PLUGIN_BUILTIN \ -DSTATEDIR=\""$(statedir)"\" \ @@ -225,7 +246,8 @@ AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ \ -DSCRIPTDIR=\""$(build_scriptdir)"\" \ -DSTORAGEDIR=\""$(storagedir)\"" \ -DVPN_STORAGEDIR=\""$(vpn_storagedir)\"" \ - -DCONFIGDIR=\""$(configdir)\"" + -DCONFIGDIR=\""$(configdir)\"" \ + -fPIE if VPN AM_CPPFLAGS = -I$(builddir)/include -I$(srcdir)/gdbus @@ -249,7 +271,7 @@ EXTRA_DIST = src/genbuiltin src/connman-dbus.conf src/connman-polkit.conf \ $(service_files_sources) scripts/connman.in if VPN -vpn_connman_vpnd_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ \ +vpn_connman_vpnd_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @XTABLES_CFLAGS@ \ $(builtin_vpn_cflags) \ -DCONNMAN_PLUGIN_BUILTIN \ -DVPN_STATEDIR=\""$(vpn_statedir)"\" \ @@ -293,13 +315,13 @@ client_connmanctl_SOURCES = client/dbus_helpers.h client/dbus_helpers.c \ client/main.c client_connmanctl_LDADD = gdbus/libgdbus-internal.la @DBUS_LIBS@ @GLIB_LIBS@ \ - -lreadline -ldl + -lreadline -ldl -lncurses endif noinst_PROGRAMS += unit/test-ippool -unit_test_ippool_SOURCES = $(backtrace_sources) src/log.c src/dbus.c \ - src/error.c src/ippool.c unit/test-ippool.c +unit_test_ippool_SOURCES = src/log.c src/dbus.c src/error.c \ + src/ippool.c unit/test-ippool.c unit_test_ippool_LDADD = gdbus/libgdbus-internal.la \ @GLIB_LIBS@ @DBUS_LIBS@ -ldl @@ -352,7 +374,7 @@ tools_polkit_test_LDADD = @DBUS_LIBS@ tools_private_network_test_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ -tools_session_test_SOURCES = $(backtrace_sources) src/log.c src/dbus.c src/error.c \ +tools_session_test_SOURCES = src/log.c src/dbus.c src/error.c \ tools/session-test.c tools/session-utils.c tools/manager-api.c \ tools/session-api.c tools/session-test.h tools_session_test_LDADD = gdbus/libgdbus-internal.la \ @@ -367,7 +389,7 @@ tools_iptables_test_LDADD = @GLIB_LIBS@ @XTABLES_LIBS@ -ldl tools_iptables_unit_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @XTABLES_CFLAGS@ \ -DIPTABLES_SAVE=\""${IPTABLES_SAVE}"\" -tools_iptables_unit_SOURCES = $(backtrace_sources) src/log.c \ +tools_iptables_unit_SOURCES = src/log.c \ src/iptables.c src/firewall-iptables.c src/nat.c \ tools/iptables-unit.c tools_iptables_unit_LDADD = gdbus/libgdbus-internal.la \ @@ -427,13 +449,12 @@ EXTRA_DIST += doc/overview-api.txt doc/behavior-api.txt \ doc/connman.8.in doc/connman-vpn.8.in EXTRA_DIST += src/main.conf \ - src/eduroam.config \ - scripts/connman_resolvconf.conf.in + src/eduroam.config -MANUAL_PAGES += doc/connmanctl.1 doc/connman.conf.5 \ - doc/connman-service.config.5 doc/connman-vpn.conf.5 \ - doc/connman-vpn-provider.config.5 \ - doc/connman.8 doc/connman-vpn.8 +#MANUAL_PAGES += doc/connmanctl.1 doc/connman.conf.5 \ +# doc/connman-service.config.5 doc/connman-vpn.conf.5 \ +# doc/connman-vpn-provider.config.5 \ +# doc/connman.8 doc/connman-vpn.8 nodist_man_MANS = $(MANUAL_PAGES) @@ -445,6 +466,7 @@ DISTCHECK_CONFIGURE_FLAGS = --disable-datafiles \ --enable-hh2serial-gps \ --enable-openconnect \ --enable-openvpn \ + --enable-ipsec \ --enable-vpnc \ --enable-session-policy-local \ --enable-nmcompat \ @@ -500,8 +522,7 @@ do_subst = $(AM_V_GEN)$(SED) \ -e 's,[@]sysconfdir[@],$(sysconfdir),g' \ -e 's,[@]storagedir[@],$(storagedir),g' \ -e 's,[@]vpn_storagedir[@],$(vpn_storagedir),g' \ - -e 's,[@]localstatedir[@],$(localstatedir),g' \ - -e 's,[@]runstatedir[@],$(runstatedir),g' + -e 's,[@]localstatedir[@],$(localstatedir),g' %.1 : %.1.in $(AM_V_at)$(MKDIR_P) $(dir $@) @@ -523,10 +544,6 @@ scripts/connman: scripts/connman.in Makefile $(AM_V_at)$(MKDIR_P) $(dir $@) $(do_subst) < $< > $@ -scripts/connman_resolvconf.conf: scripts/connman_resolvconf.conf.in - $(AM_V_at)$(MKDIR_P) $(dir $@) - $(do_subst) < $< > $@ - include/connman/version.h: include/version.h $(AM_V_at)$(MKDIR_P) include/connman $(AM_V_GEN)$(LN_S) $(abs_top_builddir)/$< $@ diff --git a/Makefile.plugins b/Makefile.plugins index dce8b283..1eb0c3f2 100644..100755 --- a/Makefile.plugins +++ b/Makefile.plugins @@ -58,6 +58,18 @@ builtin_modules += dundee builtin_sources += plugins/dundee.c endif +if TELEPHONY +if TELEPHONY_BUILTIN +builtin_modules += telephony +builtin_sources += plugins/telephony.c +else +plugin_LTLIBRARIES += plugins/telephony.la +plugin_objects += $(plugins_telephony_la_OBJECTS) +plugins_telephony_la_CFLAGS = $(plugin_cflags) +plugins_telephony_la_LDFLAGS = $(plugin_ldflags) +endif +endif + if VPN builtin_modules += vpn builtin_sources += plugins/vpn.c @@ -99,6 +111,25 @@ vpn_plugins_openvpn_la_LDFLAGS = $(plugin_ldflags) endif endif +if IPSEC +if IPSEC_BUILTIN +builtin_vpn_modules += ipsec +builtin_vpn_sources += vpn/plugins/ipsec.h vpn/plugins/ipsec.c +builtin_vpn_sources += vpn/plugins/vici-client.h vpn/plugins/vici-client.c +builtin_vpn_source = vpn/plugins/vpn.c vpn/plugins/vpn.h +builtin_vpn_cflags += -DIPSEC=\"@IPSEC@\" +else +vpn_plugin_LTLIBRARIES += vpn/plugins/ipsec.la +vpn_plugin_objects += $(plugins_ipsec_la_OBJECTS) +vpn_plugins_ipsec_la_SOURCES = vpn/plugins/vpn.h vpn/plugins/vpn.c \ + vpn/plugins/ipsec.c vpn/plugins/vici-client.c +vpn_plugins_ipsec_la_CFLAGS = $(plugin_cflags) -DIPSEC=\"@IPSEC@\" \ + -DVPN_STATEDIR=\""$(vpn_statedir)"\" \ + -DSCRIPTDIR=\""$(build_scriptdir)"\" @GIO_CFLAGS@ +vpn_plugins_ipsec_la_LDFLAGS = $(plugin_ldflags) @GIO_LIBS@ +endif +endif + if VPNC if VPNC_BUILTIN builtin_vpn_modules += vpnc @@ -216,6 +247,12 @@ script_PROGRAMS += scripts/openvpn-script scripts_openvpn_script_LDADD = @DBUS_LIBS@ endif +if IPSEC +script_PROGRAMS += scripts/ipsec-script + +scripts_ipsec_script_LDADD = @DBUS_LIBS@ +endif + if NMCOMPAT builtin_modules += nmcompat builtin_sources += plugins/nmcompat.c diff --git a/acinclude.m4 b/acinclude.m4 index 9e8e0dc5..9e8e0dc5 100644..100755 --- a/acinclude.m4 +++ b/acinclude.m4 diff --git a/client/agent.c b/client/agent.c index d0208892..d0208892 100644..100755 --- a/client/agent.c +++ b/client/agent.c diff --git a/client/agent.h b/client/agent.h index 669a5934..669a5934 100644..100755 --- a/client/agent.h +++ b/client/agent.h diff --git a/client/commands.c b/client/commands.c index 583095b1..746e1589 100644..100755 --- a/client/commands.c +++ b/client/commands.c @@ -2395,12 +2395,30 @@ static struct _peer_service *fill_in_peer_service(unsigned char *bjr_query, service = dbus_malloc0(sizeof(*service)); +#if defined TIZEN_EXT + if (!service) + return NULL; +#endif + if (bjr_query_len && bjr_response_len) { service->bjr_query = dbus_malloc0(bjr_query_len); +#if defined TIZEN_EXT + if(!service->bjr_query) { + dbus_free(service); + return NULL; + } +#endif memcpy(service->bjr_query, bjr_query, bjr_query_len); service->bjr_query_len = bjr_query_len; service->bjr_response = dbus_malloc0(bjr_response_len); +#if defined TIZEN_EXT + if(!service->bjr_response) { + dbus_free(service->bjr_query); + dbus_free(service); + return NULL; + } +#endif memcpy(service->bjr_response, bjr_response, bjr_response_len); service->bjr_response_len = bjr_response_len; } else if (upnp_service && version) { @@ -2408,6 +2426,12 @@ static struct _peer_service *fill_in_peer_service(unsigned char *bjr_query, service->version = version; } else if (wfd_ies && wfd_ies_len) { service->wfd_ies = dbus_malloc0(wfd_ies_len); +#if defined TIZEN_EXT + if (!service->wfd_ies) { + dbus_free(service); + return NULL; + } +#endif memcpy(service->wfd_ies, wfd_ies, wfd_ies_len); service->wfd_ies_len = wfd_ies_len; } else { diff --git a/client/commands.h b/client/commands.h index d5d1becf..d5d1becf 100644..100755 --- a/client/commands.h +++ b/client/commands.h diff --git a/client/dbus_helpers.c b/client/dbus_helpers.c index 6ca407d4..6ca407d4 100644..100755 --- a/client/dbus_helpers.c +++ b/client/dbus_helpers.c diff --git a/client/dbus_helpers.h b/client/dbus_helpers.h index 395808ac..395808ac 100644..100755 --- a/client/dbus_helpers.h +++ b/client/dbus_helpers.h diff --git a/client/input.c b/client/input.c index 78319ff8..d9d2b7b1 100644..100755 --- a/client/input.c +++ b/client/input.c @@ -273,7 +273,9 @@ int __connmanctl_input_init(int argc, char *argv[]) __connmanctl_monitor_completions(NULL); rl_callback_handler_remove(); +#if !defined TIZEN_EXT rl_message(""); +#endif } dbus_connection_unref(connection); diff --git a/client/input.h b/client/input.h index c7256a41..c7256a41 100644..100755 --- a/client/input.h +++ b/client/input.h diff --git a/client/main.c b/client/main.c index 6d3c57f9..6d3c57f9 100644..100755 --- a/client/main.c +++ b/client/main.c diff --git a/client/peers.c b/client/peers.c index bf1aa0ea..bf1aa0ea 100644..100755 --- a/client/peers.c +++ b/client/peers.c diff --git a/client/peers.h b/client/peers.h index fdf7ce76..fdf7ce76 100644..100755 --- a/client/peers.h +++ b/client/peers.h diff --git a/client/services.c b/client/services.c index 0c18669b..0c18669b 100644..100755 --- a/client/services.c +++ b/client/services.c diff --git a/client/services.h b/client/services.h index 9b555fe7..9b555fe7 100644..100755 --- a/client/services.h +++ b/client/services.h diff --git a/client/vpnconnections.c b/client/vpnconnections.c index d7bcbfee..d7bcbfee 100644..100755 --- a/client/vpnconnections.c +++ b/client/vpnconnections.c diff --git a/client/vpnconnections.h b/client/vpnconnections.h index a915c843..a915c843 100644..100755 --- a/client/vpnconnections.h +++ b/client/vpnconnections.h diff --git a/configure.ac b/configure.ac index 4baa6852..01ecd950 100644 --- a/configure.ac +++ b/configure.ac @@ -65,6 +65,20 @@ AC_ARG_ENABLE(hh2serial-gps, AM_CONDITIONAL(HH2SERIAL_GPS, test "${enable_hh2serial_gps}" != "no") AM_CONDITIONAL(HH2SERIAL_GPS_BUILTIN, test "${enable_hh2serial_gps}" = "builtin") +AC_ARG_ENABLE(telephony, + AC_HELP_STRING([--enable-telephony], [enable Telephony support]), + [enable_telephony=${enableval}], [enable_telephony="yes"]) +AM_CONDITIONAL(TELEPHONY, test "${enable_telephony}" != "no") +AM_CONDITIONAL(TELEPHONY_BUILTIN, test "${enable_telephony}" = "builtin") + +AC_ARG_ENABLE(tizen-ext, + AC_HELP_STRING([--enable-tizen-ext], [enable TIZEN extensions]), + [if (test "${enableval}" = "yes"); then + CFLAGS="$CFLAGS -DTIZEN_EXT" + LIBS="$LIBS -lsmack" + fi]) +AM_CONDITIONAL(TIZEN_EXT, test "${enable-tizen-ext}" != "no") + AC_ARG_WITH(openconnect, AC_HELP_STRING([--with-openconnect=PROGRAM], [specify location of openconnect binary]), [path_openconnect=${withval}]) @@ -73,7 +87,7 @@ AC_ARG_ENABLE(openconnect, [enable_openconnect=${enableval}], [enable_openconnect="no"]) if (test "${enable_openconnect}" != "no"); then if (test -z "${path_openconnect}"); then - AC_PATH_PROG(OPENCONNECT, [openconnect], [], $PATH:/sbin:/usr/sbin) + AC_PATH_PROG(OPENCONNECT, [openconnect], [], $PATH:/bin:/usr/bin) if (test -z "${OPENCONNECT}"); then AC_MSG_ERROR(openconnect binary not found) fi @@ -93,7 +107,7 @@ AC_ARG_ENABLE(openvpn, [enable_openvpn=${enableval}], [enable_openvpn="no"]) if (test "${enable_openvpn}" != "no"); then if (test -z "${path_openvpn}"); then - AC_PATH_PROG(OPENVPN, [openvpn], [], $PATH:/sbin:/usr/sbin) + AC_PATH_PROG(OPENVPN, [openvpn], [/usr/bin/openvpn], $PATH:/bin:/usr/bin) if (test -z "${OPENVPN}"); then AC_MSG_ERROR(openvpn binary not found) fi @@ -105,6 +119,30 @@ fi AM_CONDITIONAL(OPENVPN, test "${enable_openvpn}" != "no") AM_CONDITIONAL(OPENVPN_BUILTIN, test "${enable_openvpn}" = "builtin") +AC_ARG_WITH(ipsec, AC_HELP_STRING([--with-ipsec=PROGRAM], + [specify location of ipsec binary]), [path_ipsec=${withval}]) + +AC_ARG_ENABLE(ipsec, + AC_HELP_STRING([--enable-ipsec], [enable ipsec support]), + [enable_ipsec=${enableval}], [enable_ipsec="no"]) +if (test "${enable_ipsec}" != "no"); then + PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.28, dummy=yes, + AC_MSG_ERROR(GIO >= 2.28 is required)) + AC_SUBST(GIO_CFLAGS) + AC_SUBST(GIO_LIBS) + if (test -z "${path_ipsec}"); then + AC_PATH_PROG(IPSEC, [charon], [/usr/bin/charon], $PATH:/usr/bin) + if (test -z "${IPSEC}"); then + AC_MSG_ERROR(ipsec binary not found) + fi + else + IPSEC="${path_ipsec}" + AC_SUBST(IPSEC) + fi +fi +AM_CONDITIONAL(IPSEC, test "${enable_ipsec}" != "no") +AM_CONDITIONAL(IPSEC_BUILTIN, test "${enable_ipsec}" = "builtin") + AC_ARG_WITH(vpnc, AC_HELP_STRING([--with-vpnc=PROGRAM], [specify location of vpnc binary]), [path_vpnc=${withval}]) @@ -113,7 +151,7 @@ AC_ARG_ENABLE(vpnc, [enable_vpnc=${enableval}], [enable_vpnc="no"]) if (test "${enable_vpnc}" != "no"); then if (test -z "${path_vpnc}"); then - AC_PATH_PROG(VPNC, [vpnc], [], $PATH:/sbin:/usr/sbin) + AC_PATH_PROG(VPNC, [vpnc], [], $PATH:/bin:/usr/bin) if (test -z "${VPNC}"); then AC_MSG_ERROR(vpnc binary not found) fi @@ -133,7 +171,7 @@ AC_ARG_ENABLE(l2tp, [enable_l2tp=${enableval}], [enable_l2tp="no"]) if (test "${enable_l2tp}" != "no"); then if (test -z "${path_pppd}"); then - AC_PATH_PROG(PPPD, [pppd], [/usr/sbin/pppd], $PATH:/sbin:/usr/sbin) + AC_PATH_PROG(PPPD, [pppd], [/usr/bin/pppd], $PATH:/bin:/usr/bin) else PPPD="${path_pppd}" AC_SUBST(PPPD) @@ -141,7 +179,7 @@ if (test "${enable_l2tp}" != "no"); then AC_CHECK_HEADERS(pppd/pppd.h, dummy=yes, AC_MSG_ERROR(ppp header files are required)) if (test -z "${path_l2tp}"); then - AC_PATH_PROG(L2TP, [xl2tpd], [/usr/sbin/xl2tpd], $PATH:/sbin:/usr/sbin) + AC_PATH_PROG(L2TP, [xl2tpd], [/usr/bin/xl2tpd], $PATH:/bin:/usr/bin) else L2TP="${path_l2tp}" AC_SUBST(L2TP) @@ -158,7 +196,7 @@ AC_ARG_ENABLE(pptp, [enable_pptp=${enableval}], [enable_pptp="no"]) if (test "${enable_pptp}" != "no"); then if (test -z "${path_pppd}"); then - AC_PATH_PROG(PPPD, [pppd], [/usr/sbin/pppd], $PATH:/sbin:/usr/sbin) + AC_PATH_PROG(PPPD, [pppd], [/usr/bin/pppd], $PATH:/bin:/usr/bin) else PPPD="${path_pppd}" AC_SUBST(PPPD) @@ -166,7 +204,7 @@ if (test "${enable_pptp}" != "no"); then AC_CHECK_HEADERS(pppd/pppd.h, dummy=yes, AC_MSG_ERROR(ppp header files are required)) if (test -z "${path_pptp}"); then - AC_PATH_PROG(PPTP, [pptp], [/usr/sbin/pptp], $PATH:/sbin:/usr/sbin) + AC_PATH_PROG(PPTP, [pptp], [/usr/bin/pptp], $PATH:/bin:/usr/bin) else PPTP="${path_pptp}" AC_SUBST(PPTP) @@ -182,9 +220,6 @@ AC_CHECK_LIB(resolv, ns_initparse, dummy=yes, [ AC_MSG_ERROR(resolver library support is required)) ]) -AC_CHECK_HEADERS([execinfo.h]) -AM_CONDITIONAL([BACKTRACE], [test "${ac_cv_header_execinfo_h}" = "yes"]) - AC_CHECK_FUNC(signalfd, dummy=yes, AC_MSG_ERROR(signalfd support is required)) @@ -223,6 +258,11 @@ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.28, dummy=yes, AC_SUBST(GLIB_CFLAGS) AC_SUBST(GLIB_LIBS) +PKG_CHECK_MODULES(LIBSYSTEMD, libsystemd-daemon, dummy=yes, + AC_MSG_ERROR(libsystemd-daemon library is required)) +AC_SUBST(LIBSYSTEMD_CFLAGS) +AC_SUBST(LIBSYSTEMD_LIBS) + PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.4, dummy=yes, AC_MSG_ERROR(D-Bus >= 1.4 is required)) AC_SUBST(DBUS_CFLAGS) @@ -257,14 +297,6 @@ if (test -n "${path_systemdunit}"); then fi AM_CONDITIONAL(SYSTEMD, test -n "${path_systemdunit}") -AC_ARG_WITH([tmpfilesdir], AC_HELP_STRING([--with-tmpfilesdir=DIR], - [path to systemd tmpfiles.d directory]), [path_tmpfiles=${withval}], - [path_tmpfiles="`$PKG_CONFIG --variable=tmpfilesdir systemd`"]) -if (test -n "${path_tmpfiles}"); then - SYSTEMD_TMPFILESDIR="${path_tmpfiles}" - AC_SUBST(SYSTEMD_TMPFILESDIR) -fi - AC_ARG_WITH(firewall, AC_HELP_STRING([--with-firewall=TYPE], [specify which firewall type is used iptables or nftables [default=iptables]]), [firewall_type=${withval}], @@ -382,7 +414,7 @@ AM_CONDITIONAL(TOOLS, test "${enable_tools}" != "no") if (test "${enable_tools}" != "no"); then AC_PATH_PROGS(IPTABLES_SAVE, [iptables-save], [], - $PATH:/sbin:/usr/sbin) + $PATH:/bin:/usr/bin) IPTABLES_SAVE=$ac_cv_path_IPTABLES_SAVE else IPTABLES_SAVE="" @@ -414,7 +446,7 @@ fi if (test "${enable_wifi}" != "no"); then AC_PATH_PROG(WPASUPPLICANT, [wpa_supplicant], [], - $PATH:/sbin:/usr/sbin) + $PATH:/bin:/usr/bin) fi AC_ARG_ENABLE(datafiles, AC_HELP_STRING([--disable-datafiles], @@ -429,8 +461,9 @@ fi AM_CONDITIONAL(VPN, test "${enable_openconnect}" != "no" -o \ "${enable_openvpn}" != "no" -o \ + "${enable_ipsec}" != "no" -o \ "${enable_vpnc}" != "no" -o \ "${enable_l2tp}" != "no" -o \ "${enable_pptp}" != "no") -AC_OUTPUT(Makefile include/version.h connman.pc) +AC_OUTPUT(Makefile include/version.h connman.pc src/connman.service src/connman_tv.service vpn/connman-vpn.service) diff --git a/connman.manifest b/connman.manifest new file mode 100644 index 00000000..97e8c313 --- /dev/null +++ b/connman.manifest @@ -0,0 +1,5 @@ +<manifest> + <request> + <domain name="_"/> + </request> +</manifest> diff --git a/doc/advanced-configuration.txt b/doc/advanced-configuration.txt index 12c2250e..12c2250e 100644..100755 --- a/doc/advanced-configuration.txt +++ b/doc/advanced-configuration.txt diff --git a/doc/agent-api.txt b/doc/agent-api.txt index aa7271d4..aa7271d4 100644..100755 --- a/doc/agent-api.txt +++ b/doc/agent-api.txt diff --git a/doc/backtrace.txt b/doc/backtrace.txt index ac8472cc..ac8472cc 100644..100755 --- a/doc/backtrace.txt +++ b/doc/backtrace.txt diff --git a/doc/behavior-api.txt b/doc/behavior-api.txt index 5feea768..5feea768 100644..100755 --- a/doc/behavior-api.txt +++ b/doc/behavior-api.txt diff --git a/doc/clock-api.txt b/doc/clock-api.txt index 6818f5a8..6818f5a8 100644..100755 --- a/doc/clock-api.txt +++ b/doc/clock-api.txt diff --git a/doc/config-format.txt b/doc/config-format.txt index ed3123aa..ed3123aa 100644..100755 --- a/doc/config-format.txt +++ b/doc/config-format.txt diff --git a/doc/connman.conf.5.in b/doc/connman.conf.5.in index 95b177f5..fdc8e9ec 100644 --- a/doc/connman.conf.5.in +++ b/doc/connman.conf.5.in @@ -138,7 +138,7 @@ be used by DHCP servers to identify specific clients without having to rely on MAC address ranges, etc .TP .BI EnableOnlineCheck=true\ \fR|\fB\ false -Enable or disable use of HTTP GET as an online status check. +Enable or disable use of HTTP GET as on online status check. When a service is in a READY state, and is selected as default, ConnMan will issue an HTTP GET request to verify that end-to-end connectivity is successful. Only then the service will be diff --git a/doc/counter-api.txt b/doc/counter-api.txt index 32411d57..32411d57 100644..100755 --- a/doc/counter-api.txt +++ b/doc/counter-api.txt diff --git a/doc/ipconfig-api.txt b/doc/ipconfig-api.txt index 080fdac5..080fdac5 100644..100755 --- a/doc/ipconfig-api.txt +++ b/doc/ipconfig-api.txt diff --git a/doc/manager-api.txt b/doc/manager-api.txt index 31e137ca..31e137ca 100644..100755 --- a/doc/manager-api.txt +++ b/doc/manager-api.txt diff --git a/doc/overview-api.txt b/doc/overview-api.txt index fd51d706..fd51d706 100644..100755 --- a/doc/overview-api.txt +++ b/doc/overview-api.txt diff --git a/doc/peer-api.txt b/doc/peer-api.txt index cc094ff2..b871f4d5 100644..100755 --- a/doc/peer-api.txt +++ b/doc/peer-api.txt @@ -100,3 +100,4 @@ Properties string State [readonly] [experimental] The TLV formated byte array representing the WiFi Display Informations Elements. + diff --git a/doc/plugin-api.txt b/doc/plugin-api.txt index ea5ec0a1..ea5ec0a1 100644..100755 --- a/doc/plugin-api.txt +++ b/doc/plugin-api.txt diff --git a/doc/service-api.txt b/doc/service-api.txt index 6cdb0bb5..4fe4093a 100644..100755 --- 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 @@ -193,6 +200,32 @@ Properties string State [readonly] This property might be only present for WiFi services. + string BSSID [readonly] + + If the service type is WiFi, then this property + indicates the BSSID of the service. + + uint32 MaxRate [readonly] + + If the service type is WiFi, then this property + indicates the Maximum speed(bps) of the service. + + uint16 Frequency [readonly] + + If the service type is WiFi, then this property + indicates the frequency band(MHz) of the service. + + string EncryptionMode [readonly] + + If the service type is WiFi, then this property + indicates the key encryption mode. + + Possible values are "none", "wep", "tkip", "aes" + and "mixed". + + This property might be only present for WiFi + services. + uint8 Strength [readonly] Indicates the signal strength of the service. This diff --git a/doc/session-api.txt b/doc/session-api.txt index e8da5224..e8da5224 100644..100755 --- a/doc/session-api.txt +++ b/doc/session-api.txt diff --git a/doc/session-overview.txt b/doc/session-overview.txt index 976c3518..976c3518 100644..100755 --- a/doc/session-overview.txt +++ b/doc/session-overview.txt diff --git a/doc/session-policy-format.txt b/doc/session-policy-format.txt index babc2c10..babc2c10 100644..100755 --- a/doc/session-policy-format.txt +++ b/doc/session-policy-format.txt diff --git a/doc/technology-api.txt b/doc/technology-api.txt index f22e9b29..fb6bd314 100644..100755 --- 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 @@ -100,3 +112,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/doc/valgrind.suppressions b/doc/valgrind.suppressions deleted file mode 100644 index c1c7bca1..00000000 --- a/doc/valgrind.suppressions +++ /dev/null @@ -1,235 +0,0 @@ -{ - <syslog error> - Memcheck:Cond - obj:/lib/libc-*.so - ... - fun:localtime_r - fun:__vsyslog_chk - fun:__syslog_chk - fun:__connman_log_init - ... -} -{ - <iconv open> - Memcheck:Addr4 - obj:/lib/libc-*.so - obj:/lib/libglib-2.0.so* - fun:g_iconv_open - ... - fun:g_convert - fun:g_locale_to_utf8 - fun:g_strerror - fun:g_key_file_load_from_file - ... -} -{ - <ioctl ADDRT/DELRT> - Memcheck:Param - ioctl(SIOCADDRT/DELRT) - obj:/lib/ld-*.so - ... -} -{ - <g_main_loop> - Memcheck:Leak - fun:memalign - ... - fun:g_slice_alloc - ... - fun:g_main_loop_new - ... -} -{ - <g_option_context_parse> - Memcheck:Leak - ... - fun:g_slice_alloc - ... - fun:g_option_context_parse - ... -} -{ - <g_key_file_load_from_data> - Memcheck:Leak - ... - fun:g_slice_alloc - ... - fun:g_key_file_load_from_data - ... -} -{ - <g_key_file_new 1> - Memcheck:Leak - ... - fun:g_slice_alloc - ... - fun:g_key_file_new - ... -} -{ - <g_key_file_new 2> - Memcheck:Leak - fun:*alloc - ... - fun:g_key_file_new - fun:main -} -{ - <connman plugin cleanup> - Memcheck:Leak - ... - fun:__connman_plugin_cleanup - ... -} -{ - <cmd line option parsing> - Memcheck:Leak - fun:malloc - fun:g_malloc - fun:g_strdup - fun:g_set_prgname - fun:g_option_context_parse - fun:main -} -{ - <dbus system bus setup 1> - Memcheck:Leak - ... - fun:dbus_malloc* - ... - fun:g_dbus_setup_bus - fun:main -} -{ - <dbus system bus setup 2> - Memcheck:Leak - ... - fun:g_malloc* - ... - fun:dbus_connection_set_watch_functions - fun:setup_bus - ... -} -{ - <key file get charset> - Memcheck:Leak - ... - fun:g_*alloc* - ... - fun:g_strerror - fun:g_key_file_load_from_file - fun:main -} -{ - <dbus disconnect func set> - Memcheck:Leak - ... - fun:filter_data_get - fun:g_dbus_add_signal_watch - fun:g_dbus_set_disconnect_function - fun:main -} -{ - <plugin dlopen> - Memcheck:Leak - ... - fun:dlopen - fun:__connman_plugin_init - fun:main -} -{ - <dbus system bus setup 3> - Memcheck:Leak - ... - fun:dbus_malloc0 - ... - fun:dbus_parse_address - ... - fun:g_dbus_setup_bus - fun:main -} -{ - <libdbus internals 1> - Memcheck:Leak - fun:*malloc - ... - obj:/lib/libdbus-1.so.3.5.3 -} -{ - <dbus system bus setup 4> - Memcheck:Leak - fun:*alloc - ... - fun:dbus_*alloc* - ... - fun:g_dbus_setup_bus - fun:main -} -{ - <dbus system bus setup 5> - Memcheck:Leak - fun:calloc - fun:g_malloc0 - ... - fun:g_dbus_set_disconnect_function - fun:main -} -{ - <dbus bus remove match> - Memcheck:Leak - fun:malloc - fun:g_malloc - fun:g_source_set_callback - fun:g_timeout_add_full - fun:g_timeout_add - ... - fun:dbus_pending_call_block - fun:dbus_connection_send_with_reply_and_block - ... - fun:dbus_bus_remove_match -} -{ - <g_main_loop_run/new> - Memcheck:Leak - fun:*alloc - ... - fun:g_main_loop_* - fun:main -} -{ - <g_main_context_dispatch> - Memcheck:Leak - fun:*alloc - ... - fun:g_main_context_dispatch -} -{ - <libdbus internals 2> - Memcheck:Leak - fun:realloc - fun:dbus_realloc - ... - fun:dbus_message_set_reply_serial - fun:dbus_message_new_error - ... -} -{ - <libdbus internals 3> - Memcheck:Leak - fun:realloc - fun:dbus_realloc - ... - fun:dbus_message_new_signal - ... -} -{ - <dbus_bus_register> - Memcheck:Leak - fun:malloc - fun:realloc - fun:dbus_realloc - ... - fun:dbus_pending_call_block - fun:dbus_connection_send_with_reply_and_block - fun:dbus_bus_register -} diff --git a/doc/vpn-config-format.txt b/doc/vpn-config-format.txt index 0bc62c08..cb0f16a8 100644 --- a/doc/vpn-config-format.txt +++ b/doc/vpn-config-format.txt @@ -207,6 +207,35 @@ PPTP VPN supports following options (see pptp(8) and pppd(8) for details) PPPD.RequirMPPEStateful mppe-stateful Allow MPPE to use stateful mode (O) PPPD.NoVJ novj No Van Jacobson compression (O) +IPsec VPN supports following options (see swanctl.conf(5) for details): + Option name IPSec config value Description + IPsec.Version Version IKE major version to use for connection (M) + IPsec.LeftAddrs local_addrs Local address(es) to use for IKE communication (M) + IPsec.RightAddrs remote_addrs Remote address(es) to use for IKE communication (M) + + + IPsec.LocalAuth local.auth Authentication to perform locally (M) + IPsec.LocalCerts local.certs Certificate candidate to use for authentication (O) + IPsec.LocalID local.id IKE identity to use for authentication round (O) + IPsec.LocalXauthID local.xauth_id Client XAuth username used in the XAuth exchange (O) + IPsec.LocalXauthAuth local-xauth.auth Xauth round authentication to perform locally (O) + IPsec.LocalXauthXauthID local-xauth.xauth_id Xauth round client XAuth username used in the XAuth exchange (O) + + IPsec.RemoteAuth remote.auth Authentication to expect from remote (M) + IPsec.RemoteCerts remote.certs Certificate candidate to use for authentication (O) + IPsec.RemoteID remote.id IKE identity to use for authentication round (O) + IPsec.RemoteXauthAuth remote-xauth.auth Xauth round authentication to expect from remote (O) + IPsec.ChildrenLocalTs children.local_ts local selectors to include in CHILD_SA (O) + IPsec.ChildrenRemoteTs children.remote_ts Remote selectors to include in CHILD_SA (O) + + IPsec.IKEData secret.data IKE PSK raw shared key data + IPsec.IKEOwners secret.Owners list of shared key owner identities + IPsec.XauthData secret.data XAUTH raw shared key data + IPsec.XauthOwners secret.Owners list of shared key owner identities + + IPsec.CertType cert.type certificate type, X509|X509_AC|X509_CRL + IPsec.CertFlag cert.flag X.509 certificate flag, NONE|CA|AA|OCSP + IPsec.CertData cert.data PEM or DER encoded certificate data Example ======= diff --git a/doc/vpn-connection-api.txt b/doc/vpn-connection-api.txt index a814a388..a814a388 100644..100755 --- a/doc/vpn-connection-api.txt +++ b/doc/vpn-connection-api.txt diff --git a/doc/vpn-manager-api.txt b/doc/vpn-manager-api.txt index 66c5beef..66c5beef 100644..100755 --- a/doc/vpn-manager-api.txt +++ b/doc/vpn-manager-api.txt diff --git a/doc/vpn-overview.txt b/doc/vpn-overview.txt index 42b6e94a..42b6e94a 100644..100755 --- a/doc/vpn-overview.txt +++ b/doc/vpn-overview.txt diff --git a/gdbus/client.c b/gdbus/client.c index a011e19c..9748ae25 100644..100755 --- a/gdbus/client.c +++ b/gdbus/client.c @@ -58,8 +58,10 @@ struct GDBusClient { void *signal_data; GDBusProxyFunction proxy_added; GDBusProxyFunction proxy_removed; +#if !defined TIZEN_EXT GDBusClientFunction ready; void *ready_data; +#endif GDBusPropertyFunction property_changed; void *user_data; GList *proxy_list; @@ -729,6 +731,7 @@ gboolean g_dbus_proxy_set_property_basic(GDBusProxy *proxy, return TRUE; } +#if !defined TIZEN_EXT gboolean g_dbus_proxy_set_property_array(GDBusProxy *proxy, const char *name, int type, const void *value, size_t size, GDBusResultFunction function, @@ -815,6 +818,7 @@ gboolean g_dbus_proxy_set_property_array(GDBusProxy *proxy, return TRUE; } +#endif struct method_call_data { GDBusReturnFunction function; @@ -1095,8 +1099,10 @@ static void get_managed_objects_reply(DBusPendingCall *call, void *user_data) parse_managed_objects(client, reply); done: +#if !defined TIZEN_EXT if (client->ready) client->ready(client, client->ready_data); +#endif dbus_message_unref(reply); @@ -1367,6 +1373,7 @@ gboolean g_dbus_client_set_signal_watch(GDBusClient *client, return TRUE; } +#if !defined TIZEN_EXT gboolean g_dbus_client_set_ready_watch(GDBusClient *client, GDBusClientFunction ready, void *user_data) { @@ -1378,6 +1385,7 @@ gboolean g_dbus_client_set_ready_watch(GDBusClient *client, return TRUE; } +#endif gboolean g_dbus_client_set_proxy_handlers(GDBusClient *client, GDBusProxyFunction proxy_added, diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h index 69fbc107..70190b71 100644..100755 --- a/gdbus/gdbus.h +++ b/gdbus/gdbus.h @@ -339,10 +339,12 @@ gboolean g_dbus_proxy_set_property_basic(GDBusProxy *proxy, GDBusResultFunction function, void *user_data, GDBusDestroyFunction destroy); +#if !defined TIZEN_EXT gboolean g_dbus_proxy_set_property_array(GDBusProxy *proxy, const char *name, int type, const void *value, size_t size, GDBusResultFunction function, void *user_data, GDBusDestroyFunction destroy); +#endif typedef void (* GDBusSetupFunction) (DBusMessageIter *iter, void *user_data); typedef void (* GDBusReturnFunction) (DBusMessage *message, void *user_data); @@ -352,7 +354,9 @@ gboolean g_dbus_proxy_method_call(GDBusProxy *proxy, const char *method, GDBusReturnFunction function, void *user_data, GDBusDestroyFunction destroy); +#if !defined TIZEN_EXT typedef void (* GDBusClientFunction) (GDBusClient *client, void *user_data); +#endif typedef void (* GDBusProxyFunction) (GDBusProxy *proxy, void *user_data); typedef void (* GDBusPropertyFunction) (GDBusProxy *proxy, const char *name, DBusMessageIter *iter, void *user_data); @@ -379,8 +383,10 @@ gboolean g_dbus_client_set_disconnect_watch(GDBusClient *client, GDBusWatchFunction function, void *user_data); gboolean g_dbus_client_set_signal_watch(GDBusClient *client, GDBusMessageFunction function, void *user_data); +#if !defined TIZEN_EXT gboolean g_dbus_client_set_ready_watch(GDBusClient *client, GDBusClientFunction ready, void *user_data); +#endif gboolean g_dbus_client_set_proxy_handlers(GDBusClient *client, GDBusProxyFunction proxy_added, GDBusProxyFunction proxy_removed, diff --git a/gdbus/mainloop.c b/gdbus/mainloop.c index b90a8447..edb384ef 100644..100755 --- a/gdbus/mainloop.c +++ b/gdbus/mainloop.c @@ -30,6 +30,8 @@ #include "gdbus.h" +#define DISPATCH_TIMEOUT 0 + #define info(fmt...) #define error(fmt...) #define debug(fmt...) @@ -68,6 +70,8 @@ static gboolean message_dispatch(void *data) { DBusConnection *conn = data; + dbus_connection_ref(conn); + /* Dispatch messages */ while (dbus_connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS); diff --git a/gdbus/object.c b/gdbus/object.c index a2201016..c333d5b7 100644..100755 --- a/gdbus/object.c +++ b/gdbus/object.c @@ -1248,8 +1248,10 @@ static struct generic_data *object_path_ref(DBusConnection *connection, if (!dbus_connection_register_object_path(connection, path, &generic_table, data)) { +#if !defined TIZEN_EXT dbus_connection_unref(data->conn); g_free(data->path); +#endif g_free(data->introspect); g_free(data); return NULL; diff --git a/gdbus/polkit.c b/gdbus/polkit.c index 9e95fa38..9e95fa38 100644..100755 --- a/gdbus/polkit.c +++ b/gdbus/polkit.c diff --git a/gdbus/watch.c b/gdbus/watch.c index 447e4867..447e4867 100644..100755 --- a/gdbus/watch.c +++ b/gdbus/watch.c diff --git a/gdhcp/client.c b/gdhcp/client.c index 3e67fcd5..5a455f08 100644..100755 --- a/gdhcp/client.c +++ b/gdhcp/client.c @@ -50,9 +50,30 @@ #define DISCOVER_TIMEOUT 5 #define DISCOVER_RETRIES 6 +#if defined TIZEN_EXT +#define REQUEST_TIMEOUT 1 +#else #define REQUEST_TIMEOUT 5 +#endif #define REQUEST_RETRIES 3 +#if defined TIZEN_EXT +#define DISCOVER_TIMEOUT_WIFI 1 +#define DISCOVER_RETRIES_WIFI 10 +static int dhcp_discover_timeout = DISCOVER_TIMEOUT_WIFI; +static int dhcp_discover_max_retry = DISCOVER_RETRIES_WIFI; + +void set_dhcp_discover_timeout(int timeout_value) +{ + dhcp_discover_timeout = timeout_value; +} + +void set_dhcp_discover_retry_count(int retry_count) +{ + dhcp_discover_max_retry = retry_count; +} +#endif + typedef enum _listen_mode { L_NONE, L2, @@ -156,6 +177,10 @@ struct _GDHCPClient { bool retransmit; struct timeval start_time; bool request_bcast; +#if defined TIZEN_EXT + uint32_t dhcp_lease_seconds; + gboolean init_reboot; +#endif }; static inline void debug(GDHCPClient *client, const char *format, ...) @@ -480,6 +505,9 @@ static int send_request(GDHCPClient *dhcp_client) init_packet(dhcp_client, &packet, DHCPREQUEST); packet.xid = dhcp_client->xid; +#if defined TIZEN_EXT + if (dhcp_client->init_reboot != TRUE) +#endif packet.secs = dhcp_attempt_secs(dhcp_client); if (dhcp_client->state == REQUESTING || dhcp_client->state == REBOOTING) @@ -1516,6 +1544,21 @@ static gboolean request_timeout(gpointer user_data) { GDHCPClient *dhcp_client = user_data; +#if defined TIZEN_EXT + if (dhcp_client->init_reboot) { + debug(dhcp_client, "DHCPREQUEST of INIT-REBOOT has failed"); + + /* Start DHCPDISCOVERY when DHCPREQUEST of INIT-REBOOT has failed */ + g_dhcp_client_set_address_known(dhcp_client, FALSE); + + dhcp_client->retry_times = 0; + dhcp_client->requested_ip = 0; + + g_dhcp_client_start(dhcp_client, dhcp_client->last_address); + + return FALSE; + } +#endif debug(dhcp_client, "request timeout (retries %d)", dhcp_client->retry_times); @@ -1817,71 +1860,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; @@ -2405,6 +2383,10 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition, dhcp_client->lease_seconds = get_lease(&packet); +#if defined TIZEN_EXT + dhcp_client->dhcp_lease_seconds = dhcp_client->lease_seconds; +#endif + get_request(dhcp_client, &packet); switch_listening_mode(dhcp_client, L_NONE); @@ -2429,6 +2411,18 @@ static gboolean listener_event(GIOChannel *channel, GIOCondition condition, remove_timeouts(dhcp_client); +#if defined TIZEN_EXT + if (dhcp_client->init_reboot) { + g_dhcp_client_set_address_known(dhcp_client, FALSE); + dhcp_client->timeout = g_idle_add_full( + G_PRIORITY_HIGH, + restart_dhcp_timeout, + dhcp_client, + NULL); + + break; + } +#endif dhcp_client->timeout = g_timeout_add_seconds_full( G_PRIORITY_HIGH, 3, restart_dhcp_timeout, @@ -2666,6 +2660,11 @@ static gboolean ipv4ll_announce_timeout(gpointer dhcp_data) GDHCPClient *dhcp_client = dhcp_data; uint32_t ip; +#if defined TIZEN_EXT + if (!dhcp_client) + return FALSE; +#endif + debug(dhcp_client, "request timeout (retries %d)", dhcp_client->retry_times); @@ -2717,6 +2716,11 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address) uint32_t addr; uint64_t rand; +#if defined TIZEN_EXT + int discover_retry = 0; + int timeout = 0; +#endif + remove_timeouts(dhcp_client); if (dhcp_client->type == G_DHCP_IPV6) { @@ -2803,13 +2807,32 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address) return 0; } +#if defined TIZEN_EXT + if (g_ascii_strncasecmp(dhcp_client->interface, "wlan", 4) + == 0) { + discover_retry = DISCOVER_RETRIES_WIFI; + timeout = DISCOVER_TIMEOUT_WIFI; + } else { + discover_retry = DISCOVER_RETRIES; + timeout = DISCOVER_TIMEOUT; + } + + debug(dhcp_client, "[DHCPC] Discover retry/total : [%d]/[%d] timeout [%d]", + dhcp_client->retry_times, discover_retry, timeout); +#endif + + if (dhcp_client->type == G_DHCP_IPV4LL) { dhcp_client->state = INIT_SELECTING; ipv4ll_start(dhcp_client); return 0; } - if (dhcp_client->retry_times == DISCOVER_RETRIES) { +#if defined TIZEN_EXT + if (dhcp_client->retry_times == discover_retry) { +#else + if (dhcp_client->retry_times == DISCOVER_RETRIES) { +#endif if (dhcp_client->no_lease_cb) dhcp_client->no_lease_cb(dhcp_client, dhcp_client->no_lease_data); @@ -2852,7 +2875,11 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address) dhcp_client->timeout = g_timeout_add_seconds_full( G_PRIORITY_HIGH, +#if defined TIZEN_EXT + timeout, +#else REQUEST_TIMEOUT, +#endif reboot_timeout, dhcp_client, NULL); @@ -2861,7 +2888,11 @@ int g_dhcp_client_start(GDHCPClient *dhcp_client, const char *last_address) send_discover(dhcp_client, addr); dhcp_client->timeout = g_timeout_add_seconds_full(G_PRIORITY_HIGH, +#if defined TIZEN_EXT + timeout, +#else DISCOVER_TIMEOUT, +#endif discover_timeout, dhcp_client, NULL); @@ -3002,8 +3033,19 @@ char *g_dhcp_client_get_server_address(GDHCPClient *dhcp_client) if (!dhcp_client) return NULL; +#if defined TIZEN_EXT + return get_ip(htonl(dhcp_client->server_ip)); +#else return get_ip(dhcp_client->server_ip); +#endif +} + +#if defined TIZEN_EXT +int g_dhcp_client_get_dhcp_lease_duration(GDHCPClient *dhcp_client) +{ + return dhcp_client->dhcp_lease_seconds; } +#endif char *g_dhcp_client_get_address(GDHCPClient *dhcp_client) { @@ -3230,6 +3272,9 @@ void g_dhcp_client_unref(GDHCPClient *dhcp_client) g_hash_table_destroy(dhcp_client->send_value_hash); g_free(dhcp_client); +#if defined TIZEN_EXT + dhcp_client = NULL; +#endif } void g_dhcp_client_set_debug(GDHCPClient *dhcp_client, @@ -3265,3 +3310,19 @@ GSList *g_dhcpv6_copy_prefixes(GSList *prefixes) return copy; } + +#if defined TIZEN_EXT +void g_dhcp_client_set_address_known(GDHCPClient *dhcp_client, gboolean known) +{ + /* DHCPREQUEST during INIT-REBOOT state (rfc2131) + * 4.4.3 Initialization with known network address + * 4.3.2 DHCPREQUEST generated during INIT-REBOOT state + */ + debug(dhcp_client, "known network address (%d)", known); + + if (dhcp_client->init_reboot == known) + return; + + dhcp_client->init_reboot = known; +} +#endif diff --git a/gdhcp/common.c b/gdhcp/common.c index 6f816718..b8c5091a 100644..100755 --- a/gdhcp/common.c +++ b/gdhcp/common.c @@ -182,6 +182,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 75abc183..7da13135 100644..100755 --- a/gdhcp/common.h +++ b/gdhcp/common.h @@ -178,6 +178,7 @@ struct in6_pktinfo { }; #endif +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 eaf6a748..f51a8b05 100644..100755 --- a/gdhcp/gdhcp.h +++ b/gdhcp/gdhcp.h @@ -153,6 +153,11 @@ GDHCPClientError g_dhcp_client_set_send(GDHCPClient *client, const char *option_value); char *g_dhcp_client_get_server_address(GDHCPClient *client); + +#if defined TIZEN_EXT +int g_dhcp_client_get_dhcp_lease_duration(GDHCPClient *client); +#endif + char *g_dhcp_client_get_address(GDHCPClient *client); char *g_dhcp_client_get_netmask(GDHCPClient *client); GList *g_dhcp_client_get_option(GDHCPClient *client, @@ -211,6 +216,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); @@ -231,10 +239,16 @@ void g_dhcp_server_set_save_lease(GDHCPServer *dhcp_server, GDHCPSaveLeaseFunc func, gpointer user_data); void g_dhcp_server_set_lease_added_cb(GDHCPServer *dhcp_server, GDHCPLeaseAddedCb cb); +void g_dhcp_server_set_save_ack_lease(GDHCPServer *dhcp_server, + GDHCPSaveACKLeaseFunc func, gpointer user_data); int dhcp_get_random(uint64_t *val); void dhcp_cleanup_random(void); +#if defined TIZEN_EXT +void g_dhcp_client_set_address_known(GDHCPClient *client, gboolean known); +#endif + #ifdef __cplusplus } #endif diff --git a/gdhcp/ipv4ll.c b/gdhcp/ipv4ll.c index d9001987..d9001987 100644..100755 --- a/gdhcp/ipv4ll.c +++ b/gdhcp/ipv4ll.c diff --git a/gdhcp/ipv4ll.h b/gdhcp/ipv4ll.h index bee8138a..bee8138a 100644..100755 --- a/gdhcp/ipv4ll.h +++ b/gdhcp/ipv4ll.h diff --git a/gdhcp/server.c b/gdhcp/server.c index f7795f7e..44ce771a 100644..100755 --- a/gdhcp/server.c +++ b/gdhcp/server.c @@ -66,6 +66,7 @@ struct _GDHCPServer { GHashTable *option_hash; /* Options send to client */ GDHCPSaveLeaseFunc save_lease_func; GDHCPLeaseAddedCb lease_added_cb; + GDHCPSaveACKLeaseFunc save_ack_lease_func; GDHCPDebugFunc debug_func; gpointer debug_data; }; @@ -399,6 +400,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; @@ -650,9 +652,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; @@ -698,8 +703,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; } @@ -828,6 +846,15 @@ void g_dhcp_server_set_lease_added_cb(GDHCPServer *dhcp_server, dhcp_server->lease_added_cb = cb; } +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) diff --git a/gsupplicant/dbus.c b/gsupplicant/dbus.c index 2957979a..2957979a 100644..100755 --- a/gsupplicant/dbus.c +++ b/gsupplicant/dbus.c diff --git a/gsupplicant/dbus.h b/gsupplicant/dbus.h index 3a904069..3a904069 100644..100755 --- a/gsupplicant/dbus.h +++ b/gsupplicant/dbus.h diff --git a/gsupplicant/gsupplicant.h b/gsupplicant/gsupplicant.h index db61595b..88606262 100644..100755 --- a/gsupplicant/gsupplicant.h +++ b/gsupplicant/gsupplicant.h @@ -56,8 +56,13 @@ extern "C" { #define G_SUPPLICANT_KEYMGMT_WPA_NONE (1 << 2) #define G_SUPPLICANT_KEYMGMT_WPA_PSK (1 << 3) #define G_SUPPLICANT_KEYMGMT_WPA_PSK_256 (1 << 4) +#if defined TIZEN_EXT +#define G_SUPPLICANT_KEYMGMT_WPA_FT_EAP (1 << 5) +#define G_SUPPLICANT_KEYMGMT_WPA_FT_PSK (1 << 6) +#else #define G_SUPPLICANT_KEYMGMT_WPA_FT_PSK (1 << 5) #define G_SUPPLICANT_KEYMGMT_WPA_FT_EAP (1 << 6) +#endif #define G_SUPPLICANT_KEYMGMT_WPA_EAP (1 << 7) #define G_SUPPLICANT_KEYMGMT_WPA_EAP_256 (1 << 8) #define G_SUPPLICANT_KEYMGMT_WPS (1 << 9) @@ -97,6 +102,10 @@ typedef enum { G_SUPPLICANT_SECURITY_WEP, G_SUPPLICANT_SECURITY_PSK, G_SUPPLICANT_SECURITY_IEEE8021X, +#if defined TIZEN_EXT + G_SUPPLICANT_SECURITY_FT_PSK, + G_SUPPLICANT_SECURITY_FT_IEEE8021X, +#endif } GSupplicantSecurity; typedef enum { @@ -129,6 +138,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; @@ -155,10 +170,23 @@ struct _GSupplicantSSID { dbus_bool_t use_wps; const char *pin_wps; const char *bgscan; + int ignore_broadcast_ssid; +#if defined TIZEN_EXT + unsigned char *bssid; +#endif }; typedef struct _GSupplicantSSID GSupplicantSSID; +/* + * Max number of SSIDs that can be scanned. + * In wpa_s 0.7x the limit is 4. + * In wps_s 0.8 or later it is 16. + * The value is only used if wpa_supplicant does not return any max limit + * for number of scannable SSIDs. + */ +#define WPAS_MAX_SCAN_SSIDS 4 + struct scan_ssid { unsigned char ssid[32]; uint8_t ssid_len; @@ -268,6 +296,9 @@ int g_supplicant_interface_disconnect(GSupplicantInterface *interface, GSupplicantInterfaceCallback callback, void *user_data); +#if defined TIZEN_EXT +int g_supplicant_interface_remove_network(GSupplicantInterface *interface); +#endif int g_supplicant_interface_set_apscan(GSupplicantInterface *interface, unsigned int ap_scan); @@ -337,6 +368,24 @@ GSupplicantInterface *g_supplicant_peer_get_group_interface(GSupplicantPeer *pee bool g_supplicant_peer_is_client(GSupplicantPeer *peer); bool g_supplicant_peer_has_requested_connection(GSupplicantPeer *peer); +#if defined TIZEN_EXT +/* +* Description: Network client requires additional wifi specific info +*/ +const unsigned char *g_supplicant_network_get_bssid( + GSupplicantNetwork *network); +unsigned int g_supplicant_network_get_maxrate(GSupplicantNetwork *network); +const char *g_supplicant_network_get_enc_mode(GSupplicantNetwork *network); +bool g_supplicant_network_get_rsn_mode(GSupplicantNetwork *network); +bool g_supplicant_network_is_hs20AP(GSupplicantNetwork *network); +const char *g_supplicant_network_get_eap(GSupplicantNetwork *network); +const char *g_supplicant_network_get_identity(GSupplicantNetwork *network); +const char *g_supplicant_network_get_phase2(GSupplicantNetwork *network); +unsigned int g_supplicant_network_get_keymgmt(GSupplicantNetwork *network); +const void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network, + unsigned int *wifi_vsie_len); +#endif + struct _GSupplicantCallbacks { void (*system_ready) (void); void (*system_killed) (void); @@ -349,9 +398,18 @@ struct _GSupplicantCallbacks { void (*ap_create_fail) (GSupplicantInterface *interface); void (*network_added) (GSupplicantNetwork *network); void (*network_removed) (GSupplicantNetwork *network); +#if defined TIZEN_EXT + void (*network_merged) (GSupplicantNetwork *network); +#endif void (*network_changed) (GSupplicantNetwork *network, const char *property); void (*network_associated) (GSupplicantNetwork *network); +#if defined TIZEN_EXT + void (*system_power_off) (void); + void (*assoc_failed) (void *user_data); +#endif + 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 4f790122..5e9f5095 100644 --- a/gsupplicant/supplicant.c +++ b/gsupplicant/supplicant.c @@ -191,6 +191,9 @@ struct _GSupplicantInterface { const char *pending_peer_path; GSupplicantNetwork *current_network; struct added_network_information network_info; +#if defined TIZEN_EXT + int disconnect_reason; +#endif }; struct g_supplicant_bss { @@ -215,6 +218,13 @@ struct g_supplicant_bss { dbus_bool_t privacy; dbus_bool_t psk; dbus_bool_t ieee8021x; +#if defined TIZEN_EXT + dbus_bool_t ft_psk; + dbus_bool_t ft_ieee8021x; + char *wifi_vsie; + unsigned int wifi_vsie_len; + dbus_bool_t hs20; +#endif unsigned int wps_capabilities; }; @@ -234,6 +244,15 @@ struct _GSupplicantNetwork { unsigned int wps_capabilities; GHashTable *bss_table; GHashTable *config_table; +#if defined TIZEN_EXT + bool isHS20AP; + char *eap; + char *identity; + char *phase2; + unsigned int keymgmt; + char *wifi_vsie; + unsigned int wifi_vsie_len; +#endif }; struct _GSupplicantPeer { @@ -361,6 +380,12 @@ static const char *security2string(GSupplicantSecurity security) return "psk"; case G_SUPPLICANT_SECURITY_IEEE8021X: return "ieee8021x"; +#if defined TIZEN_EXT + case G_SUPPLICANT_SECURITY_FT_PSK: + return "ft_psk"; + case G_SUPPLICANT_SECURITY_FT_IEEE8021X: + return "ft_ieee8021x"; +#endif } return NULL; @@ -525,6 +550,7 @@ static void callback_interface_removed(GSupplicantInterface *interface) callbacks_pointer->interface_removed(interface); } +#if !defined TIZEN_EXT static void callback_p2p_support(GSupplicantInterface *interface) { SUPPLICANT_DBG(""); @@ -535,6 +561,7 @@ static void callback_p2p_support(GSupplicantInterface *interface) if (callbacks_pointer && callbacks_pointer->p2p_support) callbacks_pointer->p2p_support(interface); } +#endif static void callback_scan_started(GSupplicantInterface *interface) { @@ -591,6 +618,30 @@ static void callback_network_removed(GSupplicantNetwork *network) callbacks_pointer->network_removed(network); } +#if defined TIZEN_EXT +static void callback_network_merged(GSupplicantNetwork *network) +{ + if (!callbacks_pointer) + return; + + if (!callbacks_pointer->network_merged) + return; + + callbacks_pointer->network_merged(network); +} + +static void callback_assoc_failed(void *user_data) +{ + if (!callbacks_pointer) + return; + + if (!callbacks_pointer->assoc_failed) + return; + + callbacks_pointer->assoc_failed(user_data); +} +#endif + static void callback_network_changed(GSupplicantNetwork *network, const char *property) { @@ -728,6 +779,9 @@ static void remove_interface(gpointer data) g_free(interface->wps_cred.key); g_free(interface->path); g_free(interface->network_path); +#if defined TIZEN_EXT + interface->network_path = NULL; +#endif g_free(interface->ifname); g_free(interface->driver); g_free(interface->bridge); @@ -748,6 +802,15 @@ static void remove_network(gpointer data) g_free(network->path); g_free(network->group); g_free(network->name); +#if defined TIZEN_EXT + g_free(network->eap); + g_free(network->identity); + g_free(network->phase2); +#endif +#if defined TIZEN_EXT + g_free(network->wifi_vsie); +#endif + g_free(network); } @@ -756,6 +819,9 @@ static void remove_bss(gpointer data) struct g_supplicant_bss *bss = data; g_free(bss->path); +#if defined TIZEN_EXT + g_free(bss->wifi_vsie); +#endif g_free(bss); } @@ -1101,6 +1167,9 @@ unsigned int g_supplicant_interface_get_max_scan_ssids( if (!interface) return 0; + if (interface->max_scan_ssids == 0) + return WPAS_MAX_SCAN_SSIDS; + return interface->max_scan_ssids; } @@ -1301,6 +1370,48 @@ const char *g_supplicant_peer_get_name(GSupplicantPeer *peer) return peer->name; } +#if defined TIZEN_EXT +bool g_supplicant_network_is_hs20AP(GSupplicantNetwork *network) +{ + if (!network) + return 0; + + return network->isHS20AP; +} + +const char *g_supplicant_network_get_eap(GSupplicantNetwork *network) +{ + if (!network || !network->eap) + return NULL; + + return network->eap; +} + +const char *g_supplicant_network_get_identity(GSupplicantNetwork *network) +{ + if (!network || !network->identity) + return NULL; + + return network->identity; +} + +const char *g_supplicant_network_get_phase2(GSupplicantNetwork *network) +{ + if (!network || !network->phase2) + return NULL; + + return network->phase2; +} + +unsigned int g_supplicant_network_get_keymgmt(GSupplicantNetwork *network) +{ + if (network == NULL) + return 0; + + return network->keymgmt; +} +#endif + const unsigned char *g_supplicant_peer_get_widi_ies(GSupplicantPeer *peer, int *length) { @@ -1383,16 +1494,105 @@ 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; +} + +bool g_supplicant_network_get_rsn_mode(GSupplicantNetwork *network) +{ + if (network == NULL || network->best_bss == NULL) + return 0; + + if (network->best_bss->rsn_selected) { + const char *mode = g_supplicant_network_get_enc_mode(network); + if (g_strcmp0(mode, "aes") == 0 || + g_strcmp0(mode, "mixed") == 0) + return true; + else + return false; + } else + return false; +} + +const void *g_supplicant_network_get_wifi_vsie(GSupplicantNetwork *network, + unsigned int *wifi_vsie_len) +{ + if (!network) { + *wifi_vsie_len = 0; + return NULL; + } + + *wifi_vsie_len = network->wifi_vsie_len; + return network->wifi_vsie; +} +#endif + static void merge_network(GSupplicantNetwork *network) { GString *str; const char *ssid, *mode, *key_mgmt; +#if defined TIZEN_EXT + GSupplicantInterface *interface; + const char *isHS20AP; + const char *eap, *identity, *phase2; +#endif unsigned int i, ssid_len; char *group; ssid = g_hash_table_lookup(network->config_table, "ssid"); mode = g_hash_table_lookup(network->config_table, "mode"); key_mgmt = g_hash_table_lookup(network->config_table, "key_mgmt"); +#if defined TIZEN_EXT + isHS20AP = g_hash_table_lookup(network->config_table, "isHS20AP"); + eap = g_hash_table_lookup(network->config_table, "eap"); + identity = g_hash_table_lookup(network->config_table, "identity"); + phase2 = g_hash_table_lookup(network->config_table, "phase2"); + interface = network->interface; +#endif SUPPLICANT_DBG("ssid %s mode %s", ssid, mode); @@ -1406,7 +1606,14 @@ static void merge_network(GSupplicantNetwork *network) return; for (i = 0; i < ssid_len; i++) +#if defined TIZEN_EXT + { + if (ssid[i] != '"') +#endif g_string_append_printf(str, "%02x", ssid[i]); +#if defined TIZEN_EXT + } +#endif if (g_strcmp0(mode, "0") == 0) g_string_append_printf(str, "_managed"); @@ -1415,11 +1622,41 @@ static void merge_network(GSupplicantNetwork *network) if (g_strcmp0(key_mgmt, "WPA-PSK") == 0) g_string_append_printf(str, "_psk"); +#if defined TIZEN_EXT + else if (g_strcmp0(key_mgmt, "WPA-EAP") == 0) + g_string_append_printf(str, "_ieee8021x"); + else + g_string_append_printf(str, "_none"); +#endif group = g_string_free(str, FALSE); SUPPLICANT_DBG("%s", group); +#if defined TIZEN_EXT + if (g_strcmp0(isHS20AP, "1") == 0) { + network->isHS20AP = 1; + if (network->eap) + g_free(network->eap); + network->eap = g_strdup(eap); + + if (network->identity) + g_free(network->identity); + network->identity = g_strdup(identity); + + if (network->phase2) + g_free(network->phase2); + network->phase2 = g_strdup(phase2); + } else + network->isHS20AP = 0; + + if (interface) + interface->network_path = g_strdup(network->path); + + network->group = g_strdup(group); + callback_network_merged(network); +#endif + g_free(group); g_hash_table_destroy(network->config_table); @@ -1609,6 +1846,23 @@ static int add_or_replace_bss_to_network(struct g_supplicant_bss *bss) network->frequency = bss->frequency; network->best_bss = bss; +#if defined TIZEN_EXT + network->keymgmt = bss->keymgmt; + + if (bss->wifi_vsie_len > 0) { + SUPPLICANT_DBG("vsie len: %d", bss->wifi_vsie_len); + network->wifi_vsie = (char *)g_try_malloc0(bss->wifi_vsie_len); + if(network->wifi_vsie) { + network->wifi_vsie_len = bss->wifi_vsie_len; + memcpy(network->wifi_vsie, bss->wifi_vsie, network->wifi_vsie_len); + } else { + SUPPLICANT_DBG("Failed to allocate memory for wifi_vsie"); + } + } + + network->isHS20AP = bss->hs20; +#endif + SUPPLICANT_DBG("New network %s created", network->name); network->bss_table = g_hash_table_new_full(g_str_hash, g_str_equal, @@ -1793,6 +2047,9 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data) { struct g_supplicant_bss *bss = user_data; const unsigned char WPS_OUI[] = { 0x00, 0x50, 0xf2, 0x04 }; +#if defined TIZEN_EXT + const unsigned char WIFI_OUI[] = {0x00, 0x16, 0x32}; +#endif unsigned char *ie, *ie_end; DBusMessageIter array; unsigned int value; @@ -1808,6 +2065,9 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data) #define WPS_PBC 0x04 #define WPS_PIN 0x00 #define WPS_CONFIGURED 0x02 +#if defined TIZEN_EXT +#define VENDOR_SPECIFIC_INFO 0xDD +#endif dbus_message_iter_recurse(iter, &array); dbus_message_iter_get_fixed_array(&array, &ie, &ie_len); @@ -1820,7 +2080,19 @@ static void bss_process_ies(DBusMessageIter *iter, void *user_data) for (ie_end = ie + ie_len; ie < ie_end && ie + ie[1] + 1 <= ie_end; ie += ie[1] + 2) { - +#if defined TIZEN_EXT + if((ie[0] == VENDOR_SPECIFIC_INFO) && (memcmp(ie+2, WIFI_OUI, sizeof(WIFI_OUI)) == 0)) { + SUPPLICANT_DBG("IE: match WIFI_OUI"); + bss->wifi_vsie = (char *)g_try_malloc0(ie[1] + 2); // tag number size(1), tag length size(1) + if (bss->wifi_vsie) { + bss->wifi_vsie_len = ie[1] + 2; + memcpy(bss->wifi_vsie, ie, bss->wifi_vsie_len); + } else { + SUPPLICANT_DBG("Failed to allocate memory for wifi_vsie"); + } + continue; + } +#endif if (ie[0] != WMM_WPA1_WPS_INFO || ie[1] < WPS_INFO_MIN_LEN || memcmp(ie+2, WPS_OUI, sizeof(WPS_OUI)) != 0) continue; @@ -1866,23 +2138,51 @@ static void bss_compute_security(struct g_supplicant_bss *bss) bss->ieee8021x = FALSE; bss->psk = FALSE; +#if defined TIZEN_EXT + bss->ft_ieee8021x = FALSE; + bss->ft_psk = FALSE; +#endif +#if defined TIZEN_EXT + if (bss->keymgmt & + (G_SUPPLICANT_KEYMGMT_WPA_EAP | + G_SUPPLICANT_KEYMGMT_WPA_EAP_256)) + bss->ieee8021x = TRUE; + else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_EAP) + bss->ft_ieee8021x = TRUE; +#else if (bss->keymgmt & (G_SUPPLICANT_KEYMGMT_WPA_EAP | G_SUPPLICANT_KEYMGMT_WPA_FT_EAP | G_SUPPLICANT_KEYMGMT_WPA_EAP_256)) bss->ieee8021x = TRUE; +#endif +#if defined TIZEN_EXT + if (bss->keymgmt & + (G_SUPPLICANT_KEYMGMT_WPA_PSK | + G_SUPPLICANT_KEYMGMT_WPA_PSK_256)) + bss->psk = TRUE; + else if (bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPA_FT_PSK) + bss->ft_psk = TRUE; +#else if (bss->keymgmt & (G_SUPPLICANT_KEYMGMT_WPA_PSK | G_SUPPLICANT_KEYMGMT_WPA_FT_PSK | G_SUPPLICANT_KEYMGMT_WPA_PSK_256)) bss->psk = TRUE; +#endif if (bss->ieee8021x) bss->security = G_SUPPLICANT_SECURITY_IEEE8021X; else if (bss->psk) bss->security = G_SUPPLICANT_SECURITY_PSK; +#if defined TIZEN_EXT + else if (bss->ft_psk) + bss->security = G_SUPPLICANT_SECURITY_FT_PSK; + else if (bss->ft_ieee8021x == TRUE) + bss->security = G_SUPPLICANT_SECURITY_IEEE8021X; +#endif else if (bss->privacy) bss->security = G_SUPPLICANT_SECURITY_WEP; else @@ -1984,6 +2284,12 @@ static void bss_property(const char *key, DBusMessageIter *iter, bss->rsn_selected = FALSE; supplicant_dbus_property_foreach(iter, bss_wpa, bss); +#if defined TIZEN_EXT + } else if (g_strcmp0(key, "HS20") == 0) { + dbus_bool_t hs20 = FALSE; + dbus_message_iter_get_basic(iter, &hs20); + bss->hs20 = hs20; +#endif } else if (g_strcmp0(key, "IEs") == 0) bss_process_ies(iter, bss); else @@ -2269,8 +2575,10 @@ static void interface_property(const char *key, DBusMessageIter *iter, if (g_strcmp0(key, "Capabilities") == 0) { supplicant_dbus_property_foreach(iter, interface_capability, interface); +#if !defined TIZEN_EXT if (interface->mode_capa & G_SUPPLICANT_CAPABILITY_MODE_P2P) interface->p2p_support = true; +#endif } else if (g_strcmp0(key, "State") == 0) { const char *str = NULL; @@ -2347,6 +2655,9 @@ static void interface_property(const char *key, DBusMessageIter *iter, } else if (g_strcmp0(key, "CurrentBSS") == 0) { interface_current_bss(interface, iter); } else if (g_strcmp0(key, "CurrentNetwork") == 0) { +#if defined TIZEN_EXT + if (interface->state != G_SUPPLICANT_STATE_COMPLETED) +#endif interface_network_added(iter, interface); } else if (g_strcmp0(key, "BSSs") == 0) { supplicant_dbus_array_foreach(iter, @@ -2403,15 +2714,30 @@ static void scan_bss_data(const char *key, DBusMessageIter *iter, { GSupplicantInterface *interface = user_data; +/*Fixed : stucking in scanning state when scan failed*/ +#if defined TIZEN_EXT + GSupplicantInterfaceCallback scan_callback; +#endif + if (iter) supplicant_dbus_array_foreach(iter, scan_network_update, interface); +#if defined TIZEN_EXT + scan_callback = interface->scan_callback; +#endif + if (interface->scan_callback) interface->scan_callback(0, interface, interface->scan_data); +#if defined TIZEN_EXT + if (interface->scan_callback == scan_callback) { +#endif interface->scan_callback = NULL; interface->scan_data = NULL; +#if defined TIZEN_EXT + } +#endif } static GSupplicantInterface *interface_alloc(const char *path) @@ -2740,7 +3066,9 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter) return; supplicant_dbus_property_foreach(iter, bss_property, bss); - +#if defined TIZEN_EXT + network->frequency = bss->frequency; +#endif old_security = network->security; bss_compute_security(bss); @@ -2781,12 +3109,27 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter) return; } +#if defined TIZEN_EXT + if ((bss->keymgmt & G_SUPPLICANT_KEYMGMT_WPS) != 0) { + network->wps = TRUE; + network->wps_capabilities |= bss->wps_capabilities; + } else + network->wps = FALSE; +#endif + /* Consider only property changes of the connected BSS */ if (network == interface->current_network && bss != network->best_bss) return; if (bss->signal == network->signal) +#ifndef TIZEN_EXT + return; +#else + { + callback_network_changed(network, ""); return; + } +#endif /* * If the new signal is lower than the SSID signal, we need @@ -2794,7 +3137,14 @@ static void signal_bss_changed(const char *path, DBusMessageIter *iter) */ if (bss->signal < network->signal) { if (bss != network->best_bss) +#ifndef TIZEN_EXT + return; +#else + { + callback_network_changed(network, ""); return; + } +#endif network->signal = bss->signal; update_network_signal(network); } else { @@ -2896,7 +3246,7 @@ static void signal_wps_event(const char *path, DBusMessageIter *iter) if (g_strcmp0(name, "success") == 0) interface->wps_state = G_SUPPLICANT_WPS_STATE_SUCCESS; - else if (g_strcmp0(name, "fail") == 0) + else if (g_strcmp0(name, "failed") == 0) interface->wps_state = G_SUPPLICANT_WPS_STATE_FAIL; else interface->wps_state = G_SUPPLICANT_WPS_STATE_UNKNOWN; @@ -2909,6 +3259,79 @@ static void signal_wps_event(const char *path, DBusMessageIter *iter) supplicant_dbus_property_foreach(iter, wps_event_args, interface); } +#if defined TIZEN_EXT +static void signal_power_off(const char *path, DBusMessageIter *iter) +{ + int poweroff_state = 0; + + dbus_message_iter_get_basic(iter, &poweroff_state); + + SUPPLICANT_DBG("poweroff_state(%d)", poweroff_state); + + /* POWER_OFF_DIRECT 2 && POWER_OFF_RESTART 3 */ + if (poweroff_state != 2 && poweroff_state != 3) + return; + + if (callbacks_pointer == NULL) + return; + + if (callbacks_pointer->system_power_off == NULL) + return; + + callbacks_pointer->system_power_off(); +} +#endif + +static void 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] = {}; @@ -3473,6 +3896,12 @@ static struct { { SUPPLICANT_INTERFACE ".Interface.WPS", "Credentials", signal_wps_credentials }, { SUPPLICANT_INTERFACE ".Interface.WPS", "Event", signal_wps_event }, +#if defined TIZEN_EXT + { "org.tizen.system.deviced.PowerOff", "ChangeState", signal_power_off }, +#endif + + { SUPPLICANT_INTERFACE".Interface", "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 }, @@ -3789,7 +4218,9 @@ static void interface_create_property(const char *key, DBusMessageIter *iter, if (!key) { if (data->callback) { data->callback(0, data->interface, data->user_data); +#if !defined TIZEN_EXT callback_p2p_support(interface); +#endif } interface_create_data_free(data); @@ -3908,7 +4339,9 @@ static void interface_get_result(const char *error, if (data->callback) { data->callback(0, interface, data->user_data); +#if !defined TIZEN_EXT callback_p2p_support(interface); +#endif } interface_create_data_free(data); @@ -4204,7 +4637,11 @@ static void interface_scan_params(DBusMessageIter *iter, void *user_data) supplicant_dbus_dict_append_basic(&dict, "Type", DBUS_TYPE_STRING, &type); - supplicant_dbus_dict_append_array(&dict, "SSIDs", +#if defined TIZEN_EXT + SUPPLICANT_DBG("[specific_scan] num_ssids %d", data->scan_params->num_ssids); + if (data->scan_params->num_ssids != 0) +#endif + supplicant_dbus_dict_append_array(&dict, "SSIDs", DBUS_TYPE_STRING, append_ssids, data->scan_params); @@ -4236,8 +4673,14 @@ static int interface_ready_to_scan(GSupplicantInterface *interface) case G_SUPPLICANT_STATE_4WAY_HANDSHAKE: case G_SUPPLICANT_STATE_GROUP_HANDSHAKE: return -EBUSY; +#if defined TIZEN_EXT + case G_SUPPLICANT_STATE_DISABLED: + return -ENOLINK; + case G_SUPPLICANT_STATE_UNKNOWN: +#else case G_SUPPLICANT_STATE_UNKNOWN: case G_SUPPLICANT_STATE_DISABLED: +#endif case G_SUPPLICANT_STATE_DISCONNECTED: case G_SUPPLICANT_STATE_INACTIVE: case G_SUPPLICANT_STATE_SCANNING: @@ -4266,8 +4709,13 @@ int g_supplicant_interface_scan(GSupplicantInterface *interface, data->interface = interface; data->path = g_strdup(interface->path); +#if defined TIZEN_EXT + data->interface->scan_callback = data->callback = callback; + data->interface->scan_data = data->user_data = user_data; +#else data->callback = callback; data->user_data = user_data; +#endif data->scan_params = scan_data; interface->scan_callback = callback; @@ -4322,7 +4770,11 @@ static void interface_select_network_result(const char *error, err = 0; if (error) { +#if defined TIZEN_EXT + SUPPLICANT_DBG("SelectNetwork errorFreq %s", error); +#else SUPPLICANT_DBG("SelectNetwork error %s", error); +#endif err = parse_supplicant_error(iter); } @@ -4340,9 +4792,15 @@ static void interface_select_network_params(DBusMessageIter *iter, { struct interface_connect_data *data = user_data; GSupplicantInterface *interface = data->interface; +#if defined TIZEN_EXT + GSupplicantSSID *ssid = data->ssid; +#endif dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &interface->network_path); +#if defined TIZEN_EXT + dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &ssid->freq); +#endif } static void interface_add_network_result(const char *error, @@ -4366,11 +4824,23 @@ static void interface_add_network_result(const char *error, store_network_information(interface, data->ssid); +#if defined TIZEN_EXT + SUPPLICANT_DBG(".Interface.SelectNetworkFreq"); +#endif + +#if defined TIZEN_EXT + supplicant_dbus_method_call(data->interface->path, + SUPPLICANT_INTERFACE ".Interface", "SelectNetworkFreq", + interface_select_network_params, + interface_select_network_result, data, + interface); +#else supplicant_dbus_method_call(data->interface->path, SUPPLICANT_INTERFACE ".Interface", "SelectNetwork", interface_select_network_params, interface_select_network_result, data, interface); +#endif return; @@ -4536,8 +5006,10 @@ static void add_network_security_tls(DBusMessageIter *dict, if (!ssid->private_key_path) return; +#if !defined TIZEN_EXT if (!ssid->private_key_passphrase) return; +#endif if (ssid->ca_cert_path) supplicant_dbus_dict_append_basic(dict, "ca_cert", @@ -4546,9 +5018,11 @@ static void add_network_security_tls(DBusMessageIter *dict, supplicant_dbus_dict_append_basic(dict, "private_key", DBUS_TYPE_STRING, &ssid->private_key_path); +#if !defined TIZEN_EXT supplicant_dbus_dict_append_basic(dict, "private_key_passwd", DBUS_TYPE_STRING, &ssid->private_key_passphrase); +#endif supplicant_dbus_dict_append_basic(dict, "client_cert", DBUS_TYPE_STRING, &ssid->client_cert_path); @@ -4580,8 +5054,10 @@ static void add_network_security_peap(DBusMessageIter *dict, if (!ssid->private_key_path) return; +#if !defined TIZEN_EXT if (!ssid->private_key_passphrase) return; +#endif supplicant_dbus_dict_append_basic(dict, "client_cert", DBUS_TYPE_STRING, @@ -4591,9 +5067,11 @@ static void add_network_security_peap(DBusMessageIter *dict, DBUS_TYPE_STRING, &ssid->private_key_path); +#if !defined TIZEN_EXT supplicant_dbus_dict_append_basic(dict, "private_key_passwd", DBUS_TYPE_STRING, &ssid->private_key_passphrase); +#endif } @@ -4619,19 +5097,46 @@ static void add_network_security_peap(DBusMessageIter *dict, g_free(phase2_auth); } +#if defined TIZEN_EXT +static void add_network_security_aka_sim(DBusMessageIter *dict, + GSupplicantSSID *ssid) +{ + if (!ssid->passphrase) + return; + + supplicant_dbus_dict_append_basic(dict, "password", + DBUS_TYPE_STRING, + &ssid->passphrase); +} +#endif + static void add_network_security_eap(DBusMessageIter *dict, GSupplicantSSID *ssid) { char *eap_value; +#if defined TIZEN_EXT + if (!ssid->eap) +#else if (!ssid->eap || !ssid->identity) +#endif return; if (g_strcmp0(ssid->eap, "tls") == 0) { add_network_security_tls(dict, ssid); } else if (g_strcmp0(ssid->eap, "peap") == 0 || g_strcmp0(ssid->eap, "ttls") == 0) { +#if defined TIZEN_EXT + if (!ssid->identity) + return; +#endif add_network_security_peap(dict, ssid); + +#if defined TIZEN_EXT + } else if (g_strcmp0(ssid->eap, "sim") == 0 || + g_strcmp0(ssid->eap, "aka") == 0) { + add_network_security_aka_sim(dict, ssid); +#endif } else return; @@ -4640,9 +5145,16 @@ static void add_network_security_eap(DBusMessageIter *dict, supplicant_dbus_dict_append_basic(dict, "eap", DBUS_TYPE_STRING, &eap_value); +#if defined TIZEN_EXT + if (ssid->identity != NULL) + supplicant_dbus_dict_append_basic(dict, "identity", + DBUS_TYPE_STRING, + &ssid->identity); +#else supplicant_dbus_dict_append_basic(dict, "identity", DBUS_TYPE_STRING, &ssid->identity); +#endif if(ssid->anonymous_identity) supplicant_dbus_dict_append_basic(dict, "anonymous_identity", DBUS_TYPE_STRING, @@ -4791,6 +5303,20 @@ static void add_network_security(DBusMessageIter *dict, GSupplicantSSID *ssid) add_network_security_ciphers(dict, ssid); add_network_security_proto(dict, ssid); break; +#if defined TIZEN_EXT + case G_SUPPLICANT_SECURITY_FT_PSK: + key_mgmt = "FT-PSK"; + add_network_security_psk(dict, ssid); + add_network_security_ciphers(dict, ssid); + add_network_security_proto(dict, ssid); + break; + case G_SUPPLICANT_SECURITY_FT_IEEE8021X: + key_mgmt = "FT-EAP"; + add_network_security_eap(dict, ssid); + add_network_security_ciphers(dict, ssid); + add_network_security_proto(dict, ssid); + break; +#endif } supplicant_dbus_dict_append_basic(dict, "key_mgmt", @@ -4846,6 +5372,28 @@ 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); + +#if defined TIZEN_EXT + if (ssid->bssid) { + char *bssid = NULL; + bssid = g_try_malloc0(18); + if (bssid == NULL) { + SUPPLICANT_DBG("memory allocation error"); + supplicant_dbus_dict_close(iter, &dict); + return; + } + snprintf(bssid, 18, "%02x:%02x:%02x:%02x:%02x:%02x", + ssid->bssid[0], ssid->bssid[1], ssid->bssid[2], + ssid->bssid[3], ssid->bssid[4], ssid->bssid[5]); + supplicant_dbus_dict_append_basic(&dict, "bssid", + DBUS_TYPE_STRING, &bssid); + g_free(bssid); + } +#endif + supplicant_dbus_dict_close(iter, &dict); } @@ -4895,6 +5443,12 @@ static void interface_add_wps_params(DBusMessageIter *iter, void *user_data) supplicant_dbus_dict_append_basic(&dict, "Type", DBUS_TYPE_STRING, &type); +#if defined TIZEN_EXT + if (ssid->bssid) + supplicant_dbus_dict_append_fixed_array(&dict, "Bssid", + DBUS_TYPE_BYTE, &ssid->bssid, 6); +#endif + supplicant_dbus_dict_close(iter, &dict); } @@ -4911,7 +5465,17 @@ static void wps_start(const char *error, DBusMessageIter *iter, void *user_data) dbus_free(data); return; } - +#if defined TIZEN_EXT + GSupplicantSSID *ssid = data->ssid; + if (ssid->pin_wps != NULL) { + if (!g_utf8_validate(ssid->pin_wps, 8, NULL)) { + SUPPLICANT_DBG("Invalid characters in WPS_PIN"); + g_free(data->ssid); + dbus_free(data); + return; + } + } +#endif supplicant_dbus_method_call(data->interface->path, SUPPLICANT_INTERFACE ".Interface.WPS", "Start", interface_add_wps_params, @@ -4928,6 +5492,136 @@ static void wps_process_credentials(DBusMessageIter *iter, void *user_data) } +#if defined TIZEN_EXT +#define NETCONFIG_SERVICE "net.netconfig" +#define NETCONFIG_WIFI_PATH "/net/netconfig/wifi" +#define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi" + +struct dec_method_call_data { + struct interface_connect_data *data; + DBusPendingCall *pending_call; +}; + +static struct dec_method_call_data decrypt_request_data; + +static void crypt_method_call_cancel(void) +{ + if (decrypt_request_data.pending_call) { + dbus_pending_call_cancel(decrypt_request_data.pending_call); + dbus_pending_call_unref(decrypt_request_data.pending_call); + decrypt_request_data.pending_call = NULL; + } + + g_free(decrypt_request_data.data->path); + g_free(decrypt_request_data.data->ssid); + dbus_free(decrypt_request_data.data); + decrypt_request_data.data = NULL; +} + +static void decryption_request_reply(DBusPendingCall *call, + void *user_data) +{ + DBusMessage *reply; + DBusError error; + DBusMessageIter args; + char *out_data; + int ret; + static gchar* origin_value = NULL; + struct interface_connect_data *data = user_data; + + g_free(origin_value); + origin_value = NULL; + + SUPPLICANT_DBG(""); + + reply = dbus_pending_call_steal_reply(call); + + dbus_error_init(&error); + if (dbus_set_error_from_message(&error, reply)) { + SUPPLICANT_DBG("decryption_request_reply() %s %s", error.name, error.message); + dbus_error_free(&error); + goto done; + } + + if (dbus_message_iter_init(reply, &args) == FALSE) { + SUPPLICANT_DBG("dbus_message_iter_init() failed"); + goto done; + } + + dbus_message_iter_get_basic(&args, &out_data); + + origin_value = g_strdup((const gchar *)out_data); + data->ssid->passphrase = origin_value; + + ret = supplicant_dbus_method_call(data->interface->path, + SUPPLICANT_INTERFACE ".Interface", "AddNetwork", + interface_add_network_params, + interface_add_network_result, data, + data->interface); + + if (ret < 0) { + SUPPLICANT_DBG("AddNetwork failed %d", ret); + callback_assoc_failed(decrypt_request_data.data->user_data); + g_free(data->path); + g_free(data->ssid); + dbus_free(data); + } + +done: + dbus_message_unref(reply); + dbus_pending_call_unref(call); + + decrypt_request_data.pending_call = NULL; + decrypt_request_data.data = NULL; +} + +static int send_decryption_request(const char *passphrase, + struct interface_connect_data *data) +{ + DBusMessage *msg = NULL; + DBusPendingCall *call; + + SUPPLICANT_DBG("Decryption request"); + + if (!passphrase) { + SUPPLICANT_DBG("Invalid parameter"); + return -EINVAL; + } + + if (!connection) + return -EINVAL; + + msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH, + NETCONFIG_WIFI_INTERFACE, "DecryptPassphrase"); + if (!msg) + return -EINVAL; + + dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase, + DBUS_TYPE_INVALID); + + if (!dbus_connection_send_with_reply(connection, msg, + &call, DBUS_TIMEOUT_USE_DEFAULT)) { + dbus_message_unref(msg); + return -EIO; + } + + if (!call) { + dbus_message_unref(msg); + return -EIO; + } + + decrypt_request_data.pending_call = call; + decrypt_request_data.data = data; + + dbus_pending_call_set_notify(call, decryption_request_reply, data, NULL); + dbus_message_unref(msg); + + SUPPLICANT_DBG("Decryption request succeeded"); + + return 0; +} +#endif + int g_supplicant_interface_connect(GSupplicantInterface *interface, GSupplicantSSID *ssid, GSupplicantInterfaceCallback callback, @@ -5010,14 +5704,20 @@ int g_supplicant_interface_connect(GSupplicantInterface *interface, intf_data->user_data = user_data; intf_data->network_remove_in_progress = TRUE; network_remove(intf_data); - } else { - ret = supplicant_dbus_method_call(interface->path, - SUPPLICANT_INTERFACE ".Interface", "AddNetwork", - interface_add_network_params, - interface_add_network_result, data, - interface); - } - } + } else +#if defined TIZEN_EXT + if (ssid->passphrase && g_strcmp0(ssid->passphrase, "") != 0) { + ret = send_decryption_request(ssid->passphrase, data); + if (ret < 0) + SUPPLICANT_DBG("Decryption request failed %d", ret); + } else +#endif + ret = supplicant_dbus_method_call(interface->path, + SUPPLICANT_INTERFACE ".Interface", "AddNetwork", + interface_add_network_params, + interface_add_network_result, data, + interface); + } if (ret < 0) { g_free(data->path); @@ -5092,6 +5792,16 @@ static int network_remove(struct interface_data *data) SUPPLICANT_DBG(""); +#if defined TIZEN_EXT + GSupplicantInterface *intf = NULL; + /* + * Check if 'interface' is valid + */ + intf = g_hash_table_lookup(interface_table, interface->path); + if (intf == NULL) + return -EINVAL; +#endif + return supplicant_dbus_method_call(interface->path, SUPPLICANT_INTERFACE ".Interface", "RemoveNetwork", network_remove_params, network_remove_result, data, @@ -5158,7 +5868,17 @@ int g_supplicant_interface_disconnect(GSupplicantInterface *interface, if (!system_available) return -EFAULT; +#if defined TIZEN_EXT + if (decrypt_request_data.pending_call && + decrypt_request_data.data && + decrypt_request_data.data->user_data == user_data) { + + callback_assoc_failed(decrypt_request_data.data->user_data); + crypt_method_call_cancel(); + return 0; + } +#endif data = dbus_malloc0(sizeof(*data)); if (!data) return -ENOMEM; @@ -5633,6 +6353,28 @@ int g_supplicant_set_widi_ies(GSupplicantP2PServiceParams *p2p_service_params, return -EINPROGRESS; } +#if defined TIZEN_EXT +int g_supplicant_interface_remove_network(GSupplicantInterface *interface) +{ + struct interface_data *data; + + SUPPLICANT_DBG(""); + + if (interface == NULL) + return -EINVAL; + + if (system_available == FALSE) + return -EFAULT; + + data = dbus_malloc0(sizeof(*data)); + if (data == NULL) + return -ENOMEM; + + data->interface = interface; + + return network_remove(data); +} +#endif static const char *g_supplicant_rule0 = "type=signal," "path=" DBUS_PATH_DBUS "," @@ -5650,12 +6392,14 @@ static const char *g_supplicant_rule4 = "type=signal," "interface=" SUPPLICANT_INTERFACE ".BSS"; static const char *g_supplicant_rule5 = "type=signal," "interface=" SUPPLICANT_INTERFACE ".Network"; +#if !defined TIZEN_EXT static const char *g_supplicant_rule6 = "type=signal," "interface=" SUPPLICANT_INTERFACE ".Interface.P2PDevice"; static const char *g_supplicant_rule7 = "type=signal," "interface=" SUPPLICANT_INTERFACE ".Peer"; static const char *g_supplicant_rule8 = "type=signal," "interface=" SUPPLICANT_INTERFACE ".Group"; +#endif static void invoke_introspect_method(void) { @@ -5712,9 +6456,16 @@ int g_supplicant_register(const GSupplicantCallbacks *callbacks) dbus_bus_add_match(connection, g_supplicant_rule3, NULL); dbus_bus_add_match(connection, g_supplicant_rule4, NULL); dbus_bus_add_match(connection, g_supplicant_rule5, NULL); +#if defined TIZEN_EXT + dbus_bus_add_match(connection, + "type=signal,interface=org.tizen.system.deviced.PowerOff," + "member=ChangeState", NULL); +#endif +#if !defined TIZEN_EXT dbus_bus_add_match(connection, g_supplicant_rule6, NULL); dbus_bus_add_match(connection, g_supplicant_rule7, NULL); dbus_bus_add_match(connection, g_supplicant_rule8, NULL); +#endif dbus_connection_flush(connection); if (dbus_bus_name_has_owner(connection, @@ -5756,9 +6507,11 @@ void g_supplicant_unregister(const GSupplicantCallbacks *callbacks) SUPPLICANT_DBG(""); if (connection) { +#if !defined TIZEN_EXT dbus_bus_remove_match(connection, g_supplicant_rule8, NULL); dbus_bus_remove_match(connection, g_supplicant_rule7, NULL); dbus_bus_remove_match(connection, g_supplicant_rule6, NULL); +#endif dbus_bus_remove_match(connection, g_supplicant_rule5, NULL); dbus_bus_remove_match(connection, g_supplicant_rule4, NULL); dbus_bus_remove_match(connection, g_supplicant_rule3, NULL); diff --git a/gweb/giognutls.c b/gweb/giognutls.c index 09dc9e72..31cf9020 100644..100755 --- a/gweb/giognutls.c +++ b/gweb/giognutls.c @@ -458,7 +458,6 @@ GIOChannel *g_io_channel_gnutls_new(int fd) gnutls_priority_set_direct(gnutls_channel->session, "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.0:+VERS-SSL3.0:%COMPAT", NULL); #endif - gnutls_certificate_allocate_credentials(&gnutls_channel->cred); gnutls_credentials_set(gnutls_channel->session, GNUTLS_CRD_CERTIFICATE, gnutls_channel->cred); diff --git a/gweb/giognutls.h b/gweb/giognutls.h index ea0df8ff..ea0df8ff 100644..100755 --- a/gweb/giognutls.h +++ b/gweb/giognutls.h diff --git a/gweb/gionotls.c b/gweb/gionotls.c index 29988954..29988954 100644..100755 --- a/gweb/gionotls.c +++ b/gweb/gionotls.c diff --git a/gweb/gresolv.c b/gweb/gresolv.c index 8a51a9f6..cf16a48c 100644..100755 --- a/gweb/gresolv.c +++ b/gweb/gresolv.c @@ -946,10 +946,12 @@ bool g_resolv_add_nameserver(GResolv *resolv, const char *address, nameserver->flags = flags; nameserver->resolv = resolv; + debug(resolv, ""); if (connect_udp_channel(nameserver) < 0) { free_nameserver(nameserver); return false; } + debug(resolv, ""); resolv->nameserver_list = g_list_append(resolv->nameserver_list, nameserver); @@ -1051,6 +1053,8 @@ guint g_resolv_lookup_hostname(GResolv *resolv, const char *hostname, lookup->result_data = user_data; lookup->id = resolv->next_lookup_id++; + debug(resolv, ""); + if (resolv->result_family != AF_INET6) { if (add_query(lookup, hostname, ns_t_a)) { g_free(lookup); @@ -1058,6 +1062,8 @@ guint g_resolv_lookup_hostname(GResolv *resolv, const char *hostname, } } + debug(resolv, ""); + if (resolv->result_family != AF_INET) { if (add_query(lookup, hostname, ns_t_aaaa)) { if (resolv->result_family != AF_INET6) { @@ -1071,6 +1077,8 @@ guint g_resolv_lookup_hostname(GResolv *resolv, const char *hostname, } } + debug(resolv, ""); + g_queue_push_tail(resolv->lookup_queue, lookup); debug(resolv, "lookup %p id %d", lookup, lookup->id); diff --git a/gweb/gresolv.h b/gweb/gresolv.h index fac14f54..fac14f54 100644..100755 --- a/gweb/gresolv.h +++ b/gweb/gresolv.h diff --git a/gweb/gweb.c b/gweb/gweb.c index 393afe0a..7037cd94 100644..100755 --- a/gweb/gweb.c +++ b/gweb/gweb.c @@ -809,6 +809,10 @@ static void handle_multi_line(struct web_session *session) g_string_insert_c(session->current_header, 0, ' '); } +#if defined TIZEN_EXT + if (session->result.last_key == NULL) + return; +#endif value = g_hash_table_lookup(session->result.headers, session->result.last_key); if (value) { @@ -1257,6 +1261,16 @@ static void resolv_result(GResolvResultStatus status, return; } +#if defined TIZEN_EXT + // check the DNS address validation + // if dns is the class c private address + // wispr should be stopped - non internet connection + if(g_str_has_prefix(results[0],"192.168.")){ + call_result_func(session, 404); + return; + } +#endif + g_free(session->address); session->address = g_strdup(results[0]); diff --git a/gweb/gweb.h b/gweb/gweb.h index 6c28542a..6c28542a 100644..100755 --- a/gweb/gweb.h +++ b/gweb/gweb.h diff --git a/include/agent.h b/include/agent.h index 6961f7a1..6961f7a1 100644..100755 --- a/include/agent.h +++ b/include/agent.h diff --git a/include/backtrace.h b/include/backtrace.h deleted file mode 100644 index 12a202d7..00000000 --- a/include/backtrace.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * - * Connection Manager - * - * Copyright (C) 2016 Yann E. MORIN <yann.morin.1998@free.fr>. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifndef __CONNMAN_BACKTRACE_H -#define __CONNMAN_BACKTRACE_H - -#ifdef HAVE_EXECINFO_H -void print_backtrace(const char* program_path, const char* program_exec, - unsigned int offset); -#else -#define print_backtrace(P,E,O) -#endif - -#endif /* __CONNMAN_BACKTRACE_H */ diff --git a/include/dbus.h b/include/dbus.h index 26f94d63..3087fe40 100644..100755 --- 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/include/device.h b/include/device.h index 9ac800a2..36b2f550 100644..100755 --- a/include/device.h +++ b/include/device.h @@ -126,6 +126,11 @@ struct connman_device_driver { const char *security, void *user_data); int (*set_regdom) (struct connman_device *device, const char *alpha2); +#if defined TIZEN_EXT + int (*specific_scan) (enum connman_service_type type, + struct connman_device *device, int scan_type, + GSList *specific_scan_list, void *user_data); +#endif }; int connman_device_driver_register(struct connman_device_driver *driver); diff --git a/include/inet.h b/include/inet.h index 6482934a..07427300 100644..100755 --- a/include/inet.h +++ b/include/inet.h @@ -39,6 +39,10 @@ char *connman_inet_ifname(int index); int connman_inet_ifup(int index); int connman_inet_ifdown(int index); +#if defined TIZEN_EXT +void connman_inet_update_device_ident(struct connman_device *device); +#endif + int connman_inet_set_address(int index, struct connman_ipaddress *ipaddress); int connman_inet_clear_address(int index, struct connman_ipaddress *ipaddress); int connman_inet_add_host_route(int index, const char *host, const char *gateway); diff --git a/include/inotify.h b/include/inotify.h index 4bc63303..4bc63303 100644..100755 --- a/include/inotify.h +++ b/include/inotify.h diff --git a/include/ipaddress.h b/include/ipaddress.h index 3655ca86..3655ca86 100644..100755 --- a/include/ipaddress.h +++ b/include/ipaddress.h diff --git a/include/ipconfig.h b/include/ipconfig.h index 68ef40b6..68ef40b6 100644..100755 --- a/include/ipconfig.h +++ b/include/ipconfig.h diff --git a/include/log.h b/include/log.h index 8b00e9dc..7687ed0b 100644..100755 --- a/include/log.h +++ b/include/log.h @@ -52,7 +52,11 @@ void connman_debug(const char *format, ...) struct connman_debug_desc { const char *name; const char *file; +#if defined TIZEN_EXT +#define CONNMAN_DEBUG_FLAG_DEFAULT (1) +#else #define CONNMAN_DEBUG_FLAG_DEFAULT (0) +#endif #define CONNMAN_DEBUG_FLAG_PRINT (1 << 0) #define CONNMAN_DEBUG_FLAG_ALIAS (1 << 1) unsigned int flags; diff --git a/include/machine.h b/include/machine.h index c8d8735e..c8d8735e 100644..100755 --- a/include/machine.h +++ b/include/machine.h diff --git a/include/network.h b/include/network.h index 4fc20c1c..4be5fbf0 100644..100755 --- a/include/network.h +++ b/include/network.h @@ -55,7 +55,11 @@ enum connman_network_error { CONNMAN_NETWORK_ERROR_CONFIGURE_FAIL = 2, CONNMAN_NETWORK_ERROR_INVALID_KEY = 3, CONNMAN_NETWORK_ERROR_CONNECT_FAIL = 4, - CONNMAN_NETWORK_ERROR_BLOCKED = 5, +#if defined TIZEN_EXT + CONNMAN_NETWORK_ERROR_DHCP_FAIL = 5, +#endif + CONNMAN_NETWORK_ERROR_BLOCKED = 6, + }; #define CONNMAN_NETWORK_PRIORITY_LOW -100 @@ -90,6 +94,9 @@ void connman_network_set_group(struct connman_network *network, const char *connman_network_get_group(struct connman_network *network); bool connman_network_get_connecting(struct connman_network *network); +#if defined TIZEN_EXT +void connman_network_set_connecting(struct connman_network *network); +#endif int connman_network_set_available(struct connman_network *network, bool available); bool connman_network_get_available(struct connman_network *network); @@ -117,6 +124,41 @@ 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); + +int connman_network_set_rsn_mode(struct connman_network *network, + bool rsn_mode); + +int connman_network_set_proxy(struct connman_network *network, + const char *proxies); + +void connman_network_clear_associating(struct connman_network *network); + +int connman_network_set_keymgmt(struct connman_network *network, + unsigned int keymgmt); +unsigned int connman_network_get_keymgmt(struct connman_network *network); +int connman_network_set_disconnect_reason(struct connman_network *network, + int reason_code); +int connman_network_get_disconnect_reason(struct connman_network *network); +int connman_network_get_assoc_status_code(struct connman_network *network); +int connman_network_set_assoc_status_code(struct connman_network *network, + int assoc_status_code); +#endif + int connman_network_set_name(struct connman_network *network, const char *name); int connman_network_set_strength(struct connman_network *network, @@ -157,6 +199,9 @@ struct connman_network_driver { void (*remove) (struct connman_network *network); int (*connect) (struct connman_network *network); int (*disconnect) (struct connman_network *network); +#if defined TIZEN_EXT + int (*merge) (struct connman_network *network); +#endif }; int connman_network_driver_register(struct connman_network_driver *driver); diff --git a/include/notifier.h b/include/notifier.h index 50b5fb4c..50b5fb4c 100644..100755 --- a/include/notifier.h +++ b/include/notifier.h diff --git a/include/option.h b/include/option.h index 5e97ed4c..5e97ed4c 100644..100755 --- a/include/option.h +++ b/include/option.h diff --git a/include/peer.h b/include/peer.h index 80663932..80663932 100644..100755 --- a/include/peer.h +++ b/include/peer.h diff --git a/include/plugin.h b/include/plugin.h index 8d2bb08e..8d2bb08e 100644..100755 --- a/include/plugin.h +++ b/include/plugin.h diff --git a/include/provider.h b/include/provider.h index d28651ad..d28651ad 100644..100755 --- a/include/provider.h +++ b/include/provider.h diff --git a/include/provision.h b/include/provision.h index 3eb80a86..3eb80a86 100644..100755 --- a/include/provision.h +++ b/include/provision.h diff --git a/include/proxy.h b/include/proxy.h index 7842f65f..7842f65f 100644..100755 --- a/include/proxy.h +++ b/include/proxy.h diff --git a/include/resolver.h b/include/resolver.h index 70a02ade..70a02ade 100644..100755 --- a/include/resolver.h +++ b/include/resolver.h diff --git a/include/rtnl.h b/include/rtnl.h index aa70f4d8..aa70f4d8 100644..100755 --- a/include/rtnl.h +++ b/include/rtnl.h diff --git a/include/service.h b/include/service.h index 958e7fd1..30550233 100644..100755 --- a/include/service.h +++ b/include/service.h @@ -24,6 +24,10 @@ #include <stdbool.h> +#if defined TIZEN_EXT +#include <glib.h> +#endif + #ifdef __cplusplus extern "C" { #endif @@ -137,6 +141,43 @@ void connman_service_create_ip4config(struct connman_service *service, void connman_service_create_ip6config(struct connman_service *service, int index); +#if defined TIZEN_EXT +/* + * Description: TIZEN implements system global connection management. + * It's only for PDP (cellular) bearer. Wi-Fi is managed by ConnMan automatically. + * Reference count can help to manage open/close connection requests by each application. + */ + +/* + * Increase reference count of user-initiated packet data network connection + */ +void connman_service_user_pdn_connection_ref(struct connman_service *service); + +/* + * Decrease reference count of user initiated packet data network connection + * and return TRUE if counter is zero. + */ +gboolean connman_service_user_pdn_connection_unref_and_test( + struct connman_service *service); + +/* + * Test reference count of user initiated packet data network connection + * and return TRUE if counter is zero. No impact to reference count + */ +gboolean connman_service_is_no_ref_user_pdn_connection( + struct connman_service *service); +#endif + +#if defined TIZEN_EXT +struct connman_service *connman_service_get_default_connection(void); + +/* + * Description: telephony plug-in requires manual PROXY setting + */ +int connman_service_set_proxy(struct connman_service *service, + const char *proxy, gboolean active); +#endif + #ifdef __cplusplus } #endif diff --git a/include/session.h b/include/session.h index 5106e886..5106e886 100644..100755 --- a/include/session.h +++ b/include/session.h diff --git a/include/setting.h b/include/setting.h index a8820217..a8820217 100644..100755 --- a/include/setting.h +++ b/include/setting.h diff --git a/include/storage.h b/include/storage.h index 4c23a14e..4c23a14e 100644..100755 --- a/include/storage.h +++ b/include/storage.h diff --git a/include/task.h b/include/task.h index 9977d634..9977d634 100644..100755 --- a/include/task.h +++ b/include/task.h diff --git a/include/technology.h b/include/technology.h index 97db6607..55bb3dd5 100644..100755 --- 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); + int connman_technology_tethering_notify(struct connman_technology *technology, bool enabled); int connman_technology_set_regdom(const char *alpha2); diff --git a/include/timeserver.h b/include/timeserver.h index 48ea1945..48ea1945 100644..100755 --- a/include/timeserver.h +++ b/include/timeserver.h diff --git a/include/utsname.h b/include/utsname.h index b8165f68..b8165f68 100644..100755 --- a/include/utsname.h +++ b/include/utsname.h diff --git a/include/version.h.in b/include/version.h.in index d3d6dd37..d3d6dd37 100644..100755 --- a/include/version.h.in +++ b/include/version.h.in diff --git a/include/vpn-dbus.h b/include/vpn-dbus.h index 01780cbd..01780cbd 100644..100755 --- a/include/vpn-dbus.h +++ b/include/vpn-dbus.h diff --git a/packaging/connman.spec b/packaging/connman.spec new file mode 100755 index 00000000..0554f9a7 --- /dev/null +++ b/packaging/connman.spec @@ -0,0 +1,343 @@ +%bcond_with connman_openconnect +%bcond_without connman_openvpn +%bcond_without connman_ipsec +%bcond_without connman_vpnd + +Name: connman +Version: 1.35 +Release: 26 +License: GPL-2.0+ +Summary: Connection Manager +Url: http://connman.net +Group: Network & Connectivity/Connection Management +Source0: %{name}-%{version}.tar.gz +BuildRequires: systemd-devel +BuildRequires: pkgconfig(dbus-1) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(gio-2.0) +BuildRequires: pkgconfig(libiptc) +BuildRequires: pkgconfig(xtables) +BuildRequires: pkgconfig(libsmack) +BuildRequires: pkgconfig(libsystemd-daemon) +%if %{with connman_openconnect} +BuildRequires: openconnect +%endif +%if %{with connman_openvpn} +BuildRequires: openvpn +%endif +%if %{with connman_ipsec} +BuildRequires: strongswan +%endif +BuildRequires: readline-devel +#%systemd_requires +Requires: iptables +Requires: systemd +Requires(post): systemd +Requires(preun): systemd +Requires(postun): systemd +Requires: net-config +Requires: security-config +Provides: %{name}-profile_common = %{version}-%{release} +Provides: %{name}-profile_mobile = %{version}-%{release} +Provides: %{name}-profile_wearable = %{version}-%{release} + +%define upgrade_script_filename 500.connman_upgrade.sh +%define upgrade_script_path /usr/share/upgrade/scripts + +%description +Connection Manager provides a daemon for managing Internet connections +within embedded devices running the Linux operating system. + +%if %{with connman_openconnect} +%package plugin-openconnect +Summary: Openconnect Support for Connman +Requires: %{name} = %{version} +Requires: openconnect + +%description plugin-openconnect +Openconnect Support for Connman. +%endif + +%if %{with connman_openvpn} +%package plugin-openvpn +Summary: Openvpn Support for Connman +Requires: %{name} = %{version} +Requires: openvpn + +%description plugin-openvpn +OpenVPN support for Connman. +%endif + +%if %{with connman_ipsec} +%package plugin-ipsec +Summary: IPsec Support for Connman +Requires: %{name} = %{version} +Requires: strongswan + +%description plugin-ipsec +OpenVPN support for Connman. +%endif + +%if %{with connman_vpnd} +%package connman-vpnd +Summary: VPN Support for Connman +#BuildRequires: %{name} = %{version} +Requires: %{name} = %{version} + +%description connman-vpnd +Provides VPN support for Connman +%endif + +%package test +Summary: Test Scripts for Connection Manager +Group: Development/Tools +Requires: %{name} = %{version} +Requires: dbus-python +Requires: pygobject +Requires: python-xml + +%description test +Scripts for testing Connman and its functionality + +%package devel +Summary: Development Files for connman +Group: Development/Tools +Requires: %{name} = %{version} + +%description devel +Header files and development files for connman. + +%package extension-tv +Summary: Connman service script for TV profile +Requires: %{name} = %{version}-%{release} +Provides: %{name}-profile_tv = %{version}-%{release} +Conflicts: %{name}-extension-ivi +Conflicts: %{name}-extension-disable-eth +%description extension-tv +Supplies Tizen TV profile systemd service scripts instead of the default one. +This overwrites service script of %{name}. + +%package extension-ivi +Summary: Connman configuration for IVI profile +Requires: %{name} = %{version}-%{release} +Provides: %{name}-profile_ivi = %{version}-%{release} +Conflicts: %{name}-extension-tv +Conflicts: %{name}-extension-disable-eth +%description extension-ivi +Supplies Tizen IVI profile configuration instead of the default one. +This overwrites conf file of %{name}. + +%package extension-disable-eth +Summary: Connman configuration for testing which requires the ethernet to be disabled +Requires: %{name} = %{version}-%{release} +Conflicts: %{name}-extension-tv +Conflicts: %{name}-extension-ivi +%description extension-disable-eth +Connman without ethernet support +This overwrites conf file of %{name}. + +%prep +%setup -q + + +%build +#CFLAGS+=" -DTIZEN_EXT -lsmack -Werror" + +%if %{with connman_vpnd} +VPN_CFLAGS+=" -DTIZEN_EXT -lsmack -Werror" +%endif + +chmod +x bootstrap +./bootstrap +%configure \ + --sysconfdir=/etc \ + --enable-client \ + --enable-tizen-ext \ + --enable-pacrunner \ + --enable-wifi=builtin \ +%if %{with connman_openconnect} + --enable-openconnect \ +%endif +%if %{with connman_openvpn} + --enable-openvpn \ +%endif +%if %{with connman_ipsec} + --enable-ipsec \ +%endif +%if 0%{?enable_connman_features} + %connman_features \ +%endif + --disable-ofono \ + --enable-telephony=builtin \ + --enable-test \ + --enable-loopback \ + --enable-ethernet \ + --with-systemdunitdir=%{_libdir}/systemd/system \ + --enable-pie \ + --disable-wispr + +make %{?_smp_mflags} + +%install +%make_install + +#Systemd service file +mkdir -p %{buildroot}%{_libdir}/systemd/system/ +%if "%{?_lib}" == "lib64" +mkdir -p %{buildroot}%{_unitdir} +%endif + +%if "%{?_lib}" == "lib64" +cp src/connman_tv.service %{buildroot}%{_unitdir}/connman.service.tv +cp src/connman.service %{buildroot}%{_unitdir}/connman.service +cp vpn/connman-vpn.service %{buildroot}%{_unitdir}/connman-vpn.service +%else +cp src/connman_tv.service %{buildroot}%{_libdir}/systemd/system/connman.service.tv +%endif + +mkdir -p %{buildroot}%{_libdir}/systemd/system/multi-user.target.wants +ln -s ../connman.service %{buildroot}%{_libdir}/systemd/system/multi-user.target.wants/connman.service +%if "%{?_lib}" == "lib64" +mkdir -p %{buildroot}%{_unitdir}/multi-user.target.wants +ln -s ../connman.service %{buildroot}%{_unitdir}/multi-user.target.wants/connman.service +%endif + +#Systemd socket file for DNS proxy +%if "%{?_lib}" == "lib64" +cp src/connman.socket %{buildroot}%{_unitdir}/connman.socket +mkdir -p %{buildroot}%{_unitdir}/sockets.target.wants +ln -s ../connman.socket %{buildroot}%{_unitdir}/sockets.target.wants/connman.socket +%else +cp src/connman.socket %{buildroot}%{_libdir}/systemd/system/connman.socket +mkdir -p %{buildroot}%{_libdir}/systemd/system/sockets.target.wants +ln -s ../connman.socket %{buildroot}%{_libdir}/systemd/system/sockets.target.wants/connman.socket +%endif + +mkdir -p %{buildroot}/%{_localstatedir}/lib/connman +cp resources/var/lib/connman/settings %{buildroot}/%{_localstatedir}/lib/connman/settings +mkdir -p %{buildroot}%{_datadir}/dbus-1/system-services +cp resources/usr/share/dbus-1/system-services/net.connman.service %{buildroot}%{_datadir}/dbus-1/system-services/net.connman.service +mkdir -p %{buildroot}/etc/connman + +cp src/main_ivi.conf %{buildroot}/etc/connman/main.conf.ivi +cp src/main_tv.conf %{buildroot}/etc/connman/main.conf.tv +cp src/main_disable_eth.conf %{buildroot}/etc/connman/main.conf.disable.eth +cp src/main.conf %{buildroot}/etc/connman/main.conf + +rm %{buildroot}%{_sysconfdir}/dbus-1/system.d/*.conf +mkdir -p %{buildroot}%{_sysconfdir}/dbus-1/system.d/ +cp src/connman.conf %{buildroot}%{_sysconfdir}/dbus-1/system.d/ + +%if %{with connman_vpnd} +cp vpn/vpn-dbus.conf %{buildroot}%{_sysconfdir}/dbus-1/system.d/connman-vpn-dbus.conf +%endif + +#OS Upgrade +mkdir -p %{buildroot}%{upgrade_script_path} +cp -f scripts/%{upgrade_script_filename} %{buildroot}%{upgrade_script_path} + +%post +#chsmack -a 'System' /%{_localstatedir}/lib/connman +#chsmack -a 'System' /%{_localstatedir}/lib/connman/settings + +%preun + +%postun +systemctl daemon-reload + +%docs_package + +%files +%manifest connman.manifest +%attr(500,network_fw,network_fw) %{_bindir}/connmand +%attr(500,network_fw,network_fw) %{_bindir}/connmanctl +%attr(755,network_fw,network_fw) /%{_localstatedir}/lib/connman +%attr(600,network_fw,network_fw) /%{_localstatedir}/lib/connman/settings +%attr(644,root,root) %{_datadir}/dbus-1/system-services/net.connman.service +%{_sysconfdir}/dbus-1/system.d/* +%attr(644,network_fw,network_fw) %{_sysconfdir}/connman/main.conf +%{_sysconfdir}/dbus-1/system.d/*.conf +%attr(644,root,root) %{_libdir}/systemd/system/connman.service +%attr(644,root,root) %{_libdir}/systemd/system/multi-user.target.wants/connman.service +%if "%{?_lib}" == "lib64" +%attr(644,root,root) %{_unitdir}/connman.service +%attr(644,root,root) %{_unitdir}/multi-user.target.wants/connman.service +%attr(644,root,root) %{_unitdir}/connman.socket +%attr(644,root,root) %{_unitdir}/sockets.target.wants/connman.socket +%else +%attr(644,root,root) %{_libdir}/systemd/system/connman.socket +%attr(644,root,root) %{_libdir}/systemd/system/sockets.target.wants/connman.socket +%endif +%license COPYING +%{upgrade_script_path}/%{upgrade_script_filename} + +%files test +%manifest connman.manifest +%{_libdir}/%{name}/test/* + +%files devel +%manifest connman.manifest +%{_includedir}/* +%{_libdir}/pkgconfig/*.pc + +%if %{with connman_openconnect} +%files plugin-openconnect +%manifest %{name}.manifest +%{_libdir}/connman/plugins-vpn/openconnect.so +%{_libdir}/connman/scripts/openconnect-script +%license COPYING +%endif + +%if %{with connman_openvpn} +%files plugin-openvpn +%manifest %{name}.manifest +%{_libdir}/%{name}/plugins-vpn/openvpn.so +%{_libdir}/%{name}/scripts/openvpn-script +%license COPYING +%endif + +%if %{with connman_ipsec} +%files plugin-ipsec +%manifest %{name}.manifest +%{_libdir}/%{name}/plugins-vpn/ipsec.so +%{_libdir}/%{name}/scripts/ipsec-script +%license COPYING +%endif + +%if %{with connman_vpnd} +%files connman-vpnd +%manifest %{name}.manifest +%{_bindir}/connman-vpnd +%dir %{_libdir}/%{name} +%dir %{_libdir}/%{name}/scripts +%dir %{_libdir}/%{name}/plugins-vpn +%config %{_sysconfdir}/dbus-1/system.d/connman-vpn-dbus.conf +%{_datadir}/dbus-1/system-services/net.connman.vpn.service +%license COPYING +%attr(644,root,root) %{_libdir}/systemd/system/connman-vpn.service +%if "%{?_lib}" == "lib64" +%attr(644,root,root) %{_unitdir}/connman-vpn.service +%endif +%endif + +%post extension-tv +mv -f %{_libdir}/systemd/system/connman.service.tv %{_libdir}/systemd/system/connman.service +mv -f %{_sysconfdir}/connman/main.conf.tv %{_sysconfdir}/connman/main.conf +%files extension-tv +%attr(644,network_fw,network_fw) %{_sysconfdir}/connman/main.conf.tv +%license COPYING +%if "%{?_lib}" == "lib64" +%attr(644,root,root) %{_unitdir}/connman.service.tv +%else +%attr(644,root,root) %{_libdir}/systemd/system/connman.service.tv +%endif +%post extension-ivi +mv -f %{_sysconfdir}/connman/main.conf.ivi %{_sysconfdir}/connman/main.conf +%files extension-ivi +%attr(644,network_fw,network_fw) %{_sysconfdir}/connman/main.conf.ivi +%license COPYING +%post extension-disable-eth +mv -f %{_sysconfdir}/connman/main.conf.disable.eth %{_sysconfdir}/connman/main.conf +%files extension-disable-eth +%attr(644,network_fw,network_fw) %{_sysconfdir}/connman/main.conf.disable.eth +%license COPYING diff --git a/plugins/bluetooth.c b/plugins/bluetooth.c index f759a902..f89edfa0 100644..100755 --- a/plugins/bluetooth.c +++ b/plugins/bluetooth.c @@ -192,8 +192,14 @@ static bool pan_connect(struct bluetooth_pan *pan, return false; } +#if defined TIZEN_EXT + if (pan->network) { +#endif connman_network_set_index(pan->network, index); connman_network_set_connected(pan->network, true); +#if defined TIZEN_EXT + } +#endif return true; } @@ -211,6 +217,18 @@ static void pan_connect_cb(DBusMessage *message, void *user_data) return; } +#ifdef TIZEN_EXT + /* + * Network could be removed because of BT adapter power off + * This is to handle the scenario where network is removed + * before the connect_cb is called + */ + if (!pan->network) { + DBG("network already removed"); + return; + } +#endif + if (dbus_message_get_type(message) == DBUS_MESSAGE_TYPE_ERROR) { const char *dbus_error = dbus_message_get_error_name(message); @@ -262,6 +280,9 @@ static int bluetooth_pan_connect(struct connman_network *network) g_strdup(path), g_free)) return -EIO; +#if defined TIZEN_EXT + if (pan->network) +#endif connman_network_set_associating(pan->network, true); return -EINPROGRESS; @@ -286,6 +307,9 @@ static void pan_disconnect_cb(DBusMessage *message, void *user_data) DBG("network %p", pan->network); +#if defined TIZEN_EXT + if (pan->network) +#endif connman_network_set_connected(pan->network, false); } @@ -299,6 +323,11 @@ static int bluetooth_pan_disconnect(struct connman_network *network) if (!pan) return -EINVAL; +#if defined TIZEN_EXT + if (connman_network_get_associating(network) == TRUE) + connman_network_clear_associating(network); +#endif + path = g_dbus_proxy_get_path(pan->btnetwork_proxy); if (!g_dbus_proxy_method_call(pan->btnetwork_proxy, "Disconnect", @@ -524,7 +553,10 @@ static void device_enable_cb(const DBusError *error, void *user_data) goto out; } +#if !defined TIZEN_EXT enable_device(device, path); +#endif + out: g_free(path); } @@ -591,7 +623,9 @@ static void device_disable_cb(const DBusError *error, void *user_data) goto out; } +#if !defined TIZEN_EXT disable_device(device, path); +#endif out: g_free(path); @@ -883,7 +917,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/connman-nmcompat.conf b/plugins/connman-nmcompat.conf index 5887a345..a051d927 100644..100755 --- a/plugins/connman-nmcompat.conf +++ b/plugins/connman-nmcompat.conf @@ -5,6 +5,10 @@ <allow own="org.freedesktop.NetworkManager"/> <allow send_destination="org.freedesktop.NetworkManager"/> </policy> + <policy user="network_fw"> + <allow own="org.freedesktop.NetworkManager"/> + <allow send_destination="org.freedesktop.NetworkManager"/> + </policy> <policy at_console="true"> <allow send_destination="org.freedesktop.NetworkManager"/> </policy> diff --git a/plugins/dundee.c b/plugins/dundee.c index b5420acf..b5420acf 100644..100755 --- a/plugins/dundee.c +++ b/plugins/dundee.c diff --git a/plugins/ethernet.c b/plugins/ethernet.c index 9a4d7413..9a4d7413 100644..100755 --- a/plugins/ethernet.c +++ b/plugins/ethernet.c diff --git a/plugins/gadget.c b/plugins/gadget.c index 94f66487..cce51e26 100644..100755 --- a/plugins/gadget.c +++ b/plugins/gadget.c @@ -25,6 +25,8 @@ #include <errno.h> #include <net/if.h> +#include <stdio.h> +#include <string.h> #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 = { diff --git a/plugins/hh2serial-gps.c b/plugins/hh2serial-gps.c index 99394e1c..99394e1c 100644..100755 --- a/plugins/hh2serial-gps.c +++ b/plugins/hh2serial-gps.c diff --git a/plugins/iospm.c b/plugins/iospm.c index fcb4cea1..fcb4cea1 100644..100755 --- a/plugins/iospm.c +++ b/plugins/iospm.c diff --git a/plugins/loopback.c b/plugins/loopback.c index e113887d..44100c64 100644..100755 --- a/plugins/loopback.c +++ b/plugins/loopback.c @@ -23,6 +23,8 @@ #include <config.h> #endif +#include <stdio.h> + #include <errno.h> #include <unistd.h> #include <limits.h> @@ -34,6 +36,8 @@ #include <net/if.h> #include <glib.h> +#include <glib/gprintf.h> + #define CONNMAN_API_SUBJECT_TO_CHANGE #include <connman/plugin.h> @@ -62,16 +66,47 @@ static int setup_hostname(void) memset(system_hostname, 0, sizeof(system_hostname)); - if (gethostname(system_hostname, HOST_NAME_MAX) < 0) { - connman_error("Failed to get current hostname"); - return -EIO; - } +#if defined TIZEN_EXT + FILE *fp = NULL; +#define WIFI_MAC "/opt/etc/.mac.info" + { + char* rv = 0; + gchar* dev_id = "TIZEN"; + char wifi_mac[HOST_NAME_MAX + 1]; + + fp = fopen(WIFI_MAC, "r"); + if(!fp){ + connman_error("Failed to get current hostname"); + strncpy(system_hostname, dev_id, strlen(dev_id)); + goto host_name_end; + } + + rv = fgets(wifi_mac, HOST_NAME_MAX, fp); + if(!rv){ + connman_error("Failed to get current hostname"); + strncpy(system_hostname, dev_id, strlen(dev_id)); + fclose(fp); + goto host_name_end; + } + + dev_id = g_base64_encode((const guchar *)wifi_mac, strlen(wifi_mac)); + g_sprintf(system_hostname, "TIZEN-%s", dev_id); + g_free(dev_id); + fclose(fp); + } - if (strlen(system_hostname) > 0 && - strcmp(system_hostname, "(none)") != 0) - connman_info("System hostname is %s", system_hostname); - else - create_hostname(); + host_name_end : +#else + if (gethostname(system_hostname, HOST_NAME_MAX) < 0) { + connman_error("Failed to get current hostname"); + return -EIO; + } +#endif + if (strlen(system_hostname) > 0 && + strcmp(system_hostname, "(none)") != 0) + connman_info("System hostname is %s", system_hostname); + else + create_hostname(); memset(name, 0, sizeof(name)); diff --git a/plugins/mcc.h b/plugins/mcc.h index 0e0407c9..0e0407c9 100644..100755 --- a/plugins/mcc.h +++ b/plugins/mcc.h diff --git a/plugins/neard.c b/plugins/neard.c index 69586df6..69586df6 100644..100755 --- a/plugins/neard.c +++ b/plugins/neard.c diff --git a/plugins/nmcompat.c b/plugins/nmcompat.c index 883ce9bd..883ce9bd 100644..100755 --- a/plugins/nmcompat.c +++ b/plugins/nmcompat.c diff --git a/plugins/ofono.c b/plugins/ofono.c index 78f8f196..78f8f196 100644..100755 --- a/plugins/ofono.c +++ b/plugins/ofono.c diff --git a/plugins/pacrunner.c b/plugins/pacrunner.c index d2464a5e..d2464a5e 100644..100755 --- a/plugins/pacrunner.c +++ b/plugins/pacrunner.c diff --git a/plugins/polkit.c b/plugins/polkit.c index ae38364a..ae38364a 100644..100755 --- a/plugins/polkit.c +++ b/plugins/polkit.c diff --git a/plugins/polkit.policy b/plugins/polkit.policy index 0de152ce..0de152ce 100644..100755 --- a/plugins/polkit.policy +++ b/plugins/polkit.policy diff --git a/plugins/session_policy_local.c b/plugins/session_policy_local.c index f003c0e1..f003c0e1 100644..100755 --- a/plugins/session_policy_local.c +++ b/plugins/session_policy_local.c diff --git a/plugins/telephony.c b/plugins/telephony.c new file mode 100755 index 00000000..2b4c5a4a --- /dev/null +++ b/plugins/telephony.c @@ -0,0 +1,1934 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <errno.h> +#include <gdbus.h> +#include <stdlib.h> +#include <string.h> + +#define CONNMAN_API_SUBJECT_TO_CHANGE +#include <connman/dbus.h> +#include <connman/inet.h> +#include <connman/plugin.h> +#include <connman/network.h> +#include <connman/setting.h> +#include <connman/technology.h> + +#include <connman.h> + +#define PS_DBUS_SERVICE "com.tcore.ps" + +#define PS_MASTER_INTERFACE PS_DBUS_SERVICE ".master" +#define PS_MODEM_INTERFACE PS_DBUS_SERVICE ".modem" +#define PS_SERVICE_INTERFACE PS_DBUS_SERVICE ".service" +#define PS_CONTEXT_INTERFACE PS_DBUS_SERVICE ".context" + +/* methods */ +#define GET_MODEMS "GetModems" +#define GET_SERVICES "GetServices" +#define GET_CONTEXTS "GetContexts" +#define ACTIVATE_CONTEXT "Activate" +#define DEACTIVATE_CONTEXT "Deactivate" +#define GET_PROPERTIES "GetProperties" +#define SET_PROPERTY "SetProperties" + +/* signals */ +#define MODEM_ADDED "ModemAdded" +#define MODEM_REMOVED "ModemRemoved" +#define SERVICE_ADDED "ServiceAdded" +#define SERVICE_REMOVED "ServiceRemoved" +#define CONTEXT_ADDED "ContextAdded" +#define CONTEXT_REMOVED "ContextRemoved" +#define PROPERTY_CHANGED "PropertyChanged" + +#define TIMEOUT 130000 + +#define STRING2BOOL(a) (!(g_strcmp0(a, "TRUE")) ? (TRUE):(FALSE)) + +static DBusConnection *connection; +static GHashTable *modem_hash; +static GHashTable *service_hash; +static GHashTable *network_hash; + +struct telephony_service { + char *path; + + gpointer p_modem; + char *act; + gboolean roaming; /* global roaming state */ + gboolean ps_attached; /* packet service is available */ +}; + +struct telephony_modem { + char *path; + + char *operator; + gboolean powered; + gboolean sim_init; + gboolean flight_mode; + gboolean data_allowed; + gboolean roaming_allowed; + + struct connman_device *device; + struct telephony_service *s_service; +}; + +struct telephony_network { + char *path; + int if_index; + gboolean routing_only; + gboolean ipv6_link_only; + + struct connman_network *network; + + enum connman_ipconfig_method ipv4_method; + struct connman_ipaddress *ipv4_address; + + enum connman_ipconfig_method ipv6_method; + struct connman_ipaddress *ipv6_address; +}; + +static int telephony_default_subscription_id = 0; + +/* function prototype */ +static void telephony_connect(DBusConnection *connection, void *user_data); +static void telephony_disconnect(DBusConnection *connection, void *user_data); +static void __remove_modem(gpointer data); +static void __remove_service(gpointer data); +static void __remove_network(gpointer data); + +static int __modem_probe(struct connman_device *device); +static void __modem_remove(struct connman_device *device); +static int __modem_enable(struct connman_device *device); +static int __modem_disable(struct connman_device *device); + +static int __network_probe(struct connman_network *network); +static void __network_remove(struct connman_network *network); +static int __network_connect(struct connman_network *network); +static int __network_disconnect(struct connman_network *network); + + +/* dbus request and reply */ +static int __dbus_request(const char *path, const char *interface, + const char *method, + DBusPendingCallNotifyFunction notify, void *user_data, + DBusFreeFunction free_function, int type, ...); + +static int __request_get_modems(void); +static void __response_get_modems(DBusPendingCall *call, void *user_data); +static int __request_get_services(const char *path); +static void __response_get_services(DBusPendingCall *call, void *user_data); +static int __request_get_contexts(struct telephony_modem *modem); +static void __response_get_contexts(DBusPendingCall *call, void *user_data); +static int __request_network_activate(struct connman_network *network); +static void __response_network_activate(DBusPendingCall *call, void *user_data); +static int __request_network_deactivate(struct connman_network *network); + +/* telephony internal function */ +static void __add_modem(const char *path, DBusMessageIter *prop); +static void __add_service(struct telephony_modem *modem, + const char *service_path, DBusMessageIter *prop); +static void __add_connman_device(const char *modem_path, const char *operator); +static void __remove_connman_device(struct telephony_modem *modem); +static void __remove_connman_networks(struct connman_device *device); +static int __add_context(struct connman_device *device, const char *path, + DBusMessageIter *prop); + +/* signal handler */ +static gboolean __changed_modem(DBusConnection *connection, + DBusMessage *message, void *user_data); +static gboolean __added_modem(DBusConnection *connection, + DBusMessage *message, void *user_data); +static gboolean __removed_modem(DBusConnection *connection, + DBusMessage *message, void *user_data); +static gboolean __changed_service(DBusConnection *connection, + DBusMessage *message, void *user_data); +static gboolean __added_service(DBusConnection *connection, + DBusMessage *message, void *user_data); +static gboolean __removed_service(DBusConnection *connection, + DBusMessage *message, void *user_data); +static gboolean __changed_context(DBusConnection *connection, + DBusMessage *message, void *user_data); +static gboolean __added_context(DBusConnection *connection, + DBusMessage *message, void *user_data); +static gboolean __removed_context(DBusConnection *connection, + DBusMessage *message, void *user_data); + +/* device driver */ +static struct connman_device_driver modem_driver = { + .name = "device", + .type = CONNMAN_DEVICE_TYPE_CELLULAR, + .probe = __modem_probe, + .remove = __modem_remove, + .enable = __modem_enable, + .disable = __modem_disable, +}; + +/* network driver */ +static struct connman_network_driver network_driver = { + .name = "network", + .type = CONNMAN_NETWORK_TYPE_CELLULAR, + .probe = __network_probe, + .remove = __network_remove, + .connect = __network_connect, + .disconnect = __network_disconnect, +}; + +static int tech_probe(struct connman_technology *technology) +{ + return 0; +} + +static void tech_remove(struct connman_technology *technology) +{ + return; +} + +static struct connman_technology_driver tech_driver = { + .name = "cellular", + .type = CONNMAN_SERVICE_TYPE_CELLULAR, + .probe = tech_probe, + .remove = tech_remove, +}; + +/* local function */ +static void telephony_connect(DBusConnection *connection, void *user_data) +{ + DBG("connection %p", connection); + modem_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, __remove_modem); + service_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, __remove_service); + network_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, __remove_network); + + __request_get_modems(); +} + +static void telephony_disconnect(DBusConnection *connection, void *user_data) +{ + DBG("connection %p", connection); + + if (modem_hash != NULL) { + g_hash_table_destroy(modem_hash); + modem_hash = NULL; + } + + if (network_hash != NULL) { + g_hash_table_destroy(network_hash); + network_hash = NULL; + } +} + +static void __remove_modem(gpointer data) +{ + struct telephony_modem *modem = data; + + __remove_connman_device(modem); + + g_free(modem->path); + g_free(modem->operator); + g_free(modem); +} + +static void __remove_service(gpointer data) +{ + struct telephony_service *service = data; + + g_free(service->path); + g_free(service->act); + g_free(service); +} + +static void __remove_network(gpointer data) +{ + struct telephony_network *info = data; + struct connman_device *device; + + device = connman_network_get_device(info->network); + if (device != NULL) + connman_device_remove_network(device, info->network); + + connman_network_unref(info->network); + + g_free(info->path); + + connman_ipaddress_free(info->ipv4_address); + connman_ipaddress_free(info->ipv6_address); + + g_free(info); +} + +static void __set_device_powered(struct telephony_modem *modem, + gboolean powered) +{ + DBG("set modem(%s) powered(%d)", modem->path, powered); + + if (modem->device) + connman_device_set_powered(modem->device, powered); +} + +static int __check_device_powered(const char *path, gboolean powered) +{ + struct telephony_modem *modem = g_hash_table_lookup(modem_hash, path); + + if (modem == NULL) + return -ENODEV; + + DBG("check modem (%s) powered (%d)", modem->path, modem->powered); + + if (modem->powered == powered) + return -EALREADY; + + return 0; +} + +static int __modem_probe(struct connman_device *device) +{ + DBG("device %p", device); + return 0; +} + +static void __modem_remove(struct connman_device *device) +{ + DBG("device %p", device); +} + +static int __modem_enable(struct connman_device *device) +{ + const char *path = connman_device_get_string(device, "Path"); + DBG("device %p, path, %s", device, path); + + return __check_device_powered(path, TRUE); +} + +static int __modem_disable(struct connman_device *device) +{ + const char *path = connman_device_get_string(device, "Path"); + DBG("device %p, path, %s", device, path); + + return __check_device_powered(path, FALSE); +} + +static int __network_probe(struct connman_network *network) +{ + DBG("network_prove network(%p)", network); + return 0; +} + +static int __network_connect(struct connman_network *network) +{ + DBG("network %p", network); + + return __request_network_activate(network); +} + +static int __network_disconnect(struct connman_network *network) +{ + DBG("network %p", network); + + if (connman_network_get_associating(network) == TRUE) + connman_network_clear_associating(network); + + connman_network_set_associating(network, FALSE); + + return __request_network_deactivate(network); +} + +static void __network_remove(struct connman_network *network) +{ + char const *path = connman_network_get_string(network, "Path"); + DBG("network %p path %s", network, path); + + g_hash_table_remove(network_hash, path); +} + +static int __dbus_request(const char *path, const char *interface, + const char *method, + DBusPendingCallNotifyFunction notify, void *user_data, + DBusFreeFunction free_function, int type, ...) +{ + DBusMessage *message; + DBusPendingCall *call; + dbus_bool_t ok; + va_list va; + + DBG("path %s %s.%s", path, interface, method); + + if (path == NULL) + return -EINVAL; + + message = dbus_message_new_method_call(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); + + /* DBG("message type (%d) dic(%d)", + * dbus_message_iter_get_arg_type(&dict), DBUS_TYPE_DICT_ENTRY); + */ + + while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) { + DBusMessageIter entry, property; + const char *modem_path; + + dbus_message_iter_recurse(&dict, &entry); + dbus_message_iter_get_basic(&entry, &modem_path); + DBG("modem path (%s)", modem_path); + + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &property); + + __add_modem(modem_path, &property); + + dbus_message_iter_next(&dict); + } + +done: + dbus_message_unref(reply); + dbus_pending_call_unref(call); +} + +static int __request_get_services(const char *path) +{ + DBG("request get service"); + return __dbus_request(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); + + /* DBG("message type (%d) dic(%d)", + * dbus_message_iter_get_arg_type(&dict), DBUS_TYPE_DICT_ENTRY); + */ + + while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) { + DBusMessageIter entry, property; + const char *service_path; + + dbus_message_iter_recurse(&dict, &entry); + dbus_message_iter_get_basic(&entry, &service_path); + DBG("service path (%s)", service_path); + + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &property); + + __add_service(modem, service_path, &property); + + dbus_message_iter_next(&dict); + } + +done: + dbus_message_unref(reply); + dbus_pending_call_unref(call); +} + +static int __request_get_contexts(struct telephony_modem *modem) +{ + DBG("request get contexts"); + return __dbus_request(modem->s_service->path, + PS_SERVICE_INTERFACE, GET_CONTEXTS, + __response_get_contexts, g_strdup(modem->path), + g_free, DBUS_TYPE_INVALID); +} + +static void __response_get_contexts(DBusPendingCall *call, void *user_data) +{ + DBusError error; + DBusMessage *reply; + DBusMessageIter args, dict; + + const char *path = user_data; + struct telephony_modem *modem; + + DBG(""); + + modem = g_hash_table_lookup(modem_hash, path); + if (modem == NULL) + return; + if (modem->s_service == NULL) + return; + if (modem->device == NULL) + return; + + reply = dbus_pending_call_steal_reply(call); + + dbus_error_init(&error); + + if (dbus_set_error_from_message(&error, reply)) { + connman_error("GetContexts() %s %s", error.name, error.message); + dbus_error_free(&error); + goto done; + } + + DBG("message signature (%s)", dbus_message_get_signature(reply)); + + if (dbus_message_iter_init(reply, &args) == FALSE) + goto done; + + dbus_message_iter_recurse(&args, &dict); + + while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) { + DBusMessageIter entry, property; + const char *context_path; + + dbus_message_iter_recurse(&dict, &entry); + dbus_message_iter_get_basic(&entry, &context_path); + DBG("context path (%s)", context_path); + + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &property); + + __add_context(modem->device, context_path, &property); + + dbus_message_iter_next(&dict); + } + +done: + dbus_message_unref(reply); + dbus_pending_call_unref(call); +} + +static int __request_network_activate(struct connman_network *network) +{ + int n_modems; + const char *path = NULL; + struct telephony_modem *modem = NULL; + + n_modems = g_hash_table_size(modem_hash); + path = connman_network_get_string(network, "Path"); + modem = connman_device_get_data(connman_network_get_device(network)); + DBG("network %p, path %s, modem %s[%d]", network, path, modem->path, + telephony_default_subscription_id); + + if (modem && n_modems > 1 && g_str_has_suffix(path, "_1") == TRUE) { + char *subscribe_id = g_strdup_printf("%d", telephony_default_subscription_id); + + if (g_str_has_suffix(modem->path, subscribe_id) != TRUE) { + g_free(subscribe_id); + return -ENOLINK; + } + g_free(subscribe_id); + } + + return __dbus_request(path, PS_CONTEXT_INTERFACE, ACTIVATE_CONTEXT, + __response_network_activate, + g_strdup(path), NULL, DBUS_TYPE_INVALID); +} + +static gboolean __check_network_available(struct connman_network *network) +{ + if (network == NULL || connman_network_get_device(network) == NULL) + return FALSE; + + return TRUE; +} + +static void __response_network_activate(DBusPendingCall *call, void *user_data) +{ + DBG("network activation response"); + + DBusError error; + DBusMessage *reply; + + struct telephony_network *info; + const char *path = user_data; + + info = g_hash_table_lookup(network_hash, path); + reply = dbus_pending_call_steal_reply(call); + + if (info == NULL) + goto done; + + if (__check_network_available(info->network) == FALSE) { + g_hash_table_remove(network_hash, path); + goto done; + } + + dbus_error_init(&error); + if (dbus_set_error_from_message(&error, reply)) { + connman_error("connection activate() %s %s", + error.name, error.message); + + if (connman_network_get_associating(info->network) == TRUE) + connman_network_set_error(info->network, + CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); + + if (connman_network_get_connecting(info->network) == TRUE) + connman_network_set_error(info->network, + CONNMAN_NETWORK_ERROR_CONNECT_FAIL); + + if (connman_network_get_index(info->network) < 0) + connman_network_set_error(info->network, + CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); + + dbus_error_free(&error); + goto done; + } + +done: + dbus_message_unref(reply); + dbus_pending_call_unref(call); +} + +static int __request_network_deactivate(struct connman_network *network) +{ + const char *path = connman_network_get_string(network, "Path"); + DBG("network %p, path %s", network, path); + + return __dbus_request(path, PS_CONTEXT_INTERFACE, DEACTIVATE_CONTEXT, + NULL, NULL, NULL, DBUS_TYPE_INVALID); +} + +static void __response_get_default_subscription_id(DBusPendingCall *call, + void *user_data) +{ + DBusMessage *reply; + DBusError error; + DBusMessageIter args; + + DBG(""); + + reply = dbus_pending_call_steal_reply(call); + + dbus_error_init(&error); + if (dbus_set_error_from_message(&error, reply)) { + connman_error("GetDefaultDataSubscription() %s %s", error.name, error.message); + dbus_error_free(&error); + goto done; + } + + DBG("message signature (%s)", dbus_message_get_signature(reply)); + + if (dbus_message_iter_init(reply, &args) == FALSE) + goto done; + + dbus_message_iter_get_basic(&args, &telephony_default_subscription_id); + DBG("default subscription: %d", telephony_default_subscription_id); + +done: + dbus_message_unref(reply); + dbus_pending_call_unref(call); +} + +static int __request_get_default_subscription_id(const char *path) +{ + int ret; + char *telephony_modem_path = NULL; + + telephony_modem_path = g_strdup_printf("/org/tizen/telephony%s", path); + DBG("request get default subscription id %s", telephony_modem_path); + + ret = __dbus_request(telephony_modem_path, + "org.tizen.telephony.Network", "GetDefaultDataSubscription", + __response_get_default_subscription_id, NULL, NULL, DBUS_TYPE_INVALID); + + g_free(telephony_modem_path); + return ret; +} + +static void __add_modem(const char *path, DBusMessageIter *prop) +{ + struct telephony_modem *modem; + + modem = g_hash_table_lookup(modem_hash, path); + if (modem != NULL) + return; + + modem = g_try_new0(struct telephony_modem, 1); + if (modem == NULL) + return; + + modem->path = g_strdup(path); + modem->device = NULL; + modem->s_service = NULL; + + g_hash_table_insert(modem_hash, g_strdup(path), modem); + + while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key, *tmp; + + dbus_message_iter_recurse(prop, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_get_basic(&entry, &tmp); + + DBG("key (%s) value(%s)", key, tmp); + + if (g_strcmp0(key, "powered") == 0) { + modem->powered = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "operator") == 0) { + modem->operator = g_strdup(tmp); + } else if (g_strcmp0(key, "sim_init") == 0) { + modem->sim_init = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "flight_mode") == 0) { + modem->flight_mode = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "roaming_allowed") == 0) { + modem->roaming_allowed = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "data_allowed") == 0) { + modem->data_allowed = STRING2BOOL(tmp); + } + dbus_message_iter_next(prop); + } + + __add_connman_device(path, modem->operator); + __set_device_powered(modem, modem->powered); + + if (g_hash_table_size(modem_hash) > 1) + __request_get_default_subscription_id(modem->path); + + if (modem->powered != TRUE) { + DBG("modem is not powered"); + return; + } + + __request_get_services(modem->path); +} + +static void __add_service(struct telephony_modem *modem, + const char *service_path, DBusMessageIter *prop) +{ + struct telephony_service *service; + + if (modem->s_service != NULL) + return; + + service = g_try_new0(struct telephony_service, 1); + if (service == NULL) + return; + + service->path = g_strdup(service_path); + service->p_modem = modem; + g_hash_table_insert(service_hash, g_strdup(service_path), service); + + while (dbus_message_iter_get_arg_type(prop) != DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key, *tmp; + + dbus_message_iter_recurse(prop, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_get_basic(&entry, &tmp); + + DBG("key (%s) value(%s)", key, tmp); + + if (g_strcmp0(key, "roaming") == 0) { + service->roaming = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "act") == 0) { + service->act = g_strdup(tmp); + } else if (g_strcmp0(key, "ps_attached") == 0) { + service->ps_attached = STRING2BOOL(tmp); + } + + dbus_message_iter_next(prop); + } + + modem->s_service = service; + __request_get_contexts(modem); +} + +static char *__get_ident(const char *path) +{ + char *pos; + + if (*path != '/') + return NULL; + + pos = strrchr(path, '/'); + if (pos == NULL) + return NULL; + + return pos + 1; +} + +static void __add_connman_device(const char *modem_path, const char *operator) +{ + char* ident = NULL; + struct telephony_modem *modem; + struct connman_device *device; + + DBG("path %s operator %s", modem_path, operator); + + if (modem_path == NULL) + return; + + if (operator == NULL) + return; + + modem = g_hash_table_lookup(modem_hash, modem_path); + if (modem == NULL) + return; + + if (modem->device) { + if (!g_strcmp0(operator, + connman_device_get_ident(modem->device))) + return; + + __remove_connman_device(modem); + } + + if (strlen(operator) == 0) + return; + + device = connman_device_create(operator, CONNMAN_DEVICE_TYPE_CELLULAR); + if (device == NULL) + return; + + ident = g_strdup_printf("%s_%s", __get_ident(modem_path), operator); + connman_device_set_ident(device, ident); + g_free(ident); + + connman_device_set_string(device, "Path", modem_path); + connman_device_set_data(device, modem); + + if (connman_device_register(device) < 0) { + connman_error("Failed to register cellular device"); + connman_device_unref(device); + return; + } + + modem->device = device; +} + +static void __remove_connman_device(struct telephony_modem *modem) +{ + DBG("modem %p path %s device %p", modem, modem->path, modem->device); + + if (modem->device == NULL) + return; + + __remove_connman_networks(modem->device); + + connman_device_unregister(modem->device); + connman_device_unref(modem->device); + + modem->device = NULL; +} + +static void __remove_connman_networks(struct connman_device *device) +{ + GHashTableIter iter; + gpointer key, value; + GSList *info_list = NULL; + GSList *list; + + if (network_hash == NULL) + return; + + g_hash_table_iter_init(&iter, network_hash); + + while (g_hash_table_iter_next(&iter, &key, &value) == TRUE) { + struct telephony_network *info = value; + + if (connman_network_get_device(info->network) != device) + continue; + + info_list = g_slist_append(info_list, info); + } + + for (list = info_list; list != NULL; list = list->next) { + struct telephony_network *info = list->data; + connman_device_remove_network(device, info->network); + } + + g_slist_free(info_list); +} + +static gboolean connman_ipaddress_updated(struct connman_ipaddress *ipaddress, + const char *address, const char *gateway) +{ + if (ipaddress == NULL || address == NULL) + return FALSE; + + if (g_strcmp0(ipaddress->local, address) != 0) + return TRUE; + + if (g_strcmp0(ipaddress->gateway, gateway) != 0) + return TRUE; + + return FALSE; +} + +static void __set_network_connected(struct telephony_network *network, + gboolean connected) +{ + gboolean setip = FALSE; + + DBG("network %p connected %d", network, connected); + + connman_network_set_index(network->network, network->if_index); + if (connman_network_get_connected(network->network) == connected) + return; + + switch (network->ipv4_method) { + case CONNMAN_IPCONFIG_METHOD_UNKNOWN: + case CONNMAN_IPCONFIG_METHOD_DHCP: + case CONNMAN_IPCONFIG_METHOD_AUTO: + case CONNMAN_IPCONFIG_METHOD_OFF: + connman_network_set_ipv4_method(network->network, + network->ipv4_method); + break; + case CONNMAN_IPCONFIG_METHOD_MANUAL: + case CONNMAN_IPCONFIG_METHOD_FIXED: + connman_network_set_ipv4_method(network->network, + network->ipv4_method); + connman_network_set_ipaddress(network->network, + network->ipv4_address); + setip = TRUE; + break; + } + + switch (network->ipv6_method) { + case CONNMAN_IPCONFIG_METHOD_UNKNOWN: + case CONNMAN_IPCONFIG_METHOD_OFF: + case CONNMAN_IPCONFIG_METHOD_DHCP: + break; + case CONNMAN_IPCONFIG_METHOD_AUTO: + connman_network_set_ipv6_method(network->network, + network->ipv6_method); + setip = TRUE; + break; + case CONNMAN_IPCONFIG_METHOD_MANUAL: + case CONNMAN_IPCONFIG_METHOD_FIXED: + connman_network_set_ipv6_method(network->network, + network->ipv6_method); + connman_network_set_ipaddress(network->network, + network->ipv6_address); + setip = TRUE; + break; + } + + if (setip == TRUE) + connman_network_set_connected(network->network, connected); +} + +static gboolean __set_network_context( + struct telephony_network *network, + DBusMessageIter *dict) +{ + int index = 0; + gboolean active = FALSE; + gboolean routing_only = FALSE; + gboolean ipv4_updated = FALSE; + gboolean ipv6_updated = FALSE; + gboolean ipv6_link_only = FALSE; + gboolean default_internet = FALSE; + gboolean active_proxy = FALSE; + char **proxies = NULL; + const char *dev_name = NULL; + const char *proxy_addr = NULL; + char *ipv4_addr = NULL, *ipv4_gw = NULL, *ipv4_netmask = NULL, + *ipv4_dns1 = NULL, *ipv4_dns2 = NULL; + char *ipv6_addr = NULL, *ipv6_gw = NULL, *ipv6_netmask = NULL, + *ipv6_dns1 = NULL, *ipv6_dns2 = NULL; + struct connman_service *service; + + while (dbus_message_iter_get_arg_type(dict) != DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key, *value; + + dbus_message_iter_recurse(dict, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + + if (g_strcmp0(key, "dev_name") == 0) { + dbus_message_iter_get_basic(&entry, &dev_name); + DBG("dev_name (%s)", dev_name); + } else if (g_strcmp0(key, "proxy") == 0) { + dbus_message_iter_get_basic(&entry, &proxy_addr); + DBG("proxy_addr (%s)", proxy_addr); + } else if (g_strcmp0(key, "ipv4_address") == 0) { + dbus_message_iter_get_basic(&entry, &ipv4_addr); + DBG("ipv4_addr (%s)", ipv4_addr); + } else if (g_strcmp0(key, "ipv4_gateway") == 0) { + dbus_message_iter_get_basic(&entry, &ipv4_gw); + DBG("ipv4_gw (%s)", ipv4_gw); + } else if (g_strcmp0(key, "ipv4_netmask") == 0) { + dbus_message_iter_get_basic(&entry, &ipv4_netmask); + DBG("ipv4_netmask (%s)", ipv4_netmask); + } else if (g_strcmp0(key, "ipv4_dns1") == 0) { + dbus_message_iter_get_basic(&entry, &ipv4_dns1); + DBG("ipv4_dns1 (%s)", ipv4_dns1); + } else if (g_strcmp0(key, "ipv4_dns2") == 0) { + dbus_message_iter_get_basic(&entry, &ipv4_dns2); + DBG("ipv4_dns2 (%s)", ipv4_dns2); + } else if (g_strcmp0(key, "ipv6_address") == 0) { + dbus_message_iter_get_basic(&entry, &ipv6_addr); + DBG("ipv6 address (%s)", ipv6_addr); + } else if (g_strcmp0(key, "ipv6_gateway") == 0) { + dbus_message_iter_get_basic(&entry, &ipv6_gw); + DBG("ipv6_gw (%s)", ipv6_gw); + } else if (g_strcmp0(key, "ipv6_netmask") == 0) { + dbus_message_iter_get_basic(&entry, &ipv6_netmask); + DBG("ipv6_netmask (%s)", ipv6_netmask); + } else if (g_strcmp0(key, "ipv6_dns1") == 0) { + dbus_message_iter_get_basic(&entry, &ipv6_dns1); + DBG("ipv6_dns1 (%s)", ipv6_dns1); + } else if (g_strcmp0(key, "ipv6_dns2") == 0) { + dbus_message_iter_get_basic(&entry, &ipv6_dns2); + DBG("ipv6_dns2 (%s)", ipv6_dns2); + } else if (g_strcmp0(key, "active") == 0) { + dbus_message_iter_get_basic(&entry, &value); + DBG("active (%s)", value); + active = STRING2BOOL(value); + } else if (g_strcmp0(key, "routing_only") == 0) { + dbus_message_iter_get_basic(&entry, &value); + DBG("routing_only (%s)", value); + routing_only = STRING2BOOL(value); + network->routing_only = routing_only; + } else if (g_strcmp0(key, "ipv6_link_only") == 0) { + dbus_message_iter_get_basic(&entry, &value); + DBG("ipv6_link_only (%s)", value); + ipv6_link_only = STRING2BOOL(value); + network->ipv6_link_only = ipv6_link_only; + } + else if (g_strcmp0(key, "default_internet_conn") == 0) { + dbus_message_iter_get_basic(&entry, &value); + DBG("default_internet (%s)", value); + default_internet = STRING2BOOL(value); + } + + dbus_message_iter_next(dict); + } + + if(routing_only){ + //context active does not effect the connman service status. + //it only for setting the routing path. + DBG("routing_only(%d), active(%d)", routing_only, active); + return active; + } + + if (g_strcmp0(proxy_addr, ":") == 0) + proxy_addr = NULL; + if (g_strcmp0(ipv4_addr, "0.0.0.0") == 0) + ipv4_addr = NULL; + if (g_strcmp0(ipv4_gw, "0.0.0.0") == 0) + ipv4_gw = NULL; + if (g_strcmp0(ipv4_netmask, "0.0.0.0") == 0) + ipv4_netmask = NULL; + if (g_strcmp0(ipv4_dns1, "0.0.0.0") == 0) + ipv4_dns1 = NULL; + if (g_strcmp0(ipv4_dns2, "0.0.0.0") == 0) + ipv4_dns2 = NULL; + if (g_strcmp0(ipv6_addr, "::") == 0) + ipv6_addr = NULL; + if (g_strcmp0(ipv6_gw, "::") == 0) + ipv6_gw = NULL; + if (g_strcmp0(ipv6_netmask, "::") == 0) + ipv6_netmask = NULL; + if (g_strcmp0(ipv6_dns1, "::") == 0) + ipv6_dns1 = NULL; + if (g_strcmp0(ipv6_dns2, "::") == 0) + ipv6_dns2 = NULL; + + connman_network_set_bool(network->network, "DefaultInternet", + (bool)default_internet); + + service = connman_service_lookup_from_network(network->network); + if (service == NULL) + return FALSE; + + if (connman_setting_get_bool("SingleConnectedTechnology") == TRUE) { + /* Wi-Fi technology is always a top priority */ + if (active == TRUE && + connman_service_is_no_ref_user_pdn_connection(service) == TRUE && + connman_service_get_type(connman_service_get_default_connection()) + == CONNMAN_SERVICE_TYPE_WIFI) { + __request_network_deactivate(network->network); + + return FALSE; + } + } + + /* interface index set */ + if (dev_name != NULL) { + index = connman_inet_ifindex(dev_name); + network->if_index = index; + DBG("interface index %d", index); + } + + /* proxy set */ + if (active == TRUE && + connman_network_get_connected(network->network) == TRUE) + active_proxy = TRUE; + + proxies = connman_service_get_proxy_servers(service); + if (proxies != NULL) { + if (proxy_addr == NULL) + connman_service_set_proxy(service, proxy_addr, active_proxy); + else if (g_strcmp0(proxy_addr, proxies[0]) != 0) + connman_service_set_proxy(service, proxy_addr, active_proxy); + } else if (proxy_addr != NULL) + connman_service_set_proxy(service, proxy_addr, active_proxy); + + if (proxies != NULL) + g_strfreev(proxies); + + __connman_service_nameserver_clear(service); + + /* ipv4 set */ + if (network->ipv4_address == NULL) + network->ipv4_address = + connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV4); + + if (network->ipv4_address == NULL) + return FALSE; + + if (ipv4_addr == NULL && active == TRUE) + network->ipv4_method = CONNMAN_IPCONFIG_METHOD_OFF; + else + network->ipv4_method = CONNMAN_IPCONFIG_METHOD_FIXED; + + connman_network_set_ipv4_method(network->network, network->ipv4_method); + + ipv4_updated = connman_ipaddress_updated(network->ipv4_address, + ipv4_addr, ipv4_gw); + if (ipv4_updated == TRUE) + connman_ipaddress_set_ipv4(network->ipv4_address, ipv4_addr, + ipv4_netmask, ipv4_gw); + + if (ipv4_dns1) +#if defined TIZEN_EXT + __connman_service_nameserver_append(service, ipv4_dns1, FALSE, + CONNMAN_IPCONFIG_TYPE_IPV4); +#else + __connman_service_nameserver_append(service, ipv4_dns1, FALSE); +#endif + //if (ipv4_dns2) + if (ipv4_dns2 && !ipv4_dns1) +#if defined TIZEN_EXT + __connman_service_nameserver_append(service, ipv4_dns2, FALSE, + CONNMAN_IPCONFIG_TYPE_IPV4); +#else + __connman_service_nameserver_append(service, ipv4_dns2, FALSE); +#endif + /* ipv6 set */ + if (network->ipv6_address == NULL) + network->ipv6_address = + connman_ipaddress_alloc(CONNMAN_IPCONFIG_TYPE_IPV6); + + if (network->ipv6_address == NULL) + return FALSE; + + if(ipv6_link_only) + network->ipv6_method = CONNMAN_IPCONFIG_METHOD_AUTO; + else + network->ipv6_method = CONNMAN_IPCONFIG_METHOD_FIXED; + + if (ipv6_addr == NULL) + network->ipv6_method = CONNMAN_IPCONFIG_METHOD_OFF; + + connman_network_set_ipv6_method(network->network, network->ipv6_method); + + ipv6_updated = connman_ipaddress_updated(network->ipv6_address, + ipv6_addr, ipv6_gw); + if (ipv6_updated == TRUE) + connman_ipaddress_set_ipv6(network->ipv6_address, ipv6_addr, + 64, ipv6_gw); + + if (ipv6_dns1) +#if defined TIZEN_EXT + __connman_service_nameserver_append(service, ipv6_dns1, FALSE, + CONNMAN_IPCONFIG_TYPE_IPV6); +#else + __connman_service_nameserver_append(service, ipv6_dns1, FALSE); +#endif + //if (ipv6_dns2) + if (ipv6_dns2 && !ipv6_dns1) +#if defined TIZEN_EXT + __connman_service_nameserver_append(service, ipv6_dns2, FALSE, + CONNMAN_IPCONFIG_TYPE_IPV6); +#else + __connman_service_nameserver_append(service, ipv6_dns2, FALSE); +#endif + + if (active == TRUE && + connman_network_get_connected(network->network) == TRUE) { + if (ipv4_updated == TRUE || ipv6_updated == TRUE) { + DBG("IPv4 updated %d, IPv6 updated %d", ipv4_updated, ipv6_updated); + + __set_network_connected(network, FALSE); + } else { + DBG("Already connected"); + + return active; + } + } + + if (active == TRUE) + connman_network_set_associating(network->network, TRUE); + + return active; +} + +static int __add_context(struct connman_device *device, const char *path, + DBusMessageIter *prop) +{ + char *ident; + gboolean active = FALSE; + + struct telephony_modem *modem = connman_device_get_data(device); + struct connman_network *network; + struct telephony_network *info; + + DBG("modem %p device %p path %s", modem, device, path); + + ident = __get_ident(path); + + network = connman_device_get_network(device, ident); + if (network != NULL) + return -EALREADY; + + info = g_hash_table_lookup(network_hash, path); + if (info != NULL) { + DBG("path %p already exists with device %p", path, + connman_network_get_device(info->network)); + + if (connman_network_get_device(info->network)) + return -EALREADY; + + g_hash_table_remove(network_hash, path); + } + + network = connman_network_create(ident, CONNMAN_NETWORK_TYPE_CELLULAR); + if (network == NULL) + return -ENOMEM; + + info = g_try_new0(struct telephony_network, 1); + if (info == NULL) { + connman_network_unref(network); + return -ENOMEM; + } + + info->path = g_strdup(path); + + connman_ipaddress_clear(info->ipv4_address); + connman_ipaddress_clear(info->ipv6_address); + + info->network = network; + + connman_network_set_string(network, "Path", path); + connman_network_set_name(network, path); + + connman_network_set_group(network, ident); + + g_hash_table_insert(network_hash, g_strdup(path), info); + + connman_network_set_available(network, TRUE); + connman_network_set_bool(network, "Roaming", (bool)modem->s_service->roaming); + + if (connman_device_add_network(device, network) != 0) { + g_hash_table_remove(network_hash, path); + return -EIO; + } + + active = __set_network_context(info, prop); + if(info->routing_only){ + int err = 0; + struct connman_service *routing_service; + struct connman_ipconfig *routing_ipconfig; + + if(!active) + return TRUE; + + routing_service = connman_service_lookup_from_network(info->network); + routing_ipconfig = __connman_service_get_ip4config(routing_service); + err = __connman_ipconfig_gateway_add(routing_ipconfig, routing_service); + + DBG("set gateway rv(%d)", err); + return TRUE; + } + + if (active == TRUE && (connman_network_get_associating(network) == TRUE || + connman_network_get_connecting(network) == TRUE)) + __set_network_connected(info, active); + + return 0; +} + +static gboolean __changed_modem(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + gboolean old_powered; + DBusMessageIter args, dict; + struct telephony_modem *modem; + const char *path = dbus_message_get_path(message); + + DBG("modem changed signal %s", path); + + modem = g_hash_table_lookup(modem_hash, path); + if (modem == NULL) { + DBG("modem object does not exists"); + return TRUE; + } + + old_powered = modem->powered; + + DBG("message signature (%s)", dbus_message_get_signature(message)); + + if (dbus_message_iter_init(message, &args) == FALSE) { + DBG("error to read message"); + return TRUE; + } + + dbus_message_iter_recurse(&args, &dict); + + while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key, *tmp; + + dbus_message_iter_recurse(&dict, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_get_basic(&entry, &tmp); + + DBG("key(%s), value(%s)", key, tmp); + + if (g_strcmp0(key, "powered") == 0) { + modem->powered = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "operator") == 0) { + modem->operator = g_strdup(tmp); + } else if (g_strcmp0(key, "sim_init") == 0) { + modem->sim_init = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "flight_mode") == 0) { + modem->flight_mode = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "roaming_allowed") == 0) { + modem->roaming_allowed = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "data_allowed") == 0) { + modem->data_allowed = STRING2BOOL(tmp); + } + + dbus_message_iter_next(&dict); + } + + if (modem->device == NULL) + __add_connman_device(path, modem->operator); + + if (old_powered != modem->powered) + __set_device_powered(modem, modem->powered); + + if (modem->powered != TRUE) { + DBG("modem is not powered"); + return TRUE; + } + + if (modem->s_service == NULL) { + __request_get_services(modem->path); + return TRUE; + } + + DBG("modem(%s) flight mode(%d) data allowed(%d)", + modem->path, modem->flight_mode, modem->data_allowed); + + return TRUE; +} + +static gboolean __added_modem(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + const char *modem_path = NULL; + DBusMessageIter args, dict, tmp; + + DBG("modem added signal (%s)", dbus_message_get_signature(message)); + + if (dbus_message_iter_init(message, &args) == FALSE) { + DBG("error to read message"); + return TRUE; + } + + dbus_message_iter_recurse(&args, &dict); + memcpy(&tmp, &dict, sizeof(struct DBusMessageIter)); + + while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key, *value; + + dbus_message_iter_recurse(&tmp, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_get_basic(&entry, &value); + + DBG("key (%s) value(%s)", key, value); + + if (g_strcmp0(key, "path") == 0) + modem_path = g_strdup(value); + + dbus_message_iter_next(&tmp); + } + + if (modem_path != NULL) + __add_modem(modem_path, &dict); + + return TRUE; +} + +static gboolean __removed_modem(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + DBusMessageIter iter; + const char *modem_path; + + DBG("modem removed signal"); + + if (dbus_message_iter_init(message, &iter) == FALSE) { + DBG("error to read message"); + return TRUE; + } + + dbus_message_iter_get_basic(&iter, &modem_path); + g_hash_table_remove(modem_hash, modem_path); + + return TRUE; +} + +static gboolean __changed_service(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + DBusMessageIter args, dict; + struct telephony_modem *modem; + gboolean roaming_option = TRUE; + struct telephony_service *s_service; + const char *service_path = dbus_message_get_path(message); + + DBG("service changed signal %s", service_path); + + s_service = g_hash_table_lookup(service_hash, service_path); + if (s_service == NULL) { + DBG("service object does not exists"); + return TRUE; + } + + modem = s_service->p_modem; + if (modem == NULL) { + DBG("modem object does not exists"); + return TRUE; + } + + DBG("message signature (%s)", dbus_message_get_signature(message)); + + if (dbus_message_iter_init(message, &args) == FALSE) { + DBG("error to read message"); + return TRUE; + } + + dbus_message_iter_recurse(&args, &dict); + + while (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key, *tmp; + + dbus_message_iter_recurse(&dict, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_get_basic(&entry, &tmp); + + DBG("key(%s), value(%s)", key, tmp); + + if (g_strcmp0(key, "roaming") == 0) { + s_service->roaming = STRING2BOOL(tmp); + } else if (g_strcmp0(key, "act") == 0) { + s_service->act = g_strdup(tmp); + } else if (g_strcmp0(key, "ps_attached") == 0) { + s_service->ps_attached = STRING2BOOL(tmp); + } + + dbus_message_iter_next(&dict); + } + + roaming_option &= (!s_service->roaming && !modem->roaming_allowed) + || modem->roaming_allowed; + + return TRUE; +} + +static gboolean __added_service(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct telephony_modem *modem; + const char *service_path = NULL; + DBusMessageIter args, dict, tmp; + const char *path = dbus_message_get_path(message); + + DBG("service added signal %s", path); + + modem = g_hash_table_lookup(modem_hash, path); + if (modem == NULL || modem->device == NULL) + return TRUE; + + DBG("message signature (%s)", dbus_message_get_signature(message)); + if (dbus_message_iter_init(message, &args) == FALSE) { + DBG("error to read message"); + return TRUE; + } + + dbus_message_iter_recurse(&args, &dict); + memcpy(&tmp, &dict, sizeof(struct DBusMessageIter)); + + while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key, *value; + + dbus_message_iter_recurse(&tmp, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_get_basic(&entry, &value); + + DBG("key (%s) value(%s)", key, value); + + if (g_strcmp0(key, "path") == 0) + service_path = value; + + dbus_message_iter_next(&tmp); + } + + if (service_path != NULL) + __add_service(modem, service_path, &dict); + + return TRUE; +} + +static gboolean __removed_service(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + DBusMessageIter iter; + const char *service_path; + + DBG("service removed signal"); + + if (dbus_message_iter_init(message, &iter) == FALSE) { + DBG("error to read message"); + return TRUE; + } + + dbus_message_iter_get_basic(&iter, &service_path); + g_hash_table_remove(service_hash, service_path); + + return TRUE; +} + +static gboolean __changed_context(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + gboolean active = FALSE; + DBusMessageIter args, dict; + struct telephony_network *info; + const char *path = dbus_message_get_path(message); + + DBG("network changed signal %s", path); + + info = g_hash_table_lookup(network_hash, path); + if (info == NULL) + return TRUE; + + if (__check_network_available(info->network) == FALSE) { + g_hash_table_remove(network_hash, path); + return TRUE; + } + + if (dbus_message_iter_init(message, &args) == FALSE) { + DBG("error to read message"); + return TRUE; + } + + dbus_message_iter_recurse(&args, &dict); + + active = __set_network_context(info, &dict); + if(info->routing_only){ + int err = 0; + struct connman_service *routing_service; + struct connman_ipconfig *routing_ipconfig; + + if(!active) + return TRUE; + + routing_service = connman_service_lookup_from_network(info->network); + routing_ipconfig = __connman_service_get_ip4config(routing_service); + err = __connman_ipconfig_gateway_add(routing_ipconfig, routing_service); + + DBG("set gateway rv(%d)", err); + return TRUE; + } + + __set_network_connected(info, active); + + if (active == FALSE && + connman_network_get_connecting(info->network) == TRUE) + connman_network_set_connected(info->network, FALSE); + + return TRUE; +} + +static gboolean __added_context(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + const char *network_path = NULL; + DBusMessageIter args, dict, tmp; + struct telephony_modem *modem = NULL; + struct telephony_service *service = NULL; + const char *path = dbus_message_get_path(message); + + DBG("network added signal %s", path); + + service = g_hash_table_lookup(service_hash, path); + if (service == NULL || service->p_modem == NULL) + return TRUE; + + modem = service->p_modem; + if (modem == NULL || modem->device == NULL) + return TRUE; + + DBG("message signature (%s)", dbus_message_get_signature(message)); + if (dbus_message_iter_init(message, &args) == FALSE) { + DBG("error to read message"); + return TRUE; + } + + dbus_message_iter_recurse(&args, &dict); + memcpy(&tmp, &dict, sizeof(struct DBusMessageIter)); + + while (dbus_message_iter_get_arg_type(&tmp) != DBUS_TYPE_INVALID) { + DBusMessageIter entry; + const char *key, *value; + + dbus_message_iter_recurse(&tmp, &entry); + dbus_message_iter_get_basic(&entry, &key); + + dbus_message_iter_next(&entry); + dbus_message_iter_get_basic(&entry, &value); + + DBG("key (%s) value(%s)", key, value); + + if (g_strcmp0(key, "path") == 0) + network_path = g_strdup(value); + + dbus_message_iter_next(&tmp); + } + + if (network_path != NULL) + __add_context(modem->device, network_path, &dict); + + return TRUE; +} + +static gboolean __removed_context(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + DBusMessageIter iter; + const char *network_path = NULL; + struct telephony_service *service = NULL; + const char *path = dbus_message_get_path(message); + + DBG("network removed signal %s", path); + + service = g_hash_table_lookup(service_hash, path); + if (service == NULL || service->p_modem == NULL) + return TRUE; + + if (dbus_message_iter_init(message, &iter) == FALSE) { + DBG("error to read message"); + return TRUE; + } + + dbus_message_iter_get_basic(&iter, &network_path); + g_hash_table_remove(network_hash, network_path); + + return TRUE; +} + +static gboolean __changed_default_subscription(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + DBusMessageIter args; + + DBG("message signature (%s)", dbus_message_get_signature(message)); + if (dbus_message_iter_init(message, &args) == FALSE) + return TRUE; + + dbus_message_iter_get_basic(&args, &telephony_default_subscription_id); + DBG("default subscription: %d", telephony_default_subscription_id); + + return TRUE; +} + +/* telephony initialization */ +static guint watch = 0; +static guint modem_watch = 0; +static guint modem_added_watch = 0; +static guint modem_removed_watch = 0; +static guint service_watch = 0; +static guint service_added_watch = 0; +static guint service_removed_watch = 0; +static guint context_watch = 0; +static guint context_added_watch = 0; +static guint context_removed_watch = 0; +static guint default_subscription_watch = 0; + +static int telephony_init(void) +{ + int err; + + DBG("telephony plugin"); + + connection = connman_dbus_get_connection(); + if (connection == NULL) + return -EIO; + + /* telephony watch */ + watch = g_dbus_add_service_watch(connection, PS_DBUS_SERVICE, + telephony_connect, telephony_disconnect, + NULL, NULL); + + modem_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_MODEM_INTERFACE, + PROPERTY_CHANGED, + __changed_modem, + NULL, NULL); + + modem_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_MASTER_INTERFACE, + MODEM_ADDED, + __added_modem, + NULL, NULL); + + modem_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_MASTER_INTERFACE, + MODEM_REMOVED, + __removed_modem, + NULL, NULL); + + service_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_SERVICE_INTERFACE, + PROPERTY_CHANGED, + __changed_service, + NULL, NULL); + + service_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_MODEM_INTERFACE, + SERVICE_ADDED, + __added_service, + NULL, NULL); + + service_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_MODEM_INTERFACE, + SERVICE_REMOVED, + __removed_service, + NULL, NULL); + + context_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_CONTEXT_INTERFACE, + PROPERTY_CHANGED, + __changed_context, + NULL, NULL); + + context_added_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_SERVICE_INTERFACE, + CONTEXT_ADDED, + __added_context, + NULL, NULL); + + context_removed_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + PS_SERVICE_INTERFACE, + CONTEXT_REMOVED, + __removed_context, + NULL, NULL); + + default_subscription_watch = g_dbus_add_signal_watch(connection, NULL, NULL, + "org.tizen.telephony.Network", + "DefaultDataSubscription", + __changed_default_subscription, + NULL, NULL); + + if (watch == 0 || modem_watch == 0 || modem_added_watch == 0 + || modem_removed_watch == 0 || service_watch == 0 + || service_added_watch == 0 || context_watch == 0 + || service_removed_watch == 0 + || context_added_watch == 0 + || context_removed_watch == 0 + || default_subscription_watch == 0) { + err = -EIO; + goto remove; + } + + err = connman_network_driver_register(&network_driver); + if (err < 0) + goto remove; + + err = connman_device_driver_register(&modem_driver); + if (err < 0) { + connman_network_driver_unregister(&network_driver); + goto remove; + } + + err = connman_technology_driver_register(&tech_driver); + if (err < 0) { + connman_device_driver_unregister(&modem_driver); + connman_network_driver_unregister(&network_driver); + goto remove; + } + + return 0; + +remove: + g_dbus_remove_watch(connection, watch); + g_dbus_remove_watch(connection, modem_watch); + g_dbus_remove_watch(connection, modem_added_watch); + g_dbus_remove_watch(connection, modem_removed_watch); + g_dbus_remove_watch(connection, service_watch); + g_dbus_remove_watch(connection, service_added_watch); + g_dbus_remove_watch(connection, service_removed_watch); + g_dbus_remove_watch(connection, context_watch); + g_dbus_remove_watch(connection, context_added_watch); + g_dbus_remove_watch(connection, context_removed_watch); + g_dbus_remove_watch(connection, default_subscription_watch); + + dbus_connection_unref(connection); + return err; +} + +static void telephony_exit(void) +{ + g_dbus_remove_watch(connection, watch); + g_dbus_remove_watch(connection, modem_watch); + g_dbus_remove_watch(connection, modem_added_watch); + g_dbus_remove_watch(connection, modem_removed_watch); + g_dbus_remove_watch(connection, service_watch); + g_dbus_remove_watch(connection, service_added_watch); + g_dbus_remove_watch(connection, service_removed_watch); + g_dbus_remove_watch(connection, context_watch); + g_dbus_remove_watch(connection, context_added_watch); + g_dbus_remove_watch(connection, context_removed_watch); + g_dbus_remove_watch(connection, default_subscription_watch); + + telephony_disconnect(connection, NULL); + + connman_device_driver_unregister(&modem_driver); + connman_network_driver_unregister(&network_driver); + + dbus_connection_unref(connection); +} + +CONNMAN_PLUGIN_DEFINE(telephony, "Samsung Telephony Framework plug-in", VERSION, + CONNMAN_PLUGIN_PRIORITY_DEFAULT, telephony_init, telephony_exit) diff --git a/plugins/tist.c b/plugins/tist.c index ad5ef79e..ad5ef79e 100644..100755 --- a/plugins/tist.c +++ b/plugins/tist.c diff --git a/plugins/vpn.c b/plugins/vpn.c index c2a332ba..d3d75b81 100644..100755 --- a/plugins/vpn.c +++ b/plugins/vpn.c @@ -1726,7 +1726,7 @@ static gboolean property_changed(DBusConnection *conn, struct connection_data *data = NULL; DBusMessageIter iter, value; bool ip_set = false; - int err; + int err = 0; char *str; const char *key; const char *signature = DBUS_TYPE_STRING_AS_STRING diff --git a/plugins/wifi.c b/plugins/wifi.c index 34c16dfd..8bc6307b 100644..100755 --- a/plugins/wifi.c +++ b/plugins/wifi.c @@ -152,10 +152,27 @@ struct wifi_data { bool p2p_connecting; bool p2p_device; int servicing; +#if defined TIZEN_EXT + int assoc_retry_count; + struct connman_network *scan_pending_network; + bool allow_full_scan; +#endif int disconnect_code; int assoc_code; }; +#if defined TIZEN_EXT +#include "connman.h" +#include "dbus.h" + +#define TIZEN_ASSOC_RETRY_COUNT 4 + +static gboolean wifi_first_scan = false; +static gboolean found_with_first_scan = false; +static gboolean is_wifi_notifier_registered = false; +#endif + + static GList *iface_list = NULL; static GList *pending_wifi_device = NULL; @@ -163,10 +180,128 @@ static GList *p2p_iface_list = NULL; bool wfd_service_registered = false; static void start_autoscan(struct connman_device *device); + static int tech_set_tethering(struct connman_technology *technology, const char *identifier, const char *passphrase, const char *bridge, bool enabled); +#if defined TIZEN_EXT +#define NETCONFIG_SERVICE "net.netconfig" +#define NETCONFIG_WIFI_PATH "/net/netconfig/wifi" +#define NETCONFIG_WIFI_INTERFACE NETCONFIG_SERVICE ".wifi" + +struct enc_method_call_data { + DBusConnection *connection; + struct connman_network *network; +}; + +static struct enc_method_call_data encrypt_request_data; + +static void encryption_request_reply(DBusPendingCall *call, + void *user_data) +{ + DBusMessage *reply; + DBusError error; + DBusMessageIter args; + char *out_data; + struct connman_service *service; + gchar* encrypted_value = NULL; + struct connman_network *network = encrypt_request_data.network; + + DBG(""); + + reply = dbus_pending_call_steal_reply(call); + + dbus_error_init(&error); + if (dbus_set_error_from_message(&error, reply)) { + DBG("send_encryption_request() %s %s", error.name, error.message); + dbus_error_free(&error); + goto done; + } + + if (dbus_message_iter_init(reply, &args) == FALSE) + goto done; + + dbus_message_iter_get_basic(&args, &out_data); + + encrypted_value = g_strdup((const gchar *)out_data); + service = connman_service_lookup_from_network(network); + + if (!service) { + DBG("encryption result: no service"); + goto done; + } + + if (connman_service_get_favorite(service)) { + __connman_service_set_passphrase(service, encrypted_value); + __connman_service_save(service); + } else + connman_network_set_string(network, "WiFi.Passphrase", + encrypted_value); + + DBG("encryption result: succeeded"); + +done: + dbus_message_unref(reply); + dbus_pending_call_unref(call); + dbus_connection_unref(encrypt_request_data.connection); + g_free(encrypted_value); + + encrypt_request_data.connection = NULL; + encrypt_request_data.network = NULL; +} + +static int send_encryption_request(const char *passphrase, + struct connman_network *network) +{ + DBusConnection *connection = NULL; + DBusMessage *msg = NULL; + DBusPendingCall *call; + + if (!passphrase) { + DBG("Invalid parameter"); + return -EINVAL; + } + + connection = connman_dbus_get_connection(); + if (!connection) { + DBG("dbus connection does not exist"); + return -EINVAL; + } + + msg = dbus_message_new_method_call(NETCONFIG_SERVICE, NETCONFIG_WIFI_PATH, + NETCONFIG_WIFI_INTERFACE, "EncryptPassphrase"); + if (!msg) { + dbus_connection_unref(connection); + return -EINVAL; + } + + dbus_message_append_args(msg, DBUS_TYPE_STRING, &passphrase, + DBUS_TYPE_INVALID); + + if (!dbus_connection_send_with_reply(connection, msg, + &call, DBUS_TIMEOUT_USE_DEFAULT)) { + dbus_message_unref(msg); + dbus_connection_unref(connection); + return -EIO; + } + + if (!call) { + dbus_message_unref(msg); + dbus_connection_unref(connection); + return -EIO; + } + + encrypt_request_data.connection = connection; + encrypt_request_data.network = network; + + dbus_pending_call_set_notify(call, encryption_request_reply, NULL, NULL); + dbus_message_unref(msg); + + return 0; +} +#endif + static int p2p_tech_probe(struct connman_technology *technology) { p2p_technology = technology; @@ -545,6 +680,11 @@ static void register_peer_service_cb(int result, struct wifi_data *wifi = g_supplicant_interface_get_data(iface); struct peer_service_registration *reg_data = user_data; +#if defined TIZEN_EXT + if (!wifi) + return; +#endif + DBG(""); if (result == 0) @@ -1069,6 +1209,15 @@ static int get_hidden_connections(GSupplicantScanParams *scan_data) continue; } +#if defined TIZEN_EXT + value = g_key_file_get_boolean(keyfile, + services[i], "AutoConnect", NULL); + if (!value) { + g_key_file_free(keyfile); + continue; + } +#endif + ssid = g_key_file_get_string(keyfile, services[i], "SSID", NULL); @@ -1208,8 +1357,11 @@ static int throw_wifi_scan(struct connman_device *device, if (wifi->tethering) return -EBUSY; - +#if defined TIZEN_EXT + if (connman_device_get_scanning(device) && !wifi->allow_full_scan) +#else if (connman_device_get_scanning(device)) +#endif return -EALREADY; connman_device_ref(device); @@ -1238,6 +1390,45 @@ static void hidden_free(struct hidden_params *hidden) g_free(hidden); } +#if defined TIZEN_EXT +static void service_state_changed(struct connman_service *service, + enum connman_service_state state); + +static int network_connect(struct connman_network *network); + +static struct connman_notifier notifier = { + .name = "wifi", + .priority = CONNMAN_NOTIFIER_PRIORITY_DEFAULT, + .service_state_changed = service_state_changed, +}; + +static void service_state_changed(struct connman_service *service, + enum connman_service_state state) +{ + enum connman_service_type type; + + type = connman_service_get_type(service); + if (type != CONNMAN_SERVICE_TYPE_WIFI) + return; + + DBG("service %p state %d", service, state); + + switch (state) { + case CONNMAN_SERVICE_STATE_READY: + case CONNMAN_SERVICE_STATE_ONLINE: + case CONNMAN_SERVICE_STATE_FAILURE: + connman_notifier_unregister(¬ifier); + is_wifi_notifier_registered = FALSE; + + __connman_device_request_scan(type); + break; + + default: + break; + } +} +#endif + static void scan_callback(int result, GSupplicantInterface *interface, void *user_data) { @@ -1283,14 +1474,31 @@ static void scan_callback(int result, GSupplicantInterface *interface, return scan_callback(ret, interface, user_data); } - scanning = connman_device_get_scanning(device); +#if defined TIZEN_EXT + if (wifi && wifi->allow_full_scan) { + int ret; + DBG("Trigger Full Channel Scan"); + wifi->allow_full_scan = FALSE; - if (scanning) { + ret = g_supplicant_interface_scan(wifi->interface, NULL, + scan_callback, device); + if (ret == 0) + return; + + /* On error, let's recall scan_callback, which will cleanup */ + return scan_callback(ret, interface, user_data); + } +#endif + + scanning = connman_device_get_scanning(device); + if (scanning) connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, false); - } if (result != -ENOLINK) +#if defined TIZEN_EXT + if (result != -EIO) +#endif start_autoscan(device); /* @@ -1302,6 +1510,23 @@ static void scan_callback(int result, GSupplicantInterface *interface, if (scanning) connman_device_unref(device); + +#if defined TIZEN_EXT + if (wifi && wifi->scan_pending_network && result != -EIO) { + network_connect(wifi->scan_pending_network); + wifi->scan_pending_network = NULL; + connman_network_set_connecting(wifi->network); + } + + if (is_wifi_notifier_registered != true && + wifi_first_scan == true && found_with_first_scan == true) { + wifi_first_scan = false; + found_with_first_scan = false; + + connman_notifier_register(¬ifier); + is_wifi_notifier_registered = true; + } +#endif } static void scan_callback_hidden(int result, @@ -1358,7 +1583,11 @@ static gboolean autoscan_timeout(gpointer data) } else interval = autoscan->interval * autoscan->base; +#if defined TIZEN_EXT + if (autoscan->interval >= autoscan->limit) +#else if (interval > autoscan->limit) +#endif interval = autoscan->limit; throw_wifi_scan(wifi->device, scan_callback_hidden); @@ -1552,6 +1781,15 @@ static int wifi_disable(struct connman_device *device) remove_networks(device, wifi); remove_peers(wifi); +#if defined TIZEN_EXT + wifi->scan_pending_network = NULL; + + if (is_wifi_notifier_registered == true) { + connman_notifier_unregister(¬ifier); + is_wifi_notifier_registered = false; + } +#endif + ret = g_supplicant_interface_remove(wifi->interface, NULL, NULL); if (ret < 0) return ret; @@ -1779,6 +2017,137 @@ static int p2p_find(struct connman_device *device) return ret; } +#if defined TIZEN_EXT +static void specific_scan_callback(int result, GSupplicantInterface *interface, + void *user_data) +{ + struct connman_device *device = user_data; + struct wifi_data *wifi = connman_device_get_data(device); + bool scanning; + + DBG("result %d wifi %p", result, wifi); + + if (wifi && wifi->scan_params) { + g_supplicant_free_scan_params(wifi->scan_params); + wifi->scan_params = NULL; + } + + scanning = connman_device_get_scanning(device); + if (scanning) { + connman_device_set_scanning(device, + CONNMAN_SERVICE_TYPE_WIFI, false); + connman_device_unref(device); + } +} + +static int wifi_specific_scan(enum connman_service_type type, + struct connman_device *device, int scan_type, + GSList *specific_scan_list, void *user_data) +{ + GSList *list = NULL; + char *ssid = NULL; + struct wifi_data *wifi = connman_device_get_data(device); + GSupplicantScanParams *scan_params = NULL; + struct scan_ssid *scan_ssid = NULL; + bool scanning; + int ret; + int freq; + int count = 0; + + if (!wifi) + return -ENODEV; + + if (wifi->p2p_device) + return 0; + + if (type == CONNMAN_SERVICE_TYPE_P2P) + return p2p_find(device); + + if (wifi->tethering) + return 0; + + scanning = connman_device_get_scanning(device); + if (scanning) + return -EALREADY; + + DBG("scan_type: %d", scan_type); + if (scan_type == 1) { /* ssid based scan */ + scan_params = g_try_malloc0(sizeof(GSupplicantScanParams)); + if (!scan_params) { + DBG("Failed to allocate memory."); + return -ENOMEM; + } + + for (list = specific_scan_list; list; list = list->next) { + ssid = (char *)list->data; + int ssid_len = strlen(ssid); + + scan_ssid = g_try_new0(struct scan_ssid, 1); + if (!scan_ssid) { + DBG("Failed to allocate memory."); + g_supplicant_free_scan_params(scan_params); + return -ENOMEM; + } + + memcpy(scan_ssid->ssid, ssid, (ssid_len + 1)); + DBG("scan ssid %s len: %d", scan_ssid->ssid, ssid_len); + scan_ssid->ssid_len = ssid_len; + scan_params->ssids = g_slist_prepend(scan_params->ssids, scan_ssid); + count++; + } + scan_params->num_ssids = count; + + } else if (scan_type == 2) { /* frequency based scan */ + + scan_params = g_try_malloc0(sizeof(GSupplicantScanParams)); + if (!scan_params) { + DBG("Failed to allocate memory."); + return -ENOMEM; + } + + guint num_freqs = g_slist_length(specific_scan_list); + DBG("num_freqs: %d", num_freqs); + + scan_params->freqs = g_try_new0(uint16_t, num_freqs); + if (!scan_params->freqs) { + DBG("Failed to allocate memory."); + g_free(scan_params); + return -ENOMEM; + } + + count = 0; + for (list = specific_scan_list; list; list = list->next) { + freq = (int)list->data; + + scan_params->freqs[count] = freq; + DBG("scan_params->freqs[%d]: %d", count, scan_params->freqs[count]); + count++; + } + scan_params->num_freqs = count; + + } else { + DBG("Invalid scan"); + return -EINVAL; + } + + reset_autoscan(device); + connman_device_ref(device); + + ret = g_supplicant_interface_scan(wifi->interface, scan_params, + specific_scan_callback, device); + + if (ret == 0) { + connman_device_set_scanning(device, + CONNMAN_SERVICE_TYPE_WIFI, true); + } else { + g_supplicant_free_scan_params(scan_params); + connman_device_unref(device); + } + + return ret; +} +#endif + /* * Note that the hidden scan is only used when connecting to this specific * hidden AP first time. It is not used when system autoconnects to hidden AP. @@ -1893,9 +2262,18 @@ static int wifi_scan(enum connman_service_type type, ret = g_supplicant_interface_scan(wifi->interface, scan_params, scan_callback, device); + if (ret == 0) { connman_device_set_scanning(device, CONNMAN_SERVICE_TYPE_WIFI, true); +#if defined TIZEN_EXT + /*To allow the Full Scan after ssid based scan, set the flag here + It is required because Tizen does not use the ConnMan specific + backgroung Scan feature.Tizen has added the BG Scan feature in + net-config. To sync with up ConnMan, we need to issue the Full Scan + after SSID specific scan.*/ + wifi->allow_full_scan = TRUE; +#endif } else { g_supplicant_free_scan_params(scan_params); connman_device_unref(device); @@ -1949,6 +2327,9 @@ static struct connman_device_driver wifi_ng_driver = { .disable = wifi_disable, .scan = wifi_scan, .set_regdom = wifi_set_regdom, +#if defined TIZEN_EXT + .specific_scan = wifi_specific_scan, +#endif }; static void system_ready(void) @@ -1988,15 +2369,42 @@ static void network_remove(struct connman_network *network) return; wifi->network = NULL; + +#if defined TIZEN_EXT + wifi->disconnecting = false; + + if (wifi->pending_network == network) + wifi->pending_network = NULL; + + if (wifi->scan_pending_network == network) + wifi->scan_pending_network = NULL; +#endif } static void connect_callback(int result, GSupplicantInterface *interface, void *user_data) { +#if defined TIZEN_EXT + GList *list; + struct wifi_data *wifi; +#endif struct connman_network *network = user_data; DBG("network %p result %d", network, result); +#if defined TIZEN_EXT + for (list = iface_list; list; list = list->next) { + wifi = list->data; + + if (wifi && wifi->network == network) + goto found; + } + + /* wifi_data may be invalid because wifi is already disabled */ + return; + +found: +#endif if (result == -ENOKEY) { connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY); @@ -2022,6 +2430,12 @@ static GSupplicantSecurity network_security(const char *security) return G_SUPPLICANT_SECURITY_PSK; else if (g_str_equal(security, "ieee8021x")) return G_SUPPLICANT_SECURITY_IEEE8021X; +#if defined TIZEN_EXT + else if (g_str_equal(security, "ft_psk") == TRUE) + return G_SUPPLICANT_SECURITY_FT_PSK; + else if (g_str_equal(security, "ft_ieee8021x") == TRUE) + return G_SUPPLICANT_SECURITY_FT_IEEE8021X; +#endif return G_SUPPLICANT_SECURITY_UNKNOWN; } @@ -2039,7 +2453,6 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network) ssid->security = network_security(security); ssid->passphrase = connman_network_get_string(network, "WiFi.Passphrase"); - ssid->eap = connman_network_get_string(network, "WiFi.EAP"); /* @@ -2083,6 +2496,13 @@ static void ssid_init(GSupplicantSSID *ssid, struct connman_network *network) ssid->use_wps = connman_network_get_bool(network, "WiFi.UseWPS"); ssid->pin_wps = connman_network_get_string(network, "WiFi.PinWPS"); +#if defined TIZEN_EXT + ssid->bssid = connman_network_get_bssid(network); +#endif +#if defined TIZEN_EXT + ssid->freq = connman_network_get_frequency(network); +#endif + if (connman_setting_get_bool("BackgroundScanning")) ssid->bgscan = BGSCAN_DEFAULT; } @@ -2117,6 +2537,9 @@ static int network_connect(struct connman_network *network) } else { wifi->network = connman_network_ref(network); wifi->retries = 0; +#if defined TIZEN_EXT + wifi->scan_pending_network = NULL; +#endif return g_supplicant_interface_connect(interface, ssid, connect_callback, network); @@ -2128,7 +2551,30 @@ static int network_connect(struct connman_network *network) static void disconnect_callback(int result, GSupplicantInterface *interface, void *user_data) { +#if defined TIZEN_EXT + GList *list; + struct wifi_data *wifi; + struct connman_network *network = user_data; + + DBG("network %p result %d", network, result); + + for (list = iface_list; list; list = list->next) { + wifi = list->data; + + if (wifi->network == NULL && wifi->disconnecting == true) + wifi->disconnecting = false; + + if (wifi->network == network) + goto found; + } + + /* wifi_data may be invalid because wifi is already disabled */ + return; + +found: +#else struct wifi_data *wifi = user_data; +#endif DBG("result %d supplicant interface %p wifi %p", result, interface, wifi); @@ -2159,6 +2605,9 @@ static int network_disconnect(struct connman_network *network) struct connman_device *device = connman_network_get_device(network); struct wifi_data *wifi; int err; +#if defined TIZEN_EXT + struct connman_service *service; +#endif DBG("network %p", network); @@ -2166,6 +2615,29 @@ static int network_disconnect(struct connman_network *network) if (!wifi || !wifi->interface) return -ENODEV; +#if defined TIZEN_EXT + if (connman_network_get_associating(network) == true) { + connman_network_clear_associating(network); + connman_network_set_bool(network, "WiFi.UseWPS", false); + } else { + service = connman_service_lookup_from_network(network); + + if (service != NULL && + (__connman_service_is_connected_state(service, + CONNMAN_IPCONFIG_TYPE_IPV4) == false && + __connman_service_is_connected_state(service, + CONNMAN_IPCONFIG_TYPE_IPV6) == false) && + (connman_service_get_favorite(service) == false)) + __connman_service_set_passphrase(service, NULL); + } + + if (wifi->pending_network == network) + wifi->pending_network = NULL; + + if (wifi->scan_pending_network == network) + wifi->scan_pending_network = NULL; + +#endif connman_network_set_associating(network, false); if (wifi->disconnecting) @@ -2173,8 +2645,14 @@ static int network_disconnect(struct connman_network *network) wifi->disconnecting = true; +#if defined TIZEN_EXT + err = g_supplicant_interface_disconnect(wifi->interface, + disconnect_callback, network); +#else err = g_supplicant_interface_disconnect(wifi->interface, disconnect_callback, wifi); +#endif + if (err < 0) wifi->disconnecting = false; @@ -2297,16 +2775,49 @@ static bool handle_wps_completion(GSupplicantInterface *interface, if (!wps_ssid || wps_ssid_len != ssid_len || memcmp(ssid, wps_ssid, ssid_len) != 0) { connman_network_set_associating(network, false); +#if defined TIZEN_EXT + g_supplicant_interface_disconnect(wifi->interface, + disconnect_callback, wifi->network); + + connman_network_set_bool(network, "WiFi.UseWPS", false); + connman_network_set_string(network, "WiFi.PinWPS", NULL); +#else g_supplicant_interface_disconnect(wifi->interface, disconnect_callback, wifi); +#endif return false; } wps_key = g_supplicant_interface_get_wps_key(interface); +#if defined TIZEN_EXT + /* Check the passphrase and encrypt it + */ + int ret; + gchar *passphrase = g_strdup(wps_key); + + connman_network_set_string(network, "WiFi.PinWPS", NULL); + + if (check_passphrase_ext(network, passphrase) < 0) { + DBG("[WPS] Invalid passphrase"); + g_free(passphrase); + return true; + } + + ret = send_encryption_request(passphrase, passphrase); + + g_free(passphrase); + + if (!ret) + DBG("[WPS] Encryption request succeeded"); + else + DBG("[WPS] Encryption request failed %d", ret); + +#else connman_network_set_string(network, "WiFi.Passphrase", wps_key); connman_network_set_string(network, "WiFi.PinWPS", NULL); +#endif } return true; @@ -2329,6 +2840,26 @@ static bool handle_4way_handshake_failure(GSupplicantInterface *interface, struct connman_network *network, struct wifi_data *wifi) { +#if defined TIZEN_EXT + const char *security; + struct connman_service *service; + + if (wifi->connected) + return false; + + security = connman_network_get_string(network, "WiFi.Security"); + + if (security && g_str_equal(security, "ieee8021x") == true && + wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) { + wifi->retries = 0; + connman_network_set_error(network, CONNMAN_NETWORK_ERROR_INVALID_KEY); + + return false; + } + + if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE) + return false; +#else struct connman_service *service; if (wifi->state != G_SUPPLICANT_STATE_4WAY_HANDSHAKE) @@ -2336,6 +2867,7 @@ static bool handle_4way_handshake_failure(GSupplicantInterface *interface, if (wifi->connected) return false; +#endif service = connman_service_lookup_from_network(network); if (!service) @@ -2354,6 +2886,47 @@ static bool handle_4way_handshake_failure(GSupplicantInterface *interface, return false; } +#if defined TIZEN_EXT +static bool handle_wifi_assoc_retry(struct connman_network *network, + struct wifi_data *wifi) +{ + const char *security; + + if (!wifi->network || wifi->connected || wifi->disconnecting || + connman_network_get_connecting(network) != true) { + wifi->assoc_retry_count = 0; + return false; + } + + if (wifi->state != G_SUPPLICANT_STATE_ASSOCIATING && + wifi->state != G_SUPPLICANT_STATE_ASSOCIATED) { + wifi->assoc_retry_count = 0; + return false; + } + + security = connman_network_get_string(network, "WiFi.Security"); + if (security && g_str_equal(security, "ieee8021x") == true && + wifi->state == G_SUPPLICANT_STATE_ASSOCIATED) { + wifi->assoc_retry_count = 0; + return false; + } + + if (++wifi->assoc_retry_count >= TIZEN_ASSOC_RETRY_COUNT) { + wifi->assoc_retry_count = 0; + + /* Honestly it's not an invalid-key error, + * however QA team recommends that the invalid-key error + * might be better to display for user experience. + */ + connman_network_set_error(network, CONNMAN_NETWORK_ERROR_ASSOCIATE_FAIL); + + return false; + } + + return true; +} +#endif + static void interface_state(GSupplicantInterface *interface) { struct connman_network *network; @@ -2401,7 +2974,11 @@ static void interface_state(GSupplicantInterface *interface) case G_SUPPLICANT_STATE_AUTHENTICATING: case G_SUPPLICANT_STATE_ASSOCIATING: +#if defined TIZEN_EXT + reset_autoscan(device); +#else stop_autoscan(device); +#endif if (!wifi->connected) connman_network_set_associating(network, true); @@ -2409,8 +2986,25 @@ static void interface_state(GSupplicantInterface *interface) break; case G_SUPPLICANT_STATE_COMPLETED: +#if defined TIZEN_EXT + /* though it should be already reset: */ + reset_autoscan(device); + + wifi->assoc_retry_count = 0; + + wifi->scan_pending_network = NULL; + + /* should be cleared scanning flag */ + bool scanning = connman_device_get_scanning(device); + if (scanning){ + connman_device_set_scanning(device, + CONNMAN_SERVICE_TYPE_WIFI, false); + connman_device_unref(device); + } +#else /* though it should be already stopped: */ stop_autoscan(device); +#endif if (!handle_wps_completion(interface, network, device, wifi)) break; @@ -2461,6 +3055,46 @@ static void interface_state(GSupplicantInterface *interface) default: break; } + +#if defined TIZEN_EXT + int err; + + err = g_supplicant_interface_remove_network(wifi->interface); + if (err < 0) + DBG("Failed to remove network(%d)", err); + + + /* Some of Wi-Fi networks are not comply Wi-Fi specification. + * Retry association until its retry count is expired */ + if (handle_wifi_assoc_retry(network, wifi) == true) { + throw_wifi_scan(wifi->device, scan_callback); + wifi->scan_pending_network = wifi->network; + break; + } + + if(wifi->disconnect_code > 0){ + DBG("Set disconnect reason code(%d)", wifi->disconnect_code); + connman_network_set_disconnect_reason(network, wifi->disconnect_code); + } + + /* To avoid unnecessary repeated association in wpa_supplicant, + * "RemoveNetwork" should be made when Wi-Fi is disconnected */ + if (wps != true && wifi->network && wifi->disconnecting == false) { + wifi->disconnecting = true; + err = g_supplicant_interface_disconnect(wifi->interface, + disconnect_callback, wifi->network); + if (err < 0) + wifi->disconnecting = false; + + connman_network_set_connected(network, false); + connman_network_set_associating(network, false); + + start_autoscan(device); + + break; + } +#endif + connman_network_set_connected(network, false); connman_network_set_associating(network, false); wifi->disconnecting = false; @@ -2470,6 +3104,10 @@ static void interface_state(GSupplicantInterface *interface) break; case G_SUPPLICANT_STATE_INACTIVE: +#if defined TIZEN_EXT + if (handle_wps_completion(interface, network, device, wifi) == false) + break; +#endif connman_network_set_associating(network, false); start_autoscan(device); @@ -2606,7 +3244,38 @@ static void scan_started(GSupplicantInterface *interface) static void scan_finished(GSupplicantInterface *interface) { +#if defined TIZEN_EXT + struct wifi_data *wifi; + bool is_associating = false; + static bool is_scanning = true; +#endif + DBG(""); + +#if defined TIZEN_EXT + wifi = g_supplicant_interface_get_data(interface); + if (wifi && wifi->scan_pending_network) { + network_connect(wifi->scan_pending_network); + wifi->scan_pending_network = NULL; + } + + //service state - associating + if(!wifi || !wifi->network) + return; + + is_associating = connman_network_get_associating(wifi->network); + if(is_associating && is_scanning){ + is_scanning = false; + DBG("send scan for connecting"); + throw_wifi_scan(wifi->device, scan_callback); + + return; + } + is_scanning = true; + + //go scan + +#endif } static void ap_create_fail(GSupplicantInterface *interface) @@ -2644,9 +3313,11 @@ static unsigned char calculate_strength(GSupplicantNetwork *supplicant_network) unsigned char strength; strength = 120 + g_supplicant_network_get_signal(supplicant_network); + +#if !defined TIZEN_EXT if (strength > 100) strength = 100; - +#endif return strength; } @@ -2663,6 +3334,11 @@ static void network_added(GSupplicantNetwork *supplicant_network) bool wps_ready; bool wps_advertizing; +#if defined TIZEN_EXT + const char *wifi_vsie; + unsigned int wifi_vsie_len; +#endif + mode = g_supplicant_network_get_mode(supplicant_network); identifier = g_supplicant_network_get_identifier(supplicant_network); @@ -2687,6 +3363,9 @@ static void network_added(GSupplicantNetwork *supplicant_network) ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len); +#if defined TIZEN_EXT + wifi_vsie = g_supplicant_network_get_wifi_vsie(supplicant_network, &wifi_vsie_len); +#endif network = connman_device_get_network(wifi->device, identifier); if (!network) { @@ -2710,6 +3389,11 @@ static void network_added(GSupplicantNetwork *supplicant_network) connman_network_set_blob(network, "WiFi.SSID", ssid, ssid_len); +#if defined TIZEN_EXT + if(wifi_vsie_len > 0 && wifi_vsie) + connman_network_set_blob(network, "WiFi.Vsie", + wifi_vsie, wifi_vsie_len); +#endif connman_network_set_string(network, "WiFi.Security", security); connman_network_set_strength(network, calculate_strength(supplicant_network)); @@ -2719,21 +3403,53 @@ static void network_added(GSupplicantNetwork *supplicant_network) /* Is AP advertizing for WPS association? * If so, we decide to use WPS by default */ if (wps_ready && wps_pbc && - wps_advertizing) + wps_advertizing) { +#if !defined TIZEN_EXT connman_network_set_bool(network, "WiFi.UseWPS", true); +#else + DBG("wps is activating by ap but ignore it."); +#endif + } } connman_network_set_frequency(network, g_supplicant_network_get_frequency(supplicant_network)); - +#if defined TIZEN_EXT + 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)); + connman_network_set_rsn_mode(network, + g_supplicant_network_get_rsn_mode(supplicant_network)); + connman_network_set_keymgmt(network, + g_supplicant_network_get_keymgmt(supplicant_network)); + connman_network_set_bool(network, "WiFi.HS20AP", + g_supplicant_network_is_hs20AP(supplicant_network)); +#endif connman_network_set_available(network, true); connman_network_set_string(network, "WiFi.Mode", mode); +#if defined TIZEN_EXT + if (group) +#else if (ssid) +#endif connman_network_set_group(network, group); +#if defined TIZEN_EXT + if (wifi_first_scan == true) + found_with_first_scan = true; +#endif + if (wifi->hidden && ssid) { +#if defined TIZEN_EXT + if (network_security(wifi->hidden->security) == + network_security(security) && +#else if (!g_strcmp0(wifi->hidden->security, security) && +#endif wifi->hidden->ssid_len == ssid_len && !memcmp(wifi->hidden->ssid, ssid, ssid_len)) { connman_network_connect_hidden(network, @@ -2768,6 +3484,18 @@ static void network_removed(GSupplicantNetwork *network) if (!connman_network) return; +#if defined TIZEN_EXT + if (connman_network == wifi->scan_pending_network) + wifi->scan_pending_network = NULL; + + if (connman_network == wifi->pending_network) + wifi->pending_network = NULL; + + if(connman_network_get_connecting(connman_network) == true){ + connman_network_set_connected(connman_network, false); + } +#endif + wifi->networks = g_slist_remove(wifi->networks, connman_network); connman_device_remove_network(wifi->device, connman_network); @@ -2781,6 +3509,13 @@ 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; + bool wps; +#endif + interface = g_supplicant_network_get_interface(network); wifi = g_supplicant_interface_get_data(interface); identifier = g_supplicant_network_get_identifier(network); @@ -2800,6 +3535,18 @@ 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); + wps = g_supplicant_network_get_wps(network); + + connman_network_set_bssid(connman_network, bssid); + connman_network_set_maxrate(connman_network, maxrate); + connman_network_set_frequency(connman_network, frequency); + connman_network_set_bool(connman_network, "WiFi.WPS", wps); +#endif } static void network_associated(GSupplicantNetwork *network) @@ -2870,6 +3617,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); @@ -2877,7 +3635,10 @@ static void peer_found(GSupplicantPeer *peer) struct connman_peer *connman_peer; const char *identifier, *name; int ret; - +#if defined TIZEN_EXT + if (!wifi) + return; +#endif identifier = g_supplicant_peer_get_identifier(peer); name = g_supplicant_peer_get_name(peer); @@ -2934,6 +3695,11 @@ static void peer_changed(GSupplicantPeer *peer, GSupplicantPeerState state) struct connman_peer *connman_peer; const char *identifier; +#if defined TIZEN_EXT + if (!wifi) + return; +#endif + identifier = g_supplicant_peer_get_identifier(peer); DBG("ident: %s", identifier); @@ -3023,6 +3789,11 @@ static void peer_request(GSupplicantPeer *peer) struct connman_peer *connman_peer; const char *identifier; +#if defined TIZEN_EXT + if (!wifi) + return; +#endif + identifier = g_supplicant_peer_get_identifier(peer); DBG("ident: %s", identifier); @@ -3034,6 +3805,100 @@ static void peer_request(GSupplicantPeer *peer) connman_peer_request_connection(connman_peer); } +#if defined TIZEN_EXT +static void system_power_off(void) +{ + GList *list; + struct wifi_data *wifi; + struct connman_service *service; + struct connman_ipconfig *ipconfig_ipv4; + + if (connman_setting_get_bool("WiFiDHCPRelease") == true) { + for (list = iface_list; list; list = list->next) { + wifi = list->data; + + if (wifi->network != NULL) { + service = connman_service_lookup_from_network(wifi->network); + ipconfig_ipv4 = __connman_service_get_ip4config(service); + __connman_dhcp_stop(ipconfig_ipv4); + } + } + } +} + +static void network_merged(GSupplicantNetwork *network) +{ + GSupplicantInterface *interface; + GSupplicantState state; + struct wifi_data *wifi; + const char *identifier; + struct connman_network *connman_network; + bool ishs20AP = 0; + char *temp = NULL; + + interface = g_supplicant_network_get_interface(network); + if (!interface) + return; + + state = g_supplicant_interface_get_state(interface); + if (state < G_SUPPLICANT_STATE_AUTHENTICATING) + return; + + wifi = g_supplicant_interface_get_data(interface); + if (!wifi) + return; + + identifier = g_supplicant_network_get_identifier(network); + + connman_network = connman_device_get_network(wifi->device, identifier); + if (!connman_network) + return; + + DBG("merged identifier %s", identifier); + + if (wifi->connected == FALSE) { + switch (state) { + case G_SUPPLICANT_STATE_AUTHENTICATING: + case G_SUPPLICANT_STATE_ASSOCIATING: + case G_SUPPLICANT_STATE_ASSOCIATED: + case G_SUPPLICANT_STATE_4WAY_HANDSHAKE: + case G_SUPPLICANT_STATE_GROUP_HANDSHAKE: + connman_network_set_associating(connman_network, TRUE); + break; + case G_SUPPLICANT_STATE_COMPLETED: + connman_network_set_connected(connman_network, TRUE); + break; + default: + DBG("Not handled the state : %d", state); + break; + } + } + + ishs20AP = g_supplicant_network_is_hs20AP(network); + + if (ishs20AP && + g_strcmp0(g_supplicant_network_get_security(network), "ieee8021x") == 0) { + temp = g_ascii_strdown(g_supplicant_network_get_eap(network), -1); + connman_network_set_string(connman_network, "WiFi.EAP", + temp); + connman_network_set_string(connman_network, "WiFi.Identity", + g_supplicant_network_get_identity(network)); + connman_network_set_string(connman_network, "WiFi.Phase2", + g_supplicant_network_get_phase2(network)); + + g_free(temp); + } + + wifi->network = connman_network; +} + +static void assoc_failed(void *user_data) +{ + struct connman_network *network = user_data; + connman_network_set_associating(network, false); +} +#endif + static void debug(const char *str) { if (getenv("CONNMAN_SUPPLICANT_DEBUG")) @@ -3073,10 +3938,17 @@ static const GSupplicantCallbacks callbacks = { .network_removed = network_removed, .network_changed = network_changed, .network_associated = network_associated, + .add_station = add_station, + .remove_station = remove_station, .peer_found = peer_found, .peer_lost = peer_lost, .peer_changed = peer_changed, .peer_request = peer_request, +#if defined TIZEN_EXT + .system_power_off = system_power_off, + .network_merged = network_merged, + .assoc_failed = assoc_failed, +#endif .debug = debug, .disconnect_reasoncode = disconnect_reasoncode, .assoc_status_code = assoc_status_code, @@ -3095,7 +3967,8 @@ static void tech_remove(struct connman_technology *technology) wifi_technology = NULL; } -static GSupplicantSSID *ssid_ap_init(const char *ssid, const char *passphrase) +static GSupplicantSSID *ssid_ap_init(const char *ssid, + const char *passphrase) { GSupplicantSSID *ap; @@ -3193,7 +4066,7 @@ static void sta_remove_callback(int result, DBG("ifname %s result %d ", info->ifname, result); - if ((result < 0) || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) { + if (result < 0 || (info->wifi->ap_supported != WIFI_AP_SUPPORTED)) { info->wifi->tethering = false; connman_technology_tethering_notify(info->technology, false); @@ -3239,10 +4112,11 @@ static int enable_wifi_tethering(struct connman_technology *technology, if (!interface) continue; - ifname = g_supplicant_interface_get_ifname(wifi->interface); - if (!ifname) + if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) continue; + ifname = g_supplicant_interface_get_ifname(wifi->interface); + if (wifi->ap_supported == WIFI_AP_NOT_SUPPORTED) { DBG("%s does not support AP mode (detected)", ifname); continue; @@ -3276,6 +4150,8 @@ static int enable_wifi_tethering(struct connman_technology *technology, goto failed; info->ifname = g_strdup(ifname); + if (!info->ifname) + goto failed; wifi->tethering_param->technology = technology; wifi->tethering_param->ssid = ssid_ap_init(identifier, passphrase); diff --git a/resources/usr/share/dbus-1/system-services/net.connman.service b/resources/usr/share/dbus-1/system-services/net.connman.service new file mode 100644 index 00000000..990eb66b --- /dev/null +++ b/resources/usr/share/dbus-1/system-services/net.connman.service @@ -0,0 +1,6 @@ +[D-BUS Service] +Name=net.connman +Exec=/bin/false +User=network_fw +Group=network_fw +SystemdService=connman.service diff --git a/resources/var/lib/connman/settings b/resources/var/lib/connman/settings new file mode 100644 index 00000000..ba476b5d --- /dev/null +++ b/resources/var/lib/connman/settings @@ -0,0 +1,15 @@ + +[global] +OfflineMode=false + +[WiFi] +Enable=false + +[Bluetooth] +Enable=true + +[Wired] +Enable=true + +[Cellular] +Enable=true diff --git a/scripts/500.connman_upgrade.sh b/scripts/500.connman_upgrade.sh new file mode 100644 index 00000000..a21336e2 --- /dev/null +++ b/scripts/500.connman_upgrade.sh @@ -0,0 +1,9 @@ +#!/bin/sh +PATH=/bin:/usr/bin:/sbin:/usr/sbin + +#------------------------------------------------------------# +# connman patch script for upgrade (3.0 -> the latest tizen) # +#------------------------------------------------------------# + +chmod 755 /var/lib/connman +chown -R network_fw:network_fw /var/lib/connman diff --git a/scripts/connman.in b/scripts/connman.in index 0b9f63c5..f3d438f3 100644..100755 --- a/scripts/connman.in +++ b/scripts/connman.in @@ -1,6 +1,6 @@ #!/bin/sh -DAEMON=@sbindir@/connmand +DAEMON=@bindir@/connmand DESC="Connection Manager" . /lib/lsb/init-functions diff --git a/scripts/connman_resolvconf.conf.in b/scripts/connman_resolvconf.conf.in deleted file mode 100644 index 2d61dfe1..00000000 --- a/scripts/connman_resolvconf.conf.in +++ /dev/null @@ -1,2 +0,0 @@ -d @runstatedir@/connman - - - - -L+ /etc/resolv.conf - - - - @runstatedir@/connman/resolv.conf diff --git a/scripts/ipsec-script.c b/scripts/ipsec-script.c new file mode 100755 index 00000000..6ba0d292 --- /dev/null +++ b/scripts/ipsec-script.c @@ -0,0 +1,146 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2010,2012-2014 BMW Car IT GmbH. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> +#include <libgen.h> + +#include <dbus/dbus.h> + +extern char **environ; + +static void print(const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vsyslog(LOG_INFO, format, ap); + va_end(ap); +} + +static void append(DBusMessageIter *dict, const char *pattern) +{ + DBusMessageIter entry; + const char *key, *value; + char *delim; + + delim = strchr(pattern, '='); + *delim = '\0'; + + key = pattern; + value = delim + 1; + + dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY, + NULL, &entry); + + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key); + + dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &value); + + dbus_message_iter_close_container(dict, &entry); +} + +int main(int argc, char *argv[]) +{ + DBusConnection *conn; + DBusError error; + DBusMessage *msg; + DBusMessageIter iter, dict; + char **envp, *busname, *interface, *path, *reason; + int ret = 0; + + openlog(basename(argv[0]), LOG_NDELAY | LOG_PID, LOG_DAEMON); + + busname = getenv("CONNMAN_BUSNAME"); + interface = getenv("CONNMAN_INTERFACE"); + path = getenv("CONNMAN_PATH"); + + reason = getenv("script_type"); + + if (!busname || !interface || !path || !reason) { + print("Required environment variables not set; " + "bus=%s iface=%s path=%s reason=%s", + busname, interface, path, reason); + ret = 1; + goto out; + } + dbus_error_init(&error); + + conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + if (!conn) { + if (dbus_error_is_set(&error)) { + print("%s", error.message); + dbus_error_free(&error); + } else + print("Failed to get on system bus"); + + goto out; + } + + msg = dbus_message_new_method_call(busname, path, + interface, "notify"); + if (!msg) { + dbus_connection_unref(conn); + print("Failed to allocate method call"); + goto out; + } + + dbus_message_set_no_reply(msg, TRUE); + + dbus_message_append_args(msg, + DBUS_TYPE_STRING, &reason, + DBUS_TYPE_INVALID); + + dbus_message_iter_init_append(msg, &iter); + + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); + + for (envp = environ; envp && *envp; envp++) + append(&dict, *envp); + + dbus_message_iter_close_container(&iter, &dict); + + if (!dbus_connection_send(conn, msg, NULL)) { + print("Failed to send message"); + goto out; + } + + dbus_connection_flush(conn); + + dbus_message_unref(msg); + + dbus_connection_unref(conn); + +out: + closelog(); + + return ret; +} diff --git a/scripts/libppp-plugin.c b/scripts/libppp-plugin.c index 0dd8b471..0dd8b471 100644..100755 --- a/scripts/libppp-plugin.c +++ b/scripts/libppp-plugin.c diff --git a/scripts/openconnect-script.c b/scripts/openconnect-script.c index 5e04144f..5e04144f 100644..100755 --- a/scripts/openconnect-script.c +++ b/scripts/openconnect-script.c diff --git a/scripts/openvpn-script.c b/scripts/openvpn-script.c index 6ba0d292..6ba0d292 100644..100755 --- a/scripts/openvpn-script.c +++ b/scripts/openvpn-script.c diff --git a/src/6to4.c b/src/6to4.c index 71a28827..71a28827 100644..100755 --- a/src/6to4.c +++ b/src/6to4.c diff --git a/src/agent-connman.c b/src/agent-connman.c index fca7cc1f..e4850a8f 100644..100755 --- a/src/agent-connman.c +++ b/src/agent-connman.c @@ -253,6 +253,9 @@ static void request_input_append_passphrase(DBusMessageIter *iter, value = "wep"; break; case CONNMAN_SERVICE_SECURITY_PSK: +#if defined TIZEN_EXT + case CONNMAN_SERVICE_SECURITY_RSN: +#endif value = "psk"; break; case CONNMAN_SERVICE_SECURITY_8021X: @@ -386,6 +389,9 @@ static void previous_passphrase_handler(DBusMessageIter *iter, data.type = "wep"; break; case CONNMAN_SERVICE_SECURITY_PSK: +#if defined TIZEN_EXT + case CONNMAN_SERVICE_SECURITY_RSN: +#endif data.type = "psk"; break; /* diff --git a/src/agent.c b/src/agent.c index 8f7b19ba..8f7b19ba 100644..100755 --- a/src/agent.c +++ b/src/agent.c diff --git a/src/backtrace.c b/src/backtrace.c deleted file mode 100644 index 6a66c0ac..00000000 --- a/src/backtrace.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * - * Connection Manager - * - * Copyright (C) 2007-2013 Intel Corporation. All rights reserved. - * Copyright (C) 2016 Yann E. MORIN <yann.morin.1998@free.fr>. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#define _GNU_SOURCE -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <string.h> -#include <execinfo.h> -#include <dlfcn.h> - -#include "connman.h" - -void print_backtrace(const char* program_path, const char* program_exec, - unsigned int offset) -{ - void *frames[99]; - size_t n_ptrs; - unsigned int i; - int outfd[2], infd[2]; - int pathlen; - pid_t pid; - - if (!program_exec) - return; - - pathlen = strlen(program_path); - - n_ptrs = backtrace(frames, G_N_ELEMENTS(frames)); - if (n_ptrs < offset) - return; - - if (pipe(outfd) < 0) - return; - - if (pipe(infd) < 0) { - close(outfd[0]); - close(outfd[1]); - return; - } - - pid = fork(); - if (pid < 0) { - close(outfd[0]); - close(outfd[1]); - close(infd[0]); - close(infd[1]); - return; - } - - if (pid == 0) { - close(outfd[1]); - close(infd[0]); - - dup2(outfd[0], STDIN_FILENO); - dup2(infd[1], STDOUT_FILENO); - - execlp("addr2line", "-C", "-f", "-e", program_exec, NULL); - - exit(EXIT_FAILURE); - } - - close(outfd[0]); - close(infd[1]); - - connman_error("++++++++ backtrace ++++++++"); - - for (i = offset; i < n_ptrs - 1; i++) { - Dl_info info; - char addr[20], buf[PATH_MAX * 2]; - int len, written; - char *ptr, *pos; - - dladdr(frames[i], &info); - - len = snprintf(addr, sizeof(addr), "%p\n", frames[i]); - if (len < 0) - break; - - written = write(outfd[1], addr, len); - if (written < 0) - break; - - len = read(infd[0], buf, sizeof(buf) - 1); - if (len < 0) - break; - - buf[len] = '\0'; - - pos = strchr(buf, '\n'); - *pos++ = '\0'; - - if (strcmp(buf, "??") == 0) { - connman_error("#%-2u %p in %s", i - offset, - frames[i], info.dli_fname); - continue; - } - - ptr = strchr(pos, '\n'); - *ptr++ = '\0'; - - if (strncmp(pos, program_path, pathlen) == 0) - pos += pathlen + 1; - - connman_error("#%-2u %p in %s() at %s", i - offset, - frames[i], buf, pos); - } - - connman_error("+++++++++++++++++++++++++++"); - - kill(pid, SIGTERM); - - close(outfd[1]); - close(infd[0]); -} diff --git a/src/bridge.c b/src/bridge.c index cd2d9cee..cd2d9cee 100644..100755 --- a/src/bridge.c +++ b/src/bridge.c diff --git a/src/clock.c b/src/clock.c index 0fde2c34..f04cf175 100644..100755 --- a/src/clock.c +++ b/src/clock.c @@ -241,6 +241,11 @@ static DBusMessage *set_property(DBusConnection *conn, type = dbus_message_iter_get_arg_type(&value); if (g_str_equal(name, "Time")) { +#if defined TIZEN_EXT + /* Tizen updates time (ntp) by system service */ + + return __connman_error_permission_denied(msg); +#else struct timeval tv; dbus_uint64_t newval; @@ -261,6 +266,7 @@ static DBusMessage *set_property(DBusConnection *conn, connman_dbus_property_changed_basic(CONNMAN_MANAGER_PATH, CONNMAN_CLOCK_INTERFACE, "Time", DBUS_TYPE_UINT64, &newval); +#endif } else if (g_str_equal(name, "TimeUpdates")) { const char *strval; enum time_updates newval; diff --git a/src/config.c b/src/config.c index a8c3da89..75cd717f 100644..100755 --- a/src/config.c +++ b/src/config.c @@ -740,6 +740,9 @@ static bool load_service(GKeyFile *keyfile, const char *group, if (str) { if (security == CONNMAN_SERVICE_SECURITY_PSK || +#if defined TIZEN_EXT + security == CONNMAN_SERVICE_SECURITY_RSN || +#endif security == CONNMAN_SERVICE_SECURITY_WEP) { service->security = security; } else { @@ -755,14 +758,14 @@ static bool load_service(GKeyFile *keyfile, const char *group, service->security = CONNMAN_SERVICE_SECURITY_PSK; } else if (str) { - if (security != CONNMAN_SERVICE_SECURITY_NONE) + if (security != CONNMAN_SERVICE_SECURITY_NONE) { connman_info("Mismatch no security and " "setting %s = %s", SERVICE_KEY_SECURITY, str); - - service->security = CONNMAN_SERVICE_SECURITY_NONE; + } + service->security = CONNMAN_SERVICE_SECURITY_NONE; } else - service->security = CONNMAN_SERVICE_SECURITY_NONE; + service->security = CONNMAN_SERVICE_SECURITY_NONE; g_free(str); @@ -1154,6 +1157,10 @@ static void provision_service_wifi(struct connman_config_service *config, if (config->phase2) __connman_service_set_string(service, "Phase2", config->phase2); +#if defined TIZEN_EXT + else + __connman_service_set_string(service, "Phase2", NULL); +#endif if (config->passphrase) __connman_service_set_string(service, "Passphrase", @@ -1181,6 +1188,20 @@ static gboolean remove_virtual_config(gpointer user_data) return FALSE; } +#if defined TIZEN_EXT +static bool __check_address_type(int address_family, const char *address) +{ + unsigned char buf[sizeof(struct in6_addr)] = {0, }; + int err = 0; + + err = inet_pton(address_family, address, buf); + if(err > 0) + return TRUE; + + return FALSE; +} +#endif + static int try_provision_service(struct connman_config_service *config, struct connman_service *service) { @@ -1189,7 +1210,6 @@ static int try_provision_service(struct connman_config_service *config, enum connman_service_type type; const void *ssid; unsigned int ssid_len; - const char *str; network = __connman_service_get_network(service); if (!network) { @@ -1220,10 +1240,6 @@ static int try_provision_service(struct connman_config_service *config, if (memcmp(config->ssid, ssid, ssid_len)) return -ENOENT; - str = connman_network_get_string(network, "WiFi.Security"); - if (config->security != __connman_service_string2security(str)) - return -ENOENT; - break; case CONNMAN_SERVICE_TYPE_ETHERNET: @@ -1368,8 +1384,19 @@ static int try_provision_service(struct connman_config_service *config, __connman_service_nameserver_clear(service); for (i = 0; config->nameservers[i]; i++) { +#if defined TIZEN_EXT + if (__check_address_type(AF_INET, config->nameservers[i])) + __connman_service_nameserver_append(service, + config->nameservers[i], false, + CONNMAN_IPCONFIG_TYPE_IPV4); + else if (__check_address_type(AF_INET6, config->nameservers[i])) + __connman_service_nameserver_append(service, + config->nameservers[i], false, + CONNMAN_IPCONFIG_TYPE_IPV6); +#else __connman_service_nameserver_append(service, config->nameservers[i], false); +#endif } } @@ -1465,6 +1492,13 @@ int __connman_config_provision_service(struct connman_service *service) type != CONNMAN_SERVICE_TYPE_GADGET) return -ENOSYS; +#if defined TIZEN_EXT + if(type == CONNMAN_SERVICE_TYPE_WIFI && + __connman_service_get_security(service) == + CONNMAN_SERVICE_SECURITY_NONE) + return -ENOSYS; +#endif + return find_and_provision_service(service); } diff --git a/src/connection.c b/src/connection.c index 6b005e7f..64d48b7d 100644..100755 --- a/src/connection.c +++ b/src/connection.c @@ -657,8 +657,15 @@ static void connection_newgateway(int index, const char *gateway) } if (!found) { +#if defined TIZEN_EXT + if (data->ipv4_gateway != NULL){ + set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4); + connman_check_proxy_setup_and_wispr_start(data->service); + } +#else if (data->ipv4_gateway) set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV4); +#endif if (data->ipv6_gateway) set_default_gateway(data, CONNMAN_IPCONFIG_TYPE_IPV6); @@ -786,6 +793,32 @@ static void add_host_route(int family, int index, const char *gateway, } } +#if defined TIZEN_EXT +static bool __connman_service_is_not_cellular_internet_profile( + struct connman_service *cellular) +{ + char *suffix; + const char *path; + const char internet_suffix[] = "_1"; + const char prepaid_internet_suffix[] = "_3"; + + if (connman_service_get_type(cellular) != CONNMAN_SERVICE_TYPE_CELLULAR) + return FALSE; + + path = __connman_service_get_path(cellular); + + suffix = strrchr(path, '_'); + + if (g_strcmp0(suffix, internet_suffix) != 0 && + g_strcmp0(suffix, prepaid_internet_suffix) != 0) { + DBG("not internet service profile: %s", path); + return TRUE; + } + + return FALSE; +} +#endif + int __connman_connection_gateway_add(struct connman_service *service, const char *gateway, enum connman_ipconfig_type type, @@ -812,6 +845,28 @@ int __connman_connection_gateway_add(struct connman_service *service, if (!gateway && type == CONNMAN_IPCONFIG_TYPE_IPV6) gateway = "::"; +#if defined TIZEN_EXT + if (__connman_service_is_not_cellular_internet_profile(service) == TRUE) { + /* not internet service should not be default gateway */ + + DBG("no internet service %p index %d gateway %s vpn ip %s type %d", + service, index, gateway, peer, type); + + if (type == CONNMAN_IPCONFIG_TYPE_IPV4) { + add_host_route(AF_INET, index, gateway, service_type); + __connman_service_nameserver_add_routes(service, gateway); + type4 = CONNMAN_IPCONFIG_TYPE_IPV4; + } + + if (type == CONNMAN_IPCONFIG_TYPE_IPV6) { + add_host_route(AF_INET6, index, gateway, service_type); + __connman_service_nameserver_add_routes(service, gateway); + type6 = CONNMAN_IPCONFIG_TYPE_IPV6; + } + + goto done; + } +#endif DBG("service %p index %d gateway %s vpn ip %s type %d", service, index, gateway, peer, type); @@ -856,6 +911,12 @@ int __connman_connection_gateway_add(struct connman_service *service, } if (!active_gateway) { +#if defined TIZEN_EXT + if(new_gateway->ipv4_gateway) + DBG("ConnMan, Set default gateway[%s], active[%d]", + new_gateway->ipv4_gateway->gateway, + new_gateway->ipv4_gateway->active); +#endif set_default_gateway(new_gateway, type); goto done; } @@ -971,6 +1032,9 @@ bool __connman_connection_update_gateway(void) bool updated = false; GHashTableIter iter; gpointer value, key; +#if defined TIZEN_EXT + static struct gateway_data *old_default = NULL; +#endif if (!gateway_hash) return updated; @@ -1008,6 +1072,12 @@ bool __connman_connection_update_gateway(void) } } +#if defined TIZEN_EXT + if (updated == false && old_default != default_gateway) { + updated = true; + old_default = default_gateway; + } +#endif if (updated && default_gateway) { if (default_gateway->ipv4_gateway) set_default_gateway(default_gateway, diff --git a/src/connman-dbus.conf b/src/connman-dbus.conf index 98a773ea..29106dc7 100644..100755 --- a/src/connman-dbus.conf +++ b/src/connman-dbus.conf @@ -6,6 +6,19 @@ <allow send_destination="net.connman"/> <allow send_interface="net.connman.Agent"/> <allow send_interface="net.connman.Counter"/> + <allow send_interface="net.connman.Manager"/> + <allow send_interface="net.connman.Service"/> + <allow send_interface="net.connman.Technology"/> + <allow send_interface="net.connman.Notification"/> + </policy> + <policy user="network_fw"> + <allow own="net.connman"/> + <allow send_destination="net.connman"/> + <allow send_interface="net.connman.Agent"/> + <allow send_interface="net.connman.Counter"/> + <allow send_interface="net.connman.Manager"/> + <allow send_interface="net.connman.Service"/> + <allow send_interface="net.connman.Technology"/> <allow send_interface="net.connman.Notification"/> </policy> <policy at_console="true"> diff --git a/src/connman-polkit.conf b/src/connman-polkit.conf index b13d339b..03154faf 100644..100755 --- a/src/connman-polkit.conf +++ b/src/connman-polkit.conf @@ -7,6 +7,12 @@ <allow send_interface="net.connman.Counter"/> <allow send_interface="net.connman.Notification"/> </policy> + <policy user="network_fw"> + <allow own="net.connman"/> + <allow send_interface="net.connman.Agent"/> + <allow send_interface="net.connman.Counter"/> + <allow send_interface="net.connman.Notification"/> + </policy> <policy context="default"> <allow send_destination="net.connman"/> </policy> diff --git a/src/connman-wait-online.service.in b/src/connman-wait-online.service.in deleted file mode 100644 index c2ad5cc9..00000000 --- a/src/connman-wait-online.service.in +++ /dev/null @@ -1,15 +0,0 @@ -[Unit] -Description=Wait for network to be configured by ConnMan -Requisite=connman.service -After=connman.service -Before=network-online.target -DefaultDependencies=no -Conflicts=shutdown.target - -[Service] -Type=oneshot -ExecStart=@sbindir@/connmand-wait-online -RemainAfterExit=yes - -[Install] -WantedBy=network-online.target diff --git a/src/connman.conf b/src/connman.conf new file mode 100644 index 00000000..6c6d23b6 --- /dev/null +++ b/src/connman.conf @@ -0,0 +1,30 @@ +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> +<busconfig> + <policy user="root"> + <allow own="net.connman"/> + <allow send_destination="net.connman"/> + </policy> + <policy user="network_fw"> + <allow own="net.connman"/> + <allow send_destination="net.connman"/> + </policy> + <policy context="default"> + <deny own="net.connman"/> + <deny send_destination="net.connman"/> + <allow send_destination="net.connman" send_type="signal"/> + <allow send_destination="net.connman" send_interface="net.connman.Technology" send_member="GetScanState" /> + + <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetTechnologies" privilege="http://tizen.org/privilege/network.get" /> + <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetProperties" privilege="http://tizen.org/privilege/network.get" /> + <check send_destination="net.connman" send_interface="net.connman.Manager" send_member="GetServices" privilege="http://tizen.org/privilege/network.get" /> + <check send_destination="net.connman" send_interface="net.connman.Service" send_member="Connect" privilege="http://tizen.org/privilege/network.set" /> + <check send_destination="net.connman" send_interface="net.connman.Service" send_member="Disconnect" privilege="http://tizen.org/privilege/network.set" /> + <check send_destination="net.connman" send_interface="net.connman.Service" send_member="SetProperty" privilege="http://tizen.org/privilege/network.profile" /> + <check send_destination="net.connman" send_interface="net.connman.Service" send_member="GetProperties" privilege="http://tizen.org/privilege/network.get" /> + <check send_destination="net.connman" send_interface="net.connman.Service" send_member="Remove" privilege="http://tizen.org/privilege/network.profile" /> + <check send_destination="net.connman" send_interface="net.connman.Service" send_member="PropertyChanged" privilege="http://tizen.org/privilege/network.get" /> + <check send_destination="net.connman" send_interface="net.connman.Technology" send_member="Scan" privilege="http://tizen.org/privilege/network.set" /> + <check send_destination="net.connman" send_interface="net.connman.Technology" send_member="SpecificScan" privilege="http://tizen.org/privilege/network.set" /> + </policy> +</busconfig> diff --git a/src/connman.h b/src/connman.h index 21b70802..4125463b 100644..100755 --- a/src/connman.h +++ b/src/connman.h @@ -125,7 +125,6 @@ int __connman_agent_request_peer_authorization(struct connman_peer *peer, bool wps_requested, const char *dbus_sender, void *user_data); - #include <connman/log.h> int __connman_log_init(const char *program, const char *debug, @@ -135,8 +134,6 @@ void __connman_log_cleanup(gboolean backtrace); void __connman_log_enable(struct connman_debug_desc *start, struct connman_debug_desc *stop); -#include <connman/backtrace.h> - #include <connman/option.h> #include <connman/setting.h> @@ -172,6 +169,9 @@ int __connman_inet_ipv6_send_rs(int index, int timeout, __connman_inet_rs_cb_t callback, void *user_data); int __connman_inet_ipv6_send_ra(int index, struct in6_addr *src_addr, GSList *prefixes, int router_lifetime); +#if defined TIZEN_EXT +void __connman_network_set_auto_ipv6_gateway(char *gateway, void *user_data); +#endif typedef void (*__connman_inet_ns_cb_t) (struct nd_neighbor_advert *reply, unsigned int length, @@ -371,6 +371,11 @@ const char *__connman_ipconfig_get_broadcast(struct connman_ipconfig *ipconfig); void __connman_ipconfig_set_broadcast(struct connman_ipconfig *ipconfig, const char *broadcast); const char *__connman_ipconfig_get_gateway(struct connman_ipconfig *ipconfig); void __connman_ipconfig_set_gateway(struct connman_ipconfig *ipconfig, const char *gateway); + +#if defined TIZEN_EXT +void __connman_ipconfig_set_dhcp_lease_duration(struct connman_ipconfig *ipconfig, int dhcp_lease_duration); +#endif + unsigned char __connman_ipconfig_get_prefixlen(struct connman_ipconfig *ipconfig); void __connman_ipconfig_set_prefixlen(struct connman_ipconfig *ipconfig, unsigned char prefixlen); @@ -401,7 +406,15 @@ enum connman_ipconfig_method __connman_ipconfig_get_method( int __connman_ipconfig_address_add(struct connman_ipconfig *ipconfig); int __connman_ipconfig_address_remove(struct connman_ipconfig *ipconfig); int __connman_ipconfig_address_unset(struct connman_ipconfig *ipconfig); +#if defined TIZEN_EXT +/* + * Description: __connman_service_lookup_from_index cannot find correct service + * e.g. same interface or same APN of cellular profile + */ +int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig, struct connman_service *service); +#else int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig); +#endif void __connman_ipconfig_gateway_remove(struct connman_ipconfig *ipconfig); int __connman_ipconfig_set_proxy_autoconfig(struct connman_ipconfig *ipconfig, @@ -451,6 +464,11 @@ enum __connman_dhcpv6_status { CONNMAN_DHCPV6_STATUS_RESTART = 2, }; +#if defined TIZEN_EXT +void set_dhcp_discover_timeout(int timeout_value); +void set_dhcp_discover_retry_count(int retry_count); +#endif + typedef void (* dhcpv6_cb) (struct connman_network *network, enum __connman_dhcpv6_status status, gpointer data); @@ -560,6 +578,10 @@ int __connman_device_request_hidden_scan(struct connman_device *device, const char *ssid, unsigned int ssid_len, const char *identity, const char *passphrase, const char *security, void *user_data); +#if defined TIZEN_EXT +int __connman_device_request_specific_scan(enum connman_service_type type, + int scan_type, GSList *specific_scan_list); +#endif bool __connman_device_isfiltered(const char *devname); @@ -579,6 +601,11 @@ int __connman_rfkill_init(void); void __connman_rfkill_cleanup(void); int __connman_rfkill_block(enum connman_service_type type, bool block); +#if defined TIZEN_EXT +char *index2ident(int index, const char *prefix); +char *index2addr(int index); +#endif + #include <connman/network.h> int __connman_network_init(void); @@ -660,6 +687,15 @@ int __connman_service_load_modifiable(struct connman_service *service); void __connman_service_list_struct(DBusMessageIter *iter); +#if defined TIZEN_EXT +int connman_service_get_ipv6_dns_method(struct connman_service *service); +enum connman_dnsconfig_method { + CONNMAN_DNSCONFIG_METHOD_UNKNOWN = 0, + CONNMAN_DNSCONFIG_METHOD_MANUAL = 1, + CONNMAN_DNSCONFIG_METHOD_DHCP = 2, +}; +#endif + int __connman_service_compare(const struct connman_service *a, const struct connman_service *b); @@ -693,6 +729,10 @@ struct connman_network *__connman_service_get_network(struct connman_service *se enum connman_service_security __connman_service_get_security(struct connman_service *service); const char *__connman_service_get_phase2(struct connman_service *service); bool __connman_service_wps_enabled(struct connman_service *service); +#if defined TIZEN_EXT +void __connman_service_set_storage_reload(struct connman_service *service, + bool storage_reload); +#endif int __connman_service_set_favorite(struct connman_service *service, bool favorite); int __connman_service_set_favorite_delayed(struct connman_service *service, @@ -716,6 +756,10 @@ enum connman_service_state __connman_service_ipconfig_get_state( struct connman_service *service, enum connman_ipconfig_type type); +#if defined TIZEN_EXT +void connman_check_proxy_setup_and_wispr_start(struct connman_service *service); +#endif + int __connman_service_indicate_error(struct connman_service *service, enum connman_service_error error); int __connman_service_clear_error(struct connman_service *service); @@ -727,6 +771,12 @@ int __connman_service_disconnect(struct connman_service *service); int __connman_service_disconnect_all(void); void __connman_service_set_active_session(bool enable, GSList *list); void __connman_service_auto_connect(enum connman_service_connect_reason reason); + +#if defined TIZEN_EXT +bool __connman_service_get_auto_connect_mode(void); +void __connman_service_set_auto_connect_mode(bool enable); +#endif + bool __connman_service_remove(struct connman_service *service); bool __connman_service_is_provider_pending(struct connman_service *service); void __connman_service_set_provider_pending(struct connman_service *service, @@ -744,10 +794,19 @@ const char *__connman_service_type2string(enum connman_service_type type); enum connman_service_type __connman_service_string2type(const char *str); enum connman_service_security __connman_service_string2security(const char *str); +#if defined TIZEN_EXT +int __connman_service_nameserver_append(struct connman_service *service, + const char *nameserver, bool is_auto, + enum connman_ipconfig_type type); +int __connman_service_nameserver_remove(struct connman_service *service, + const char *nameserver, bool is_auto, + enum connman_ipconfig_type type); +#else int __connman_service_nameserver_append(struct connman_service *service, const char *nameserver, bool is_auto); int __connman_service_nameserver_remove(struct connman_service *service, const char *nameserver, bool is_auto); +#endif void __connman_service_nameserver_clear(struct connman_service *service); void __connman_service_nameserver_add_routes(struct connman_service *service, const char *gw); @@ -763,6 +822,17 @@ void __connman_service_timeserver_changed(struct connman_service *service, GSList *ts_list); void __connman_service_set_pac(struct connman_service *service, const char *pac); +#if defined TIZEN_EXT +/* + * Returns profile count if there is any connected profiles + * that use same interface + */ +int __connman_service_get_connected_count_of_iface(struct connman_service *service); +void __connman_service_set_proxy(struct connman_service *service, + const char *proxies); +int check_passphrase_ext(struct connman_network *network, + const char *passphrase); +#endif bool __connman_service_is_hidden(struct connman_service *service); bool __connman_service_is_split_routing(struct connman_service *service); bool __connman_service_index_is_split_routing(int index); @@ -806,6 +876,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); @@ -875,12 +948,21 @@ int __connman_rtnl_init(void); void __connman_rtnl_start(void); void __connman_rtnl_cleanup(void); +#if defined TIZEN_EXT +void __connman_wifi_vsie_list_struct(DBusMessageIter *iter); +#endif + enum connman_device_type __connman_rtnl_get_device_type(int index); unsigned int __connman_rtnl_update_interval_add(unsigned int interval); unsigned int __connman_rtnl_update_interval_remove(unsigned int interval); int __connman_rtnl_request_update(void); int __connman_rtnl_send(const void *buf, size_t len); +#if defined TIZEN_EXT +void rtnl_nameserver_add_all(struct connman_service *service, + enum connman_ipconfig_type type); +#endif + bool __connman_session_policy_autoconnect(enum connman_service_connect_reason reason); int __connman_session_create(DBusMessage *msg); @@ -1062,3 +1144,12 @@ void __connman_machine_cleanup(void); int __connman_util_get_random(uint64_t *val); int __connman_util_init(void); void __connman_util_cleanup(void); + +#ifdef TIZEN_EXT +__attribute__ ((unused)) static int __tizentvextension = -1; +#define TIZEN_TV_EXT (__builtin_expect(__tizentvextension != -1, 1) ? \ + __tizentvextension : \ + (__tizentvextension = connman_setting_get_bool("TizenTVExtension"))) +#else /* TIZEN_EXT */ +#define TIZEN_TV_EXT (0) /* Always False */ +#endif /* TIZEN_EXT */ diff --git a/src/connman.service.in b/src/connman.service.in index 9f5c10fe..9eb75b24 100644..100755 --- a/src/connman.service.in +++ b/src/connman.service.in @@ -1,21 +1,19 @@ [Unit] Description=Connection service -DefaultDependencies=false -Conflicts=shutdown.target -RequiresMountsFor=@localstatedir@/lib/connman -After=dbus.service network-pre.target systemd-sysusers.service -Before=network.target multi-user.target shutdown.target -Wants=network.target +After=net-config.service +DefaultDependencies=no [Service] Type=dbus +User=network_fw +Group=network_fw BusName=net.connman Restart=on-failure -ExecStart=@sbindir@/connmand -n +SmackProcessLabel=System +ExecStart=@bindir@/connmand -n --noplugin vpn StandardOutput=null -CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SYS_TIME CAP_SYS_MODULE -ProtectHome=true -ProtectSystem=full +Capabilities=cap_setgid,cap_net_admin,cap_net_bind_service,cap_net_broadcast,cap_net_raw,cap_dac_override=i +SecureBits=keep-caps [Install] WantedBy=multi-user.target diff --git a/src/connman.socket b/src/connman.socket new file mode 100644 index 00000000..5d0a280f --- /dev/null +++ b/src/connman.socket @@ -0,0 +1,13 @@ +[Unit] +Description=DNS Proxy Socket +Before=connman.service + +[Socket] +ListenStream=127.0.0.1:53 +ListenDatagram=0.0.0.0:53 +FreeBind=true +SmackLabelIPIn=* +SmackLabelIPOut=@ + +[Install] +WantedBy=sockets.target
\ No newline at end of file diff --git a/src/connman_tv.service.in b/src/connman_tv.service.in new file mode 100644 index 00000000..9eb75b24 --- /dev/null +++ b/src/connman_tv.service.in @@ -0,0 +1,19 @@ +[Unit] +Description=Connection service +After=net-config.service +DefaultDependencies=no + +[Service] +Type=dbus +User=network_fw +Group=network_fw +BusName=net.connman +Restart=on-failure +SmackProcessLabel=System +ExecStart=@bindir@/connmand -n --noplugin vpn +StandardOutput=null +Capabilities=cap_setgid,cap_net_admin,cap_net_bind_service,cap_net_broadcast,cap_net_raw,cap_dac_override=i +SecureBits=keep-caps + +[Install] +WantedBy=multi-user.target diff --git a/src/counter.c b/src/counter.c index 8ea6205b..8ea6205b 100644..100755 --- a/src/counter.c +++ b/src/counter.c diff --git a/src/dbus.c b/src/dbus.c index d80a46ce..71728300 100644..100755 --- a/src/dbus.c +++ b/src/dbus.c @@ -524,6 +524,35 @@ err: return err; } +int connman_dbus_get_connection_unix_user_sync(DBusConnection *connection, + const char *bus_name, + unsigned int *user_id) +{ +#if defined TIZEN_EXT + *user_id = 0; +#else + 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; +#endif + + return 0; +} + static unsigned char *parse_context(DBusMessage *msg) { DBusMessageIter iter, array; diff --git a/src/detect.c b/src/detect.c index 6c039206..7f20870c 100644..100755 --- a/src/detect.c +++ b/src/detect.c @@ -67,8 +67,15 @@ static void detect_newlink(unsigned short type, int index, } device = find_device(index); +#if defined TIZEN_EXT + if (device) { + connman_inet_update_device_ident(device); + return; + } +#else if (device) return; +#endif device = connman_device_create_from_index(index); if (!device) diff --git a/src/device.c b/src/device.c index a563f464..3ec8f715 100644..100755 --- a/src/device.c +++ b/src/device.c @@ -1042,6 +1042,73 @@ void connman_device_regdom_notify(struct connman_device *device, __connman_technology_notify_regdom_by_device(device, result, alpha2); } +#if defined TIZEN_EXT +static int device_specific_scan(enum connman_service_type type, + struct connman_device *device, + int scan_type, GSList *specific_scan_list) +{ + if (!device->driver || !device->driver->specific_scan) + return -EOPNOTSUPP; + + if (!device->powered) + return -ENOLINK; + + return device->driver->specific_scan(type, device, scan_type, + specific_scan_list, NULL); +} + +int __connman_device_request_specific_scan(enum connman_service_type type, + int scan_type, GSList *specific_scan_list) +{ + bool success = false; + int last_err = -ENOSYS; + GSList *list; + int err; + + switch (type) { + case CONNMAN_SERVICE_TYPE_UNKNOWN: + case CONNMAN_SERVICE_TYPE_SYSTEM: + case CONNMAN_SERVICE_TYPE_ETHERNET: + case CONNMAN_SERVICE_TYPE_BLUETOOTH: + case CONNMAN_SERVICE_TYPE_CELLULAR: + case CONNMAN_SERVICE_TYPE_GPS: + case CONNMAN_SERVICE_TYPE_VPN: + case CONNMAN_SERVICE_TYPE_GADGET: + return -EOPNOTSUPP; + case CONNMAN_SERVICE_TYPE_WIFI: + case CONNMAN_SERVICE_TYPE_P2P: + break; + } + + for (list = device_list; list; list = list->next) { + struct connman_device *device = list->data; + enum connman_service_type service_type = + __connman_device_get_service_type(device); + + if (service_type != CONNMAN_SERVICE_TYPE_UNKNOWN) { + if (type == CONNMAN_SERVICE_TYPE_P2P) { + if (service_type != CONNMAN_SERVICE_TYPE_WIFI) + continue; + } else if (service_type != type) + continue; + } + + err = device_specific_scan(type, device, scan_type, specific_scan_list); + if (err == 0 || err == -EINPROGRESS) { + success = true; + } else { + last_err = err; + DBG("device %p err %d", device, err); + } + } + + if (success) + return 0; + + return last_err; +} +#endif + int __connman_device_request_scan(enum connman_service_type type) { bool success = false; @@ -1078,7 +1145,15 @@ int __connman_device_request_scan(enum connman_service_type type) } err = device_scan(type, device); +#if defined TIZEN_EXT + /* When Scan is already in progress then return Error so that + * wifi-manager can block the scan-done signal to be sent to + * application and start requested scan after scan already in progress + * is completed then notify to application about the scan event */ + if (err == 0 || err == -EINPROGRESS) { +#else if (err == 0 || err == -EALREADY || err == -EINPROGRESS) { +#endif success = true; } else { last_err = err; @@ -1108,7 +1183,11 @@ int __connman_device_request_hidden_scan(struct connman_device *device, passphrase, security, user_data); } +#if defined TIZEN_EXT +char *index2ident(int index, const char *prefix) +#else static char *index2ident(int index, const char *prefix) +#endif { struct ifreq ifr; struct ether_addr eth; @@ -1154,7 +1233,11 @@ static char *index2ident(int index, const char *prefix) return str; } +#if defined TIZEN_EXT +char *index2addr(int index) +#else static char *index2addr(int index) +#endif { struct ifreq ifr; struct ether_addr eth; @@ -1394,6 +1477,9 @@ static void cleanup_devices(void) DBG("cleaning up %s index %d", interfaces[i], index); +#if defined TIZEN_EXT + if (strcmp(interfaces[i], "wlan0") != 0) +#endif connman_inet_ifdown(index); /* diff --git a/src/dhcp.c b/src/dhcp.c index 1af1eb52..c428c1d4 100644..100755 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -67,6 +67,9 @@ static GHashTable *ipconfig_table; static void dhcp_free(struct connman_dhcp *dhcp) { +#if defined TIZEN_EXT + DBG("dhcp_free [%p]", dhcp); +#endif g_strfreev(dhcp->nameservers); g_strfreev(dhcp->timeservers); g_free(dhcp->pac); @@ -76,10 +79,16 @@ static void dhcp_free(struct connman_dhcp *dhcp) dhcp->pac = NULL; g_free(dhcp); +#if defined TIZEN_EXT + dhcp = NULL; +#endif } static void ipv4ll_stop_client(struct connman_dhcp *dhcp) { +#if defined TIZEN_EXT + DBG("dhcp [%p] ipv4ll_client [%p]", dhcp, dhcp->ipv4ll_client); +#endif if (!dhcp->ipv4ll_client) return; @@ -119,8 +128,14 @@ static bool apply_dhcp_invalidate_on_network(struct connman_dhcp *dhcp) } if (dhcp->nameservers) { for (i = 0; dhcp->nameservers[i]; i++) { +#if defined TIZEN_EXT __connman_service_nameserver_remove(service, - dhcp->nameservers[i], false); + dhcp->nameservers[i], false, + CONNMAN_IPCONFIG_TYPE_IPV4); +#else + __connman_service_nameserver_remove(service, + dhcp->nameservers[i], false); +#endif } g_strfreev(dhcp->nameservers); dhcp->nameservers = NULL; @@ -193,6 +208,10 @@ static int ipv4ll_start_client(struct connman_dhcp *dhcp) int index; int err; +#if defined TIZEN_EXT + DBG("dhcp %p", dhcp); +#endif + if (dhcp->ipv4ll_client) return -EALREADY; @@ -202,12 +221,16 @@ static int ipv4ll_start_client(struct connman_dhcp *dhcp) if (error != G_DHCP_CLIENT_ERROR_NONE) return -EINVAL; +#if !defined TIZEN_EXT if (getenv("CONNMAN_DHCP_DEBUG")) { +#endif dhcp->ipv4ll_debug_prefix = g_strdup_printf("IPv4LL index %d", index); g_dhcp_client_set_debug(ipv4ll_client, dhcp_debug, dhcp->ipv4ll_debug_prefix); +#if !defined TIZEN_EXT } +#endif g_dhcp_client_set_id(ipv4ll_client); @@ -242,7 +265,10 @@ static gboolean dhcp_retry_cb(gpointer user_data) struct connman_dhcp *dhcp = user_data; dhcp->timeout = 0; - +#if defined TIZEN_EXT + DBG("dhcp %p", dhcp); + DBG("dhcp->timeout %d", dhcp->timeout); +#endif g_dhcp_client_start(dhcp->dhcp_client, __connman_ipconfig_get_dhcp_address(dhcp->ipconfig)); @@ -382,18 +408,32 @@ static bool apply_lease_available_on_network(GDHCPClient *dhcp_client, if (!compare_string_arrays(nameservers, dhcp->nameservers)) { if (dhcp->nameservers) { +#if defined TIZEN_EXT + for (i = 0; dhcp->nameservers[i] != NULL; i++) { + __connman_service_nameserver_remove(service, + dhcp->nameservers[i], false, + CONNMAN_IPCONFIG_TYPE_IPV4); + } +#else for (i = 0; dhcp->nameservers[i]; i++) { __connman_service_nameserver_remove(service, dhcp->nameservers[i], false); } +#endif g_strfreev(dhcp->nameservers); } dhcp->nameservers = nameservers; for (i = 0; dhcp->nameservers && dhcp->nameservers[i]; i++) { +#if defined TIZEN_EXT + __connman_service_nameserver_append(service, + dhcp->nameservers[i], false, + CONNMAN_IPCONFIG_TYPE_IPV4); +#else __connman_service_nameserver_append(service, dhcp->nameservers[i], false); +#endif } } else { g_strfreev(nameservers); @@ -458,6 +498,10 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data) __connman_ipconfig_set_dhcp_address(dhcp->ipconfig, address); DBG("last address %s", address); +#if defined TIZEN_EXT + int dhcp_lease_duration = g_dhcp_client_get_dhcp_lease_duration(dhcp_client); +#endif + option = g_dhcp_client_get_option(dhcp_client, G_DHCP_SUBNET); if (option) netmask = g_strdup(option->data); @@ -492,6 +536,10 @@ static void lease_available_cb(GDHCPClient *dhcp_client, gpointer user_data) __connman_ipconfig_set_method(dhcp->ipconfig, CONNMAN_IPCONFIG_METHOD_DHCP); +#if defined TIZEN_EXT + __connman_ipconfig_set_dhcp_lease_duration(dhcp->ipconfig, dhcp_lease_duration); +#endif + /* * Notify IPv4.Configuration's method moved back to DHCP. * @@ -580,14 +628,25 @@ static int dhcp_initialize(struct connman_dhcp *dhcp) dhcp_client = g_dhcp_client_new(G_DHCP_IPV4, index, &error); if (error != G_DHCP_CLIENT_ERROR_NONE) +#if defined TIZEN_EXT + { + DBG("failed g_dhcp_client_new(%d), index(%d)", error, index); +#endif return -EINVAL; +#if defined TIZEN_EXT + } +#endif +#if !defined TIZEN_EXT if (getenv("CONNMAN_DHCP_DEBUG")) { +#endif dhcp->dhcp_debug_prefix = g_strdup_printf("DHCP index %d", index); g_dhcp_client_set_debug(dhcp_client, dhcp_debug, dhcp->dhcp_debug_prefix); +#if !defined TIZEN_EXT } +#endif g_dhcp_client_set_id(dhcp_client); @@ -675,7 +734,9 @@ int __connman_dhcp_start(struct connman_ipconfig *ipconfig, struct connman_network *network, dhcp_cb callback, gpointer user_data) { +#if !defined TIZEN_EXT const char *last_addr = NULL; +#endif struct connman_dhcp *dhcp; int err; @@ -689,7 +750,9 @@ int __connman_dhcp_start(struct connman_ipconfig *ipconfig, return -EINVAL; } +#if !defined TIZEN_EXT last_addr = __connman_ipconfig_get_dhcp_address(ipconfig); +#endif dhcp = g_hash_table_lookup(ipconfig_table, ipconfig); if (!dhcp) { @@ -721,7 +784,13 @@ int __connman_dhcp_start(struct connman_ipconfig *ipconfig, dhcp->callback = callback; dhcp->user_data = user_data; +#if defined TIZEN_EXT + DBG("Start DHCP with DHCPDISCOVER request"); + + return g_dhcp_client_start(dhcp->dhcp_client, NULL); +#else return g_dhcp_client_start(dhcp->dhcp_client, last_addr); +#endif } void __connman_dhcp_stop(struct connman_ipconfig *ipconfig) diff --git a/src/dhcpv6.c b/src/dhcpv6.c index cbf7974f..c624cb00 100644..100755 --- a/src/dhcpv6.c +++ b/src/dhcpv6.c @@ -197,10 +197,23 @@ static int set_duid(struct connman_service *service, int duid_len; ident = __connman_service_get_ident(service); +#if defined TIZEN_EXT + if(ident != NULL) + DBG("ident : %s", ident); +#endif keyfile = connman_storage_load_service(ident); + +#if defined TIZEN_EXT + if (!keyfile) { + keyfile = g_key_file_new(); + if (!keyfile) + return -EIO; + } +#else if (!keyfile) return -EINVAL; +#endif hex_duid = g_key_file_get_string(keyfile, ident, "IPv6.DHCP.DUID", NULL); @@ -322,9 +335,19 @@ static void info_req_cb(GDHCPClient *dhcp_client, gpointer user_data) if (!compare_string_arrays(nameservers, dhcp->nameservers)) { if (dhcp->nameservers) { for (i = 0; dhcp->nameservers[i]; i++) +#if defined TIZEN_EXT + { __connman_service_nameserver_remove(service, - dhcp->nameservers[i], - false); + dhcp->nameservers[i], false, + CONNMAN_IPCONFIG_TYPE_IPV6); +#else + __connman_service_nameserver_remove(service, + dhcp->nameservers[i], + false); +#endif +#if defined TIZEN_EXT + } +#endif g_strfreev(dhcp->nameservers); } @@ -332,9 +355,19 @@ static void info_req_cb(GDHCPClient *dhcp_client, gpointer user_data) for (i = 0; dhcp->nameservers && dhcp->nameservers[i]; i++) +#if defined TIZEN_EXT + { + __connman_service_nameserver_append(service, + dhcp->nameservers[i], false, + CONNMAN_IPCONFIG_TYPE_IPV6); +#else __connman_service_nameserver_append(service, dhcp->nameservers[i], false); +#endif +#if defined TIZEN_EXT + } +#endif } else g_strfreev(nameservers); @@ -392,7 +425,9 @@ static int dhcpv6_info_request(struct connman_dhcpv6 *dhcp) return -EINVAL; } +#if !defined TIZEN_EXT if (getenv("CONNMAN_DHCPV6_DEBUG")) +#endif g_dhcp_client_set_debug(dhcp_client, dhcpv6_debug, "DHCPv6"); service = connman_service_lookup_from_network(dhcp->network); @@ -517,9 +552,19 @@ static int set_other_addresses(GDHCPClient *dhcp_client, if (!compare_string_arrays(nameservers, dhcp->nameservers)) { if (dhcp->nameservers) { for (i = 0; dhcp->nameservers[i]; i++) +#if defined TIZEN_EXT + { + __connman_service_nameserver_remove(service, + dhcp->nameservers[i], + false, CONNMAN_IPCONFIG_TYPE_IPV6); +#else __connman_service_nameserver_remove(service, dhcp->nameservers[i], false); +#endif +#if defined TIZEN_EXT + } +#endif g_strfreev(dhcp->nameservers); } @@ -527,9 +572,19 @@ static int set_other_addresses(GDHCPClient *dhcp_client, for (i = 0; dhcp->nameservers && dhcp->nameservers[i]; i++) +#if defined TIZEN_EXT + { __connman_service_nameserver_append(service, - dhcp->nameservers[i], - false); + dhcp->nameservers[i], + false, CONNMAN_IPCONFIG_TYPE_IPV6); +#else + __connman_service_nameserver_append(service, + dhcp->nameservers[i], + false); +#endif +#if defined TIZEN_EXT + } +#endif } else g_strfreev(nameservers); @@ -638,6 +693,9 @@ static void set_address(int ifindex, struct connman_ipconfig *ipconfig, /* Is this prefix part of the subnet we are suppose to use? */ prefix_len = check_ipv6_addr_prefix(prefixes, address); +#if defined TIZEN_EXT + char *gateway = g_strdup(__connman_ipconfig_get_gateway(ipconfig)); +#endif __connman_ipconfig_address_remove(ipconfig); __connman_ipconfig_set_local(ipconfig, address); __connman_ipconfig_set_prefixlen(ipconfig, prefix_len); @@ -645,6 +703,11 @@ static void set_address(int ifindex, struct connman_ipconfig *ipconfig, DBG("new address %s/%d", address, prefix_len); __connman_ipconfig_set_dhcp_address(ipconfig, address); +#if defined TIZEN_EXT + DBG("Set gateway %s", gateway); + __connman_ipconfig_set_gateway(ipconfig, gateway); + g_free(gateway); +#endif __connman_service_save( __connman_service_lookup_from_index(ifindex)); } @@ -1713,7 +1776,9 @@ static gboolean timeout_solicitation(gpointer user_data) static int dhcpv6_solicitation(struct connman_dhcpv6 *dhcp) { struct connman_service *service; +#if !defined TIZEN_EXT struct connman_ipconfig *ipconfig_ipv6; +#endif GDHCPClient *dhcp_client; GDHCPClientError error; int index, ret; @@ -1728,7 +1793,9 @@ static int dhcpv6_solicitation(struct connman_dhcpv6 *dhcp) return -EINVAL; } +#if !defined TIZEN_EXT if (getenv("CONNMAN_DHCPV6_DEBUG")) +#endif g_dhcp_client_set_debug(dhcp_client, dhcpv6_debug, "DHCPv6"); service = connman_service_lookup_from_network(dhcp->network); @@ -1754,8 +1821,20 @@ static int dhcpv6_solicitation(struct connman_dhcpv6 *dhcp) g_dhcpv6_client_set_oro(dhcp_client, 3, G_DHCPV6_DNS_SERVERS, G_DHCPV6_DOMAIN_LIST, G_DHCPV6_SNTP_SERVERS); +#if defined TIZEN_EXT + /** + When privacy extension is enabled then connman requests + OPTION_IA_TA (4) from DHCPv6 server. This option is used to request + temporary IPv6 address from DHCPv6 server but we found that DHCPv6 + server never provided temporary IPv6 address and connman resend dhcpv6 + requests. So always set OPTION_IA_NA in dhcpv6 request to get IPv6 + address from DHCPv6 server. + */ + dhcp->use_ta = FALSE; +#else ipconfig_ipv6 = __connman_service_get_ip6config(service); dhcp->use_ta = __connman_ipconfig_ipv6_privacy_enabled(ipconfig_ipv6); +#endif g_dhcpv6_client_set_ia(dhcp_client, index, dhcp->use_ta ? G_DHCPV6_IA_TA : G_DHCPV6_IA_NA, @@ -2045,7 +2124,9 @@ static GDHCPClient *create_pd_client(struct connman_dhcpv6 *dhcp, int *err) return NULL; } +#if !defined TIZEN_EXT if (getenv("CONNMAN_DHCPV6_DEBUG")) +#endif g_dhcp_client_set_debug(dhcp_client, dhcpv6_debug, "DHCPv6:PD"); service = connman_service_lookup_from_network(dhcp->network); diff --git a/src/dnsproxy.c b/src/dnsproxy.c index 40b4f159..3fa7bf46 100644..100755 --- a/src/dnsproxy.c +++ b/src/dnsproxy.c @@ -41,6 +41,11 @@ #include "connman.h" +#if defined TIZEN_EXT +#include <sys/smack.h> +#include <systemd/sd-daemon.h> +#endif + #define debug(fmt...) do { } while (0) #if __BYTE_ORDER == __LITTLE_ENDIAN @@ -194,7 +199,11 @@ struct domain_rr { * By default the TTL (time-to-live) of the DNS response is used * when setting the cache entry life time. The value is in seconds. */ +#if defined TIZEN_EXT +#define MAX_CACHE_TTL (60 * 60) +#else #define MAX_CACHE_TTL (60 * 30) +#endif /* * Also limit the other end, cache at least for 30 seconds. */ @@ -213,12 +222,22 @@ static int cache_size; static GHashTable *cache; static int cache_refcount; static GSList *server_list = NULL; +#if defined TIZEN_EXT +static GSList *server_list_sec = NULL; +#endif static GSList *request_list = NULL; static GHashTable *listener_table = NULL; static time_t next_refresh; static GHashTable *partial_tcp_req_table; static guint cache_timer = 0; +#if defined TIZEN_EXT +static void destroy_server_sec(struct server_data *server); +static struct server_data *create_server_sec(int index, + const char *domain, const char *server, + int protocol); +#endif + static guint16 get_id(void) { uint64_t rand; @@ -1642,6 +1661,31 @@ static int ns_resolv(struct server_data *server, struct request_data *req, } } +#if defined TIZEN_EXT + if (server->protocol == IPPROTO_UDP) { + GList *domains; + struct server_data *new_server = NULL; + + new_server = create_server_sec(server->index, NULL, + server->server, IPPROTO_UDP); + + if (new_server != NULL) { + for (domains = server->domains; domains; + domains = domains->next) { + char *dom = domains->data; + + DBG("Adding domain %s to %s", + dom, new_server->server); + + new_server->domains = g_list_append( + new_server->domains, + g_strdup(dom)); + } + + server = new_server; + } + } +#endif sk = g_io_channel_unix_get_fd(server->channel); err = sendto(sk, request, req->request_len, MSG_NOSIGNAL, @@ -2240,6 +2284,19 @@ static gboolean udp_server_event(GIOChannel *channel, GIOCondition condition, if (err < 0) return TRUE; +#if defined TIZEN_EXT + GSList *list; + + for (list = server_list_sec; list; list = list->next) { + struct server_data *new_data = list->data; + + if (new_data == data) { + destroy_server_sec(data); + return TRUE; + } + } +#endif + return TRUE; } @@ -2550,6 +2607,177 @@ static void enable_fallback(bool enable) } } +#if defined TIZEN_EXT + +static void destroy_server_sec(struct server_data *server) +{ + GList *list; + int fd; + + if (server->channel) + fd = g_io_channel_unix_get_fd(server->channel); + else + fd = -1; + + DBG("index %d server %s sock %d", server->index, server->server, fd); + + server_list_sec = g_slist_remove(server_list_sec, server); + + if (fd > 0) + close(fd); + + server_destroy_socket(server); + + if (server->protocol == IPPROTO_UDP && server->enabled) + DBG("Removing DNS server %s", server->server); + + g_free(server->server); + for (list = server->domains; list; list = list->next) { + char *domain = list->data; + + server->domains = g_list_remove(server->domains, domain); + g_free(domain); + } + g_free(server->server_addr); + + /* + * We do not remove cache right away but delay it few seconds. + * The idea is that when IPv6 DNS server is added via RDNSS, it has a + * lifetime. When the lifetime expires we decrease the refcount so it + * is possible that the cache is then removed. Because a new DNS server + * is usually created almost immediately we would then loose the cache + * without any good reason. The small delay allows the new RDNSS to + * create a new DNS server instance and the refcount does not go to 0. + */ + /* TODO: Need to check this */ + /* g_timeout_add_seconds(3, try_remove_cache, NULL); */ + + g_free(server); +} + +static void destroy_all_server_sec() +{ + GSList *list; + + DBG("remove all dns server"); + + for (list = server_list_sec; list; list = list->next) { + struct server_data *server = list->data; + destroy_server_sec(server); + } + server_list_sec = NULL; +} + +static gboolean sec_udp_idle_timeout(gpointer user_data) +{ + struct server_data *server = user_data; + + DBG(""); + + if (server == NULL) + return FALSE; + + destroy_server_sec(server); + + return FALSE; +} + +static struct server_data *create_server_sec(int index, + const char *domain, const char *server, + int protocol) +{ + struct server_data *data; + struct addrinfo hints, *rp; + int ret; + + DBG("index %d server %s", index, server); + + data = g_try_new0(struct server_data, 1); + if (data == NULL) { + connman_error("Failed to allocate server %s data", server); + return NULL; + } + + data->index = index; + if (domain) + data->domains = g_list_append(data->domains, g_strdup(domain)); + data->server = g_strdup(server); + data->protocol = protocol; + + memset(&hints, 0, sizeof(hints)); + + switch (protocol) { + case IPPROTO_UDP: + hints.ai_socktype = SOCK_DGRAM; + break; + + case IPPROTO_TCP: + hints.ai_socktype = SOCK_STREAM; + break; + + default: + destroy_server_sec(data); + return NULL; + } + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_NUMERICSERV | AI_NUMERICHOST; + + ret = getaddrinfo(data->server, "53", &hints, &rp); + if (ret) { + connman_error("Failed to parse server %s address: %s\n", + data->server, gai_strerror(ret)); + freeaddrinfo(rp); + destroy_server_sec(data); + return NULL; + } + + /* Do not blindly copy this code elsewhere; it doesn't loop over the + results using ->ai_next as it should. That's OK in *this* case + because it was a numeric lookup; we *know* there's only one. */ + + data->server_addr_len = rp->ai_addrlen; + + switch (rp->ai_family) { + case AF_INET: + data->server_addr = (struct sockaddr *) + g_try_new0(struct sockaddr_in, 1); + break; + case AF_INET6: + data->server_addr = (struct sockaddr *) + g_try_new0(struct sockaddr_in6, 1); + break; + default: + connman_error("Wrong address family %d", rp->ai_family); + break; + } + if (data->server_addr == NULL) { + freeaddrinfo(rp); + destroy_server_sec(data); + return NULL; + } + memcpy(data->server_addr, rp->ai_addr, rp->ai_addrlen); + freeaddrinfo(rp); + + if (server_create_socket(data) != 0) { + destroy_server_sec(data); + return NULL; + } + + if (protocol == IPPROTO_UDP) { + /* Enable new servers by default */ + data->enabled = TRUE; + DBG("Adding DNS server %s", data->server); + + data->timeout = g_timeout_add_seconds(30, sec_udp_idle_timeout, + data); + + server_list_sec = g_slist_append(server_list_sec, data); + } + + return data; +} +#endif + static struct server_data *create_server(int index, const char *domain, const char *server, int protocol) @@ -2840,6 +3068,10 @@ int __connman_dnsproxy_remove(int index, const char *domain, remove_server(index, domain, server, IPPROTO_UDP); remove_server(index, domain, server, IPPROTO_TCP); +#if defined TIZEN_EXT + destroy_all_server_sec(); +#endif + return 0; } @@ -3288,6 +3520,23 @@ static gboolean client_timeout(gpointer user_data) return FALSE; } +#if defined TIZEN_EXT +static void recover_listener(GIOChannel *channel, struct listener_data *ifdata) +{ + int sk, index; + + index = ifdata->index; + + sk = g_io_channel_unix_get_fd(channel); + close(sk); + + __connman_dnsproxy_remove_listener(index); + + if (__connman_dnsproxy_add_listener(index) == 0) + DBG("listener %d successfully recovered", index); +} +#endif + static bool tcp_listener_event(GIOChannel *channel, GIOCondition condition, struct listener_data *ifdata, int family, guint *listener_watch) @@ -3308,11 +3557,17 @@ static bool tcp_listener_event(GIOChannel *channel, GIOCondition condition, condition, channel, ifdata, family); if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) { +#if defined TIZEN_EXT + connman_error("Error %d with TCP listener channel", condition); + + recover_listener(channel, ifdata); +#else if (*listener_watch > 0) g_source_remove(*listener_watch); *listener_watch = 0; connman_error("Error with TCP listener channel"); +#endif return false; } @@ -3426,7 +3681,11 @@ static bool tcp_listener_event(GIOChannel *channel, GIOCondition condition, * The packet length bytes do not contain the total message length, * that is the reason to -2 below. */ +#if defined TIZEN_EXT + if (msg_len > (unsigned int)(len - 2)) { +#else if (msg_len != (unsigned int)(len - 2)) { +#endif debug("client %d sent %d bytes but expecting %u pending %d", client_sk, len, msg_len + 2, msg_len + 2 - len); @@ -3471,8 +3730,14 @@ static bool udp_listener_event(GIOChannel *channel, GIOCondition condition, int sk, err, len; if (condition & (G_IO_NVAL | G_IO_ERR | G_IO_HUP)) { +#if defined TIZEN_EXT + connman_error("Error %d with UDP listener channel", condition); + + recover_listener(channel, ifdata); +#else connman_error("Error with UDP listener channel"); *listener_watch = 0; +#endif return false; } @@ -3531,7 +3796,12 @@ static bool udp_listener_event(GIOChannel *channel, GIOCondition condition, req->name = g_strdup(query); req->request = g_malloc(len); memcpy(req->request, buf, len); +#if defined TIZEN_EXT + DBG("req %p dstid 0x%04x altid 0x%04x", req, req->dstid, req->altid); + req->timeout = g_timeout_add_seconds(30, request_timeout, req); +#else req->timeout = g_timeout_add_seconds(5, request_timeout, req); +#endif request_list = g_slist_append(request_list, req); return true; @@ -3559,14 +3829,24 @@ static GIOChannel *get_listener(int family, int protocol, int index) { GIOChannel *channel; const char *proto; +#if !defined TIZEN_EXT union { struct sockaddr sa; struct sockaddr_in6 sin6; struct sockaddr_in sin; } s; socklen_t slen; +#endif int sk, type; +#if !defined TIZEN_EXT char *interface; +#endif +#if defined TIZEN_EXT + int option; + int sd_num = 0; + int rv; + int is_socket_inet = 0; +#endif debug("family %d protocol %d index %d", family, protocol, index); @@ -3584,7 +3864,33 @@ static GIOChannel *get_listener(int family, int protocol, int index) default: return NULL; } +#if defined TIZEN_EXT + sd_num = sd_listen_fds(0); + DBG("socket type(%s) systemd number of fds(%d)", proto, sd_num); + if(sd_num < 1){ + DBG("fail to get the fd from systemd"); + return NULL; + } + if(protocol == IPPROTO_TCP) + type = SOCK_STREAM; + else + type = SOCK_DGRAM; + + for(sk = SD_LISTEN_FDS_START; sk < SD_LISTEN_FDS_START+sd_num; ++sk){ + rv = sd_is_socket_inet(sk, family, type, -1, 53); + if(rv > 0){ + DBG("socket fd (%d) is passed by systemd", sk); + is_socket_inet = 1; + break; + } + } + + if (!is_socket_inet) { + DBG("socket fd is not matched what connman requests"); + return NULL; + } +#else sk = socket(family, type, protocol); if (sk < 0 && family == AF_INET6 && errno == EAFNOSUPPORT) { connman_error("No IPv6 support"); @@ -3596,6 +3902,9 @@ static GIOChannel *get_listener(int family, int protocol, int index) return NULL; } + /* ConnMan listens DNS from multiple interfaces + * E.g. various technology based and tethering interfaces + */ interface = connman_inet_ifname(index); if (!interface || setsockopt(sk, SOL_SOCKET, SO_BINDTODEVICE, interface, @@ -3632,7 +3941,6 @@ static GIOChannel *get_listener(int family, int protocol, int index) s.sin.sin_family = AF_INET; s.sin.sin_port = htons(53); slen = sizeof(s.sin); - if (__connman_inet_get_interface_address(index, AF_INET, &s.sin.sin_addr) < 0) { @@ -3643,22 +3951,30 @@ static GIOChannel *get_listener(int family, int protocol, int index) close(sk); return NULL; } - +#endif +#if defined TIZEN_EXT + /* When ConnMan crashed, + * probably DNS listener cannot bind existing address */ + option = 1; + setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)); +#endif +#if !defined TIZEN_EXT if (bind(sk, &s.sa, slen) < 0) { connman_error("Failed to bind %s listener socket", proto); close(sk); return NULL; } +#endif if (protocol == IPPROTO_TCP) { - +#if !defined TIZEN_EXT if (listen(sk, 10) < 0) { connman_error("Failed to listen on TCP socket %d/%s", -errno, strerror(errno)); close(sk); return NULL; } - +#endif fcntl(sk, F_SETFL, O_NONBLOCK); } @@ -3691,40 +4007,68 @@ static int create_dns_listener(int protocol, struct listener_data *ifdata) ifdata->tcp4_listener_channel = get_listener(AF_INET, protocol, ifdata->index); if (ifdata->tcp4_listener_channel) +#if defined TIZEN_EXT + ifdata->tcp4_listener_watch = + g_io_add_watch(ifdata->tcp4_listener_channel, + G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, + tcp4_listener_event, (gpointer)ifdata); +#else ifdata->tcp4_listener_watch = g_io_add_watch(ifdata->tcp4_listener_channel, G_IO_IN, tcp4_listener_event, (gpointer)ifdata); +#endif else ret |= TCP_IPv4_FAILED; ifdata->tcp6_listener_channel = get_listener(AF_INET6, protocol, ifdata->index); if (ifdata->tcp6_listener_channel) +#if defined TIZEN_EXT + ifdata->tcp6_listener_watch = + g_io_add_watch(ifdata->tcp6_listener_channel, + G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, + tcp6_listener_event, (gpointer)ifdata); +#else ifdata->tcp6_listener_watch = g_io_add_watch(ifdata->tcp6_listener_channel, G_IO_IN, tcp6_listener_event, (gpointer)ifdata); +#endif else ret |= TCP_IPv6_FAILED; } else { ifdata->udp4_listener_channel = get_listener(AF_INET, protocol, ifdata->index); if (ifdata->udp4_listener_channel) +#if defined TIZEN_EXT + ifdata->udp4_listener_watch = + g_io_add_watch(ifdata->udp4_listener_channel, + G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, + udp4_listener_event, (gpointer)ifdata); +#else ifdata->udp4_listener_watch = g_io_add_watch(ifdata->udp4_listener_channel, G_IO_IN, udp4_listener_event, (gpointer)ifdata); +#endif else ret |= UDP_IPv4_FAILED; ifdata->udp6_listener_channel = get_listener(AF_INET6, protocol, ifdata->index); if (ifdata->udp6_listener_channel) +#if defined TIZEN_EXT + ifdata->udp6_listener_watch = + g_io_add_watch(ifdata->udp6_listener_channel, + G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, + udp6_listener_event, (gpointer)ifdata); +#else ifdata->udp6_listener_watch = g_io_add_watch(ifdata->udp6_listener_channel, G_IO_IN, udp6_listener_event, (gpointer)ifdata); +#endif else ret |= UDP_IPv6_FAILED; } diff --git a/src/eduroam.config b/src/eduroam.config index 768b7b40..768b7b40 100644..100755 --- a/src/eduroam.config +++ b/src/eduroam.config diff --git a/src/error.c b/src/error.c index 4f24ae25..4f24ae25 100644..100755 --- a/src/error.c +++ b/src/error.c diff --git a/src/inet.c b/src/inet.c index b887aa0b..008f3de7 100644..100755 --- a/src/inet.c +++ b/src/inet.c @@ -330,6 +330,61 @@ done: return err; } +#if defined TIZEN_EXT +void connman_inet_update_device_ident(struct connman_device *device) +{ + int index; + enum connman_device_type type; + char *ident = NULL, *addr = NULL; + + index = connman_device_get_index(device); + type = connman_device_get_type(device); + + switch (type) { + case CONNMAN_DEVICE_TYPE_UNKNOWN: + return; + case CONNMAN_DEVICE_TYPE_ETHERNET: + case CONNMAN_DEVICE_TYPE_GADGET: + case CONNMAN_DEVICE_TYPE_WIFI: + addr = index2addr(index); + break; + case CONNMAN_DEVICE_TYPE_BLUETOOTH: + case CONNMAN_DEVICE_TYPE_CELLULAR: + case CONNMAN_DEVICE_TYPE_GPS: + case CONNMAN_DEVICE_TYPE_VENDOR: + break; + } + + switch (type) { + case CONNMAN_DEVICE_TYPE_VENDOR: + case CONNMAN_DEVICE_TYPE_GPS: + break; + case CONNMAN_DEVICE_TYPE_ETHERNET: + case CONNMAN_DEVICE_TYPE_GADGET: + ident = index2ident(index, NULL); + break; + case CONNMAN_DEVICE_TYPE_WIFI: + ident = index2ident(index, NULL); + break; + case CONNMAN_DEVICE_TYPE_BLUETOOTH: + break; + case CONNMAN_DEVICE_TYPE_CELLULAR: + ident = index2ident(index, NULL); + break; + } + + if (ident != NULL) { + connman_device_set_ident(device, ident); + g_free(ident); + } + + if (addr != NULL) { + connman_device_set_string(device, "Address", addr); + g_free(addr); + } +} +#endif + struct in6_ifreq { struct in6_addr ifr6_addr; __u32 ifr6_prefixlen; @@ -1282,6 +1337,37 @@ static int icmpv6_recv(int fd, struct xs_cb_data *data) return -errno; } +#if defined TIZEN_EXT + /* Set Received Source Address from router as IPv6 Gateway Address */ + char src_addr[INET6_ADDRSTRLEN]; + if(inet_ntop(AF_INET6, &(saddr.sin6_addr), src_addr, INET6_ADDRSTRLEN) + == NULL) { + xs_cleanup(data); + return -errno; + } + DBG("Received Source Address %s from router", src_addr); + + /* icmpv6_recv() function can be called in two scenarios : + * 1. When __connman_inet_ipv6_send_rs() is called from check_dhcpv6() + * 2. When __connman_inet_ipv6_send_rs() is called from + * __connman_6to4_probe() + * In the second case it is not required to set DHCPv6 Gateway Address + * as DHCPv6 was not started and network structure was not passed as + * user_data. If it is tried to add Source Address as Gateway Address + * then it will lead to crash because of user_data being ip_address + * instead of network structure. So Adding Gateway Address in case 1st + * case only. + */ + char *address = data->user_data; + int err = 0; + unsigned char buffer[sizeof(struct in6_addr)] = {0, }; + /* Checking if user_data is an ip_address */ + err = inet_pton(AF_INET, address, buffer); + /* Setting Received Source Address from + * router as Gateway Address */ + if(err <= 0) + __connman_network_set_auto_ipv6_gateway(src_addr, data->user_data); +#endif hdr = (struct nd_router_advert *)buf; DBG("code %d len %zd hdr %zd", hdr->nd_ra_code, len, sizeof(struct nd_router_advert)); @@ -1381,6 +1467,9 @@ static int ndisc_send_unspec(int type, int oif, const struct in6_addr *dest, char cbuf[CMSG_SPACE(sizeof(*pinfo))]; struct iovec iov[2]; int fd, datalen, ret, iovlen = 1; +#if defined TIZEN_EXT + char ebuf[256]; +#endif DBG(""); @@ -1459,6 +1548,9 @@ static int ndisc_send_unspec(int type, int oif, const struct in6_addr *dest, msgh.msg_controllen = cmsg->cmsg_len; ret = sendmsg(fd, &msgh, 0); +#if defined TIZEN_EXT + DBG("sendmsg errno: %d/%s", errno, strerror_r(errno, ebuf, sizeof(ebuf))); +#endif close(fd); return ret; @@ -2651,7 +2743,8 @@ char **__connman_inet_get_running_interfaces(void) g_free(ifr); - if (count < numif) { + if (count < numif) + { char **prev_result = result; result = g_try_realloc(result, (count + 1) * sizeof(char *)); if (!result) { diff --git a/src/inotify.c b/src/inotify.c index c251c6ff..c251c6ff 100644..100755 --- a/src/inotify.c +++ b/src/inotify.c diff --git a/src/ipaddress.c b/src/ipaddress.c index d63d95c3..d63d95c3 100644..100755 --- a/src/ipaddress.c +++ b/src/ipaddress.c diff --git a/src/ipconfig.c b/src/ipconfig.c index 25657733..d94b8734 100644..100755 --- a/src/ipconfig.c +++ b/src/ipconfig.c @@ -52,6 +52,10 @@ struct connman_ipconfig { struct connman_ipaddress *address; struct connman_ipaddress *system; +#if defined TIZEN_EXT + int dhcp_lease_duration; +#endif + int ipv6_privacy_config; char *last_dhcp_address; char **last_dhcpv6_prefixes; @@ -488,6 +492,16 @@ void __connman_ipconfig_newlink(int index, unsigned short type, index, type, type2str(type)); update: +#if defined TIZEN_EXT + if (g_strcmp0(ipdevice->address, address) != 0) { + /* If an original address is built-in physical device, + * it's hardly get an address at a initial creation + */ + g_free(ipdevice->address); + ipdevice->address = g_strdup(address); + } +#endif + ipdevice->mtu = mtu; update_stats(ipdevice, ifname, stats); @@ -1047,16 +1061,32 @@ void __connman_ipconfig_set_gateway(struct connman_ipconfig *ipconfig, ipconfig->address->gateway = g_strdup(gateway); } +#if defined TIZEN_EXT +void __connman_ipconfig_set_dhcp_lease_duration(struct connman_ipconfig *ipconfig, + int dhcp_lease_duration) +{ + ipconfig->dhcp_lease_duration = dhcp_lease_duration; +} +#endif + +#if defined TIZEN_EXT +int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig, struct connman_service *service) +#else int __connman_ipconfig_gateway_add(struct connman_ipconfig *ipconfig) +#endif { +#if !defined TIZEN_EXT struct connman_service *service; +#endif DBG(""); if (!ipconfig->address) return -EINVAL; +#if !defined TIZEN_EXT service = __connman_service_lookup_from_index(ipconfig->index); +#endif if (!service) return -EINVAL; @@ -1122,8 +1152,11 @@ static struct connman_ipconfig *create_ipv6config(int index) ipdevice = g_hash_table_lookup(ipdevice_hash, GINT_TO_POINTER(index)); if (ipdevice) +#if !defined TIZEN_EXT ipv6config->ipv6_privacy_config = ipdevice->ipv6_privacy; - +#else + ipv6config->ipv6_privacy_config = ipdevice->ipv6_privacy = 2; +#endif ipv6config->address = connman_ipaddress_alloc(AF_INET6); if (!ipv6config->address) { g_free(ipv6config); @@ -1353,6 +1386,12 @@ int __connman_ipconfig_address_unset(struct connman_ipconfig *ipconfig) if (!ipconfig) return 0; +#if defined TIZEN_EXT + DBG("ipconfig method %d type %d", ipconfig->method, ipconfig->type); +#else + DBG("method %d", ipconfig->method); +#endif + switch (ipconfig->method) { case CONNMAN_IPCONFIG_METHOD_UNKNOWN: case CONNMAN_IPCONFIG_METHOD_OFF: @@ -1639,6 +1678,11 @@ int __connman_ipconfig_disable(struct connman_ipconfig *ipconfig) if (ipdevice->config_ipv6 == ipconfig) { ipconfig_list = g_list_remove(ipconfig_list, ipconfig); +#if defined TIZEN_EXT + if (ipdevice->config_ipv6->method == + CONNMAN_IPCONFIG_METHOD_AUTO) + disable_ipv6(ipdevice->config_ipv6); +#endif connman_ipaddress_clear(ipdevice->config_ipv6->system); __connman_ipconfig_unref(ipdevice->config_ipv6); ipdevice->config_ipv6 = NULL; @@ -1772,6 +1816,11 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig, case CONNMAN_IPCONFIG_METHOD_MANUAL: case CONNMAN_IPCONFIG_METHOD_DHCP: append_addr = ipconfig->system; +#if defined TIZEN_EXT + /* TIZEN enables get_properties before __connman_ipconfig_newaddr */ + if (append_addr && append_addr->local == NULL) + append_addr = ipconfig->address; +#endif break; } @@ -1796,6 +1845,20 @@ void __connman_ipconfig_append_ipv4(struct connman_ipconfig *ipconfig, if (append_addr->gateway) connman_dbus_dict_append_basic(iter, "Gateway", DBUS_TYPE_STRING, &append_addr->gateway); + +#if defined TIZEN_EXT + if (ipconfig->method == CONNMAN_IPCONFIG_METHOD_DHCP) { + char *server_ip; + server_ip = __connman_dhcp_get_server_address(ipconfig); + if (server_ip) { + connman_dbus_dict_append_basic(iter, "DHCPServerIP", + DBUS_TYPE_STRING, &server_ip); + g_free(server_ip); + } + connman_dbus_dict_append_basic(iter, "DHCPLeaseDuration", + DBUS_TYPE_INT32, &ipconfig->dhcp_lease_duration); + } +#endif } void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig, @@ -1833,6 +1896,11 @@ void __connman_ipconfig_append_ipv6(struct connman_ipconfig *ipconfig, case CONNMAN_IPCONFIG_METHOD_DHCP: case CONNMAN_IPCONFIG_METHOD_AUTO: append_addr = ipconfig->system; +#if defined TIZEN_EXT + /* TIZEN enables get_properties before __connman_ipconfig_newaddr */ + if (append_addr && append_addr->local == NULL) + append_addr = ipconfig->address; +#endif break; } @@ -2032,7 +2100,10 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig, case CONNMAN_IPCONFIG_METHOD_OFF: ipconfig->method = method; - +#if defined TIZEN_EXT + if (ipconfig->type == CONNMAN_IPCONFIG_TYPE_IPV6) + disable_ipv6(ipconfig); +#endif break; case CONNMAN_IPCONFIG_METHOD_AUTO: @@ -2042,7 +2113,9 @@ int __connman_ipconfig_set_config(struct connman_ipconfig *ipconfig, ipconfig->method = method; if (privacy_string) ipconfig->ipv6_privacy_config = privacy; - +#if defined TIZEN_EXT + enable_ipv6(ipconfig); +#endif break; case CONNMAN_IPCONFIG_METHOD_MANUAL: diff --git a/src/ippool.c b/src/ippool.c index cea1dccd..cea1dccd 100644..100755 --- a/src/ippool.c +++ b/src/ippool.c diff --git a/src/iptables.c b/src/iptables.c index 5ef757a3..aaddf9d6 100644..100755 --- a/src/iptables.c +++ b/src/iptables.c @@ -2350,7 +2350,7 @@ int __connman_iptables_commit(const char *table_name) return -EINVAL; repl = iptables_blob(table); - if (!repl) + if(!repl) return -ENOMEM; if (debug_enabled) diff --git a/src/ipv6pd.c b/src/ipv6pd.c index 0d221f07..0d221f07 100644..100755 --- a/src/ipv6pd.c +++ b/src/ipv6pd.c diff --git a/src/log.c b/src/log.c index 9bae4a3d..fa8ac31f 100644..100755 --- a/src/log.c +++ b/src/log.c @@ -30,6 +30,7 @@ #include <stdlib.h> #include <string.h> #include <syslog.h> +#include <execinfo.h> #include <dlfcn.h> #include "connman.h" @@ -37,6 +38,132 @@ static const char *program_exec; static const char *program_path; +#if defined TIZEN_EXT +#include <sys/stat.h> +#include <sys/time.h> + +#define LOG_FILE_PATH "/opt/usr/data/network/connman.log" +#define MAX_LOG_SIZE 1 * 1024 * 1024 +#define MAX_LOG_COUNT 1 + +#define openlog __connman_log_open +#define closelog __connman_log_close +#define vsyslog __connman_log +#define syslog __connman_log_s + +static FILE *log_file = NULL; + +void __connman_log_open(const char *ident, int option, int facility) +{ + if (!log_file) + log_file = (FILE *)fopen(LOG_FILE_PATH, "a+"); +} + +void __connman_log_close(void) +{ + fclose(log_file); + log_file = NULL; +} + +static void __connman_log_update_file_revision(int rev) +{ + int next_log_rev = 0; + char *log_file = NULL; + char *next_log_file = NULL; + + next_log_rev = rev + 1; + + log_file = g_strdup_printf("%s.%d", LOG_FILE_PATH, rev); + next_log_file = g_strdup_printf("%s.%d", LOG_FILE_PATH, next_log_rev); + + if (next_log_rev >= MAX_LOG_COUNT) + remove(next_log_file); + + if (access(next_log_file, F_OK) == 0) + __connman_log_update_file_revision(next_log_rev); + + if (rename(log_file, next_log_file) != 0) + remove(log_file); + + g_free(log_file); + g_free(next_log_file); +} + +static void __connman_log_make_backup(void) +{ + const int rev = 0; + char *backup = NULL; + + backup = g_strdup_printf("%s.%d", LOG_FILE_PATH, rev); + + if (access(backup, F_OK) == 0) + __connman_log_update_file_revision(rev); + + if (rename(LOG_FILE_PATH, backup) != 0) + remove(LOG_FILE_PATH); + + g_free(backup); +} + +static void __connman_log_get_local_time(char *strtime, const int size) +{ + struct timeval tv; + struct tm *local_ptm; + char buf[32]; + + gettimeofday(&tv, NULL); + local_ptm = localtime(&tv.tv_sec); + + strftime(buf, sizeof(buf), "%m/%d %H:%M:%S", local_ptm); + snprintf(strtime, size, "%s.%03ld", buf, tv.tv_usec / 1000); +} + +void __connman_log(const int log_priority, const char *format, va_list ap) +{ + int log_size = 0; + struct stat buf; + char str[256]; + char strtime[40]; + + if (!log_file) + log_file = (FILE *)fopen(LOG_FILE_PATH, "a+"); + + if (!log_file) + return; + + fstat(fileno(log_file), &buf); + log_size = buf.st_size; + + if (log_size >= MAX_LOG_SIZE) { + fclose(log_file); + log_file = NULL; + + __connman_log_make_backup(); + + log_file = (FILE *)fopen(LOG_FILE_PATH, "a+"); + + if (!log_file) + return; + } + + __connman_log_get_local_time(strtime, sizeof(strtime)); + + if (vsnprintf(str, sizeof(str), format, ap) > 0) + fprintf(log_file, "%s %s\n", strtime, str); +} + +void __connman_log_s(int log_priority, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + + vsyslog(LOG_DEBUG, format, ap); + + va_end(ap); +} +#endif + /** * connman_info: * @format: format string @@ -89,6 +216,7 @@ void connman_error(const char *format, ...) vsyslog(LOG_ERR, format, ap); va_end(ap); + fflush(log_file); } /** @@ -107,13 +235,116 @@ void connman_debug(const char *format, ...) vsyslog(LOG_DEBUG, format, ap); va_end(ap); + fflush(log_file); +} + +static void print_backtrace(unsigned int offset) +{ + void *frames[99]; + size_t n_ptrs; + unsigned int i; + int outfd[2], infd[2]; + int pathlen; + pid_t pid; + + if (!program_exec) + return; + + pathlen = strlen(program_path); + + n_ptrs = backtrace(frames, G_N_ELEMENTS(frames)); + if (n_ptrs < offset) + return; + + if (pipe(outfd) < 0) + return; + + if (pipe(infd) < 0) { + close(outfd[0]); + close(outfd[1]); + return; + } + + pid = fork(); + if (pid < 0) { + close(outfd[0]); + close(outfd[1]); + close(infd[0]); + close(infd[1]); + return; + } + + if (pid == 0) { + close(outfd[1]); + close(infd[0]); + + dup2(outfd[0], STDIN_FILENO); + dup2(infd[1], STDOUT_FILENO); + + execlp("addr2line", "-C", "-f", "-e", program_exec, NULL); + + exit(EXIT_FAILURE); + } + + close(outfd[0]); + close(infd[1]); + + connman_error("++++++++ backtrace ++++++++"); + + for (i = offset; i < n_ptrs - 1; i++) { + Dl_info info; + char addr[20], buf[PATH_MAX * 2]; + int len, written; + char *ptr, *pos; + + dladdr(frames[i], &info); + + len = snprintf(addr, sizeof(addr), "%p\n", frames[i]); + if (len < 0) + break; + + written = write(outfd[1], addr, len); + if (written < 0) + break; + + len = read(infd[0], buf, sizeof(buf) - 1); + if (len < 0) + break; + + buf[len] = '\0'; + + pos = strchr(buf, '\n'); + *pos++ = '\0'; + + if (strcmp(buf, "??") == 0) { + connman_error("#%-2u %p in %s", i - offset, + frames[i], info.dli_fname); + continue; + } + + ptr = strchr(pos, '\n'); + *ptr++ = '\0'; + + if (strncmp(pos, program_path, pathlen) == 0) + pos += pathlen + 1; + + connman_error("#%-2u %p in %s() at %s", i - offset, + frames[i], buf, pos); + } + + connman_error("+++++++++++++++++++++++++++"); + + kill(pid, SIGTERM); + + close(outfd[1]); + close(infd[0]); } static void signal_handler(int signo) { connman_error("Aborting (signal %d) [%s]", signo, program_exec); - print_backtrace(program_path, program_exec, 2); + print_backtrace(2); exit(EXIT_FAILURE); } diff --git a/src/machine.c b/src/machine.c index 14ea3667..14ea3667 100644..100755 --- a/src/machine.c +++ b/src/machine.c diff --git a/src/main.c b/src/main.c index b78a0461..4bc2266b 100644..100755 --- a/src/main.c +++ b/src/main.c @@ -30,6 +30,8 @@ #include <string.h> #include <signal.h> #include <sys/signalfd.h> +#include <sys/types.h> +#include <sys/resource.h> #include <getopt.h> #include <sys/stat.h> #include <net/if.h> @@ -79,6 +81,10 @@ static struct { bool enable_6to4; char *vendor_class_id; bool enable_online_check; +#if defined TIZEN_EXT + char **cellular_interfaces; + bool tizen_tv_extension; +#endif } connman_settings = { .bg_scan = true, .pref_timeservers = NULL, @@ -96,6 +102,10 @@ static struct { .enable_6to4 = false, .vendor_class_id = NULL, .enable_online_check = true, +#if defined TIZEN_EXT + .cellular_interfaces = NULL, + .tizen_tv_extension = false, +#endif }; #define CONF_BG_SCAN "BackgroundScanning" @@ -114,6 +124,10 @@ static struct { #define CONF_ENABLE_6TO4 "Enable6to4" #define CONF_VENDOR_CLASS_ID "VendorClassID" #define CONF_ENABLE_ONLINE_CHECK "EnableOnlineCheck" +#if defined TIZEN_EXT +#define CONF_CELLULAR_INTERFACE "NetworkCellularInterfaceList" +#define CONF_TIZEN_TV_EXT "TizenTVExtension" +#endif static const char *supported_options[] = { CONF_BG_SCAN, @@ -130,8 +144,11 @@ static const char *supported_options[] = { CONF_TETHERING_TECHNOLOGIES, CONF_PERSISTENT_TETHERING_MODE, CONF_ENABLE_6TO4, - CONF_VENDOR_CLASS_ID, CONF_ENABLE_ONLINE_CHECK, +#if defined TIZEN_EXT + CONF_CELLULAR_INTERFACE, + CONF_TIZEN_TV_EXT, +#endif NULL }; @@ -246,6 +263,46 @@ static void check_config(GKeyFile *config) g_strfreev(keys); } +#if defined TIZEN_EXT +static void check_Tizen_configuration(GKeyFile *config) +{ + GError *error = NULL; + char **cellular_interfaces; + bool boolean; + gsize len; + + cellular_interfaces = g_key_file_get_string_list(config, "General", + CONF_CELLULAR_INTERFACE, &len, &error); + + if (error == NULL) + connman_settings.cellular_interfaces = cellular_interfaces; + + g_clear_error(&error); + + boolean = __connman_config_get_bool(config, "General", + CONF_TIZEN_TV_EXT, &error); + if (!error) + connman_settings.tizen_tv_extension = boolean; + + g_clear_error(&error); +} + +static void set_nofile_inc(void) +{ + int err; + struct rlimit rlim; + + rlim.rlim_cur = 8192; + rlim.rlim_max = 8192; + + err = setrlimit(RLIMIT_NOFILE, &rlim); + if (err) + DBG("fail to increase FILENO err(%d)", err); + + return; +} +#endif + static void parse_config(GKeyFile *config) { GError *error = NULL; @@ -408,12 +465,19 @@ static void parse_config(GKeyFile *config) } g_clear_error(&error); + +#if defined TIZEN_EXT + check_Tizen_configuration(config); +#endif } static int config_init(const char *file) { GKeyFile *config; +#if defined TIZEN_EXT + set_nofile_inc(); +#endif config = load_config(file); check_config(config); parse_config(config); @@ -632,6 +696,11 @@ char **connman_setting_get_string_list(const char *key) if (g_str_equal(key, CONF_TETHERING_TECHNOLOGIES)) return connman_settings.tethering_technologies; +#if defined TIZEN_EXT + if (g_str_equal(key, CONF_CELLULAR_INTERFACE)) + return connman_settings.cellular_interfaces; +#endif + return NULL; } @@ -768,8 +837,10 @@ int main(int argc, char *argv[]) __connman_dhcpv6_init(); __connman_wpad_init(); __connman_wispr_init(); +#if !defined TIZEN_EXT __connman_rfkill_init(); __connman_machine_init(); +#endif g_free(option_config); g_free(option_device); @@ -781,8 +852,10 @@ int main(int argc, char *argv[]) g_source_remove(signal); +#if !defined TIZEN_EXT __connman_machine_cleanup(); __connman_rfkill_cleanup(); +#endif __connman_wispr_cleanup(); __connman_wpad_cleanup(); __connman_dhcpv6_cleanup(); diff --git a/src/main.conf b/src/main.conf index 68870b28..a2cc1e20 100644..100755 --- 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 = wifi, ethernet # 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,ve-,vb-. # NetworkInterfaceBlacklist = vmnet,vboxnet,virbr,ifb,ve-,vb- +NetworkInterfaceBlacklist = veth, vmnet,vboxnet,virbr,usb,rndis,rmnet,rev_rmnet,dummy,seth_td,seth_w # Allow connman to change the system hostname. This can # happen for example if we receive DHCP hostname option. @@ -76,6 +80,7 @@ # setting enabled applications will notice more network breaks than # normal. Default value is false. # SingleConnectedTechnology = false +SingleConnectedTechnology = true # List of technologies for which tethering is allowed separated by ",". # The default value is wifi,bluetooth,gadget. Only those technologies @@ -117,3 +122,5 @@ # other which is already connected. # This setting has no effect if SingleConnectedTechnologies is enabled. # AlwaysConnectedTechnologies = + +NetworkCellularInterfaceList = pdp,rmnet,seth_td,seth_w diff --git a/src/main_disable_eth.conf b/src/main_disable_eth.conf new file mode 100755 index 00000000..c4ec3e38 --- /dev/null +++ b/src/main_disable_eth.conf @@ -0,0 +1,110 @@ +[General] + +# Set input request timeout. Default is 120 seconds +# The request for inputs like passphrase will timeout +# after certain amount of time. Use this setting to +# increase the value in case of different user +# interface designs. +# InputRequestTimeout = 120 + +# Set browser launch timeout. Default is 300 seconds +# The request for launching a browser for portal pages +# will timeout after certain amount of time. Use this +# setting to increase the value in case of different +# user interface designs. +# BrowserLaunchTimeout = 300 + +# Enable background scanning. Default is true. +# Background scanning will start every 5 minutes unless +# the scan list is empty. In that case, a simple backoff +# mechanism starting from 10s up to 5 minutes will run. +# BackgroundScanning = true +BackgroundScanning = false + +# List of Fallback timeservers separated by ",". +# These timeservers are used for NTP sync when there are +# no timeserver set by the user or by the service. +# These can contain mixed combination of fully qualified +# domain names, IPv4 and IPv6 addresses. +# FallbackTimeservers = +#FallbackTimeservers = pool.ntp.org + +# List of fallback nameservers separated by "," used if no +# nameservers are otherwise provided by the service. The +# nameserver entries must be in numeric format, host +# names are ignored. +# FallbackNameservers = + +# List of technologies that are marked autoconnectable +# by default, separated by commas ",". The default value +# for this entry when empty is ethernet,wifi,cellular. +# Services that are automatically connected must have been +# set up and saved to storage beforehand. +# DefaultAutoConnectTechnologies = + +# List of preferred technologies from the most preferred +# one to the least preferred one separated by commas ",". +# Services of the listed technology type will be tried one +# by one in the order given, until one of them gets connected +# or they are all tried. A service of a preferred technology +# type in state 'ready' will get the default route when +# compared to another preferred type further down the list +# with state 'ready' or with a non-preferred type; a service +# of a preferred technology type in state 'online' will get +# the default route when compared to either a non-preferred +# type or a preferred type further down in the list. +# PreferredTechnologies = +PreferredTechnologies = wifi, ethernet + +# List of blacklisted network interfaces separated by ",". +# Found interfaces will be compared to the list and will +# not be handled by connman, if their first characters +# match any of the list entries. Default value is +# vmnet,vboxnet,virbr,ifb. +# NetworkInterfaceBlacklist = vmnet,vboxnet,virbr,ifb +NetworkInterfaceBlacklist = veth, vmnet,vboxnet,virbr,usb,rndis,rmnet,rev_rmnet,dummy,seth_td,seth_w,eth + +# Allow connman to change the system hostname. This can +# happen for example if we receive DHCP hostname option. +# Default value is true. +# AllowHostnameUpdates = true + +# Keep only a single connected technology at any time. When a new +# service is connected by the user or a better one is found according +# to PreferredTechnologies, the new service is kept connected and all +# the other previously connected services are disconnected. With this +# setting it does not matter whether the previously connected services +# are in 'online' or 'ready' states, the newly connected service is +# the only one that will be kept connected. A service connected by the +# user will be used until going out of network coverage. With this +# setting enabled applications will notice more network breaks than +# normal. Default value is false. +# SingleConnectedTechnology = false +SingleConnectedTechnology = true + +# List of technologies for which tethering is allowed separated by ",". +# The default value is wifi,bluetooth,gadget. Only those technologies +# listed here are used for tethering. If ethernet tethering is desired, +# then ethernet should be added to the list. The technologies listed here +# have to support tethering, currently tethering is implemented for wifi, +# bluetooth, gadget and ethernet. +# NOTE that if ethernet tethering is enabled, then a DHCP server is +# started on all ethernet interfaces. Tethered ethernet should +# never be connected to corporate or home network as it will disrupt +# normal operation of these networks. Due to this ethernet is not +# tethered by default. Do not activate ethernet tethering unless you +# really know what you are doing. +# TetheringTechnologies = wifi,bluetooth,gadget + +# Restore earlier tethering status when returning from offline mode, +# re-enabling a technology, and after restarts and reboots. +# Default value is false. +# PersistentTetheringMode = false + +# Automatically enable Anycast 6to4 if possible. This is not recommended, as +# the use of 6to4 will generally lead to a severe degradation of connection +# quality. See RFC6343. Default value is false (as recommended by RFC6343 +# section 4.1). +# Enable6to4 = false + +NetworkCellularInterfaceList = pdp,rmnet,seth_td,seth_w diff --git a/src/main_ivi.conf b/src/main_ivi.conf new file mode 100755 index 00000000..627bd061 --- /dev/null +++ b/src/main_ivi.conf @@ -0,0 +1,110 @@ +[General] + +# Set input request timeout. Default is 120 seconds +# The request for inputs like passphrase will timeout +# after certain amount of time. Use this setting to +# increase the value in case of different user +# interface designs. +# InputRequestTimeout = 120 + +# Set browser launch timeout. Default is 300 seconds +# The request for launching a browser for portal pages +# will timeout after certain amount of time. Use this +# setting to increase the value in case of different +# user interface designs. +# BrowserLaunchTimeout = 300 + +# Enable background scanning. Default is true. +# Background scanning will start every 5 minutes unless +# the scan list is empty. In that case, a simple backoff +# mechanism starting from 10s up to 5 minutes will run. +# BackgroundScanning = true +BackgroundScanning = false + +# List of Fallback timeservers separated by ",". +# These timeservers are used for NTP sync when there are +# no timeserver set by the user or by the service. +# These can contain mixed combination of fully qualified +# domain names, IPv4 and IPv6 addresses. +# FallbackTimeservers = +#FallbackTimeservers = pool.ntp.org + +# List of fallback nameservers separated by "," used if no +# nameservers are otherwise provided by the service. The +# nameserver entries must be in numeric format, host +# names are ignored. +# FallbackNameservers = + +# List of technologies that are marked autoconnectable +# by default, separated by commas ",". The default value +# for this entry when empty is ethernet,wifi,cellular. +# Services that are automatically connected must have been +# set up and saved to storage beforehand. +# DefaultAutoConnectTechnologies = + +# List of preferred technologies from the most preferred +# one to the least preferred one separated by commas ",". +# Services of the listed technology type will be tried one +# by one in the order given, until one of them gets connected +# or they are all tried. A service of a preferred technology +# type in state 'ready' will get the default route when +# compared to another preferred type further down the list +# with state 'ready' or with a non-preferred type; a service +# of a preferred technology type in state 'online' will get +# the default route when compared to either a non-preferred +# type or a preferred type further down in the list. +# PreferredTechnologies = +PreferredTechnologies = wifi, ethernet + +# List of blacklisted network interfaces separated by ",". +# Found interfaces will be compared to the list and will +# not be handled by connman, if their first characters +# match any of the list entries. Default value is +# vmnet,vboxnet,virbr,ifb. +# NetworkInterfaceBlacklist = vmnet,vboxnet,virbr,ifb +NetworkInterfaceBlacklist = veth, vmnet,vboxnet,virbr,usb,rndis,rmnet,rev_rmnet,dummy,seth_td,seth_w,eth0 + +# Allow connman to change the system hostname. This can +# happen for example if we receive DHCP hostname option. +# Default value is true. +# AllowHostnameUpdates = true + +# Keep only a single connected technology at any time. When a new +# service is connected by the user or a better one is found according +# to PreferredTechnologies, the new service is kept connected and all +# the other previously connected services are disconnected. With this +# setting it does not matter whether the previously connected services +# are in 'online' or 'ready' states, the newly connected service is +# the only one that will be kept connected. A service connected by the +# user will be used until going out of network coverage. With this +# setting enabled applications will notice more network breaks than +# normal. Default value is false. +# SingleConnectedTechnology = false +SingleConnectedTechnology = true + +# List of technologies for which tethering is allowed separated by ",". +# The default value is wifi,bluetooth,gadget. Only those technologies +# listed here are used for tethering. If ethernet tethering is desired, +# then ethernet should be added to the list. The technologies listed here +# have to support tethering, currently tethering is implemented for wifi, +# bluetooth, gadget and ethernet. +# NOTE that if ethernet tethering is enabled, then a DHCP server is +# started on all ethernet interfaces. Tethered ethernet should +# never be connected to corporate or home network as it will disrupt +# normal operation of these networks. Due to this ethernet is not +# tethered by default. Do not activate ethernet tethering unless you +# really know what you are doing. +# TetheringTechnologies = wifi,bluetooth,gadget + +# Restore earlier tethering status when returning from offline mode, +# re-enabling a technology, and after restarts and reboots. +# Default value is false. +# PersistentTetheringMode = false + +# Automatically enable Anycast 6to4 if possible. This is not recommended, as +# the use of 6to4 will generally lead to a severe degradation of connection +# quality. See RFC6343. Default value is false (as recommended by RFC6343 +# section 4.1). +# Enable6to4 = false + +NetworkCellularInterfaceList = pdp,rmnet,seth_td,seth_w diff --git a/src/main_tv.conf b/src/main_tv.conf new file mode 100755 index 00000000..fd3afc90 --- /dev/null +++ b/src/main_tv.conf @@ -0,0 +1,116 @@ +[General] + +# Set input request timeout. Default is 120 seconds +# The request for inputs like passphrase will timeout +# after certain amount of time. Use this setting to +# increase the value in case of different user +# interface designs. +# InputRequestTimeout = 120 + +# Set browser launch timeout. Default is 300 seconds +# The request for launching a browser for portal pages +# will timeout after certain amount of time. Use this +# setting to increase the value in case of different +# user interface designs. +# BrowserLaunchTimeout = 300 + +# Enable background scanning. Default is true. +# Background scanning will start every 5 minutes unless +# the scan list is empty. In that case, a simple backoff +# mechanism starting from 10s up to 5 minutes will run. +# BackgroundScanning = true +BackgroundScanning = false + +# List of Fallback timeservers separated by ",". +# These timeservers are used for NTP sync when there are +# no timeserver set by the user or by the service. +# These can contain mixed combination of fully qualified +# domain names, IPv4 and IPv6 addresses. +# FallbackTimeservers = +#FallbackTimeservers = pool.ntp.org + +# List of fallback nameservers separated by "," used if no +# nameservers are otherwise provided by the service. The +# nameserver entries must be in numeric format, host +# names are ignored. +# FallbackNameservers = + +# List of technologies that are marked autoconnectable +# by default, separated by commas ",". The default value +# for this entry when empty is ethernet,wifi,cellular. +# Services that are automatically connected must have been +# set up and saved to storage beforehand. +# DefaultAutoConnectTechnologies = + +# List of preferred technologies from the most preferred +# one to the least preferred one separated by commas ",". +# Services of the listed technology type will be tried one +# by one in the order given, until one of them gets connected +# or they are all tried. A service of a preferred technology +# type in state 'ready' will get the default route when +# compared to another preferred type further down the list +# with state 'ready' or with a non-preferred type; a service +# of a preferred technology type in state 'online' will get +# the default route when compared to either a non-preferred +# type or a preferred type further down in the list. +# PreferredTechnologies = +PreferredTechnologies = wifi, ethernet + +# List of blacklisted network interfaces separated by ",". +# Found interfaces will be compared to the list and will +# not be handled by connman, if their first characters +# match any of the list entries. Default value is +# vmnet,vboxnet,virbr,ifb. +# NetworkInterfaceBlacklist = vmnet,vboxnet,virbr,ifb +NetworkInterfaceBlacklist = veth, vmnet,vboxnet,virbr,usb,rndis,rmnet,rev_rmnet,dummy,seth_td,seth_w + +# Allow connman to change the system hostname. This can +# happen for example if we receive DHCP hostname option. +# Default value is true. +# AllowHostnameUpdates = true + +# Keep only a single connected technology at any time. When a new +# service is connected by the user or a better one is found according +# to PreferredTechnologies, the new service is kept connected and all +# the other previously connected services are disconnected. With this +# setting it does not matter whether the previously connected services +# are in 'online' or 'ready' states, the newly connected service is +# the only one that will be kept connected. A service connected by the +# user will be used until going out of network coverage. With this +# setting enabled applications will notice more network breaks than +# normal. Default value is false. +# SingleConnectedTechnology = false +SingleConnectedTechnology = true + +# List of technologies for which tethering is allowed separated by ",". +# The default value is wifi,bluetooth,gadget. Only those technologies +# listed here are used for tethering. If ethernet tethering is desired, +# then ethernet should be added to the list. The technologies listed here +# have to support tethering, currently tethering is implemented for wifi, +# bluetooth, gadget and ethernet. +# NOTE that if ethernet tethering is enabled, then a DHCP server is +# started on all ethernet interfaces. Tethered ethernet should +# never be connected to corporate or home network as it will disrupt +# normal operation of these networks. Due to this ethernet is not +# tethered by default. Do not activate ethernet tethering unless you +# really know what you are doing. +# TetheringTechnologies = wifi,bluetooth,gadget + +# Restore earlier tethering status when returning from offline mode, +# re-enabling a technology, and after restarts and reboots. +# Default value is false. +# PersistentTetheringMode = false + +# Automatically enable Anycast 6to4 if possible. This is not recommended, as +# the use of 6to4 will generally lead to a severe degradation of connection +# quality. See RFC6343. Default value is false (as recommended by RFC6343 +# section 4.1). +# Enable6to4 = false + +NetworkCellularInterfaceList = pdp,rmnet,seth_td,seth_w + + + +# Enable Tizen TV Profile Features +TizenTVExtension = true + diff --git a/src/manager.c b/src/manager.c index d15ce203..2e1367ff 100644..100755 --- a/src/manager.c +++ b/src/manager.c @@ -41,6 +41,9 @@ static DBusMessage *get_properties(DBusConnection *conn, DBusMessageIter array, dict; dbus_bool_t offlinemode; const char *str; +#if defined TIZEN_EXT + dbus_bool_t autoconnectmode; +#endif DBG("conn %p", conn); @@ -63,6 +66,12 @@ static DBusMessage *get_properties(DBusConnection *conn, connman_dbus_dict_append_basic(&dict, "SessionMode", DBUS_TYPE_BOOLEAN, &sessionmode); +#if defined TIZEN_EXT + autoconnectmode = __connman_service_get_auto_connect_mode(); + connman_dbus_dict_append_basic(&dict, "AutoConnectMode", + DBUS_TYPE_BOOLEAN, + &autoconnectmode); +#endif connman_dbus_dict_close(&array, &dict); @@ -102,6 +111,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")) { @@ -109,8 +132,20 @@ static DBusMessage *set_property(DBusConnection *conn, return __connman_error_invalid_arguments(msg); dbus_message_iter_get_basic(&value, &sessionmode); + } +#if defined TIZEN_EXT + else if (g_str_equal(name, "AutoConnectMode") == TRUE) { + bool automode; - } else + if (type != DBUS_TYPE_BOOLEAN) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_get_basic(&value, &automode); + + __connman_service_set_auto_connect_mode(automode); + } +#endif + else return __connman_error_invalid_property(msg); return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); @@ -126,7 +161,9 @@ static DBusMessage *get_technologies(DBusConnection *conn, { DBusMessage *reply; +#if !defined TIZEN_EXT DBG(""); +#endif reply = dbus_message_new_method_return(msg); if (!reply) diff --git a/src/nat.c b/src/nat.c index fb557101..fb557101 100644..100755 --- a/src/nat.c +++ b/src/nat.c diff --git a/src/net.connman.service.in b/src/net.connman.service.in index f7f6a7c0..990eb66b 100644..100755 --- a/src/net.connman.service.in +++ b/src/net.connman.service.in @@ -1,5 +1,6 @@ [D-BUS Service] Name=net.connman -Exec=@sbindir@/connmand -n -User=root +Exec=/bin/false +User=network_fw +Group=network_fw SystemdService=connman.service diff --git a/src/network.c b/src/network.c index ed56210f..d38fc0af 100644..100755 --- a/src/network.c +++ b/src/network.c @@ -41,6 +41,18 @@ */ #define RS_REFRESH_TIMEOUT 3 +#if defined TIZEN_EXT +#define WIFI_ENCYPTION_MODE_LEN_MAX 6 +#define WIFI_BSSID_LEN_MAX 6 +#endif + +/* + * As per RFC 4861, a host should transmit up to MAX_RTR_SOLICITATIONS(3) + * Router Solicitation messages, each separated by at least + * RTR_SOLICITATION_INTERVAL(4) seconds to obtain RA for IPv6 auto-configuration. + */ +#define RTR_SOLICITATION_INTERVAL 4 + static GSList *network_list = NULL; static GSList *driver_list = NULL; @@ -92,8 +104,26 @@ 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; + bool isHS20AP; + unsigned int keymgmt; + char *keymgmt_type; + bool rsn_mode; + int disconnect_reason; + int assoc_status_code; + void *wifi_vsie; + unsigned int wifi_vsie_len; +#endif } wifi; +#if defined TIZEN_EXT + /* Multiple APN services and a default APN which a user selected */ + bool default_internet; +#endif + }; static const char *type2string(enum connman_network_type type) @@ -167,7 +197,11 @@ static void dhcp_success(struct connman_network *network) if (err < 0) goto err; +#if defined TIZEN_EXT + err = __connman_ipconfig_gateway_add(ipconfig_ipv4, service); +#else err = __connman_ipconfig_gateway_add(ipconfig_ipv4); +#endif if (err < 0) goto err; @@ -233,7 +267,11 @@ static int set_connected_manual(struct connman_network *network) if (err < 0) goto err; +#if defined TIZEN_EXT + err = __connman_ipconfig_gateway_add(ipconfig, service); +#else err = __connman_ipconfig_gateway_add(ipconfig); +#endif if (err < 0) goto err; @@ -287,7 +325,11 @@ static int manual_ipv6_set(struct connman_network *network, return err; } +#if defined TIZEN_EXT + err = __connman_ipconfig_gateway_add(ipconfig_ipv6, service); +#else err = __connman_ipconfig_gateway_add(ipconfig_ipv6); +#endif if (err < 0) return err; @@ -427,10 +469,13 @@ static void check_dhcpv6(struct nd_router_advert *reply, DBG("re-send router solicitation %d", network->router_solicit_count); network->router_solicit_count--; - __connman_inet_ipv6_send_rs(network->index, 1, + __connman_inet_ipv6_send_rs(network->index, RTR_SOLICITATION_INTERVAL, check_dhcpv6, network); return; } +#if defined TIZEN_EXT + DBG("RA message is not received from server in reply of RS."); +#endif connman_network_unref(network); return; } @@ -443,6 +488,9 @@ static void check_dhcpv6(struct nd_router_advert *reply, */ if (!network->connected) { connman_network_unref(network); +#if defined TIZEN_EXT + DBG("Network is not connected"); +#endif return; } @@ -471,11 +519,21 @@ static void check_dhcpv6(struct nd_router_advert *reply, * We do stateful/stateless DHCPv6 if router advertisement says so. */ if (reply->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED) { +#if defined TIZEN_EXT + DBG("IPv6 ND_RA_FLAG_MANAGED"); +#endif __connman_dhcpv6_start(network, prefixes, dhcpv6_callback); } else { if (reply->nd_ra_flags_reserved & ND_RA_FLAG_OTHER) +#if defined TIZEN_EXT + { + DBG("IPv6 ND_RA_FLAG_OTHER"); +#endif __connman_dhcpv6_start_info(network, dhcpv6_info_callback); +#if defined TIZEN_EXT + } +#endif g_slist_free_full(prefixes, g_free); network->connecting = false; @@ -557,6 +615,11 @@ static void autoconf_ipv6_set(struct connman_network *network) __connman_device_set_network(network->device, network); +#if defined TIZEN_EXT + if(network->type == CONNMAN_NETWORK_TYPE_CELLULAR) + return; +#endif + service = connman_service_lookup_from_network(network); if (!service) return; @@ -577,7 +640,8 @@ static void autoconf_ipv6_set(struct connman_network *network) /* Try to get stateless DHCPv6 information, RFC 3736 */ network->router_solicit_count = 3; - __connman_inet_ipv6_send_rs(index, 1, check_dhcpv6, network); + __connman_inet_ipv6_send_rs(index, RTR_SOLICITATION_INTERVAL, + check_dhcpv6, network); } static void set_connected(struct connman_network *network) @@ -690,12 +754,22 @@ static void set_disconnected(struct connman_network *network) CONNMAN_IPCONFIG_TYPE_IPV6); if (network->connected) { +#if defined TIZEN_EXT + /** + * Do not remove gateway and its address, + * if there are connected profiles that use same interface (multiple PDN) + */ + if (connman_service_get_type(service) != CONNMAN_SERVICE_TYPE_CELLULAR || + __connman_service_get_connected_count_of_iface(service) <= 0) { +#endif __connman_connection_gateway_remove(service, CONNMAN_IPCONFIG_TYPE_ALL); __connman_ipconfig_address_unset(ipconfig_ipv4); __connman_ipconfig_address_unset(ipconfig_ipv6); - +#if defined TIZEN_EXT + } +#endif /* * Special handling for IPv6 autoconfigured address. * The simplest way to remove autoconfigured routes is to @@ -905,7 +979,9 @@ static void network_destruct(struct connman_network *network) g_free(network->wifi.private_key_passphrase); g_free(network->wifi.phase2_auth); g_free(network->wifi.pin_wps); - +#if defined TIZEN_EXT + g_free(network->wifi.wifi_vsie); +#endif g_free(network->path); g_free(network->group); g_free(network->node); @@ -1147,6 +1223,15 @@ bool __connman_network_get_weakness(struct connman_network *network) return false; } +#if defined TIZEN_EXT +void connman_network_set_connecting(struct connman_network *network) +{ + DBG("set network connecting true"); + network->connecting = TRUE; + return; +} +#endif + bool connman_network_get_connecting(struct connman_network *network) { return network->connecting; @@ -1162,7 +1247,9 @@ bool connman_network_get_connecting(struct connman_network *network) int connman_network_set_available(struct connman_network *network, bool available) { +#if !defined TIZEN_EXT DBG("network %p available %d", network, available); +#endif if (network->available == available) return -EALREADY; @@ -1183,6 +1270,113 @@ bool connman_network_get_available(struct connman_network *network) return network->available; } +#if defined TIZEN_EXT +void connman_network_clear_associating(struct connman_network *network) +{ + struct connman_service *service; + enum connman_service_state state; + + DBG("network %p", network); + + network->connecting = FALSE; + network->associating = FALSE; + + service = connman_service_lookup_from_network(network); + if (!service) + return; + + state = __connman_service_ipconfig_get_state(service, + CONNMAN_IPCONFIG_TYPE_IPV4); + if (state != CONNMAN_SERVICE_STATE_IDLE && + state != CONNMAN_SERVICE_STATE_FAILURE) + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_DISCONNECT, + CONNMAN_IPCONFIG_TYPE_IPV4); + + state = __connman_service_ipconfig_get_state(service, + CONNMAN_IPCONFIG_TYPE_IPV6); + if (state != CONNMAN_SERVICE_STATE_IDLE && + state != CONNMAN_SERVICE_STATE_FAILURE) + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_DISCONNECT, + CONNMAN_IPCONFIG_TYPE_IPV6); + + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_IDLE, + CONNMAN_IPCONFIG_TYPE_IPV4); + + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_IDLE, + CONNMAN_IPCONFIG_TYPE_IPV6); +} + +static gboolean __connman_network_clear_associating_delayed(gpointer user_data) +{ + GSList *list; + gboolean found = FALSE; + enum connman_service_state state_ipv4; + enum connman_service_state state_ipv6; + struct connman_service *service; + struct connman_network *network = (struct connman_network *)user_data; + + for (list = network_list; list != NULL; list = list->next) { + struct connman_network *item = list->data; + + if (item == network) { + found = TRUE; + break; + } + } + + if (found != TRUE) + return FALSE; + + DBG("network %p name %s", network, network->name); + service = connman_service_lookup_from_network(network); + + state_ipv4 = __connman_service_ipconfig_get_state(service, + CONNMAN_IPCONFIG_TYPE_IPV4); + state_ipv6 = __connman_service_ipconfig_get_state(service, + CONNMAN_IPCONFIG_TYPE_IPV6); + + DBG("service %p state %d/%d", service, state_ipv4, state_ipv6); + + if (network->associating == FALSE && + state_ipv4 == CONNMAN_SERVICE_STATE_ASSOCIATION && + state_ipv6 == CONNMAN_SERVICE_STATE_ASSOCIATION) { + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_IDLE, + CONNMAN_IPCONFIG_TYPE_IPV4); + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_IDLE, + CONNMAN_IPCONFIG_TYPE_IPV6); + } else { + if (network->associating == FALSE) { + struct connman_ipconfig *ipconfig_ipv4, *ipconfig_ipv6; + enum connman_ipconfig_method ipv4_method, ipv6_method; + + ipconfig_ipv4 = __connman_service_get_ip4config(service); + ipv4_method = __connman_ipconfig_get_method(ipconfig_ipv4); + ipconfig_ipv6 = __connman_service_get_ip4config(service); + ipv6_method = __connman_ipconfig_get_method(ipconfig_ipv6); + + if((ipv4_method == CONNMAN_IPCONFIG_METHOD_UNKNOWN || ipv4_method == CONNMAN_IPCONFIG_METHOD_OFF) && + (state_ipv6 == CONNMAN_SERVICE_STATE_ASSOCIATION)) + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_IDLE, + CONNMAN_IPCONFIG_TYPE_IPV6); + if((ipv6_method == CONNMAN_IPCONFIG_METHOD_UNKNOWN || ipv6_method == CONNMAN_IPCONFIG_METHOD_OFF) && + (state_ipv4 == CONNMAN_SERVICE_STATE_ASSOCIATION)) + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_IDLE, + CONNMAN_IPCONFIG_TYPE_IPV4); + } + } + + return FALSE; +} +#endif + /** * connman_network_set_associating: * @network: network structure @@ -1212,6 +1406,14 @@ int connman_network_set_associating(struct connman_network *network, CONNMAN_IPCONFIG_TYPE_IPV6); } +#if defined TIZEN_EXT + if (associating == FALSE && + connman_network_get_bool(network, "WiFi.UseWPS") == FALSE) + g_timeout_add_seconds(1, + __connman_network_clear_associating_delayed, + network); +#endif + return 0; } @@ -1221,8 +1423,13 @@ static void set_associate_error(struct connman_network *network) service = connman_service_lookup_from_network(network); +#if defined TIZEN_EXT + __connman_service_indicate_error(service, + CONNMAN_SERVICE_ERROR_AUTH_FAILED); +#else __connman_service_indicate_error(service, CONNMAN_SERVICE_ERROR_CONNECT_FAILED); +#endif } static void set_configure_error(struct connman_network *network) @@ -1241,6 +1448,10 @@ static void set_invalid_key_error(struct connman_network *network) service = connman_service_lookup_from_network(network); +#if defined TIZEN_EXT + if (service) + __connman_service_set_favorite(service, false); +#endif __connman_service_indicate_error(service, CONNMAN_SERVICE_ERROR_INVALID_KEY); } @@ -1265,6 +1476,22 @@ static void set_blocked_error(struct connman_network *network) CONNMAN_SERVICE_ERROR_BLOCKED); } + +#if defined TIZEN_EXT +static void set_dhcp_error(struct connman_network *network) +{ + struct connman_service *service; + + if (network->associating != FALSE) + network->associating = FALSE; + + service = connman_service_lookup_from_network(network); + + __connman_service_indicate_error(service, + CONNMAN_SERVICE_ERROR_DHCP_FAILED); +} +#endif + void connman_network_set_ipv4_method(struct connman_network *network, enum connman_ipconfig_method method) { @@ -1319,9 +1546,16 @@ void connman_network_set_error(struct connman_network *network, case CONNMAN_NETWORK_ERROR_CONNECT_FAIL: set_connect_error(network); break; +#if defined TIZEN_EXT + case CONNMAN_NETWORK_ERROR_DHCP_FAIL: + set_dhcp_error(network); + break; +#endif + case CONNMAN_NETWORK_ERROR_BLOCKED: set_blocked_error(network); break; + } __connman_network_disconnect(network); @@ -1461,13 +1695,21 @@ int __connman_network_connect(struct connman_network *network) network->connecting = true; +#if defined TIZEN_EXT + if (network->type != CONNMAN_NETWORK_TYPE_CELLULAR) +#endif __connman_device_disconnect(network->device); - +#if defined TIZEN_EXT + DBG("ConnMan, Connect Request [%s]", network->name); +#endif err = network->driver->connect(network); if (err < 0) { - if (err == -EINPROGRESS) + if (err == -EINPROGRESS) { +#if defined TIZEN_EXT + if (network->type != CONNMAN_NETWORK_TYPE_CELLULAR) +#endif connman_network_set_associating(network, true); - else + } else network->connecting = false; return err; @@ -1498,7 +1740,9 @@ int __connman_network_disconnect(struct connman_network *network) return -EUNATCH; network->connecting = false; - +#if defined TIZEN_EXT + DBG("ConnMan, Disconnect request"); +#endif if (network->driver->disconnect) err = network->driver->disconnect(network); @@ -1552,12 +1796,38 @@ int __connman_network_clear_ipconfig(struct connman_network *network, return 0; } +#if defined TIZEN_EXT +void __connman_network_set_auto_ipv6_gateway(char *gateway, void *user_data) +{ + DBG(""); + + struct connman_network *network = user_data; + struct connman_service *service; + struct connman_ipconfig *ipconfig = NULL; + + service = connman_service_lookup_from_network(network); + if (service == NULL) + return; + + ipconfig = __connman_service_get_ipconfig(service, AF_INET6); + if (ipconfig == NULL) + return; + + __connman_ipconfig_set_gateway(ipconfig, gateway); + + return; +} +#endif + int __connman_network_enable_ipconfig(struct connman_network *network, struct connman_ipconfig *ipconfig) { int r = 0; enum connman_ipconfig_type type; enum connman_ipconfig_method method; +#if defined TIZEN_EXT + struct connman_service *service; +#endif if (!network || !ipconfig) return -EINVAL; @@ -1585,6 +1855,14 @@ int __connman_network_enable_ipconfig(struct connman_network *network, break; case CONNMAN_IPCONFIG_METHOD_AUTO: +#if defined TIZEN_EXT + service = connman_service_lookup_from_network(network); + + if(network->type == CONNMAN_NETWORK_TYPE_CELLULAR) + __connman_service_ipconfig_indicate_state(service, + CONNMAN_SERVICE_STATE_CONFIGURATION, + CONNMAN_IPCONFIG_TYPE_IPV6); +#endif autoconf_ipv6_set(network); break; @@ -1661,6 +1939,142 @@ 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) +{ +#if !defined TIZEN_EXT + DBG("network %p maxrate %d", network, maxrate); +#endif + + network->wifi.maxrate = maxrate; + + return 0; +} + +unsigned int connman_network_get_maxrate(struct connman_network *network) +{ + return network->wifi.maxrate; +} + +int connman_network_set_enc_mode(struct connman_network *network, + const char *encryption_mode) +{ + if (encryption_mode == NULL) + return -EINVAL; + + DBG("network %p encryption mode %s", network, encryption_mode); + + g_strlcpy(network->wifi.encryption_mode, encryption_mode, + WIFI_ENCYPTION_MODE_LEN_MAX); + + return 0; +} + +const char *connman_network_get_enc_mode(struct connman_network *network) +{ + return (const char *)network->wifi.encryption_mode; +} + +int connman_network_set_rsn_mode(struct connman_network *network, + bool rsn_mode) +{ + network->wifi.rsn_mode = rsn_mode; + + return 0; +} + +int connman_network_set_proxy(struct connman_network *network, + const char *proxies) +{ + struct connman_service *service; + + DBG("network %p proxies %s", network, proxies); + + service = connman_service_lookup_from_network(network); + if (service == NULL) + return -EINVAL; + + __connman_service_set_proxy(service, proxies); + + connman_service_set_proxy_method(service, + CONNMAN_SERVICE_PROXY_METHOD_MANUAL); + + return 0; +} + +int connman_network_set_keymgmt(struct connman_network *network, + unsigned int keymgmt) +{ + if (network == NULL) + return 0; + + network->wifi.keymgmt = keymgmt; + + return 0; +} + +unsigned int connman_network_get_keymgmt(struct connman_network *network) +{ + if (network == NULL) + return 0; + + return network->wifi.keymgmt; +} + +int connman_network_set_disconnect_reason(struct connman_network *network, + int reason_code) +{ + if (network == NULL) + return 0; + + network->wifi.disconnect_reason = reason_code; + + return 0; +} + +int connman_network_get_disconnect_reason(struct connman_network *network) +{ + if (network == NULL) + return 0; + + return network->wifi.disconnect_reason; +} +int connman_network_get_assoc_status_code(struct connman_network *network) +{ + if (network == NULL) + return 0; + + return network->wifi.assoc_status_code; +} +#endif + int connman_network_set_nameservers(struct connman_network *network, const char *nameservers) { @@ -1682,8 +2096,14 @@ int connman_network_set_nameservers(struct connman_network *network, nameservers_array = g_strsplit(nameservers, " ", 0); for (i = 0; nameservers_array[i]; i++) { +#if defined TIZEN_EXT + __connman_service_nameserver_append(service, + nameservers_array[i], false, + CONNMAN_IPCONFIG_TYPE_ALL); +#else __connman_service_nameserver_append(service, nameservers_array[i], false); +#endif } g_strfreev(nameservers_array); @@ -1799,6 +2219,9 @@ int connman_network_set_string(struct connman_network *network, g_free(network->wifi.security); network->wifi.security = g_strdup(value); } else if (g_str_equal(key, "WiFi.Passphrase")) { +#if defined TIZEN_EXT + DBG("ConnMan, %p key %s", network, key); +#endif g_free(network->wifi.passphrase); network->wifi.passphrase = g_strdup(value); } else if (g_str_equal(key, "WiFi.EAP")) { @@ -1869,7 +2292,15 @@ const char *connman_network_get_string(struct connman_network *network, else if (g_str_equal(key, "WiFi.Mode")) return network->wifi.mode; else if (g_str_equal(key, "WiFi.Security")) +#if defined TIZEN_EXT + if (network->wifi.rsn_mode != true || + g_str_equal(network->wifi.security, "ieee8021x")) + return network->wifi.security; + else + return "rsn"; +#else return network->wifi.security; +#endif else if (g_str_equal(key, "WiFi.Passphrase")) return network->wifi.passphrase; else if (g_str_equal(key, "WiFi.EAP")) @@ -1921,6 +2352,12 @@ int connman_network_set_bool(struct connman_network *network, network->wifi.wps = value; else if (g_strcmp0(key, "WiFi.UseWPS") == 0) network->wifi.use_wps = value; +#if defined TIZEN_EXT + else if (g_strcmp0(key, "DefaultInternet") == 0) + network->default_internet = value; + else if (g_strcmp0(key, "WiFi.HS20AP") == 0) + network->wifi.isHS20AP = value; +#endif return -EINVAL; } @@ -1941,6 +2378,12 @@ bool connman_network_get_bool(struct connman_network *network, return network->wifi.wps; else if (g_str_equal(key, "WiFi.UseWPS")) return network->wifi.use_wps; +#if defined TIZEN_EXT + else if (g_str_equal(key, "DefaultInternet")) + return network->default_internet; + else if (g_str_equal(key, "WiFi.HS20AP")) + return network->wifi.isHS20AP; +#endif return false; } @@ -1965,6 +2408,16 @@ int connman_network_set_blob(struct connman_network *network, network->wifi.ssid_len = size; } else network->wifi.ssid_len = 0; +#if defined TIZEN_EXT + } else if (g_str_equal(key, "WiFi.Vsie")){ + g_free(network->wifi.wifi_vsie); + network->wifi.wifi_vsie = g_try_malloc(size); + if (network->wifi.wifi_vsie) { + memcpy(network->wifi.wifi_vsie, data, size); + network->wifi.wifi_vsie_len = size; + } else + network->wifi.wifi_vsie_len = 0; +#endif } else { return -EINVAL; } @@ -1989,6 +2442,15 @@ const void *connman_network_get_blob(struct connman_network *network, return network->wifi.ssid; } +#if defined TIZEN_EXT + if (g_str_equal(key, "WiFi.Vsie")) { + if (size) + *size = network->wifi.wifi_vsie_len; + + return network->wifi.wifi_vsie; + } +#endif + return NULL; } diff --git a/src/notifier.c b/src/notifier.c index 5ba53242..5ba53242 100644..100755 --- a/src/notifier.c +++ b/src/notifier.c diff --git a/src/ntp.c b/src/ntp.c index 0e80c3e5..11512a02 100644..100755 --- a/src/ntp.c +++ b/src/ntp.c @@ -251,8 +251,9 @@ static void decode_msg(void *base, size_t len, struct timeval *tv, double m_delta, org, rec, xmt, dst; double delay, offset; static guint transmit_delay; +#if !defined TIZEN_EXT struct timex tmx = {}; - +#endif if (len < sizeof(*msg)) { connman_error("Invalid response from time server"); return; @@ -341,6 +342,66 @@ static void decode_msg(void *base, size_t len, struct timeval *tv, poll_id = g_timeout_add_seconds(transmit_delay, next_poll, NULL); +#if defined TIZEN_EXT + //send the dbus message to alram-manager + { +#define TIME_BUS_NAME "org.tizen.alarm.manager" +#define TIME_INTERFACE "org.tizen.alarm.manager" +#define TIME_PATH "/org/tizen/alarm/manager" +#define TIME_METHOD "alarm_set_time_with_propagation_delay" + + struct timespec cur = {0}; + struct timespec req = {0}; + double dtime; + + DBusConnection *connection = NULL; + DBusMessage *msg = NULL, *reply = NULL; + DBusError error; + + dbus_error_init(&error); + + connection = connman_dbus_get_connection(); + if(!connection){ + DBG("dbus connection does not exist"); + return; + } + + clock_gettime(CLOCK_REALTIME, &cur); + dtime = offset + cur.tv_sec + 1.0e-9 * cur.tv_nsec; + cur.tv_sec = (long) dtime; + cur.tv_nsec = (dtime - cur.tv_sec) * 1000000000; + + clock_gettime(CLOCK_REALTIME, &req); + msg = dbus_message_new_method_call(TIME_BUS_NAME, TIME_PATH, + TIME_INTERFACE, TIME_METHOD); + dbus_message_append_args(msg, DBUS_TYPE_UINT32, &(cur.tv_sec), + DBUS_TYPE_UINT32, &(cur.tv_nsec), + DBUS_TYPE_UINT32, &(req.tv_sec), + DBUS_TYPE_UINT32, &(req.tv_nsec), DBUS_TYPE_INVALID); + reply = dbus_connection_send_with_reply_and_block(connection, msg, + DBUS_TIMEOUT_USE_DEFAULT, &error); + if(reply == NULL){ + if(dbus_error_is_set(&error)){ + DBG("%s", error.message); + dbus_error_free(&error); + } + else{ + DBG("Failed to request set time"); + } + dbus_connection_unref(connection); + dbus_message_unref(msg); + return; + } + + dbus_message_unref(msg); + dbus_message_unref(reply); + dbus_connection_unref(connection); + + DBG("%lu cur seconds, %lu cur nsecs, %lu req seconds, %lu req nsecs", + cur.tv_sec, cur.tv_nsec, req.tv_sec, req.tv_nsec); + DBG("setting time"); + } +#else if (offset < STEPTIME_MIN_OFFSET && offset > -STEPTIME_MIN_OFFSET) { tmx.modes = ADJ_STATUS | ADJ_NANO | ADJ_OFFSET | ADJ_TIMECONST | ADJ_MAXERROR | ADJ_ESTERROR; tmx.status = STA_PLL; @@ -379,7 +440,8 @@ static void decode_msg(void *base, size_t len, struct timeval *tv, } DBG("interval/delta/delay/drift %fs/%+.3fs/%.3fs/%+ldppm", - LOGTOD(msg->poll), offset, delay, tmx.freq / 65536); + LOGTOD(msg->poll), offset, delay, tmx.freq / 65536); +#endif } static gboolean received_data(GIOChannel *channel, GIOCondition condition, diff --git a/src/peer.c b/src/peer.c index 340cbcc2..340cbcc2 100644..100755 --- a/src/peer.c +++ b/src/peer.c diff --git a/src/peer_service.c b/src/peer_service.c index a457bff7..a457bff7 100644..100755 --- a/src/peer_service.c +++ b/src/peer_service.c diff --git a/src/plugin.c b/src/plugin.c index 7d730582..7d730582 100644..100755 --- a/src/plugin.c +++ b/src/plugin.c diff --git a/src/provider.c b/src/provider.c index 9c71a200..c0d69e49 100644..100755 --- a/src/provider.c +++ b/src/provider.c @@ -243,7 +243,11 @@ static int set_connected(struct connman_provider *provider, } __connman_ipconfig_address_add(ipconfig); +#if defined TIZEN_EXT + __connman_ipconfig_gateway_add(ipconfig, service); +#else __connman_ipconfig_gateway_add(ipconfig); +#endif provider_indicate_state(provider, CONNMAN_SERVICE_STATE_READY); @@ -573,8 +577,14 @@ int connman_provider_set_nameservers(struct connman_provider *provider, return 0; for (i = 0; nameservers[i]; i++) +#if defined TIZEN_EXT + __connman_service_nameserver_append(provider->vpn_service, + nameservers[i], false, + CONNMAN_IPCONFIG_TYPE_ALL); +#else __connman_service_nameserver_append(provider->vpn_service, nameservers[i], false); +#endif return 0; } diff --git a/src/proxy.c b/src/proxy.c index e1bc420a..e1bc420a 100644..100755 --- a/src/proxy.c +++ b/src/proxy.c diff --git a/src/resolver.c b/src/resolver.c index 75ea5ba6..d6c20cdd 100644..100755 --- a/src/resolver.c +++ b/src/resolver.c @@ -35,9 +35,6 @@ #include "connman.h" -#define RESOLV_CONF_STATEDIR STATEDIR"/resolv.conf" -#define RESOLV_CONF_ETC "/etc/resolv.conf" - #define RESOLVER_FLAG_PUBLIC (1 << 0) /* @@ -133,19 +130,11 @@ static int resolvfile_export(void) old_umask = umask(022); - fd = open(RESOLV_CONF_STATEDIR, O_RDWR | O_CREAT | O_CLOEXEC, + fd = open("/etc/resolv.conf", O_RDWR | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (fd < 0) { - connman_warn_once("Cannot create "RESOLV_CONF_STATEDIR" " - "falling back to "RESOLV_CONF_ETC); - - fd = open(RESOLV_CONF_ETC, O_RDWR | O_CREAT | O_CLOEXEC, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - - if (fd < 0) { - err = -errno; - goto done; - } + err = -errno; + goto done; } if (ftruncate(fd, 0) < 0) { @@ -312,8 +301,14 @@ static gboolean resolver_expire_cb(gpointer user_data) struct connman_service *service; service = __connman_service_lookup_from_index(entry->index); if (service) +#if defined TIZEN_EXT + __connman_service_nameserver_remove(service, + entry->server, true, + CONNMAN_IPCONFIG_TYPE_ALL); +#else __connman_service_nameserver_remove(service, entry->server, true); +#endif } remove_entries(list); @@ -367,6 +362,11 @@ static int append_resolver(int index, const char *domain, if (!server && !domain) return -EINVAL; +#ifdef TIZEN_EXT + if (g_strcmp0(server, "0.0.0.0") == 0) + return -EINVAL; +#endif + entry = g_try_new0(struct entry_data, 1); if (!entry) return -ENOMEM; @@ -409,8 +409,14 @@ static int append_resolver(int index, const char *domain, struct connman_service *service; service = __connman_service_lookup_from_index(entry->index); if (service) +#if defined TIZEN_EXT + __connman_service_nameserver_append(service, + server, true, + CONNMAN_IPCONFIG_TYPE_ALL); +#else __connman_service_nameserver_append(service, server, true); +#endif } return 0; diff --git a/src/rfkill.c b/src/rfkill.c index d9bed4d2..fce9d720 100644..100755 --- a/src/rfkill.c +++ b/src/rfkill.c @@ -73,6 +73,7 @@ static enum connman_service_type convert_type(uint8_t type) return CONNMAN_SERVICE_TYPE_UNKNOWN; } +#if !defined TIZEN_EXT static enum rfkill_type convert_service_type(enum connman_service_type type) { switch (type) { @@ -95,6 +96,7 @@ static enum rfkill_type convert_service_type(enum connman_service_type type) return NUM_RFKILL_TYPES; } +#endif static GIOStatus rfkill_process(GIOChannel *chan) { @@ -157,13 +159,20 @@ static guint watch = 0; int __connman_rfkill_block(enum connman_service_type type, bool block) { +#if !defined TIZEN_EXT uint8_t rfkill_type; struct rfkill_event event; ssize_t len; int fd, err = 0; +#endif DBG("type %d block %d", type, block); +#if defined TIZEN_EXT + DBG("try to set rfkill block %d, but it's not permitted", block); + + return 0; +#else rfkill_type = convert_service_type(type); if (rfkill_type == NUM_RFKILL_TYPES) return -EINVAL; @@ -186,6 +195,7 @@ int __connman_rfkill_block(enum connman_service_type type, bool block) close(fd); return err; +#endif } int __connman_rfkill_init(void) diff --git a/src/rtnl.c b/src/rtnl.c index a094e257..35ae0a96 100644..100755 --- a/src/rtnl.c +++ b/src/rtnl.c @@ -46,6 +46,12 @@ #define ARPHDR_PHONET_PIPE (821) #endif +#if defined TIZEN_EXT +#ifndef ARPHDR_RMNET +#define ARPHDR_RMNET (530) +#endif +#endif + #define print(arg...) do { if (0) connman_info(arg); } while (0) //#define print(arg...) connman_info(arg) @@ -94,6 +100,7 @@ static bool ether_blacklisted(const char *name) return false; } +#if !defined TIZEN_EXT static bool wext_interface(char *ifname) { struct iwreq wrq; @@ -115,6 +122,30 @@ static bool wext_interface(char *ifname) return true; } +#endif + +#if defined TIZEN_EXT +static bool __connman_rtnl_is_cellular_device(const char *name) +{ + char **pattern; + char **cellular_interfaces; + + cellular_interfaces = + connman_setting_get_string_list( + "NetworkCellularInterfaceList"); + if (!cellular_interfaces) + return false; + + for (pattern = cellular_interfaces; *pattern; pattern++) { + if (g_str_has_prefix(name, *pattern)) { + DBG("Cellular interface: %s", name); + return true; + } + } + + return false; +} +#endif static void read_uevent(struct interface_data *interface) { @@ -124,6 +155,14 @@ static void read_uevent(struct interface_data *interface) name = connman_inet_ifname(interface->index); +#if defined TIZEN_EXT + if (__connman_rtnl_is_cellular_device(name)) { + interface->service_type = CONNMAN_SERVICE_TYPE_CELLULAR; + interface->device_type = CONNMAN_DEVICE_TYPE_CELLULAR; + return; + } +#endif + if (ether_blacklisted(name)) { interface->service_type = CONNMAN_SERVICE_TYPE_UNKNOWN; interface->device_type = CONNMAN_DEVICE_TYPE_UNKNOWN; @@ -187,6 +226,8 @@ static void read_uevent(struct interface_data *interface) if (found_devtype) goto out; +#if !defined TIZEN_EXT + /* TIZEN does not use old wext interface */ /* We haven't got a DEVTYPE, let's check if it's a wireless device */ if (wext_interface(name)) { interface->service_type = CONNMAN_SERVICE_TYPE_WIFI; @@ -194,6 +235,7 @@ static void read_uevent(struct interface_data *interface) connman_error("%s runs an unsupported 802.11 driver", name); } +#endif out: g_free(name); @@ -419,6 +461,14 @@ static void process_newlink(unsigned short type, int index, unsigned flags, if (!extract_link(msg, bytes, &address, &ifname, &mtu, &operstate, &stats)) return; +#if defined TIZEN_EXT + /* Do not accept Wi-Fi P2P interface */ + if (g_strrstr(ifname, "p2p") != NULL) { + DBG("Newlink event for Wi-Fi P2P interface ignored"); + return; + } +#endif + snprintf(ident, 13, "%02x%02x%02x%02x%02x%02x", address.ether_addr_octet[0], address.ether_addr_octet[1], @@ -441,12 +491,25 @@ static void process_newlink(unsigned short type, int index, unsigned flags, return; } +#ifdef TIZEN_EXT + if (TIZEN_TV_EXT && g_strcmp0(ident, "eeeeeeeeeeee") == 0) { + DBG("Newlink event with Dummy MAC. Ignored!"); + return; + } +#endif + switch (type) { case ARPHRD_ETHER: case ARPHRD_LOOPBACK: case ARPHDR_PHONET_PIPE: case ARPHRD_PPP: case ARPHRD_NONE: +#if defined TIZEN_EXT +/* + * Description: ARPHDR_RMNET for QC modem using QMI + */ + case ARPHDR_RMNET: +#endif __connman_ipconfig_newlink(index, type, flags, str, mtu, &stats); break; @@ -471,6 +534,25 @@ static void process_newlink(unsigned short type, int index, unsigned flags, if (type == ARPHRD_ETHER) read_uevent(interface); +#if defined TIZEN_EXT + if (type == ARPHRD_PPP || type == ARPHDR_RMNET) + read_uevent(interface); + + } else if (g_strcmp0(interface->ident, ident) != 0) { + /* If an original address is built-in physical device, + * it's hardly get an address at a initial creation + */ + __connman_technology_remove_interface(interface->service_type, + interface->index, interface->ident); + + g_free(interface->ident); + interface->ident = g_strdup(ident); + + __connman_technology_add_interface(interface->service_type, + interface->index, interface->ident); + + interface = NULL; +#endif } else if (type == ARPHRD_ETHER && interface->device_type == CONNMAN_DEVICE_TYPE_UNKNOWN) read_uevent(interface); else @@ -534,6 +616,13 @@ static void process_dellink(unsigned short type, int index, unsigned flags, case ARPHDR_PHONET_PIPE: case ARPHRD_PPP: case ARPHRD_NONE: +#if defined TIZEN_EXT + /* + * Description: SLP requires ARPHRD_PPP for PPP type device + * ARPHDR_RMNET for QC modem using QMI + */ + case ARPHDR_RMNET: +#endif __connman_ipconfig_dellink(index, &stats); break; } @@ -1229,6 +1318,37 @@ static void rtnl_newnduseropt(struct nlmsghdr *hdr) if (index < 0) return; +#if defined TIZEN_EXT + struct connman_service *service; + enum connman_service_state state; + enum connman_dnsconfig_method ipv6_dns_method; + + service = __connman_service_lookup_from_index(index); + if (!service) { + DBG("Invalid service"); + return; + } + + DBG("service: %p index: %d\n", service, index); + + if (connman_setting_get_bool("SingleConnectedTechnology") == TRUE) { + state = __connman_service_ipconfig_get_state(service, CONNMAN_IPCONFIG_TYPE_IPV6); + if (state != CONNMAN_SERVICE_STATE_ASSOCIATION && + state != CONNMAN_SERVICE_STATE_CONFIGURATION && + state != CONNMAN_SERVICE_STATE_READY && + state != CONNMAN_SERVICE_STATE_ONLINE) { + DBG("Service state[%d] is not connecting/connected", state); + return; + } + } + + ipv6_dns_method = connman_service_get_ipv6_dns_method(service); + if (ipv6_dns_method != CONNMAN_DNSCONFIG_METHOD_DHCP) { + DBG("IPv6 DNS method is not Auto ignore RA!!! [DNS method: %d]", ipv6_dns_method); + return; + } +#endif + for (opt = (void *)&msg[1]; msglen > 0; msglen -= opt->nd_opt_len * 8, @@ -1239,16 +1359,29 @@ static void rtnl_newnduseropt(struct nlmsghdr *hdr) if (opt->nd_opt_type == 25) { /* ND_OPT_RDNSS */ char buf[40]; +#if defined TIZEN_EXT + struct connman_service *service; + service = __connman_service_lookup_from_index(index); + DBG("service: %p\n",service); +#endif servers = rtnl_nd_opt_rdnss(opt, &lifetime, - &nr_servers); + &nr_servers); for (i = 0; i < nr_servers; i++) { if (!inet_ntop(AF_INET6, servers + i, buf, - sizeof(buf))) + sizeof(buf))) continue; +#if defined TIZEN_EXT + __connman_service_nameserver_remove(service, + buf, false, + CONNMAN_IPCONFIG_TYPE_IPV6); + __connman_service_nameserver_append(service, + buf, false, + CONNMAN_IPCONFIG_TYPE_IPV6); +#endif connman_resolver_append_lifetime(index, - NULL, buf, lifetime); + NULL, buf, lifetime); } } else if (opt->nd_opt_type == 31) { /* ND_OPT_DNSSL */ diff --git a/src/service.c b/src/service.c index 02cd51f2..d0543ae5 100644..100755 --- a/src/service.c +++ b/src/service.c @@ -30,6 +30,8 @@ #include <gdbus.h> #include <ctype.h> #include <stdint.h> +#include <pwd.h> +#include <utmpx.h> #include <connman/storage.h> #include <connman/setting.h> @@ -39,6 +41,13 @@ #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 + static DBusConnection *connection = NULL; static GList *service_list = NULL; @@ -49,6 +58,10 @@ static unsigned int vpn_autoconnect_timeout = 0; static struct connman_service *current_default = NULL; static bool services_dirty = false; +#if defined TIZEN_EXT +static bool auto_connect_mode = TRUE; +#endif + struct connman_stats { bool valid; bool enabled; @@ -63,6 +76,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; @@ -85,6 +103,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; @@ -130,6 +150,28 @@ struct connman_service { bool hidden_service; char *config_file; char *config_entry; +#if defined TIZEN_EXT + /* + * Description: TIZEN implements system global connection management. + * It's only for PDP (cellular) bearer. Wi-Fi is managed + * by ConnMan automatically. Reference count can help to + * manage open/close connection requests by each application. + */ + int user_pdn_connection_refcount; + bool storage_reload; + /* + * Description: In case of EAP security type, + * user can select the keymgmt type for roaming(802.11r). + * - FT, CCKM, OKC, ... + */ + char *keymgmt_type; + int disconnect_reason; + int assoc_status_code; +#endif +#ifdef TIZEN_EXT + enum connman_dnsconfig_method dns_config_method_ipv4; + enum connman_dnsconfig_method dns_config_method_ipv6; +#endif }; static bool allow_property_changed(struct connman_service *service); @@ -145,6 +187,50 @@ struct find_data { struct connman_service *service; }; +#if defined TIZEN_EXT +/* + * Public APIs to use user_pdn_connection_refcount + */ +void connman_service_user_pdn_connection_ref(struct connman_service *service) +{ + __sync_fetch_and_add(&service->user_pdn_connection_refcount, 1); + + DBG("User made PDN connection referenced: %d", + service->user_pdn_connection_refcount); +} + +gboolean connman_service_user_pdn_connection_unref_and_test( + struct connman_service *service) +{ + __sync_synchronize(); + + DBG("User made PDN connection referenced: %d, which will be decreased", + service->user_pdn_connection_refcount); + + if (service->user_pdn_connection_refcount < 1) + return TRUE; + + if (__sync_sub_and_fetch(&service->user_pdn_connection_refcount, 1) == 0) + return TRUE; + + return FALSE; +} + +gboolean connman_service_is_no_ref_user_pdn_connection( + struct connman_service *cellular) +{ + if (cellular == NULL) + return TRUE; + + __sync_synchronize(); + if (cellular->type == CONNMAN_SERVICE_TYPE_CELLULAR && + cellular->user_pdn_connection_refcount == 0) + return TRUE; + + return FALSE; +} +#endif + static void compare_path(gpointer value, gpointer user_data) { struct connman_service *service = value; @@ -253,6 +339,10 @@ enum connman_service_security __connman_service_string2security(const char *str) return CONNMAN_SERVICE_SECURITY_NONE; if (!strcmp(str, "wep")) return CONNMAN_SERVICE_SECURITY_WEP; +#if defined TIZEN_EXT + if (!strcmp(str, "rsn")) + return CONNMAN_SERVICE_SECURITY_RSN; +#endif return CONNMAN_SERVICE_SECURITY_UNKNOWN; } @@ -268,8 +358,14 @@ static const char *security2string(enum connman_service_security security) return "wep"; case CONNMAN_SERVICE_SECURITY_PSK: case CONNMAN_SERVICE_SECURITY_WPA: +#if defined TIZEN_EXT + return "psk"; + case CONNMAN_SERVICE_SECURITY_RSN: + return "rsn"; +#else case CONNMAN_SERVICE_SECURITY_RSN: return "psk"; +#endif case CONNMAN_SERVICE_SECURITY_8021X: return "ieee8021x"; } @@ -355,6 +451,116 @@ static enum connman_service_proxy_method string2proxymethod(const char *method) return CONNMAN_SERVICE_PROXY_METHOD_UNKNOWN; } +#ifdef TIZEN_EXT +static const char *__connman_dnsconfig_method2string(enum connman_dnsconfig_method method) +{ + switch (method) { + case CONNMAN_DNSCONFIG_METHOD_UNKNOWN: + return "unknown"; + case CONNMAN_DNSCONFIG_METHOD_MANUAL: + return "manual"; + case CONNMAN_DNSCONFIG_METHOD_DHCP: + return "dhcp"; + } + + return NULL; +} + +static enum connman_dnsconfig_method __connman_dnsconfig_string2method( + const char *method) +{ + if (g_strcmp0(method, "manual") == 0) + return CONNMAN_DNSCONFIG_METHOD_MANUAL; + else if (g_strcmp0(method, "dhcp") == 0) + return CONNMAN_DNSCONFIG_METHOD_DHCP; + else + return CONNMAN_DNSCONFIG_METHOD_UNKNOWN; +} +#endif + +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; +} + +#if !defined TIZEN_EXT +static GList *connman_service_get_login_users() +{ + struct utmpx *utmp; + struct passwd *pwd; + GList *user_list = NULL; + + setutxent(); + + while ((utmp = getutxent()) != NULL) { + DBG("User Name: %s", utmp->ut_user); + + pwd = getpwnam(utmp->ut_user); + if (pwd) { + 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; +} +#endif + +static bool is_service_owner_user_login(struct connman_service *service) +{ +#if defined TIZEN_EXT + return true; +#else + GList *list, *user_list; + bool ret = false; + + /* Here we only care about wifi service */ + if (service->type != CONNMAN_SERVICE_TYPE_WIFI) + return true; + + DBG("service favorite user id is: %d", service->user.favorite_user); + + user_list = connman_service_get_login_users(); + if (user_list == NULL) { + DBG("Can not get any logged in user info."); + return true; + } + + 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; +#endif +} + static void set_split_routing(struct connman_service *service, bool value) { if (service->type != CONNMAN_SERVICE_TYPE_VPN) @@ -418,6 +624,25 @@ 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; + + g_key_file_free(keyfile); + + return 0; +} + static int service_load(struct connman_service *service) { GKeyFile *keyfile; @@ -552,6 +777,18 @@ static int service_load(struct connman_service *service) service->nameservers_config = NULL; } +#ifdef TIZEN_EXT + char *dns_method; + + dns_method = g_key_file_get_string(keyfile, service->identifier, + "Nameservers.IPv4method", NULL); + service->dns_config_method_ipv4 = __connman_dnsconfig_string2method(dns_method); + + dns_method = g_key_file_get_string(keyfile, service->identifier, + "Nameservers.IPv6method", NULL); + service->dns_config_method_ipv6 = __connman_dnsconfig_string2method(dns_method); +#endif + service->timeservers_config = g_key_file_get_string_list(keyfile, service->identifier, "Timeservers", &length, NULL); if (service->timeservers_config && length == 0) { @@ -597,6 +834,63 @@ static int service_load(struct connman_service *service) service->hidden_service = g_key_file_get_boolean(keyfile, service->identifier, "Hidden", NULL); +#if defined TIZEN_EXT + if (service->type == CONNMAN_SERVICE_TYPE_WIFI && + service->security == CONNMAN_SERVICE_SECURITY_8021X) { + str = g_key_file_get_string(keyfile, + service->identifier, "EAP", NULL); + if (str != NULL) { + g_free(service->eap); + service->eap = str; + } + + str = g_key_file_get_string(keyfile, + service->identifier, "Phase2", NULL); + if (str != NULL) { + g_free(service->phase2); + service->phase2 = str; + } + + str = g_key_file_get_string(keyfile, + service->identifier, "Identity", NULL); + if (str != NULL) { + g_free(service->identity); + service->identity = str; + } + + str = g_key_file_get_string(keyfile, + service->identifier, "CACertFile", NULL); + if (str != NULL) { + g_free(service->ca_cert_file); + service->ca_cert_file = str; + } + + str = g_key_file_get_string(keyfile, + service->identifier, "ClientCertFile", NULL); + if (str != NULL) { + g_free(service->client_cert_file); + service->client_cert_file = str; + } + + str = g_key_file_get_string(keyfile, + service->identifier, "PrivateKeyFile", NULL); + if (str != NULL) { + g_free(service->private_key_file); + service->private_key_file = str; + } + + str = g_key_file_get_string(keyfile, + service->identifier, "PrivateKeyPassphrase", NULL); + if (str != NULL) { + g_free(service->private_key_passphrase); + service->private_key_passphrase = str; + } + } +#endif + + 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); @@ -642,6 +936,13 @@ static int service_save(struct connman_service *service) const unsigned char *ssid; unsigned int ssid_len = 0; + 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); @@ -697,12 +998,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, @@ -722,6 +1025,28 @@ static int service_save(struct connman_service *service) g_key_file_remove_key(keyfile, service->identifier, "Nameservers", NULL); +#if defined TIZEN_EXT + if(service->dns_config_method_ipv4 != 0) { + const char *method; + method = __connman_dnsconfig_method2string( + service->dns_config_method_ipv4); + g_key_file_set_string(keyfile, service->identifier, + "Nameservers.IPv4method", method); + } else + g_key_file_remove_key(keyfile, service->identifier, + "Nameservers.IPv4method", NULL); + + if(service->dns_config_method_ipv6 != 0) { + const char *method; + method = __connman_dnsconfig_method2string( + service->dns_config_method_ipv6); + g_key_file_set_string(keyfile, service->identifier, + "Nameservers.IPv6method", method); + } else + g_key_file_remove_key(keyfile, service->identifier, + "Nameservers.IPv6method", NULL); +#endif + if (service->timeservers_config) { guint len = g_strv_length(service->timeservers_config); @@ -787,6 +1112,60 @@ static int service_save(struct connman_service *service) g_key_file_set_string(keyfile, service->identifier, "Config.ident", service->config_entry); +#if defined TIZEN_EXT + if (service->type == CONNMAN_SERVICE_TYPE_WIFI && + service->security == CONNMAN_SERVICE_SECURITY_8021X) { + if (service->eap != NULL && strlen(service->eap) > 0) + g_key_file_set_string(keyfile, service->identifier, + "EAP", service->eap); + else + g_key_file_remove_key(keyfile, service->identifier, + "EAP", NULL); + + if (service->phase2 != NULL && strlen(service->phase2) > 0) + g_key_file_set_string(keyfile, service->identifier, + "Phase2", service->phase2); + else + g_key_file_remove_key(keyfile, service->identifier, + "Phase2", NULL); + + if (service->identity != NULL && strlen(service->identity) > 0) + g_key_file_set_string(keyfile, service->identifier, + "Identity", service->identity); + else + g_key_file_remove_key(keyfile, service->identifier, + "Identity", NULL); + + if (service->ca_cert_file != NULL && strlen(service->ca_cert_file) > 0) + g_key_file_set_string(keyfile, service->identifier, + "CACertFile", service->ca_cert_file); + else + g_key_file_remove_key(keyfile, service->identifier, + "CACertFile", NULL); + + if (service->client_cert_file != NULL && strlen(service->client_cert_file) > 0) + g_key_file_set_string(keyfile, service->identifier, + "ClientCertFile", service->client_cert_file); + else + g_key_file_remove_key(keyfile, service->identifier, + "ClientCertFile", NULL); + + if (service->private_key_file != NULL && strlen(service->private_key_file) > 0) + g_key_file_set_string(keyfile, service->identifier, + "PrivateKeyFile", service->private_key_file); + else + g_key_file_remove_key(keyfile, service->identifier, + "PrivateKeyFile", NULL); + + if (service->private_key_passphrase != NULL && strlen(service->private_key_passphrase) > 0) + g_key_file_set_string(keyfile, service->identifier, + "PrivateKeyPassphrase", service->private_key_passphrase); + else + g_key_file_remove_key(keyfile, service->identifier, + "PrivateKeyPassphrase", NULL); + } +#endif + done: __connman_storage_save_service(keyfile, service->identifier); @@ -1053,6 +1432,9 @@ static int nameserver_add(struct connman_service *service, if (index < 0) return -ENXIO; +#if defined TIZEN_EXT + DBG("Resolver append nameserver: %s", nameserver); +#endif ret = connman_resolver_append(index, NULL, nameserver); if (ret >= 0) nameservers_changed(service); @@ -1067,14 +1449,115 @@ static int nameserver_add_all(struct connman_service *service, if (service->nameservers_config) { while (service->nameservers_config[i]) { +#if defined TIZEN_EXT + DBG("type %d add service->nameservers_config[%d]:%s",type, + i, service->nameservers_config[i]); + if(strncmp(service->nameservers_config[i], "::", 2) == 0) { + DBG("Invalid nameserver"); + i++; + continue; + } + + switch(type) { + case CONNMAN_IPCONFIG_TYPE_IPV4: + if (connman_inet_check_ipaddress( + service->nameservers_config[i]) == AF_INET && + service->dns_config_method_ipv4 == + CONNMAN_DNSCONFIG_METHOD_MANUAL) { + nameserver_add(service, type, + service->nameservers_config[i]); + } + break; + case CONNMAN_IPCONFIG_TYPE_IPV6: + if (connman_inet_check_ipaddress( + service->nameservers_config[i]) == AF_INET6 && + service->dns_config_method_ipv6 == + CONNMAN_DNSCONFIG_METHOD_MANUAL) { + nameserver_add(service, type, + service->nameservers_config[i]); + } + break; + case CONNMAN_IPCONFIG_TYPE_ALL: + if (connman_inet_check_ipaddress( + service->nameservers_config[i]) == AF_INET && + service->dns_config_method_ipv4 == + CONNMAN_DNSCONFIG_METHOD_MANUAL) { + nameserver_add(service, type, + service->nameservers_config[i]); + } + if (connman_inet_check_ipaddress( + service->nameservers_config[i]) == AF_INET6 && + service->dns_config_method_ipv6 == + CONNMAN_DNSCONFIG_METHOD_MANUAL) { + nameserver_add(service, type, + service->nameservers_config[i]); + } + break; + case CONNMAN_IPCONFIG_TYPE_UNKNOWN: + DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing"); + break; + default: + DBG("default case do nothing"); + break; + } +#else nameserver_add(service, type, service->nameservers_config[i]); +#endif i++; } } else if (service->nameservers) { while (service->nameservers[i]) { +#if defined TIZEN_EXT + DBG("type %d service->nameservers[%d]: %s",type, + i, service->nameservers[i]); + + switch(type) { + case CONNMAN_IPCONFIG_TYPE_IPV4: + if (connman_inet_check_ipaddress( + service->nameservers[i]) == AF_INET && + service->dns_config_method_ipv4 == + CONNMAN_DNSCONFIG_METHOD_DHCP) { + nameserver_add(service, type, + service->nameservers[i]); + } + break; + case CONNMAN_IPCONFIG_TYPE_IPV6: + if (connman_inet_check_ipaddress( + service->nameservers[i]) == AF_INET6 && + service->dns_config_method_ipv6 == + CONNMAN_DNSCONFIG_METHOD_DHCP) { + nameserver_add(service, type, + service->nameservers[i]); + } + break; + case CONNMAN_IPCONFIG_TYPE_ALL: + if (connman_inet_check_ipaddress( + service->nameservers[i]) == AF_INET && + service->dns_config_method_ipv4 == + CONNMAN_DNSCONFIG_METHOD_DHCP) { + nameserver_add(service, type, + service->nameservers[i]); + } + if (connman_inet_check_ipaddress( + service->nameservers[i]) == AF_INET6 && + service->dns_config_method_ipv6 == + CONNMAN_DNSCONFIG_METHOD_DHCP) { + nameserver_add(service, type, + service->nameservers[i]); + } + break; + case CONNMAN_IPCONFIG_TYPE_UNKNOWN: + DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing"); + break; + default: + DBG("default case do nothing"); + break; + } +#else nameserver_add(service, type, service->nameservers[i]); +#endif i++; } } @@ -1100,6 +1583,9 @@ static int nameserver_remove(struct connman_service *service, if (index < 0) return -ENXIO; +#if defined TIZEN_EXT + DBG("Resolver remove nameserver: %s", nameserver); +#endif ret = connman_resolver_remove(index, NULL, nameserver); if (ret >= 0) nameservers_changed(service); @@ -1110,6 +1596,15 @@ static int nameserver_remove(struct connman_service *service, static int nameserver_remove_all(struct connman_service *service, enum connman_ipconfig_type type) { +#if defined TIZEN_EXT + /** + * Skip this function if there is any connected profiles + * that use same interface + */ + if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR && + __connman_service_get_connected_count_of_iface(service) > 0) + return 0; +#endif int index, i = 0; index = __connman_service_get_index(service); @@ -1117,15 +1612,124 @@ static int nameserver_remove_all(struct connman_service *service, return -ENXIO; while (service->nameservers_config && service->nameservers_config[i]) { - +#if defined TIZEN_EXT + DBG("type %d Remove service->nameservers_config[%d]: %s", + type, i, service->nameservers_config[i]); + switch(type) { + case CONNMAN_IPCONFIG_TYPE_IPV4: + if (connman_inet_check_ipaddress( + service->nameservers_config[i]) == AF_INET && + (service->dns_config_method_ipv4 == + CONNMAN_DNSCONFIG_METHOD_DHCP || + service->dns_config_method_ipv4 == + CONNMAN_DNSCONFIG_METHOD_MANUAL)) { + nameserver_remove(service, type, + service->nameservers_config[i]); + } + break; + case CONNMAN_IPCONFIG_TYPE_IPV6: + if (connman_inet_check_ipaddress( + service->nameservers_config[i]) == AF_INET6 && + (service->dns_config_method_ipv6 == + CONNMAN_DNSCONFIG_METHOD_DHCP || + service->dns_config_method_ipv6 == + CONNMAN_DNSCONFIG_METHOD_MANUAL)) { + nameserver_remove(service, type, + service->nameservers_config[i]); + } + break; + case CONNMAN_IPCONFIG_TYPE_ALL: + if (connman_inet_check_ipaddress( + service->nameservers_config[i]) == AF_INET && + (service->dns_config_method_ipv4 == + CONNMAN_DNSCONFIG_METHOD_DHCP || + service->dns_config_method_ipv4 == + CONNMAN_DNSCONFIG_METHOD_MANUAL)) { + nameserver_remove(service, type, + service->nameservers_config[i]); + } + if (connman_inet_check_ipaddress( + service->nameservers_config[i]) == AF_INET6 && + (service->dns_config_method_ipv6 == + CONNMAN_DNSCONFIG_METHOD_DHCP || + service->dns_config_method_ipv6 == + CONNMAN_DNSCONFIG_METHOD_MANUAL)) { + nameserver_remove(service, type, + service->nameservers_config[i]); + } + break; + case CONNMAN_IPCONFIG_TYPE_UNKNOWN: + DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing"); + break; + default: + DBG("default case do nothing"); + break; + } +#else nameserver_remove(service, type, service->nameservers_config[i]); +#endif i++; } i = 0; while (service->nameservers && service->nameservers[i]) { +#if defined TIZEN_EXT + DBG("type %d Remove service->nameservers[%d]: %s",type, i, + service->nameservers[i]); + switch(type) { + case CONNMAN_IPCONFIG_TYPE_IPV4: + if (connman_inet_check_ipaddress( + service->nameservers[i]) == AF_INET && + (service->dns_config_method_ipv4 == + CONNMAN_DNSCONFIG_METHOD_MANUAL || + service->dns_config_method_ipv4 == + CONNMAN_DNSCONFIG_METHOD_DHCP)) { + nameserver_remove(service, type, + service->nameservers[i]); + } + break; + case CONNMAN_IPCONFIG_TYPE_IPV6: + if (connman_inet_check_ipaddress( + service->nameservers[i]) == AF_INET6 && + (service->dns_config_method_ipv6 == + CONNMAN_DNSCONFIG_METHOD_MANUAL || + service->dns_config_method_ipv6 == + CONNMAN_DNSCONFIG_METHOD_DHCP)) { + nameserver_remove(service, type, + service->nameservers[i]); + } + break; + case CONNMAN_IPCONFIG_TYPE_ALL: + if (connman_inet_check_ipaddress( + service->nameservers[i]) == AF_INET && + (service->dns_config_method_ipv4 == + CONNMAN_DNSCONFIG_METHOD_MANUAL || + service->dns_config_method_ipv4 == + CONNMAN_DNSCONFIG_METHOD_DHCP)) { + nameserver_remove(service, type, + service->nameservers[i]); + } + if (connman_inet_check_ipaddress( + service->nameservers[i]) == AF_INET6 && + (service->dns_config_method_ipv6 == + CONNMAN_DNSCONFIG_METHOD_MANUAL || + service->dns_config_method_ipv6 == + CONNMAN_DNSCONFIG_METHOD_DHCP)) { + nameserver_remove(service, type, + service->nameservers[i]); + } + break; + case CONNMAN_IPCONFIG_TYPE_UNKNOWN: + DBG("CONNMAN_IPCONFIG_TYPE_UNKNOWN do nothing"); + break; + default: + DBG("default case do nothing"); + break; + } +#else nameserver_remove(service, type, service->nameservers[i]); +#endif i++; } @@ -1139,13 +1743,19 @@ static int nameserver_remove_all(struct connman_service *service, * inserted to resolver via netlink message (see rtnl.c:rtnl_newnduseropt() * for details) and not through service.c */ +#if defined TIZEN_EXT +int __connman_service_nameserver_append(struct connman_service *service, + const char *nameserver, bool is_auto, + enum connman_ipconfig_type type) +#else int __connman_service_nameserver_append(struct connman_service *service, const char *nameserver, bool is_auto) +#endif { char **nameservers; int len, i; - DBG("service %p nameserver %s auto %d", service, nameserver, is_auto); + DBG("service %p nameserver %s auto %d", service, nameserver, is_auto); if (!nameserver) return -EINVAL; @@ -1156,8 +1766,15 @@ int __connman_service_nameserver_append(struct connman_service *service, nameservers = service->nameservers; for (i = 0; nameservers && nameservers[i]; i++) +#if defined TIZEN_EXT + { + DBG("nameservers[%d] %s, nameserver %s", i, nameservers[i], nameserver); +#endif if (g_strcmp0(nameservers[i], nameserver) == 0) return -EEXIST; +#if defined TIZEN_EXT + } +#endif if (nameservers) { len = g_strv_length(nameservers); @@ -1173,6 +1790,16 @@ int __connman_service_nameserver_append(struct connman_service *service, nameservers[len] = g_strdup(nameserver); nameservers[len + 1] = NULL; +#ifdef TIZEN_EXT + if(type == CONNMAN_IPCONFIG_TYPE_IPV4 && + service->dns_config_method_ipv4 == CONNMAN_DNSCONFIG_METHOD_UNKNOWN) + service->dns_config_method_ipv4 = CONNMAN_DNSCONFIG_METHOD_DHCP; + + if(type == CONNMAN_IPCONFIG_TYPE_IPV6 && + service->dns_config_method_ipv6 == CONNMAN_DNSCONFIG_METHOD_UNKNOWN) + service->dns_config_method_ipv6 = CONNMAN_DNSCONFIG_METHOD_DHCP; +#endif + if (is_auto) { service->nameservers_auto = nameservers; } else { @@ -1187,8 +1814,14 @@ int __connman_service_nameserver_append(struct connman_service *service, return 0; } +#if defined TIZEN_EXT +int __connman_service_nameserver_remove(struct connman_service *service, + const char *nameserver, bool is_auto, + enum connman_ipconfig_type type) +#else int __connman_service_nameserver_remove(struct connman_service *service, const char *nameserver, bool is_auto) +#endif { char **servers, **nameservers; bool found = false; @@ -1246,8 +1879,14 @@ set_servers: service->nameservers_auto = nameservers; } else { service->nameservers = nameservers; +#if defined TIZEN_EXT + DBG("nameserver remove ip_type: %d", type); + nameserver_remove(service, type, + nameserver); +#else nameserver_remove(service, CONNMAN_IPCONFIG_TYPE_ALL, nameserver); +#endif } return 0; @@ -1473,6 +2112,71 @@ static void reset_stats(struct connman_service *service) g_timer_reset(service->stats_roaming.timer); } +#if defined TIZEN_EXT +static gboolean __connman_service_is_internet_profile( + struct connman_service *cellular) +{ + const char internet_suffix[] = "_1"; + + DBG("Service path: %s", cellular->path); + + if (g_str_has_suffix(cellular->path, internet_suffix) == TRUE) + return TRUE; + + return FALSE; +} + +static gboolean __connman_service_is_tethering_profile( + struct connman_service *cellular) +{ + const char tethering_suffix[] = "_5"; + + DBG("Service path: %s", cellular->path); + + if (g_str_has_suffix(cellular->path, tethering_suffix) == TRUE) + return TRUE; + + return FALSE; +} + +struct connman_service *connman_service_get_default_connection(void) +{ + GList *list; + struct connman_service *service; + struct connman_service *default_service = NULL; + + for (list = service_list; list; list = list->next) { + service = list->data; + + DBG("service: %p %s %s %s", service, service->name, + state2string(service->state), + __connman_service_type2string(service->type)); + + if (service->type == CONNMAN_SERVICE_TYPE_WIFI && + is_connected(service->state) == TRUE) { + return service; + } else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR && + __connman_service_is_internet_profile(service) == TRUE) { + if (default_service == NULL) + default_service = service; + else if (is_connected(service->state) == TRUE && + is_connected(default_service->state) == FALSE) + default_service = service; + } else if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET && + is_connected(service->state) == TRUE) { + if (default_service == NULL) + default_service = service; + } else if (service->type == CONNMAN_SERVICE_TYPE_BLUETOOTH && + is_connected(service->state) == TRUE) { + if (default_service == NULL) + default_service = service; + } + } + + return default_service; +} +#endif + struct connman_service *__connman_service_get_default(void) { struct connman_service *service; @@ -1511,9 +2215,15 @@ static void default_changed(void) current_default ? current_default->identifier : ""); DBG("new default %p %s", service, service ? service->identifier : ""); +#if defined TIZEN_EXT + current_default = service; + + __connman_service_timeserver_changed(service, NULL); +#else __connman_service_timeserver_changed(current_default, NULL); current_default = service; +#endif if (service) { if (service->hostname && @@ -1537,9 +2247,13 @@ static void state_changed(struct connman_service *service) if (!str) return; +#if !defined TIZEN_EXT if (!allow_property_changed(service)) return; - +#endif +#if defined TIZEN_EXT + DBG(" %s, %s", str, service->path); +#endif connman_dbus_property_changed_basic(service->path, CONNMAN_SERVICE_INTERFACE, "State", DBUS_TYPE_STRING, &str); @@ -1726,20 +2440,143 @@ static void append_nameservers(DBusMessageIter *iter, } } +#if defined TIZEN_EXT +static void append_nameserver_manual(DBusMessageIter *iter, + struct connman_service *service, const char *server) +{ + bool available = true; + + if (service) + available = nameserver_available(service, + CONNMAN_IPCONFIG_TYPE_ALL, server); + + if (available) + dbus_message_iter_append_basic(iter, + DBUS_TYPE_STRING, &server); +} + +static void append_nameserver_dhcp(DBusMessageIter *iter, + struct connman_service *service, const char *server) +{ + bool available = true; + + if (service) + available = nameserver_available(service, + CONNMAN_IPCONFIG_TYPE_ALL, server); + + if (available) + dbus_message_iter_append_basic(iter, + DBUS_TYPE_STRING, &server); +} +#endif + static void append_dns(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; +#if defined TIZEN_EXT + int i; +#endif if (!is_connected(service->state)) return; +#ifdef TIZEN_EXT + const char *str; + + str = __connman_dnsconfig_method2string(service->dns_config_method_ipv4); + if(str != NULL) { + char *str1 = g_strdup_printf("ipv4.%s", str); + dbus_message_iter_append_basic(iter, + DBUS_TYPE_STRING, &str1); + g_free(str1); + } + + str = __connman_dnsconfig_method2string(service->dns_config_method_ipv6); + if(str != NULL) { + char *str1 = g_strdup_printf("ipv6.%s", str); + dbus_message_iter_append_basic(iter, + DBUS_TYPE_STRING, &str1); + g_free(str1); + } +#endif + if (service->nameservers_config) { +#if defined TIZEN_EXT + i = 0; + while (service->nameservers_config[i]) { + if (connman_inet_check_ipaddress( + service->nameservers_config[i]) == AF_INET && + service->dns_config_method_ipv4 == + CONNMAN_DNSCONFIG_METHOD_MANUAL) { + append_nameserver_manual(iter, service, + service->nameservers_config[i]); + } + + if (connman_inet_check_ipaddress( + service->nameservers_config[i]) == AF_INET6 && + service->dns_config_method_ipv6 == + CONNMAN_DNSCONFIG_METHOD_MANUAL) { + append_nameserver_manual(iter, service, + service->nameservers_config[i]); + } + i++; + } + /* In case of mixed DNS Config Type one of IPv4/IPv6 can be + * dynamic while other is static so try to append the DNS + * Address which is dynamic also */ + if (service->nameservers != NULL) { + i = 0; + while (service->nameservers[i]) { + if (connman_inet_check_ipaddress( + service->nameservers[i]) == AF_INET && + service->dns_config_method_ipv4 == + CONNMAN_DNSCONFIG_METHOD_DHCP) { + append_nameserver_dhcp(iter, service, + service->nameservers[i]); + } + + if (connman_inet_check_ipaddress( + service->nameservers[i]) == AF_INET6 && + service->dns_config_method_ipv6 == + CONNMAN_DNSCONFIG_METHOD_DHCP) { + append_nameserver_dhcp(iter, service, + service->nameservers[i]); + } + i++; + } + } +#else append_nameservers(iter, service, service->nameservers_config); +#endif return; } else { if (service->nameservers) +#if defined TIZEN_EXT + { + i = 0; + while (service->nameservers[i]) { + if (connman_inet_check_ipaddress( + service->nameservers[i]) == AF_INET && + service->dns_config_method_ipv4 == + CONNMAN_DNSCONFIG_METHOD_DHCP) { + append_nameserver_dhcp(iter, service, + service->nameservers[i]); + } + + if (connman_inet_check_ipaddress( + service->nameservers[i]) == AF_INET6 && + service->dns_config_method_ipv6 == + CONNMAN_DNSCONFIG_METHOD_DHCP) { + append_nameserver_dhcp(iter, service, + service->nameservers[i]); + } + i++; + } + } +#else append_nameservers(iter, service, service->nameservers); +#endif if (service->nameservers_auto) append_nameservers(iter, service, @@ -1761,10 +2598,46 @@ static void append_dnsconfig(DBusMessageIter *iter, void *user_data) { struct connman_service *service = user_data; +#ifdef TIZEN_EXT + /* Append DNS Config Type */ + const char *str; + str = __connman_dnsconfig_method2string(service->dns_config_method_ipv4); + if(str != NULL) { + char *str1 = g_strdup_printf("ipv4.%s", str); + dbus_message_iter_append_basic(iter, + DBUS_TYPE_STRING, &str1); + g_free(str1); + } + + str = __connman_dnsconfig_method2string(service->dns_config_method_ipv6); + if(str != NULL) { + char *str1 = g_strdup_printf("ipv6.%s", str); + dbus_message_iter_append_basic(iter, + DBUS_TYPE_STRING, &str1); + g_free(str1); + } +#endif + if (!service->nameservers_config) return; +#if defined TIZEN_EXT + int i = 0; + while (service->nameservers_config[i]) { + if (connman_inet_check_ipaddress(service->nameservers_config[i]) == AF_INET && + service->dns_config_method_ipv4 == CONNMAN_DNSCONFIG_METHOD_MANUAL) { + append_nameserver_manual(iter, NULL, service->nameservers_config[i]); + } + + if (connman_inet_check_ipaddress(service->nameservers_config[i]) == AF_INET6 && + service->dns_config_method_ipv6 == CONNMAN_DNSCONFIG_METHOD_MANUAL) { + append_nameserver_manual(iter, NULL, service->nameservers_config[i]); + } + i++; + } +#else append_nameservers(iter, NULL, service->nameservers_config); +#endif } static void append_ts(DBusMessageIter *iter, void *user_data) @@ -2338,6 +3211,86 @@ 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; + const void *ssid; + unsigned int ssid_len; + unsigned char *bssid; + unsigned int maxrate; + unsigned int keymgmt; + uint16_t frequency; + const char *enc_mode; + const char *str; + gboolean passpoint; + + ssid = connman_network_get_blob(network, "WiFi.SSID", &ssid_len); + 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); + passpoint = connman_network_get_bool(network, "WiFi.HS20AP"); + keymgmt = connman_network_get_keymgmt(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_fixed_array(dict, "SSID", + DBUS_TYPE_BYTE, &ssid, ssid_len); + connman_dbus_dict_append_basic(dict, "BSSID", + DBUS_TYPE_STRING, &bssid_str); + connman_dbus_dict_append_basic(dict, "MaxRate", + DBUS_TYPE_UINT32, &maxrate); + connman_dbus_dict_append_basic(dict, "Frequency", + DBUS_TYPE_UINT16, &frequency); + connman_dbus_dict_append_basic(dict, "EncryptionMode", + DBUS_TYPE_STRING, &enc_mode); + connman_dbus_dict_append_basic(dict, "Passpoint", + DBUS_TYPE_BOOLEAN, &passpoint); + connman_dbus_dict_append_basic(dict, "Keymgmt", + DBUS_TYPE_UINT32, &keymgmt); + + str = connman_network_get_string(network, "WiFi.Security"); + if (str != NULL && g_str_equal(str, "ieee8021x") == TRUE) { + str = connman_network_get_string(network, "WiFi.EAP"); + if (str != NULL) + connman_dbus_dict_append_basic(dict, "EAP", + DBUS_TYPE_STRING, &str); + + str = connman_network_get_string(network, "WiFi.Phase2"); + if (str != NULL) + connman_dbus_dict_append_basic(dict, "Phase2", + DBUS_TYPE_STRING, &str); + + str = connman_network_get_string(network, "WiFi.Identity"); + if (str != NULL) + connman_dbus_dict_append_basic(dict, "Identity", + DBUS_TYPE_STRING, &str); + + str = connman_network_get_string(network, "WiFi.CACertFile"); + if (str != NULL) + connman_dbus_dict_append_basic(dict, "CACertFile", + DBUS_TYPE_STRING, &str); + + str = connman_network_get_string(network, + "WiFi.ClientCertFile"); + if (str != NULL) + connman_dbus_dict_append_basic(dict, "ClientCertFile", + DBUS_TYPE_STRING, &str); + + str = connman_network_get_string(network, + "WiFi.PrivateKeyFile"); + if (str != NULL) + connman_dbus_dict_append_basic(dict, "PrivateKeyFile", + DBUS_TYPE_STRING, &str); + } +} +#endif + static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, struct connman_service *service) { @@ -2345,6 +3298,23 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, const char *str; GSList *list; +#if defined TIZEN_EXT + unsigned int frequency = 0U; + if (service && service->network) { + frequency = connman_network_get_frequency(service->network); + connman_dbus_dict_append_basic(dict, "Frequency", + DBUS_TYPE_UINT16, &frequency); + } + const void *wifi_vsie; + unsigned int wifi_vsie_len; + wifi_vsie = connman_network_get_blob(service->network, "WiFi.Vsie", &wifi_vsie_len); + if(wifi_vsie_len > 0) { + DBG("ConnMan, service->path=%s vsie length=%d", service->path, wifi_vsie_len); + } + connman_dbus_dict_append_fixed_array(dict, "Vsie", DBUS_TYPE_BYTE, + &wifi_vsie, wifi_vsie_len); +#endif + str = __connman_service_type2string(service->type); if (str) connman_dbus_dict_append_basic(dict, "Type", @@ -2358,6 +3328,13 @@ static void append_properties(DBusMessageIter *dict, dbus_bool_t limited, connman_dbus_dict_append_basic(dict, "State", DBUS_TYPE_STRING, &str); +#ifdef TIZEN_EXT + str = state2string(service->state_ipv6); + if (str != NULL) + connman_dbus_dict_append_basic(dict, "StateIPv6", + DBUS_TYPE_STRING, &str); +#endif + str = error2string(service->error); if (str) connman_dbus_dict_append_basic(dict, "Error", @@ -2403,6 +3380,21 @@ 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); + + connman_dbus_dict_append_basic(dict, "DisconnectReason", + DBUS_TYPE_INT32, &service->disconnect_reason); + + connman_dbus_dict_append_basic(dict, "AssocStatusCode", + DBUS_TYPE_INT32, &service->assoc_status_code); + + break; +#endif case CONNMAN_SERVICE_TYPE_ETHERNET: case CONNMAN_SERVICE_TYPE_BLUETOOTH: case CONNMAN_SERVICE_TYPE_GADGET: @@ -2635,6 +3627,54 @@ char **connman_service_get_timeservers(struct connman_service *service) return service->timeservers; } +#if defined TIZEN_EXT +/* + * Description: Telephony plug-in requires manual PROXY setting function + */ +int connman_service_set_proxy(struct connman_service *service, + const char *proxy, gboolean active) +{ + char **proxies_array = NULL; + + if (service == NULL) + return -EINVAL; + + switch (service->type) { + case CONNMAN_SERVICE_TYPE_CELLULAR: + case CONNMAN_SERVICE_TYPE_ETHERNET: + case CONNMAN_SERVICE_TYPE_WIFI: + break; + + default: + return -EINVAL; + } + + g_strfreev(service->proxies); + service->proxies = NULL; + + if (proxy != NULL) + proxies_array = g_strsplit(proxy, " ", 0); + + service->proxies = proxies_array; + + if (proxy == NULL) { + service->proxy_config = CONNMAN_SERVICE_PROXY_METHOD_DIRECT; + DBG("proxy changed (%d)", active); + } else { + service->proxy_config = CONNMAN_SERVICE_PROXY_METHOD_MANUAL; + DBG("proxy chagned %s (%d)", proxy, active); + } + + if (active == TRUE) { + proxy_changed(service); + + __connman_notifier_proxy_changed(service); + } + + return 0; +} +#endif + void connman_service_set_proxy_method(struct connman_service *service, enum connman_service_proxy_method method) { @@ -2722,6 +3762,18 @@ const char *connman_service_get_proxy_autoconfig(struct connman_service *service return NULL; } +#if defined TIZEN_EXT +int connman_service_get_ipv6_dns_method(struct connman_service *service) +{ + if (!service) { + DBG("Service is NULL"); + return -1; + } + + return service->dns_config_method_ipv6; +} +#endif + void __connman_service_set_timeservers(struct connman_service *service, char **timeservers) { @@ -2849,6 +3901,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) { @@ -2968,7 +4036,9 @@ int __connman_service_check_passphrase(enum connman_service_security security, case CONNMAN_SERVICE_SECURITY_UNKNOWN: case CONNMAN_SERVICE_SECURITY_NONE: case CONNMAN_SERVICE_SECURITY_WPA: +#if !defined TIZEN_EXT case CONNMAN_SERVICE_SECURITY_RSN: +#endif DBG("service security '%s' (%d) not handled", security2string(security), security); @@ -2976,6 +4046,9 @@ int __connman_service_check_passphrase(enum connman_service_security security, return -EOPNOTSUPP; case CONNMAN_SERVICE_SECURITY_PSK: +#if defined TIZEN_EXT + case CONNMAN_SERVICE_SECURITY_RSN: +#endif /* A raw key is always 64 bytes length, * its content is in hex representation. * A PSK key must be between [8..63]. @@ -3019,7 +4092,14 @@ int __connman_service_set_passphrase(struct connman_service *service, if (service->immutable && service->security != CONNMAN_SERVICE_SECURITY_8021X) return -EINVAL; - +#if defined TIZEN_EXT + /* The encrypted passphrase is used here + * and validation is done by net-config before being encrypted. + */ + if (service->security != CONNMAN_SERVICE_SECURITY_PSK && + service->security != CONNMAN_SERVICE_SECURITY_RSN && + service->security != CONNMAN_SERVICE_SECURITY_WEP) +#endif err = __connman_service_check_passphrase(service->security, passphrase); if (err < 0) @@ -3347,6 +4427,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->state)) { + 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); @@ -3384,6 +4479,10 @@ static DBusMessage *set_property(DBusConnection *conn, GString *str; int index; const char *gw; +#if defined TIZEN_EXT + enum connman_ipconfig_type ip_type = CONNMAN_IPCONFIG_TYPE_ALL; + DBG("%s", name); +#endif if (__connman_provider_is_immutable(service->provider) || service->immutable) @@ -3400,17 +4499,64 @@ static DBusMessage *set_property(DBusConnection *conn, gw = __connman_ipconfig_get_gateway_from_index(index, CONNMAN_IPCONFIG_TYPE_ALL); +#if !defined TIZEN_EXT if (gw && strlen(gw)) __connman_service_nameserver_del_routes(service, CONNMAN_IPCONFIG_TYPE_ALL); - +#endif dbus_message_iter_recurse(&value, &entry); +#if defined TIZEN_EXT + /* IPv4/IPv6 Last DNS config method */ + int last_dns_ipv4 = service->dns_config_method_ipv4; + int last_dns_ipv6 = service->dns_config_method_ipv6; + DBG("Last DNS Config Method IPv4: %d IPv6: %d", last_dns_ipv4, last_dns_ipv6); +#endif + while (dbus_message_iter_get_arg_type(&entry) == DBUS_TYPE_STRING) { const char *val; dbus_message_iter_get_basic(&entry, &val); dbus_message_iter_next(&entry); +#ifdef TIZEN_EXT + /* First unpack the DNS Config Method */ + DBG("DNS Config Method: %s", val); + if((g_strcmp0(val, "ipv4.manual") == 0)) { + service->dns_config_method_ipv4 = + CONNMAN_DNSCONFIG_METHOD_MANUAL; + + if(last_dns_ipv4 != CONNMAN_DNSCONFIG_METHOD_MANUAL) { + if(ip_type == CONNMAN_IPCONFIG_TYPE_UNKNOWN) + ip_type = CONNMAN_IPCONFIG_TYPE_IPV4; + else + ip_type = CONNMAN_IPCONFIG_TYPE_ALL; + } + continue; + } else if(g_strcmp0(val, "ipv4.dhcp") == 0) { + service->dns_config_method_ipv4 = + CONNMAN_DNSCONFIG_METHOD_DHCP; + if(last_dns_ipv4 == CONNMAN_DNSCONFIG_METHOD_MANUAL) + ip_type = CONNMAN_IPCONFIG_TYPE_IPV4; + + continue; + } else if(g_strcmp0(val, "ipv6.manual") == 0) { + service->dns_config_method_ipv6 = + CONNMAN_DNSCONFIG_METHOD_MANUAL; + if(last_dns_ipv6 != CONNMAN_DNSCONFIG_METHOD_MANUAL) { + if(ip_type == CONNMAN_IPCONFIG_TYPE_UNKNOWN) + ip_type = CONNMAN_IPCONFIG_TYPE_IPV6; + else + ip_type = CONNMAN_IPCONFIG_TYPE_ALL; + } + continue; + } else if(g_strcmp0(val, "ipv6.dhcp") == 0) { + service->dns_config_method_ipv6 = + CONNMAN_DNSCONFIG_METHOD_DHCP; + if(last_dns_ipv6 == CONNMAN_DNSCONFIG_METHOD_MANUAL) + ip_type = CONNMAN_IPCONFIG_TYPE_IPV6; + continue; + } +#endif if (!val[0]) continue; @@ -3420,7 +4566,21 @@ static DBusMessage *set_property(DBusConnection *conn, g_string_append(str, val); } +#if defined TIZEN_EXT + if (service->dns_config_method_ipv4 == CONNMAN_DNSCONFIG_METHOD_DHCP && + service->dns_config_method_ipv6 == CONNMAN_DNSCONFIG_METHOD_DHCP) { + DBG("Both IPv4 and IPv6 DNS Method DHCP"); + ip_type = CONNMAN_IPCONFIG_TYPE_ALL; + } + if (gw && strlen(gw)) + __connman_service_nameserver_del_routes(service, + ip_type); + + DBG("%s ip_type: %d nameserver remove all", name, ip_type); + nameserver_remove_all(service, ip_type); +#else nameserver_remove_all(service, CONNMAN_IPCONFIG_TYPE_ALL); +#endif g_strfreev(service->nameservers_config); if (str->len > 0) { @@ -3443,7 +4603,12 @@ static DBusMessage *set_property(DBusConnection *conn, if (gw && strlen(gw)) __connman_service_nameserver_add_routes(service, gw); +#if defined TIZEN_EXT + DBG("%s ip_type: %d nameserver add all", name, ip_type); + nameserver_add_all(service, ip_type); +#else nameserver_add_all(service, CONNMAN_IPCONFIG_TYPE_ALL); +#endif dns_configuration_changed(service); if (__connman_service_is_connected_state(service, @@ -3646,8 +4811,10 @@ static void set_error(struct connman_service *service, if (!service->path) return; +#if !defined TIZEN_EXT if (!allow_property_changed(service)) return; +#endif str = error2string(service->error); @@ -3694,6 +4861,14 @@ static void service_complete(struct connman_service *service) service_save(service); } +static void set_idle(struct connman_service *service) +{ + service->state = service->state_ipv4 = service->state_ipv6 = + CONNMAN_SERVICE_STATE_IDLE; + set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN); + state_changed(service); +} + static DBusMessage *clear_property(DBusConnection *conn, DBusMessage *msg, void *user_data) { @@ -3856,6 +5031,17 @@ static GList *preferred_tech_list_get(void) CONNMAN_SERVICE_CONNECT_REASON_USER) { DBG("service %p name %s is user connected", service, service->name); +#if defined TIZEN_EXT + /* We can connect to a favorite service like + * wifi even we have a userconnect for cellular + * because we have refount for cellular service + */ + if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) + break; + + if (service->type == CONNMAN_SERVICE_TYPE_BLUETOOTH) + break; +#endif return NULL; } } @@ -3930,6 +5116,20 @@ static bool auto_connect_service(GList *services, continue; } +#if defined TIZEN_EXT + DBG("service %p %s %s %s, favorite(%d), ignore(%d), hidden(%d, %d)", + service, service->name, + state2string(service->state), + __connman_service_type2string(service->type), + service->favorite, is_ignore(service), + service->hidden, service->hidden_service); + + /* Tizen takes Wi-Fi as the highest priority into consideration. */ + if (service->type != CONNMAN_SERVICE_TYPE_WIFI) + if (is_connecting(service->state) == TRUE || is_connected(service->state) == TRUE) + continue; +#endif + if (service->pending || is_connecting(service->state) || is_connected(service->state)) { @@ -3949,9 +5149,21 @@ static bool auto_connect_service(GList *services, if (preferred) continue; +#if defined TIZEN_EXT + DBG("Service is not favorite, autoconnecting %d", + autoconnecting); +#endif return autoconnecting; } +#if defined TIZEN_EXT + DBG("service %p identifier %s roaming %d ignore %d " + "ipconfig_usable %d autoconnect %d state %d", + service, + service->identifier, service->roaming, + service->ignore, is_ipconfig_usable(service), + service->autoconnect, service->state); +#endif if (is_ignore(service) || service->state != CONNMAN_SERVICE_STATE_IDLE) continue; @@ -3962,6 +5174,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)); @@ -3999,6 +5216,21 @@ static gboolean run_auto_connect(gpointer data) return FALSE; } +#if defined TIZEN_EXT +bool __connman_service_get_auto_connect_mode(void) +{ + return auto_connect_mode; +} + +void __connman_service_set_auto_connect_mode(bool enable) +{ + DBG("set auto_connect_mode = %d", enable); + + if (auto_connect_mode != enable) + auto_connect_mode = enable; +} +#endif + void __connman_service_auto_connect(enum connman_service_connect_reason reason) { DBG(""); @@ -4006,10 +5238,33 @@ void __connman_service_auto_connect(enum connman_service_connect_reason reason) if (autoconnect_timeout != 0) return; +#if defined TIZEN_EXT + if (auto_connect_mode == FALSE) { + DBG("Currently, not auto connection mode"); + return; + } +#endif + if (!__connman_session_policy_autoconnect(reason)) return; +#if defined TIZEN_EXT + /* Adding Timeout of 500ms before trying to auto connect. + * This is done because of below scenario + * 1. Device is connected to AP1 + * 2. WPS Connection request is initiated for AP2 + * 3. Immediately WPS Connection is Cancelled + * When WPS Connection Connection is initiated for AP2 then + * sometimes there is a scenario where connman gets in ASSOCIATED + * state with AP1 due to autoconnect and subsequently the connection + * initiated by AP1 fails and connman service for AP1 comes in + * FAILURE state due to this when connection with AP2 is cancelled + * then autoconnect with AP1 doesn't works because its autoconnection + * is ignored as its last state was FAILURE rather than IDLE */ + autoconnect_timeout = g_timeout_add(500, run_auto_connect, +#else autoconnect_timeout = g_idle_add(run_auto_connect, +#endif GUINT_TO_POINTER(reason)); } @@ -4173,19 +5428,67 @@ static DBusMessage *connect_service(DBusConnection *conn, DBusMessage *msg, void *user_data) { struct connman_service *service = user_data; +#if defined TIZEN_EXT + int err = 0; +#else int index, err = 0; GList *list; +#endif DBG("service %p", service); +#if defined TIZEN_EXT + /* + * Description: TIZEN implements system global connection management. + */ + if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) + connman_service_user_pdn_connection_ref(service); + + /*Reset the Disconnect Reason while issue connect request*/ + service->disconnect_reason = 0; + + /*Reset the association status code while issue connect request*/ + service->assoc_status_code = 0; +#endif + 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; + + if (!service->passphrase && uid == service->user.favorite_user) { + DBG("Now load this favorite user's passphrase."); + service_load_passphrase(service); + } + } + +#if !defined TIZEN_EXT index = __connman_service_get_index(service); for (list = service_list; list; list = list->next) { struct connman_service *temp = list->data; +#if defined TIZEN_EXT + if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) + break; +#endif if (!is_connecting(temp->state) && !is_connected(temp->state)) break; @@ -4202,6 +5505,7 @@ static DBusMessage *connect_service(DBusConnection *conn, } if (err == -EINPROGRESS) return __connman_error_operation_timeout(msg); +#endif service->ignore = false; @@ -4232,6 +5536,35 @@ static DBusMessage *disconnect_service(DBusConnection *conn, DBG("service %p", service); +#if defined TIZEN_EXT + /* + * Description: TIZEN implements system global connection management. + */ + if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) { + if (connman_service_user_pdn_connection_unref_and_test(service) != TRUE) + return __connman_error_failed(msg, EISCONN); + + if (is_connected(service->state) == TRUE && + service == connman_service_get_default_connection()) + return __connman_error_failed(msg, EISCONN); + } +#endif + + 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); @@ -4241,6 +5574,24 @@ static DBusMessage *disconnect_service(DBusConnection *conn, return g_dbus_create_reply(msg, DBUS_TYPE_INVALID); } +#if defined TIZEN_EXT +static void __connman_service_cleanup_network_8021x(struct connman_service *service) +{ + if (service == NULL) + return; + + DBG("service %p ", service); + + connman_network_set_string(service->network, "WiFi.EAP", NULL); + connman_network_set_string(service->network, "WiFi.Identity", NULL); + connman_network_set_string(service->network, "WiFi.CACertFile", NULL); + connman_network_set_string(service->network, "WiFi.ClientCertFile", NULL); + connman_network_set_string(service->network, "WiFi.PrivateKeyFile", NULL); + connman_network_set_string(service->network, "WiFi.PrivateKeyPassphrase", NULL); + connman_network_set_string(service->network, "WiFi.Phase2", NULL); +} +#endif + bool __connman_service_remove(struct connman_service *service) { if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET || @@ -4251,8 +5602,10 @@ bool __connman_service_remove(struct connman_service *service) __connman_provider_is_immutable(service->provider)) return false; +#if !defined TIZEN_EXT if (!service->favorite && !is_idle(service->state)) return false; +#endif __connman_service_disconnect(service); @@ -4283,13 +5636,62 @@ bool __connman_service_remove(struct connman_service *service) g_free(service->eap); service->eap = NULL; +#if defined TIZEN_EXT + g_free(service->ca_cert_file); + service->ca_cert_file = NULL; + + g_free(service->client_cert_file); + service->client_cert_file = NULL; + + g_free(service->private_key_file); + service->private_key_file = NULL; + + g_free(service->private_key_passphrase); + service->private_key_passphrase = NULL; + + g_free(service->phase2); + service->phase2 = NULL; + + __connman_service_cleanup_network_8021x(service); + + __connman_ipconfig_set_method(service->ipconfig_ipv4, CONNMAN_IPCONFIG_METHOD_DHCP); + __connman_ipconfig_set_method(service->ipconfig_ipv6, CONNMAN_IPCONFIG_METHOD_AUTO); + connman_service_set_proxy(service, NULL, false); + + __connman_service_nameserver_clear(service); + + g_strfreev(service->nameservers_config); + service->nameservers_config = NULL; + +#endif + +#if defined TIZEN_EXT + if (service->security != CONNMAN_SERVICE_SECURITY_8021X) +#endif + set_idle(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); +#if defined TIZEN_EXT + /* Reset IP Method and DNS Method to DHCP */ + __connman_ipconfig_set_method(service->ipconfig_ipv4, + CONNMAN_IPCONFIG_METHOD_DHCP); + service->dns_config_method_ipv4 = CONNMAN_DNSCONFIG_METHOD_DHCP; + g_strfreev(service->nameservers_config); + service->nameservers_config = NULL; +#endif + +#if defined TIZEN_EXT + __connman_storage_remove_service(service->identifier); +#else service_save(service); +#endif return true; } @@ -4301,6 +5703,23 @@ 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 !defined TIZEN_EXT + 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); + } +#endif + } + if (!__connman_service_remove(service)) return __connman_error_not_supported(msg); @@ -4510,6 +5929,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; @@ -4522,17 +5965,23 @@ static void service_append_added_foreach(gpointer data, gpointer user_data) DBusMessageIter *iter = user_data; if (!service || !service->path) { +#if !defined TIZEN_EXT DBG("service %p or path is NULL", service); +#endif return; } if (g_hash_table_lookup(services_notify->add, service->path)) { +#if !defined TIZEN_EXT DBG("new %s", service->path); +#endif append_struct(service, iter); g_hash_table_remove(services_notify->add, service->path); } else { +#if !defined TIZEN_EXT DBG("changed %s", service->path); +#endif append_struct_service(iter, NULL, service); } @@ -4620,6 +6069,10 @@ static void service_schedule_removed(struct connman_service *service) static bool allow_property_changed(struct connman_service *service) { +#if defined TIZEN_EXT + if (service->path == NULL) + return FALSE; +#endif if (g_hash_table_lookup_extended(services_notify->add, service->path, NULL, NULL)) return false; @@ -4649,6 +6102,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) }, { }, }; @@ -4789,6 +6245,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; @@ -4798,6 +6259,14 @@ static void service_initialize(struct connman_service *service) service->provider = NULL; service->wps = false; +#if defined TIZEN_EXT + service->storage_reload = false; + /* + * Description: TIZEN implements system global connection management. + */ + service->user_pdn_connection_refcount = 0; + __sync_synchronize(); +#endif } /** @@ -5035,6 +6504,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->state)) { + 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 * @@ -5129,6 +6632,53 @@ void __connman_service_mark_dirty(void) services_dirty = true; } +#if defined TIZEN_EXT +/** + * Returns profile count if there is any connected profiles + * that use same interface + */ +int __connman_service_get_connected_count_of_iface( + struct connman_service *service) +{ + GList *list; + int count = 0; + int index1 = 0; + int index2 = 0; + + DBG(""); + + index1 = __connman_service_get_index(service); + + if (index1 <= 0) + return 0; + + for (list = service_list; list; list = list->next) { + struct connman_service *service2 = list->data; + + if (service == service2) + continue; + + index2 = __connman_service_get_index(service2); + + if (is_connected(service2->state) && index2 > 0 && index1 == index2) + count++; + + index2 = 0; + } + + DBG("Interface index %d, count %d", index1, count); + + return count; +} + +void __connman_service_set_storage_reload(struct connman_service *service, + bool storage_reload) +{ + if (service != NULL) + service->storage_reload = storage_reload; +} +#endif + /** * __connman_service_set_favorite_delayed: * @service: service structure @@ -5141,6 +6691,10 @@ int __connman_service_set_favorite_delayed(struct connman_service *service, bool favorite, bool delay_ordering) { +#if defined TIZEN_EXT + if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) + return -EIO; +#endif if (service->hidden) return -EOPNOTSUPP; @@ -5285,7 +6839,14 @@ static void report_error_cb(void *user_context, bool retry, /* It is not relevant to stay on Failure state * when failing is due to wrong user input */ __connman_service_clear_error(service); +#if defined TIZEN_EXT + /* Reseting the state back in case of failure state */ + service->state_ipv4 = service->state_ipv6 = + CONNMAN_SERVICE_STATE_IDLE; + if (service->error != CONNMAN_SERVICE_ERROR_AUTH_FAILED) + set_error(service, CONNMAN_SERVICE_ERROR_UNKNOWN); +#endif service_complete(service); __connman_connection_update_gateway(); } @@ -5467,6 +7028,126 @@ static int service_update_preferred_order(struct connman_service *default_servic return -EALREADY; } +#if defined TIZEN_EXT +static gboolean __connman_service_can_drop(struct connman_service *service) +{ + if (is_connected(service->state) == TRUE || is_connecting(service->state) == TRUE) { + if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR) + return TRUE; + else if (connman_service_is_no_ref_user_pdn_connection(service) == TRUE) + return TRUE; + } + return FALSE; +} + +static struct connman_device *default_connecting_device = NULL; + +static void __connman_service_disconnect_default(struct connman_service *service) +{ + struct connman_device *default_device = NULL; + + if (default_connecting_device == NULL) + return; + + default_device = connman_network_get_device( + __connman_service_get_network(service)); + + DBG("Disconnecting service %p %s", service, service->path); + DBG("Disconnecting device %p %p %s", + default_connecting_device, + default_device, + connman_device_get_string(default_device, "Name")); + + if (default_connecting_device == default_device) + default_connecting_device = NULL; +} + +static void __connman_service_connect_default(struct connman_service *current) +{ + int err; + GList *list; + bool default_internet; + struct connman_service *service; + struct connman_service *default_service = NULL; + struct connman_device *default_device = NULL; + + if (current->type == CONNMAN_SERVICE_TYPE_CELLULAR) { + switch (current->state) { + case CONNMAN_SERVICE_STATE_UNKNOWN: + case CONNMAN_SERVICE_STATE_ASSOCIATION: + case CONNMAN_SERVICE_STATE_CONFIGURATION: + return; + default: + break; + } + + if (default_connecting_device && + __connman_service_is_internet_profile(current) == TRUE) { + if (current->network == NULL) + return; + + default_device = connman_network_get_device(current->network); + if (default_connecting_device == default_device) { + DBG("Cellular service[%s] %p %s", + state2string(current->state), current, current->path); + DBG("Cellular device %p %p %s", + default_connecting_device, default_device, + connman_device_get_string(default_device, "Name")); + + default_connecting_device = NULL; + } + } + + return; + } else if (is_connected(current->state) == TRUE || is_connecting(current->state) == TRUE) + return; + + /* Always-on: keep default cellular connection as possible */ + for (list = service_list; list; list = list->next) { + service = list->data; + + if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR || + __connman_service_is_internet_profile(service) != TRUE || + service->network == NULL) { + continue; + } + + default_internet = + connman_network_get_bool(service->network, "DefaultInternet"); + + DBG("service: %p %s %s %s (default: %d)", service, service->name, + __connman_service_type2string(service->type), + state2string(service->state), default_internet); + + if (default_internet) { + default_service = service; + if (is_connected(default_service->state) == TRUE || + is_connecting(default_service->state) == TRUE) + return; + + default_device = connman_network_get_device(default_service->network); + if (default_connecting_device == default_device) { + DBG("Device is connecting (%p)", default_connecting_device); + return; + } + + default_connecting_device = default_device; + default_service->connect_reason = CONNMAN_SERVICE_CONNECT_REASON_USER; + + err = __connman_network_connect(default_service->network); + DBG("Connecting default service %p %s [%d]", + default_service, default_service->path, err); + DBG("Connecting device %p %s", default_connecting_device, + connman_device_get_string(default_connecting_device, "Name")); + if (err < 0 && err != -EINPROGRESS) { + default_connecting_device = NULL; + } else + break; + } + } +} +#endif + static void single_connected_tech(struct connman_service *allowed) { struct connman_service *service; @@ -5475,15 +7156,24 @@ static void single_connected_tech(struct connman_service *allowed) DBG("keeping %p %s", allowed, allowed->path); +#if defined TIZEN_EXT + if (!allowed || allowed->type == CONNMAN_SERVICE_TYPE_CELLULAR) + return; +#endif + for (iter = service_list; iter; iter = iter->next) { service = iter->data; +#if defined TIZEN_EXT + if (service != allowed && service->type != allowed->type && + __connman_service_can_drop(service) == TRUE) +#else if (!is_connected(service->state)) break; if (service == allowed) continue; - +#endif services = g_slist_prepend(services, service); } @@ -5491,12 +7181,32 @@ static void single_connected_tech(struct connman_service *allowed) service = list->data; DBG("disconnecting %p %s", service, service->path); +#if defined TIZEN_EXT + __connman_service_disconnect_default(service); +#endif __connman_service_disconnect(service); } g_slist_free(services); } +#if defined TIZEN_EXT +static void set_priority_connected_service(void) +{ + struct connman_service *service; + GList *list; + + for (list = service_list; list; list = list->next) { + service = list->data; + + if (is_connected(service->state) == FALSE) + service->order = 5; + else + service->order = 6; + } +} +#endif + static const char *get_dbus_sender(struct connman_service *service) { if (!service->pending) @@ -5640,6 +7350,11 @@ static int service_indicate_state(struct connman_service *service) else if (service->type != CONNMAN_SERVICE_TYPE_VPN) vpn_auto_connect(); +#if defined TIZEN_EXT + if (service->type == CONNMAN_SERVICE_TYPE_WIFI) + set_priority_connected_service(); +#endif + break; case CONNMAN_SERVICE_STATE_ONLINE: @@ -5652,6 +7367,8 @@ static int service_indicate_state(struct connman_service *service) reply_pending(service, ECONNABORTED); def_service = __connman_service_get_default(); + service->disconnect_reason = connman_network_get_disconnect_reason(service->network); + service->assoc_status_code = connman_network_get_assoc_status_code(service->network); if (!__connman_notifier_is_connected() && def_service && @@ -5664,8 +7381,20 @@ static int service_indicate_state(struct connman_service *service) __connman_wpad_stop(service); +#if defined TIZEN_EXT + /** + * Skip the functions if there is any connected profiles + * that use same interface + */ + if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR || + __connman_service_get_connected_count_of_iface( + service) <= 0) { +#endif domain_changed(service); proxy_changed(service); +#if defined TIZEN_EXT + } +#endif /* * Previous services which are connected and which states @@ -5678,7 +7407,11 @@ static int service_indicate_state(struct connman_service *service) break; case CONNMAN_SERVICE_STATE_FAILURE: - +#if defined TIZEN_EXT + if (service->type == CONNMAN_SERVICE_TYPE_WIFI) + service->order = 5; + __connman_service_auto_connect(CONNMAN_SERVICE_CONNECT_REASON_AUTO); +#endif if (service->connect_reason == CONNMAN_SERVICE_CONNECT_REASON_USER && connman_agent_report_error(service, service->path, error2string(service->error), @@ -5693,6 +7426,10 @@ static int service_indicate_state(struct connman_service *service) service_list_sort(); +#if defined TIZEN_EXT + __connman_service_connect_default(service); +#endif + __connman_connection_update_gateway(); if ((old_state == CONNMAN_SERVICE_STATE_ONLINE && @@ -5707,6 +7444,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; } @@ -5723,6 +7474,23 @@ int __connman_service_indicate_error(struct connman_service *service, set_error(service, error); +/* default internet service: fix not cleared if pdp activation*/ +#if defined TIZEN_EXT + /* + * If connection failed for default service(DefaultInternet), + * default_connecting_device should be cleared. + */ + if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR && + service->error == CONNMAN_SERVICE_ERROR_CONNECT_FAILED) + __connman_service_disconnect_default(service); + + if (service->type == CONNMAN_SERVICE_TYPE_WIFI && + service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY) { + g_free(service->passphrase); + service->passphrase = NULL; + } +#endif + __connman_service_ipconfig_indicate_state(service, CONNMAN_SERVICE_STATE_FAILURE, CONNMAN_IPCONFIG_TYPE_IPV4); @@ -5825,6 +7593,15 @@ done: __connman_wispr_start(service, CONNMAN_IPCONFIG_TYPE_IPV4); } +#if defined TIZEN_EXT +void connman_check_proxy_setup_and_wispr_start(struct connman_service *service){ + + DBG("check the proxy and start wispr"); + check_proxy_setup(service); + return; +} +#endif + /* * How many networks are connected at the same time. If more than 1, * then set the rp_filter setting properly (loose mode routing) so that network @@ -5976,6 +7753,18 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service, if (old_state == new_state) return -EALREADY; +#if defined TIZEN_EXT + __sync_synchronize(); + if (service->user_pdn_connection_refcount > 0 && + service->type == CONNMAN_SERVICE_TYPE_CELLULAR) + if (new_state == CONNMAN_SERVICE_STATE_FAILURE || + new_state == CONNMAN_SERVICE_STATE_DISCONNECT || + new_state == CONNMAN_SERVICE_STATE_IDLE) { + service->user_pdn_connection_refcount = 0; + __sync_synchronize(); + } +#endif + DBG("service %p (%s) old state %d (%s) new state %d (%s) type %d (%s)", service, service ? service->identifier : NULL, old_state, state2string(old_state), @@ -5989,14 +7778,25 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service, case CONNMAN_SERVICE_STATE_CONFIGURATION: break; case CONNMAN_SERVICE_STATE_READY: - if (connman_setting_get_bool("EnableOnlineCheck")) +#if defined TIZEN_EXT + if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR && + __connman_service_is_internet_profile(service) != TRUE) { + if (type == CONNMAN_IPCONFIG_TYPE_IPV4) + service_rp_filter(service, TRUE); + + break; + } +#endif + if (connman_setting_get_bool("EnableOnlineCheck")) { if (type == CONNMAN_IPCONFIG_TYPE_IPV4) { +#if !defined TIZEN_EXT check_proxy_setup(service); +#endif } else { service->online_check_count = 1; __connman_wispr_start(service, type); } - else + } else connman_info("Online check disabled. " "Default service remains in READY state."); if (type == CONNMAN_IPCONFIG_TYPE_IPV4) @@ -6033,6 +7833,19 @@ int __connman_service_ipconfig_indicate_state(struct connman_service *service, __connman_timeserver_sync(service); +#if defined TIZEN_EXT + int ret = service_indicate_state(service); + /*Sent the Ready changed signal again in case IPv4 IP set + after IPv6 IP set*/ + + if(ret == -EALREADY && type == CONNMAN_IPCONFIG_TYPE_IPV4 + && new_state == CONNMAN_SERVICE_STATE_READY) { + DBG("Notify IPv4 state new/old %d/%d", new_state,old_state); + state_changed(service); + } + + return ret; +#endif return service_indicate_state(service); } @@ -6129,6 +7942,33 @@ static int service_connect(struct connman_service *service) if (service->hidden) return -EPERM; +#if defined TIZEN_EXT + GList *list; + int index; + + index = __connman_service_get_index(service); + + for (list = service_list; list; list = list->next) { + struct connman_service *temp = list->data; + + if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) + break; + + if (!is_connecting(temp->state) && !is_connected(temp->state)) + break; + + if (service == temp) + continue; + + if (service->type != temp->type) + continue; + + if (__connman_service_get_index(temp) == index && + __connman_service_disconnect(temp) == -EINPROGRESS) + return -EINPROGRESS; + } +#endif + switch (service->type) { case CONNMAN_SERVICE_TYPE_UNKNOWN: case CONNMAN_SERVICE_TYPE_SYSTEM: @@ -6153,7 +7993,11 @@ static int service_connect(struct connman_service *service) if (service->error == CONNMAN_SERVICE_ERROR_INVALID_KEY) return -ENOKEY; - 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; @@ -6167,13 +8011,25 @@ 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) + */ + DBG("service eap: %s", service->eap); + if (g_str_equal(service->eap, "tls") || + g_str_equal(service->eap, "sim") || + g_str_equal(service->eap, "aka")) + 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 @@ -6279,7 +8135,6 @@ int __connman_service_connect(struct connman_service *service, DBG("service %p err %d", service, err); service->connect_reason = reason; - if (err >= 0) return 0; @@ -6361,6 +8216,14 @@ int __connman_service_disconnect(struct connman_service *service) __connman_ipconfig_set_proxy_autoconfig(service->ipconfig_ipv6, NULL); +#if defined TIZEN_EXT + /** + * Skip the functions If there is any connected profiles + * that use same interface + */ + if (service->type != CONNMAN_SERVICE_TYPE_CELLULAR || + __connman_service_get_connected_count_of_iface(service) <= 0) { +#endif __connman_ipconfig_address_remove(service->ipconfig_ipv4); settings_changed(service, service->ipconfig_ipv4); @@ -6369,6 +8232,9 @@ int __connman_service_disconnect(struct connman_service *service) __connman_ipconfig_disable(service->ipconfig_ipv4); __connman_ipconfig_disable(service->ipconfig_ipv6); +#if defined TIZEN_EXT + } +#endif __connman_stats_service_unregister(service); @@ -6581,6 +8447,9 @@ static void service_ip_bound(struct connman_ipconfig *ipconfig, struct connman_service *service = __connman_ipconfig_get_data(ipconfig); enum connman_ipconfig_method method = CONNMAN_IPCONFIG_METHOD_UNKNOWN; enum connman_ipconfig_type type = CONNMAN_IPCONFIG_TYPE_UNKNOWN; +#if defined TIZEN_EXT + int err; +#endif DBG("%s ip bound", ifname); @@ -6592,9 +8461,18 @@ static void service_ip_bound(struct connman_ipconfig *ipconfig, if (type == CONNMAN_IPCONFIG_TYPE_IPV6 && method == CONNMAN_IPCONFIG_METHOD_AUTO) +#if defined TIZEN_EXT + { + err = __connman_ipconfig_gateway_add(ipconfig, service); + + if(err < 0) + DBG("Failed to add gateway"); + } +#else __connman_service_ipconfig_indicate_state(service, CONNMAN_SERVICE_STATE_READY, CONNMAN_IPCONFIG_TYPE_IPV6); +#endif settings_changed(service, ipconfig); address_updated(service, type); @@ -6835,6 +8713,28 @@ unsigned int __connman_service_get_order(struct connman_service *service) if (!service->favorite) return 0; +#if defined TIZEN_EXT + if (service->type == CONNMAN_SERVICE_TYPE_VPN && + service->do_split_routing == FALSE) + order = 10; + else if (service->type == CONNMAN_SERVICE_TYPE_WIFI) { + if (service->order < 5) + order = 5; + } else if (service->type == CONNMAN_SERVICE_TYPE_ETHERNET) + order = 4; + else if (service->type == CONNMAN_SERVICE_TYPE_BLUETOOTH) + order = 3; + else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR && + __connman_service_is_internet_profile(service) == TRUE) + order = 1; + else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR && + __connman_service_is_tethering_profile(service) == TRUE) + order = 0; + else if (service->type == CONNMAN_SERVICE_TYPE_CELLULAR) + order = 0; + else + order = 2; +#else if (service == service_list->data) order = 1; @@ -6843,7 +8743,7 @@ unsigned int __connman_service_get_order(struct connman_service *service) service->order = 10; order = 10; } - +#endif DBG("service %p name %s order %d split %d", service, service->name, order, service->do_split_routing); @@ -6890,10 +8790,30 @@ static enum connman_service_security convert_wifi_security(const char *security) return CONNMAN_SERVICE_SECURITY_WPA; else if (g_str_equal(security, "rsn")) return CONNMAN_SERVICE_SECURITY_RSN; +#if defined TIZEN_EXT + else if (g_str_equal(security, "ft_psk") == TRUE) + return CONNMAN_SERVICE_SECURITY_PSK; + else if (g_str_equal(security, "ft_ieee8021x") == TRUE) + return CONNMAN_SERVICE_SECURITY_8021X; +#endif else return CONNMAN_SERVICE_SECURITY_UNKNOWN; } +#if defined TIZEN_EXT +int check_passphrase_ext(struct connman_network *network, + const char *passphrase) +{ + const char *str; + enum connman_service_security security; + + str = connman_network_get_string(network, "WiFi.Security"); + security = convert_wifi_security(str); + + return __connman_service_check_passphrase(security, passphrase); +} +#endif + static void update_from_network(struct connman_service *service, struct connman_network *network) { @@ -7067,6 +8987,19 @@ struct connman_service * __connman_service_create_from_network(struct connman_ne break; } } + +#if defined TIZEN_EXT + /* TIZEN synchronizes below information when the service creates */ + if (service->eap != NULL) + connman_network_set_string(service->network, "WiFi.EAP", + service->eap); + if (service->identity != NULL) + connman_network_set_string(service->network, "WiFi.Identity", + service->identity); + if (service->phase2 != NULL) + connman_network_set_string(service->network, "WiFi.Phase2", + service->phase2); +#endif } __connman_notifier_service_add(service, service->name); @@ -7090,6 +9023,13 @@ void __connman_service_update_from_network(struct connman_network *network) if (!service->network) return; +#if defined TIZEN_EXT + if (service->storage_reload) { + service_load(service); + __connman_service_set_storage_reload(service, false); + } +#endif + name = connman_network_get_string(service->network, "Name"); if (g_strcmp0(service->name, name) != 0) { g_free(service->name); diff --git a/src/session.c b/src/session.c index 9e3c5594..9e3c5594 100644..100755 --- a/src/session.c +++ b/src/session.c diff --git a/src/shared/netlink.c b/src/shared/netlink.c index b32ab854..b32ab854 100644..100755 --- a/src/shared/netlink.c +++ b/src/shared/netlink.c diff --git a/src/shared/netlink.h b/src/shared/netlink.h index 62bb3e01..62bb3e01 100644..100755 --- a/src/shared/netlink.h +++ b/src/shared/netlink.h diff --git a/src/shared/util.c b/src/shared/util.c index df045c5b..df045c5b 100644..100755 --- a/src/shared/util.c +++ b/src/shared/util.c diff --git a/src/shared/util.h b/src/shared/util.h index 293fb3a4..293fb3a4 100644..100755 --- a/src/shared/util.h +++ b/src/shared/util.h diff --git a/src/stats.c b/src/stats.c index 663bc382..663bc382 100644..100755 --- a/src/stats.c +++ b/src/stats.c diff --git a/src/storage.c b/src/storage.c index 5e877ef1..50c8e955 100644..100755 --- a/src/storage.c +++ b/src/storage.c @@ -23,6 +23,7 @@ #include <config.h> #endif +#include <stdio.h> #include <errno.h> #include <unistd.h> #include <sys/stat.h> @@ -71,6 +72,19 @@ static int storage_save(GKeyFile *keyfile, char *pathname) ret = -EIO; } +#if defined TIZEN_EXT + { + FILE *fp = NULL; + fp = fopen(pathname, "a+"); + if(fp){ + fflush(fp); + fsync(fp->_fileno); + fclose(fp); + DBG("sync the file to disk"); + } + } +#endif + g_free(data); return ret; diff --git a/src/task.c b/src/task.c index 953cc409..953cc409 100644..100755 --- a/src/task.c +++ b/src/task.c diff --git a/src/technology.c b/src/technology.c index d2f0ae2b..5aea9f4f 100644..100755 --- a/src/technology.c +++ b/src/technology.c @@ -43,6 +43,16 @@ static GHashTable *rfkill_list; static bool global_offlinemode; +#if defined TIZEN_EXT +typedef enum { + CONNMAN_SCAN_TYPE_FULL_CHANNEL = 0x00, + CONNMAN_SCAN_TYPE_SPECIFIC_AP, + CONNMAN_SCAN_TYPE_MULTI_AP, +} connman_scan_type_e; + +static connman_scan_type_e g_scan_type = -1; +#endif + struct connman_rfkill { unsigned int index; enum connman_service_type type; @@ -66,6 +76,7 @@ struct connman_technology { */ char *tethering_ident; char *tethering_passphrase; + bool tethering_hidden; bool enable_persistent; /* Save the tech state */ @@ -180,6 +191,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", @@ -253,8 +267,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; @@ -546,6 +559,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); } @@ -682,6 +700,10 @@ static void powered_changed(struct connman_technology *technology) __sync_synchronize(); enabled = technology->enabled; +#if defined TIZEN_EXT + DBG("ConnMan, Powered : %s, %s", + enabled ? "TRUE" : "FALSE",technology->path); +#endif connman_dbus_property_changed_basic(technology->path, CONNMAN_TECHNOLOGY_INTERFACE, "Powered", DBUS_TYPE_BOOLEAN, &enabled); @@ -882,6 +904,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; @@ -958,6 +995,25 @@ static DBusMessage *set_property(DBusConnection *conn, DBUS_TYPE_STRING, &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; @@ -997,9 +1053,38 @@ static void reply_scan_pending(struct connman_technology *technology, int err) } } +#if defined TIZEN_EXT +dbus_bool_t __connman_technology_notify_scan_changed(const char *key, void *val) +{ + DBG("key %s", key); + DBusMessage *signal; + DBusMessageIter iter; + dbus_bool_t result = FALSE; + + signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH, + CONNMAN_MANAGER_INTERFACE, "ScanChanged"); + if (!signal) + return result; + + dbus_message_iter_init_append(signal, &iter); + connman_dbus_property_append_basic(&iter, key, DBUS_TYPE_BOOLEAN, val); + + result = dbus_connection_send(connection, signal, NULL); + dbus_message_unref(signal); + + DBG("Successfuly sent signal"); + + return result; +} +#endif + void __connman_technology_scan_started(struct connman_device *device) { DBG("device %p", device); +#if defined TIZEN_EXT + dbus_bool_t status = 1; + __connman_technology_notify_scan_changed("scan_started", &status); +#endif } void __connman_technology_scan_stopped(struct connman_device *device, @@ -1029,8 +1114,32 @@ void __connman_technology_scan_stopped(struct connman_device *device, count += 1; } +#if defined TIZEN_EXT + if (count == 0) { + DBusMessage *signal; + DBusMessageIter iter; + dbus_bool_t status = 0; + __connman_technology_notify_scan_changed("scan_done", &status); + + signal = dbus_message_new_signal(CONNMAN_MANAGER_PATH, + CONNMAN_MANAGER_INTERFACE, "ScanDone"); + if (!signal) + return; + + dbus_message_iter_init_append(signal, &iter); + connman_dbus_property_append_basic(&iter, "Scantype", + DBUS_TYPE_INT32, &g_scan_type); + + dbus_connection_send(connection, signal, NULL); + dbus_message_unref(signal); + reply_scan_pending(technology, 0); + + DBG("Successfuly sent ScanDone signal"); + } +#else if (count == 0) reply_scan_pending(technology, 0); +#endif } void __connman_technology_notify_regdom_by_device(struct connman_device *device, @@ -1082,16 +1191,156 @@ static DBusMessage *scan(DBusConnection *conn, DBusMessage *msg, void *data) return __connman_error_permission_denied(msg); dbus_message_ref(msg); +#if !defined TIZEN_EXT technology->scan_pending = g_slist_prepend(technology->scan_pending, msg); +#endif err = __connman_device_request_scan(technology->type); +#if defined TIZEN_EXT + if (err < 0) + return __connman_error_failed(msg, -err); +#else if (err < 0) reply_scan_pending(technology, err); +#endif +#if defined TIZEN_EXT + if (err == 0) { + g_scan_type = CONNMAN_SCAN_TYPE_FULL_CHANNEL; + DBG("g_scan_type %d", g_scan_type); + } + technology->scan_pending = + g_slist_prepend(technology->scan_pending, msg); +#endif return NULL; } +#if defined TIZEN_EXT +static DBusMessage *specific_scan(DBusConnection *conn, DBusMessage *msg, void *data) +{ + struct connman_technology *technology = data; + GSList *specific_scan_list = NULL; + int scan_type = 0; + const char *name = NULL; + unsigned int freq = 0; + DBusMessageIter iter, dict; + int err; + + DBG("technology %p request from %s", technology, + dbus_message_get_sender(msg)); + + if (!dbus_message_iter_init(msg, &iter)) + return __connman_error_invalid_arguments(msg); + + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) + return __connman_error_invalid_arguments(msg); + + dbus_message_iter_recurse(&iter, &dict); + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter entry, value2; + const char *key; + int type; + + dbus_message_iter_recurse(&dict, &entry); + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) { + g_slist_free_full(specific_scan_list, g_free); + return __connman_error_invalid_arguments(msg); + } + + dbus_message_iter_get_basic(&entry, &key); + dbus_message_iter_next(&entry); + + if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) { + g_slist_free_full(specific_scan_list, g_free); + return __connman_error_invalid_arguments(msg); + } + + dbus_message_iter_recurse(&entry, &value2); + type = dbus_message_iter_get_arg_type(&value2); + if (g_str_equal(key, "SSID")) { + if (type != DBUS_TYPE_STRING) { + g_slist_free_full(specific_scan_list, g_free); + return __connman_error_invalid_arguments(msg); + } + + scan_type = 1; /* SSID based scan */ + dbus_message_iter_get_basic(&value2, &name); + DBG("name %s", name); + specific_scan_list = g_slist_append(specific_scan_list, g_strdup(name)); + } else if (g_str_equal(key, "Frequency")) { + if (type != DBUS_TYPE_UINT16) { + g_slist_free_full(specific_scan_list, g_free); + return __connman_error_invalid_arguments(msg); + } + + scan_type = 2; /* Frequency based scan */ + dbus_message_iter_get_basic(&value2, &freq); + DBG("freq %d", freq); + specific_scan_list = g_slist_append(specific_scan_list, GINT_TO_POINTER(freq)); + } + dbus_message_iter_next(&dict); + } + + dbus_message_ref(msg); + + err = __connman_device_request_specific_scan(technology->type, scan_type, specific_scan_list); + if (err < 0) + return __connman_error_failed(msg, -err); + + if (err == 0) { + guint list_size = g_slist_length(specific_scan_list); + if (list_size == 1) + g_scan_type = CONNMAN_SCAN_TYPE_SPECIFIC_AP; + else + g_scan_type = CONNMAN_SCAN_TYPE_MULTI_AP; + DBG("list_size %u g_scan_type %d", list_size, g_scan_type); + } + technology->scan_pending = + g_slist_prepend(technology->scan_pending, msg); + + if (scan_type == 1) { + g_slist_free_full(specific_scan_list, g_free); + scan_type = 0; + } + return NULL; +} + +static DBusMessage *get_scan_state(DBusConnection *conn, DBusMessage *msg, void *data) +{ + DBusMessage *reply; + DBusMessageIter iter, dict; + GSList *list; + struct connman_technology *technology = data; + dbus_bool_t scanning = false; + + DBG("technology %p", technology); + + for (list = technology->device_list; list; list = list->next) { + struct connman_device *device = list->data; + scanning = connman_device_get_scanning(device); + if(scanning) + break; + } + + DBG("scanning : %d", scanning); + reply = dbus_message_new_method_return(msg); + if (!reply) + return NULL; + + dbus_message_iter_init_append(reply, &iter); + + connman_dbus_dict_open(&iter, &dict); + connman_dbus_dict_append_basic(&dict, "Scanstate", + DBUS_TYPE_BOOLEAN, + &scanning); + + connman_dbus_dict_close(&iter, &dict); + + return reply; +} +#endif + static const GDBusMethodTable technology_methods[] = { { GDBUS_DEPRECATED_METHOD("GetProperties", NULL, GDBUS_ARGS({ "properties", "a{sv}" }), @@ -1100,12 +1349,28 @@ static const GDBusMethodTable technology_methods[] = { GDBUS_ARGS({ "name", "s" }, { "value", "v" }), NULL, set_property) }, { GDBUS_ASYNC_METHOD("Scan", NULL, NULL, scan) }, +#if defined TIZEN_EXT + { GDBUS_ASYNC_METHOD("SpecificScan", GDBUS_ARGS({ "specificscan", "a{sv}" }), + NULL, specific_scan) }, + { GDBUS_METHOD("GetScanState", NULL, GDBUS_ARGS({ "scan_state", "a{sv}" }), + get_scan_state) }, +#endif { }, }; 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" })) }, { }, }; @@ -1227,6 +1492,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); @@ -1532,12 +1798,13 @@ int __connman_technology_enabled(enum connman_service_type type) DBG("technology %p type %s rfkill %d enabled %d", technology, get_name(type), technology->rfkill_driven, technology->enabled); - +#if !defined TIZEN_EXT if (technology->rfkill_driven) { if (technology->tethering_persistent) enable_tethering(technology); return 0; } +#endif return technology_enabled(technology); } @@ -1550,10 +1817,10 @@ int __connman_technology_disabled(enum connman_service_type type) technology = technology_find(type); if (!technology) return -ENXIO; - +#if !defined TIZEN_EXT if (technology->rfkill_driven) return 0; - +#endif for (list = technology->device_list; list; list = list->next) { struct connman_device *device = list->data; @@ -1732,6 +1999,10 @@ int __connman_technology_add_rfkill(unsigned int index, g_hash_table_insert(rfkill_list, GINT_TO_POINTER(index), rfkill); done: +#if defined TIZEN_EXT + /* Fix Svace Issue [WGID: 1348]. */ + g_free(rfkill); +#endif technology = technology_get(type); /* If there is no driver for this type, ignore it. */ if (!technology) @@ -1739,11 +2010,12 @@ done: technology->rfkill_driven = true; +#if !defined TIZEN_EXT /* If hardblocked, there is no need to handle softblocked state */ if (technology_apply_rfkill_change(technology, softblock, hardblock, true)) return 0; - +#endif if (global_offlinemode) return 0; diff --git a/src/tethering.c b/src/tethering.c index c929ba71..891ee51f 100644..100755 --- 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,164 @@ 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 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; + + __sync_synchronize(); + + 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) +{ + 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) { + 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); + g_free(info_found->type); + g_free(info_found); + + return 0; +} + const char *__connman_tethering_get_bridge(void) { int sk, err; @@ -161,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; @@ -538,6 +703,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; } @@ -558,5 +726,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); } diff --git a/src/timeserver.c b/src/timeserver.c index 0e555a73..6325eceb 100644..100755 --- a/src/timeserver.c +++ b/src/timeserver.c @@ -88,6 +88,15 @@ static void resolv_result(GResolvResultStatus status, char **results, { int i; +#if defined TIZEN_EXT + gchar *server = NULL; + + server = g_strdup((gchar *)user_data); + ts_list = g_slist_append(ts_list, server); + + DBG("added server %s", server); +#endif + DBG("status %d", status); if (status == G_RESOLV_RESULT_STATUS_SUCCESS) { @@ -148,8 +157,13 @@ void __connman_timeserver_sync_next() DBG("Resolving timeserver %s", ts_current); +#if defined TIZEN_EXT + resolv_id = g_resolv_lookup_hostname(resolv, ts_current, + resolv_result, ts_current); +#else resolv_id = g_resolv_lookup_hostname(resolv, ts_current, resolv_result, NULL); +#endif return; } diff --git a/src/timezone.c b/src/timezone.c index e346b11a..e346b11a 100644..100755 --- a/src/timezone.c +++ b/src/timezone.c diff --git a/src/util.c b/src/util.c index 732d4512..732d4512 100644..100755 --- a/src/util.c +++ b/src/util.c diff --git a/src/utsname.c b/src/utsname.c index 1dd5e0f2..1dd5e0f2 100644..100755 --- a/src/utsname.c +++ b/src/utsname.c diff --git a/src/wispr.c b/src/wispr.c index 03b38bb8..adf62303 100644..100755 --- a/src/wispr.c +++ b/src/wispr.c @@ -879,7 +879,9 @@ static int wispr_portal_detect(struct connman_wispr_portal_context *wp_context) goto done; } +#if !defined TIZEN_EXT if (getenv("CONNMAN_WEB_DEBUG")) +#endif g_web_set_debug(wp_context->web, web_debug, "WEB"); if (wp_context->type == CONNMAN_IPCONFIG_TYPE_IPV4) { @@ -925,6 +927,11 @@ int __connman_wispr_start(struct connman_service *service, DBG("service %p", service); +#if defined TIZEN_EXT + if (connman_service_get_type(service) == CONNMAN_SERVICE_TYPE_CELLULAR) + return -EPERM; +#endif + if (!wispr_portal_list) return -EINVAL; diff --git a/src/wpad.c b/src/wpad.c index f066feee..b7f1f1e5 100644..100755 --- a/src/wpad.c +++ b/src/wpad.c @@ -161,7 +161,9 @@ int __connman_wpad_start(struct connman_service *service) return -ENOMEM; } +#if !defined TIZEN_EXT if (getenv("CONNMAN_RESOLV_DEBUG")) +#endif g_resolv_set_debug(wpad->resolv, resolv_debug, "RESOLV"); for (i = 0; nameservers[i]; i++) diff --git a/test/enable-tethering b/test/enable-tethering index cbcd4e72..674b3c91 100755 --- 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; diff --git a/test/set-timezone b/test/set-timezone deleted file mode 100755 index dfc1c981..00000000 --- a/test/set-timezone +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/python - -import sys -import dbus - -if (len(sys.argv) != 2): - print "Usage: %s <timezone>" % (sys.argv[0]) - sys.exit(1) - -bus = dbus.SystemBus() - -clock = dbus.Interface(bus.get_object('net.connman', '/'), - 'net.connman.Clock') - -print "Setting timezone to %s" % (sys.argv[1]) - -try: - clock.SetProperty("Timezone", dbus.String(sys.argv[1], variant_level=1), - signature=dbus.Signature('sv')) -except dbus.exceptions.DBusException, e_msg: - print e_msg diff --git a/tools/dbus-test.c b/tools/dbus-test.c index ece5d193..ece5d193 100644..100755 --- a/tools/dbus-test.c +++ b/tools/dbus-test.c diff --git a/tools/dhcp-server-test.c b/tools/dhcp-server-test.c index b7d2e540..b7d2e540 100644..100755 --- a/tools/dhcp-server-test.c +++ b/tools/dhcp-server-test.c diff --git a/tools/dhcp-test.c b/tools/dhcp-test.c index c34e10a8..c34e10a8 100644..100755 --- a/tools/dhcp-test.c +++ b/tools/dhcp-test.c diff --git a/tools/dnsproxy-test.c b/tools/dnsproxy-test.c index 551cae91..551cae91 100644..100755 --- a/tools/dnsproxy-test.c +++ b/tools/dnsproxy-test.c diff --git a/tools/iptables-test.c b/tools/iptables-test.c index 2df53ccd..2df53ccd 100644..100755 --- a/tools/iptables-test.c +++ b/tools/iptables-test.c diff --git a/tools/iptables-unit.c b/tools/iptables-unit.c index 426631a0..426631a0 100644..100755 --- a/tools/iptables-unit.c +++ b/tools/iptables-unit.c diff --git a/tools/manager-api.c b/tools/manager-api.c index e082962d..e082962d 100644..100755 --- a/tools/manager-api.c +++ b/tools/manager-api.c diff --git a/tools/netlink-test.c b/tools/netlink-test.c index 221e3490..221e3490 100644..100755 --- a/tools/netlink-test.c +++ b/tools/netlink-test.c diff --git a/tools/polkit-test.c b/tools/polkit-test.c index ea1d24ae..ea1d24ae 100644..100755 --- a/tools/polkit-test.c +++ b/tools/polkit-test.c diff --git a/tools/private-network-test.c b/tools/private-network-test.c index 3dd115ba..3dd115ba 100644..100755 --- a/tools/private-network-test.c +++ b/tools/private-network-test.c diff --git a/tools/resolv-test.c b/tools/resolv-test.c index 8953acd3..8953acd3 100644..100755 --- a/tools/resolv-test.c +++ b/tools/resolv-test.c diff --git a/tools/session-api.c b/tools/session-api.c index b97cfc01..b97cfc01 100644..100755 --- a/tools/session-api.c +++ b/tools/session-api.c diff --git a/tools/session-test.c b/tools/session-test.c index 4319e5a4..4319e5a4 100644..100755 --- a/tools/session-test.c +++ b/tools/session-test.c diff --git a/tools/session-test.h b/tools/session-test.h index 85129337..85129337 100644..100755 --- a/tools/session-test.h +++ b/tools/session-test.h diff --git a/tools/session-utils.c b/tools/session-utils.c index 51cec5c3..51cec5c3 100644..100755 --- a/tools/session-utils.c +++ b/tools/session-utils.c diff --git a/tools/stats-tool.c b/tools/stats-tool.c index efa39de2..efa39de2 100644..100755 --- a/tools/stats-tool.c +++ b/tools/stats-tool.c diff --git a/tools/supplicant-dbus.c b/tools/supplicant-dbus.c index d409da2d..d409da2d 100644..100755 --- a/tools/supplicant-dbus.c +++ b/tools/supplicant-dbus.c diff --git a/tools/supplicant-dbus.h b/tools/supplicant-dbus.h index 4452894b..4452894b 100644..100755 --- a/tools/supplicant-dbus.h +++ b/tools/supplicant-dbus.h diff --git a/tools/supplicant-test.c b/tools/supplicant-test.c index a6408076..a6408076 100644..100755 --- a/tools/supplicant-test.c +++ b/tools/supplicant-test.c diff --git a/tools/supplicant.c b/tools/supplicant.c index e2e6fea5..e2e6fea5 100644..100755 --- a/tools/supplicant.c +++ b/tools/supplicant.c diff --git a/tools/supplicant.h b/tools/supplicant.h index 556dc7d9..556dc7d9 100644..100755 --- a/tools/supplicant.h +++ b/tools/supplicant.h diff --git a/tools/tap-test.c b/tools/tap-test.c index fdc098aa..fdc098aa 100644..100755 --- a/tools/tap-test.c +++ b/tools/tap-test.c diff --git a/tools/web-test.c b/tools/web-test.c index 55c58af5..55c58af5 100644..100755 --- a/tools/web-test.c +++ b/tools/web-test.c diff --git a/tools/wispr.c b/tools/wispr.c index d5f9341f..d5f9341f 100644..100755 --- a/tools/wispr.c +++ b/tools/wispr.c diff --git a/tools/wpad-test.c b/tools/wpad-test.c index 2ecbcdae..2ecbcdae 100644..100755 --- a/tools/wpad-test.c +++ b/tools/wpad-test.c diff --git a/unit/test-ippool.c b/unit/test-ippool.c index 17fac9d9..17fac9d9 100644..100755 --- a/unit/test-ippool.c +++ b/unit/test-ippool.c diff --git a/vpn/connman-task.te b/vpn/connman-task.te index dd777107..dd777107 100644..100755 --- a/vpn/connman-task.te +++ b/vpn/connman-task.te diff --git a/vpn/connman-vpn.service.in b/vpn/connman-vpn.service.in index e98fb714..a8f2948f 100644..100755 --- a/vpn/connman-vpn.service.in +++ b/vpn/connman-vpn.service.in @@ -1,12 +1,18 @@ [Unit] Description=ConnMan VPN service +Requires=dbus.socket +After=dbus.socket [Service] Type=dbus +User=network_fw +Group=network_fw BusName=net.connman.vpn -ExecStart=@sbindir@/connman-vpnd -n +SmackProcessLabel=System +ExecStart=@bindir@/connman-vpnd -n StandardOutput=null -CapabilityBoundingSet=CAP_KILL CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_NET_RAW +Capabilities=cap_net_admin,cap_net_bind_service,cap_net_broadcast,cap_net_raw,cap_dac_override=i +SecureBits=keep-caps ProtectHome=read-only ProtectSystem=full diff --git a/vpn/main.c b/vpn/main.c index ee88aacd..c18fee4f 100644..100755 --- a/vpn/main.c +++ b/vpn/main.c @@ -45,6 +45,7 @@ #define CONFIGMAINFILE CONFIGDIR "/connman-vpn.conf" #define DEFAULT_INPUT_REQUEST_TIMEOUT 300 * 1000 +#define DEFAULT_BROWSER_LAUNCH_TIMEOUT 300 * 1000 static GMainLoop *main_loop = NULL; @@ -52,8 +53,10 @@ static unsigned int __terminated = 0; static struct { unsigned int timeout_inputreq; + unsigned int timeout_browserlaunch; } connman_vpn_settings = { .timeout_inputreq = DEFAULT_INPUT_REQUEST_TIMEOUT, + .timeout_browserlaunch = DEFAULT_BROWSER_LAUNCH_TIMEOUT, }; static GKeyFile *load_config(const char *file) @@ -224,6 +227,21 @@ static GOptionEntry options[] = { { NULL }, }; +bool connman_setting_get_bool(const char *key) +{ + return false; +} + +char **connman_setting_get_string_list(const char *key) +{ + return NULL; +} + +unsigned int *connman_setting_get_uint_list(const char *key) +{ + return NULL; +} + /* * This function will be called from generic src/agent.c code so we have * to use connman_ prefix instead of vpn_ one. @@ -233,6 +251,16 @@ unsigned int connman_timeout_input_request(void) return connman_vpn_settings.timeout_inputreq; } +unsigned int connman_timeout_browser_launch(void) +{ + return connman_vpn_settings.timeout_browserlaunch; +} + +const char *connman_option_get_string(const char *key) +{ + return NULL; +} + int main(int argc, char *argv[]) { GOptionContext *context; diff --git a/vpn/net.connman.vpn.service.in b/vpn/net.connman.vpn.service.in index e473ea9e..8ce55c20 100644..100755 --- a/vpn/net.connman.vpn.service.in +++ b/vpn/net.connman.vpn.service.in @@ -1,5 +1,6 @@ [D-BUS Service] Name=net.connman.vpn -Exec=@sbindir@/connman-vpnd -n -User=root +Exec=/bin/false +User=network_fw +Group=network_fw SystemdService=connman-vpn.service diff --git a/vpn/plugins/ipsec.c b/vpn/plugins/ipsec.c new file mode 100644 index 00000000..36502dde --- /dev/null +++ b/vpn/plugins/ipsec.c @@ -0,0 +1,925 @@ +/* + * + * ConnMan VPN daemon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <sys/stat.h> +#include <net/if.h> + +#include <glib.h> +#include <gio/gio.h> + +#define CONNMAN_API_SUBJECT_TO_CHANGE +#include <connman/plugin.h> +#include <connman/log.h> +#include <connman/task.h> +#include <connman/dbus.h> +#include <connman/ipconfig.h> + +#include "../vpn-provider.h" + +#include "vpn.h" +#include "ipsec.h" +#include "vici-client.h" + +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) + +typedef enum { + CERT_TYPE_NONE, + CERT_TYPE_DER, + CERT_TYPE_PEM, + CERT_TYPE_PKCS12, + CERT_TYPE_MAX, +} cert_type_e; + +static DBusConnection *connection; +static VICIClient *vici_client; +static GFileMonitor* monitor; + +struct ipsec_private_data { + struct vpn_provider *provider; + vpn_provider_connect_cb_t connect_cb; + void *connect_user_data; +}; + +struct ipsec_event_data { + vpn_event_callback event_cb; + void *event_user_data; +}; + +struct { + const char *cm_opt; + const char *vici_key; + const char *subsection; + vici_add_element add_elem; +} ipsec_conn_options[] = { + {"IPsec.Version", "version", NULL, vici_add_kv}, + {"IPsec.LeftAddrs", "local_addrs", NULL, vici_add_kvl}, + {"IPsec.RightAddrs", "remote_addrs", NULL, vici_add_kvl}, + + {"IPsec.LocalAuth", "auth", "local", vici_add_kv}, + {"IPsec.LocalID", "id", "local", vici_add_kv}, + {"IPsec.LocalXauthID", "xauth_id", "local", vici_add_kv}, + {"IPsec.LocalXauthAuth", "auth", "local-xauth", vici_add_kv}, + {"IPsec.LocalXauthXauthID", "xauth_id", "local-xauth", vici_add_kv}, + {"IPsec.RemoteAuth", "auth", "remote", vici_add_kv}, + {"IPsec.RemoteID", "id", "remote", vici_add_kv}, + {"IPsec.RemoteXauthID", "xauth_id", "remote", vici_add_kv}, + {"IPsec.RemoteXauthAuth", "auth", "remote-xauth", vici_add_kv}, + {"IPsec.RemoteXauthXauthID", "xauth_id", "remote-xauth", vici_add_kv}, + {"IPsec.ChildrenLocalTS", "local_ts", "children", vici_add_kvl}, + {"IPsec.ChildrenRemoteTS", "remote_ts", "children", vici_add_kvl}, +}; + +struct { + const char *cm_opt; + const char *vici_type; +} ipsec_shared_options[] = { + {"IPsec.IKEData", "data"}, + {"IPsec.IKEOwners", "owners"}, + {"IPsec.XauthData", "data"}, + {"IPsec.XauthOwners", "owners"}, +}; + +struct { + const char *cm_opt; + const char *vici_type; + const char *vici_flag; +} ipsec_cert_options[] = { + {"IPsec.CertType", "type", NULL}, + {"IPsec.CertFlag", "flag", NULL}, + {"IPsec.CertData", "data", NULL}, + {"IPsec.CertPass", "data", NULL}, +}; + +struct { + const char *cm_opt; + const char *vici_type; +} ipsec_pkey_options[] = { + {"IPsec.PKeyType", "type"}, + {"IPsec.PKeyData", "data"}, +}; + +static const char *ikev1_esp_proposals [] ={ + "aes256-sha256", + "aes128-sha256", + "aes256-sha1", + "aes128-sha1", + "aes256-md5", + "aes128-md5", + "3des-sha1", + "3des-md5", + NULL, +}; + +static const char *ikev1_proposals [] ={ + "aes256-sha256-modp1024", + "aes128-sha256-modp1024", + "aes256-sha1-modp1024", + "aes128-sha1-modp1024", + "aes256-md5-modp1024", + "aes128-md5-modp1024", + "3des-sha1-modp1024", + "3des-md5-modp1024", + NULL, +}; + +static const char *ikev2_esp_proposals = "aes256-aes128-sha256-sha1"; + +static const char *ikev2_proposals = "aes256-aes128-sha512-sha384-sha256-sha1-modp2048-modp1536-modp1024"; + +static struct ipsec_event_data event_data; + +static void free_private_data(struct ipsec_private_data *data) +{ + g_free(data); +} + +static int ipsec_notify(DBusMessage *msg, struct vpn_provider *provider) +{ + return 0; +} + +static void ipsec_set_event_cb(vpn_event_callback event_cb, struct vpn_provider *provider) +{ + DBG("set event cb!"); + event_data.event_cb = event_cb; + event_data.event_user_data = provider; + return; +} + +static int ipsec_is_same_auth(const char* req, const char* target) +{ + if (req == NULL || target == NULL) + return 0; + return (g_strcmp0(req, target) == 0); +} + +static int vici_load_cert(const char* type, const char* flag, const char* data) +{ + VICISection *sect; + int ret = 0; + + sect = vici_create_section(NULL); + if (!sect) + return -ENOMEM; + + vici_add_kv(sect, "type", type, NULL); + vici_add_kv(sect, "flag", flag, NULL); + vici_add_kv(sect, "data", data, NULL); + + ret = vici_send_request(vici_client, VICI_CMD_LOAD_CERT, sect); + if (ret < 0) + connman_error("vici_send_request failed"); + + vici_destroy_section(sect); + + return ret; +} + +static void ipsec_add_default_child_sa_data(struct vpn_provider *provider, VICISection *child) +{ + const char *version = vpn_provider_get_string(provider, "IPsec.Version"); + if (g_strcmp0(version, "1") == 0) { + int i = 0; + GSList *list; + + for (list = NULL; ikev1_esp_proposals[i] != NULL; i++) + list = g_slist_append(list, g_strdup(ikev1_esp_proposals[i])); + vici_add_list(child, "esp_proposals", list, "net"); + g_slist_free_full(list, g_free); + list = NULL; + } else { + vici_add_kvl(child, "esp_proposals", ikev2_esp_proposals, "net"); + } + return; +} + +static void ipsec_add_default_conn_data(struct vpn_provider *provider, VICISection *conn) +{ + const char *version = vpn_provider_get_string(provider, "IPsec.Version"); + const char *remote_addr = vpn_provider_get_string(provider, "Host"); + + vici_add_kvl(conn, "remote_addrs", remote_addr, NULL); + if (g_strcmp0(version, "1") == 0) { + int i = 0; + GSList *list; + + for (list = NULL; ikev1_proposals[i] != NULL; i++) + list = g_slist_append(list, g_strdup(ikev1_proposals[i])); + vici_add_list(conn, "proposals", list, NULL); + g_slist_free_full(list, g_free); + list = NULL; + + if (g_strcmp0(vpn_provider_get_string(provider, "IPsec.LocalAuth"), "psk") == 0) + vici_add_kv(conn, "aggressive", "yes", NULL); + } else { + vici_add_kvl(conn, "proposals", ikev2_proposals, NULL); + } + + vici_add_kvl(conn, "vips", "0.0.0.0", NULL); + return; +} + +static char *load_file_from_path(const char *path) +{ + struct stat st; + FILE *fp = NULL; + int fd = 0; + size_t file_size = 0; + char *file_buff = NULL; + + if (!path) { + connman_error("File path is NULL\n"); + return NULL; + } + + fp = fopen(path, "rb"); + if (!fp) { + connman_error("fopen %s is failed\n", path); + return NULL; + } + + fd = fileno(fp); + if (fd == -1) { + connman_error("fp is not a valid stream"); + fclose(fp); + return NULL; + } + + if (fstat(fd, &st) != 0) { + connman_error("fstat failed"); + fclose(fp); + return NULL; + } + + file_size = st.st_size; + file_buff = g_try_malloc0(sizeof(char)*st.st_size); + if (file_buff == NULL) { + connman_error("g_try_malloc0 failed\n"); + fclose(fp); + return NULL; + } + + if (fread(file_buff, 1, file_size, fp) != file_size) { + connman_error("file size not matched\n"); + g_free(file_buff); + file_buff = NULL; + } + + fclose(fp); + return file_buff; +} + +static char * get_local_cert_str(struct vpn_provider *provider) +{ + const char *path; + + if (!provider) + return NULL; + + path = vpn_provider_get_string(provider, "IPsec.LocalCerts"); + + return load_file_from_path(path); +} + +static int ipsec_load_conn(struct vpn_provider *provider, struct ipsec_private_data *data) +{ + const char *key; + const char *value; + const char *subsection; + char *local_cert_str; + VICISection *conn; + VICISection *children; + int i; + int ret = 0; + + if (!provider || !data) { + connman_error("invalid provider or data"); + return -EINVAL; + } + + value = vpn_provider_get_string(provider, "Name"); + DBG("Name: %s", value); + conn = vici_create_section(value); + children = vici_create_section("children"); + add_subsection("children", children, conn); + + for (i = 0; i < (int)ARRAY_SIZE(ipsec_conn_options); i++) { + value = vpn_provider_get_string(provider, ipsec_conn_options[i].cm_opt); + if (!value) + continue; + + key = ipsec_conn_options[i].vici_key; + subsection = ipsec_conn_options[i].subsection; + ipsec_conn_options[i].add_elem(conn, key, value, subsection); + } + + local_cert_str = get_local_cert_str(provider); + if (local_cert_str) { + /* TODO :remove this after debug */ + DBG("There's local certification to add local section"); + vici_add_kvl(conn, "certs", local_cert_str, "local"); + g_free(local_cert_str); + } + + ipsec_add_default_conn_data(provider, conn); + ipsec_add_default_child_sa_data(provider, children); + + ret = vici_send_request(vici_client, VICI_CMD_LOAD_CONN, conn); + if (ret < 0) + connman_error("vici_send_request failed"); + + vici_destroy_section(conn); + + return ret; +} + +static int ipsec_load_shared_psk(struct vpn_provider *provider) +{ + const char *data; + const char *owner; + VICISection *sect; + int ret = 0; + + if (!provider) { + connman_error("invalid provider"); + return -EINVAL; + } + + data = vpn_provider_get_string(provider, "IPsec.IKEData"); + owner = vpn_provider_get_string(provider, "IPsec.IKEOwners"); + DBG("IKEData: %s, IKEOwners: %s", data, owner); + + if (!data) + return 0; + + sect = vici_create_section(NULL); + if (!sect) { + return -ENOMEM; + } + + vici_add_kv(sect, "type", VICI_SHARED_TYPE_PSK, NULL); + vici_add_kv(sect, "data", data, NULL); + vici_add_kvl(sect, "owners", owner, NULL); + + ret = vici_send_request(vici_client, VICI_CMD_LOAD_SHARED, sect); + if (ret < 0) + connman_error("vici_send_request failed"); + + vici_destroy_section(sect); + + return ret; +} + +static int ipsec_load_shared_xauth(struct vpn_provider *provider) +{ + const char *data; + const char *owner; + VICISection *sect; + int ret = 0; + + if (!provider) { + connman_error("invalid provider"); + return -EINVAL; + } + + data = vpn_provider_get_string(provider, "IPsec.XauthData"); + owner = vpn_provider_get_string(provider, "IPsec.XauthOwners"); + DBG("XauthData: %s, XauthOwners: %s", data, owner); + + if (!data) + return 0; + + sect = vici_create_section(NULL); + + vici_add_kv(sect, "type", VICI_SHARED_TYPE_XAUTH, NULL); + vici_add_kv(sect, "data", data, NULL); + vici_add_kvl(sect, "owners", owner, NULL); + + ret = vici_send_request(vici_client, VICI_CMD_LOAD_SHARED, sect); + if (ret < 0) + connman_error("vici_send_request failed"); + + vici_destroy_section(sect); + + return ret; +} + +static int ipsec_load_key(struct vpn_provider *provider) +{ + const char *type; + const char *path; + char *data; + VICISection *sect; + int ret = 0; + + if (!provider) { + connman_error("invalid provider"); + return -EINVAL; + } + + type = vpn_provider_get_string(provider, "IPsec.PKeyType"); + path = vpn_provider_get_string(provider, "IPsec.PKeyData"); + DBG("PKeyType: %s, PKeyData: %s", type, path); + + if (!type || !path) + return 0; + + data = load_file_from_path(path); + if (!data) + return 0; + + sect = vici_create_section(NULL); + if (!sect) { + g_free(data); + return -ENOMEM; + } + + vici_add_kv(sect, "type", type, NULL); + vici_add_kv(sect, "data", data, NULL); + + ret = vici_send_request(vici_client, VICI_CMD_LOAD_KEY, sect); + if (ret < 0) + connman_error("vici_send_request failed"); + + vici_destroy_section(sect); + g_free(data); + + return ret; +} + +static int ipsec_initiate(struct vpn_provider *provider) +{ + VICISection *sect; + int ret = 0; + + sect = vici_create_section(NULL); + if (!sect) + return -ENOMEM; + + vici_add_kv(sect, "child", "net", NULL); + ret = vici_send_request(vici_client, VICI_CMD_INITIATE, sect); + if (ret < 0) + connman_error("vici_send_request failed"); + + vici_destroy_section(sect); + + return ret; +} + +static int ipsec_load_cert(struct vpn_provider *provider) +{ + const char *type; + const char *flag; + char *data; + const char *local_auth_type; + const char *remote_auth_type; + int ret = 0; + + if (!provider) { + connman_error("invalid provider"); + return -EINVAL; + } + + local_auth_type = vpn_provider_get_string(provider, "IPsec.LocalAuth"); + remote_auth_type = vpn_provider_get_string(provider, "IPsec.RemoteAuth"); + if (!ipsec_is_same_auth(local_auth_type, "pubkey") && + !ipsec_is_same_auth(remote_auth_type, "pubkey")) { + DBG("invalid auth type"); + return 0; + } + + type = vpn_provider_get_string(provider, "IPsec.CertType"); + flag = vpn_provider_get_string(provider, "IPsec.CertFlag"); + data = load_file_from_path(vpn_provider_get_string(provider, "IPsec.CertData")); + DBG("CertType: %s, CertFalg: %s,CertData: %s", type, flag, data); + if (!type || ! flag || !data) { + connman_error("invalid certification information"); + g_free(data); + return -EINVAL; + } + + ret = vici_load_cert(type, flag, data); + if (ret < 0) + connman_error("failed to load cert"); + + g_free(data); + + return ret; +} + +static int ipsec_terminate(struct vpn_provider *provider) +{ + VICISection *sect; + int ret = 0; + + sect = vici_create_section(NULL); + if (!sect) + return -ENOMEM; + + vici_add_kv(sect, "child", "net", NULL); + vici_add_kv(sect, "ike", vpn_provider_get_string(provider, "Name"), NULL); + vici_add_kv(sect, "timeout", "-1", NULL); + ret = vici_send_request(vici_client, VICI_CMD_TERMINATE, sect); + if (ret < 0) + connman_error("vici_send_request failed"); + + vici_destroy_section(sect); + + return ret; +} + +static void request_reply_cb(int err, void *user_data) +{ + struct ipsec_private_data *data; + + data = (struct ipsec_private_data *)user_data; + DBG("request reply cb"); + + if(err != 0) { + if (event_data.event_cb) + event_data.event_cb(event_data.event_user_data, VPN_STATE_FAILURE); + /* TODO: Does close socket needed? */ + } else { + DBG("Series of requests are succeeded"); + /* TODO: Not sure about below */ + if (event_data.event_cb) + event_data.event_cb(event_data.event_user_data, VPN_STATE_CONNECT); + } + + free_private_data(data); +} + +static void ipsec_vici_event_cb(VICIClientEvent event, void *user_data) +{ + struct vpn_provider *provider; + + provider = (struct vpn_provider *)user_data; + if (!provider) { + DBG("Invalid user data"); + return; + } + + if(event == VICI_EVENT_CHILD_UP) { + if (event_data.event_cb) + event_data.event_cb(event_data.event_user_data, VPN_STATE_READY); + } else if (event == VICI_EVENT_CHILD_DOWN) { + if (event_data.event_cb) + event_data.event_cb(event_data.event_user_data, VPN_STATE_DISCONNECT); + } else { + DBG("Unknown event"); + } + + return; +} + +static struct ipsec_private_data* create_ipsec_private_data(struct vpn_provider *provider, + vpn_provider_connect_cb_t cb, void* user_data) +{ + struct ipsec_private_data *data; + data = g_try_new0(struct ipsec_private_data, 1); + if (!data) { + connman_error("out of memory"); + return NULL; + } + + data->provider = provider; + data->connect_cb = cb; + data->connect_user_data = user_data; + return data; +} + +static void vici_connect(struct ipsec_private_data *data) +{ + struct vpn_provider *provider = NULL; + vpn_provider_connect_cb_t cb = NULL; + int err = 0; + + if (!data) + IPSEC_ERROR_CHECK_GOTO(-1, done, "Invalid data parameter"); + + provider = data->provider; + cb = data->connect_cb; + if (!provider || !cb) + IPSEC_ERROR_CHECK_GOTO(-1, done, "Invalid provider or callback"); + + DBG("data %p, provider %p", data, provider); + + /* + * Initialize vici client + */ + err = vici_initialize(&vici_client); + IPSEC_ERROR_CHECK_GOTO(err, done, "failed to initialize vici_client"); + + /* TODO :remove this after debug */ + DBG("success to initialize vici socket"); + + vici_set_request_reply_cb(vici_client, (vici_request_reply_cb)request_reply_cb, data); + /* + * Sets child-updown event + */ + err = vici_set_event_cb(vici_client, (vici_event_cb)ipsec_vici_event_cb, provider); + IPSEC_ERROR_CHECK_GOTO(err, done, "register event failed"); + + /* TODO :remove this after debug */ + DBG("success to vici_set_event_cb"); + /* + * Send the load-conn command + */ + err = ipsec_load_conn(provider, data); + IPSEC_ERROR_CHECK_GOTO(err, done, "load-conn failed"); + + /* TODO :remove this after debug */ + DBG("success to ipsec_load_conn"); + + /* + * Send the load-shared command for PSK + */ + err = ipsec_load_shared_psk(provider); + IPSEC_ERROR_CHECK_GOTO(err, done, "load-shared failed"); + + /* TODO :remove this after debug */ + DBG("success to ipsec_load_shared_psk"); + + /* + * Send the load-shared command for XAUTH + */ + err = ipsec_load_shared_xauth(provider); + IPSEC_ERROR_CHECK_GOTO(err, done, "load-shared failed"); + + /* TODO :remove this after debug */ + DBG("success to ipsec_load_shared_xauth"); + /* + * Send the load-cert command + */ + err = ipsec_load_cert(provider); + IPSEC_ERROR_CHECK_GOTO(err, done, "load-cert failed"); + + /* TODO :remove this after debug */ + DBG("success to ipsec_load_cert"); + + /* + * Send the load-key command + */ + err = ipsec_load_key(provider); + IPSEC_ERROR_CHECK_GOTO(err, done, "load-key failed"); + + /* TODO :remove this after debug */ + DBG("success to ipsec_load_cert"); + /* + * Send the initiate command + */ + err = ipsec_initiate(provider); + IPSEC_ERROR_CHECK_GOTO(err, done, "initiate failed"); + + /* TODO :remove this after debug */ + DBG("success to ipsec_initiate"); + +done: + /* refer to connect_cb on vpn-provider.c for cb */ + if(cb) + cb(provider, data->connect_user_data, -err); + /* TODO: Does close socket needed? when err is not zero */ + + return; +} + +static void monitor_changed(GFileMonitor *monitor, GFile *file, GFile *other_file, + GFileMonitorEvent event_type, gpointer user_data) +{ + DBG("file %s", g_file_get_path(file)); + if (event_type == G_FILE_MONITOR_EVENT_CREATED) { + if (g_file_test(VICI_DEFAULT_URI, G_FILE_TEST_EXISTS)) { + DBG("file created: %s", VICI_DEFAULT_URI); + struct ipsec_private_data *data = user_data; + vici_connect(data); + g_object_unref(monitor); + } + } +} + +static void monitor_vici_socket(struct ipsec_private_data *data) +{ + GError *error = NULL; + GFile* file; + + file = g_file_new_for_path(VICI_DEFAULT_URI); + monitor = g_file_monitor_file(file, G_FILE_MONITOR_SEND_MOVED, NULL, &error); + if (error) { + connman_error("g_file_monitor_directory failed: %s / %d", error->message, error->code); + g_error_free(error); + if(event_data.event_cb) + event_data.event_cb(event_data.event_user_data, VPN_STATE_FAILURE); + return; + } + /* TODO :remove this after debug */ + DBG("starting to monitor vici socket"); + g_signal_connect(monitor, "changed", G_CALLBACK(monitor_changed), data); + g_object_unref(file); +} + +static void check_vici_socket(struct ipsec_private_data *data) +{ + DBG("data %p", data); + if (g_file_test(VICI_DEFAULT_URI, G_FILE_TEST_EXISTS)) { + DBG("file exists: %s", VICI_DEFAULT_URI); + vici_connect(data); + } else { + monitor_vici_socket(data); + } +} + +static void ipsec_died(struct connman_task *task, int exit_code, void *user_data) +{ + DBG("task %p exit_code %d", task, exit_code); + unlink(VICI_DEFAULT_URI); + vpn_died(task, exit_code, user_data); +} + +static int ipsec_connect(struct vpn_provider *provider, + struct connman_task *task, const char *if_name, + vpn_provider_connect_cb_t cb, const char *dbus_sender, + void *user_data) +{ + struct ipsec_private_data *data; + int err = 0; + + data = create_ipsec_private_data(provider, cb, user_data); + if (!data) { + connman_error("create ipsec private data failed"); + return -ENOMEM; + } + /* + * Start charon daemon using ipsec script of strongSwan. + */ + err = connman_task_run(task, ipsec_died, provider, NULL, NULL, NULL); + if (err < 0) { + connman_error("charon start failed"); + if (cb) + cb(provider, user_data, err); + + g_free(data); + return err; + } + + check_vici_socket(data); +// g_usleep(G_USEC_PER_SEC); + + return err; +} + +static int ipsec_error_code(struct vpn_provider *provider, int exit_code) +{ + return 0; +} + +static int ipsec_save(struct vpn_provider *provider, GKeyFile *keyfile) +{ + int i; + const char *option; + + DBG(""); + /* + * Save IKE connection configurations + */ + for (i = 0; i < (int)ARRAY_SIZE(ipsec_conn_options); i++) { + option = vpn_provider_get_string(provider, ipsec_conn_options[i].cm_opt); + if (option) + g_key_file_set_string(keyfile, + vpn_provider_get_save_group(provider), + ipsec_conn_options[i].cm_opt, + option); + } + + /* + * Save shared IKE PSK, EAP or XAUTH secret + */ + for (i = 0; i < (int)ARRAY_SIZE(ipsec_shared_options); i++) { + option = vpn_provider_get_string(provider, ipsec_shared_options[i].cm_opt); + if (option) + g_key_file_set_string(keyfile, + vpn_provider_get_save_group(provider), + ipsec_shared_options[i].cm_opt, + option); + } + + /* + * Save certification + */ + for (i = 0; i < (int)ARRAY_SIZE(ipsec_cert_options); i++) { + option = vpn_provider_get_string(provider, ipsec_cert_options[i].cm_opt); + if (option) + g_key_file_set_string(keyfile, + vpn_provider_get_save_group(provider), + ipsec_cert_options[i].cm_opt, + option); + } + + /* + * Save private key + */ + for (i = 0; i < (int)ARRAY_SIZE(ipsec_pkey_options); i++) { + option = vpn_provider_get_string(provider, ipsec_pkey_options[i].cm_opt); + if (option) + g_key_file_set_string(keyfile, + vpn_provider_get_save_group(provider), + ipsec_pkey_options[i].cm_opt, + option); + } + + /* + * Save local certification + */ + option = vpn_provider_get_string(provider, "IPsec.LocalCerts"); + if (option) + g_key_file_set_string(keyfile, + vpn_provider_get_save_group(provider), + "IPsec.LocalCerts", + option); + option = vpn_provider_get_string(provider, "IPsec.LocalCertPass"); + if (option) + g_key_file_set_string(keyfile, + vpn_provider_get_save_group(provider), + "IPsec.LocalCertPass", + option); + /* + * Save CA certification directory + */ + option = vpn_provider_get_string(provider, "IPsec.CACertsDir"); + if (option) + g_key_file_set_string(keyfile, + vpn_provider_get_save_group(provider), + "IPsec.CACertsDir", + option); + + return 0; +} + +static void ipsec_disconnect(struct vpn_provider *provider) +{ + int err = 0; + /* + * Send the terminate command + */ + err = ipsec_terminate(provider); + IPSEC_ERROR_CHECK_RETURN(err, "terminate failed"); + + err = vici_deinitialize(vici_client); + IPSEC_ERROR_CHECK_RETURN(err, "failed to deinitialize vici_client"); + + return; +} + +static struct vpn_driver vpn_driver = { + .flags = VPN_FLAG_NO_TUN, + .notify = ipsec_notify, + .set_event_cb = ipsec_set_event_cb, + .connect = ipsec_connect, + .error_code = ipsec_error_code, + .save = ipsec_save, + .disconnect = ipsec_disconnect, +}; + +static int ipsec_init(void) +{ + connection = connman_dbus_get_connection(); + + event_data.event_cb = NULL; + event_data.event_user_data = NULL; + + return vpn_register("ipsec", &vpn_driver, IPSEC); +} + +static void ipsec_exit(void) +{ + vpn_unregister("ipsec"); + + dbus_connection_unref(connection); +} + +CONNMAN_PLUGIN_DEFINE(ipsec, "IPSec plugin", VERSION, + CONNMAN_PLUGIN_PRIORITY_DEFAULT, ipsec_init, ipsec_exit) diff --git a/vpn/plugins/ipsec.h b/vpn/plugins/ipsec.h new file mode 100644 index 00000000..14b9596f --- /dev/null +++ b/vpn/plugins/ipsec.h @@ -0,0 +1,51 @@ +/* + * + * ConnMan VPN daemon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __CONNMAN_VPND_PLUGIN_IPSEC_H +#define __CONNMAN_VPND_PLUGIN_IPSEC_H + +#define IPSEC_AUTH_PSK "PSK" +#define IPSEC_AUTH_RSA "RSA" +#define IPSEC_AUTH_XAUTH "XAUTH" + +#define VICI_SHARED_TYPE_PSK "IKE" +#define VICI_SHARED_TYPE_XAUTH "xauth" + +#define IPSEC_ERROR_CHECK_GOTO(err, target, fmt, arg...) do { \ + if (err < 0) { \ + connman_error(fmt, ## arg); \ + goto target; \ + } \ +} while (0) + +#define IPSEC_ERROR_CHECK_RETURN(err, fmt, arg...) do { \ + if (err < 0) { \ + connman_error(fmt, ## arg); \ + return; \ + } \ +} while (0) + +#define IPSEC_ERROR_CHECK_RETURN_VAL(err, ret, fmt, arg...) do { \ + if (err < 0) { \ + connman_error(fmt, ## arg); \ + return ret; \ + } \ +} while (0) + +#endif /* __CONNMAN_VPND_PLUGIN_IPSEC_H */ diff --git a/vpn/plugins/l2tp.c b/vpn/plugins/l2tp.c index a0d22c4d..a0d22c4d 100644..100755 --- a/vpn/plugins/l2tp.c +++ b/vpn/plugins/l2tp.c diff --git a/vpn/plugins/openconnect.c b/vpn/plugins/openconnect.c index 87679bfa..87679bfa 100644..100755 --- a/vpn/plugins/openconnect.c +++ b/vpn/plugins/openconnect.c diff --git a/vpn/plugins/openvpn.c b/vpn/plugins/openvpn.c index e3395097..d115df6e 100644..100755 --- a/vpn/plugins/openvpn.c +++ b/vpn/plugins/openvpn.c @@ -421,8 +421,10 @@ static int ov_connect(struct vpn_provider *provider, connman_task_add_argument(task, "--persist-tun", NULL); +#if !defined TIZEN_EXT connman_task_add_argument(task, "--route-noexec", NULL); connman_task_add_argument(task, "--ifconfig-noexec", NULL); +#endif /* * Disable client restarts because we can't handle this at the diff --git a/vpn/plugins/pptp.c b/vpn/plugins/pptp.c index 27b1d508..27b1d508 100644..100755 --- a/vpn/plugins/pptp.c +++ b/vpn/plugins/pptp.c diff --git a/vpn/plugins/vici-client.c b/vpn/plugins/vici-client.c new file mode 100644 index 00000000..67e365a5 --- /dev/null +++ b/vpn/plugins/vici-client.c @@ -0,0 +1,1290 @@ +/* + * + * ConnMan VPN daemon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <unistd.h> +#include <errno.h> + +#include <sys/poll.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/stat.h> +#include <arpa/inet.h> + +#include <glib.h> + +#include <connman/log.h> +#include "ipsec.h" +#include "vici-client.h" + +#define SOCK_FD_MIN 3 +#define VICI_REQUEST_TIMEOUT 5000 + +enum vici_element { + VICI_END = 0, + VICI_SECTION_START = 1, + VICI_SECTION_END = 2, + VICI_KEY_VALUE = 3, + VICI_LIST_START = 4, + VICI_LIST_ITEM = 5, + VICI_LIST_END = 6, +}; + +enum vici_packet_type { + VICI_CMD_REQUEST = 0, + VICI_CMD_RESPONSE = 1, + VICI_CMD_UNKNOWN = 2, + VICI_EVENT_REGISTER = 3, + VICI_EVENT_UNREGISTER = 4, + VICI_EVENT_CONFIRM = 5, + VICI_EVENT_UNKNOWN = 6, + VICI_EVENT = 7, +}; + +static const char *vici_cmd_str[] = { + "load-conn", + "load-shared", + "load-cert", + "load-authority", + "unload-authority", + "load-key", + "initiate", + "terminate", + "child-updown", + NULL, +}; + +struct request { + unsigned int allocated; + unsigned int used; + unsigned int hdr_len; + char *sndbuf; + int cmd; + int err; + /* process reply */ + unsigned int rcv_pkt_size; + char *rcvbuf; + /* davici_cb cb; */ + void *user; +}; + +struct _VICIClient { + /* io data */ + int client_sock_fd; + int client_watch; + unsigned int rcv_pkt_size; + char *rcvbuf; + GSList *request_list; + vici_request_reply_cb reply_cb; + vici_event_cb event_cb; + void *reply_user_data; + void *event_user_data; +}; + +struct _VICISection { + char *name; + GHashTable *kvs; + GHashTable *kvls; + GHashTable *subsection; +}; + +static void remove_list(gpointer data) +{ + if (data == NULL) + return; + + g_slist_free_full((GSList *)data, g_free); +} + +void vici_destroy_section(VICISection* section) +{ + g_free(section->name); + g_hash_table_destroy(section->kvs); + g_hash_table_destroy(section->kvls); + g_hash_table_destroy(section->subsection); + g_free(section); +} + +static void free_section(gpointer data) +{ + VICISection* section = (VICISection*)data; + vici_destroy_section(section); +} + +VICISection* vici_create_section(const char* name) +{ + VICISection* section; + + section = g_try_new0(VICISection, 1); + if (!section) { + connman_error("Failed to create section"); + return NULL; + } + + if (name) + section->name = g_strdup(name); + section->kvs = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + section->kvls = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, remove_list); + section->subsection = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, free_section); + return section; +} + +int add_subsection(const char* name, VICISection* child, VICISection* section) +{ + if (section == NULL || name == NULL || child == NULL) { + connman_error("invalid parameter"); + return -1; + } + + g_hash_table_insert(section->subsection, g_strdup(name), child); + return 0; +} + +static int add_kvl_to_section(const char* key, const char* value, VICISection* section) +{ + GSList *list = NULL; + if (section == NULL || key == NULL || value == NULL) { + connman_error("invalid parameter"); + return -1; + } + + list = g_hash_table_lookup(section->kvls, key); + if (list == NULL) + list = g_slist_alloc(); + + list = g_slist_prepend(list, g_strdup(value)); + g_hash_table_replace(section->kvls, g_strdup(key), list); + return 0; +} + +static int add_kv_to_section(const char* key, const char* value, VICISection* section) +{ + if (section == NULL || key == NULL || value == NULL) { + connman_error("invalid parameter"); + return -1; + } + + g_hash_table_insert(section->kvs, g_strdup(key), g_strdup(value)); + return 0; +} + +static VICISection* get_subsection(VICISection* section, const char* name) +{ + VICISection* sub = g_hash_table_lookup(section->subsection, name); + if (sub == NULL) { + sub = vici_create_section(name); + add_subsection(name, sub, section); + } + return sub; +} + +int vici_add_kv(VICISection* section, const char* key, + const char* value, const char* subsection) +{ + VICISection* target = section; + DBG("key: %s, value: %s, subsection: %s", key, value, subsection); + + if (section == NULL || key == NULL) { + connman_error("invalid parameter"); + return -1; + } + + if (subsection) + target = get_subsection(section, subsection); + + add_kv_to_section(key, value, target); + return 0; +} + +int vici_add_kvl(VICISection* section, const char* key, + const char* value, const char* subsection) +{ + VICISection* target = section; + + DBG("key: %s, value: %s, subsection: %s", key, value, subsection); + if (section == NULL || key == NULL) { + connman_error("invalid parameter"); + return -1; + } + + if (subsection) + target = get_subsection(section, subsection); + + if (g_strcmp0(subsection, "children") == 0) + target = get_subsection(target, "net"); + + add_kvl_to_section(key, value, target); + return 0; +} + +static void add_list_to_section(char *key, GSList *list, VICISection *section) +{ + if (section == NULL || key == NULL || list == NULL) + return; + + g_hash_table_insert(section->kvls, g_strdup(key), g_slist_copy_deep(list, (GCopyFunc)g_strdup, NULL)); + return; +} + +int vici_add_list(VICISection* section, char *key, GSList *list, const char* subsection) +{ + VICISection* target = section; + + DBG("key: %s, subsection: %s", key, subsection); + if (section == NULL || key == NULL) { + connman_error("invalid parameter"); + return -1; + } + + if (subsection) + target = get_subsection(section, subsection); + + if (g_strcmp0(subsection, "children") == 0) + target = get_subsection(target, "net"); + + add_list_to_section(key, list, target); + return 0; +} + +static char *load_cert_from_path(const char *path) +{ + struct stat st; + FILE *fp = NULL; + int fd = 0; + size_t file_size = 0; + char *file_buff = NULL; + + fp = fopen(path, "rb"); + if (fp == NULL) { + connman_error("fopen failed"); + return NULL; + } + + fd = fileno(fp); + if (fd == -1) { + connman_error("fp is not a valid stream"); + fclose(fp); + return NULL; + } + + if (fstat(fd, &st) != 0) { + connman_error("fstat failed"); + fclose(fp); + return NULL; + } + + file_size = st.st_size; + file_buff = g_try_malloc0(sizeof(char)*st.st_size); + if (file_buff == NULL) { + connman_error("g_try_malloc0 failed\n"); + fclose(fp); + return NULL; + } + + if (fread(file_buff, 1, file_size, fp) != file_size) { + connman_error("file size not matched\n"); + g_free(file_buff); + file_buff = NULL; + } + + fclose(fp); + return file_buff; +} + +int vici_add_cert_kv(VICISection *section, const char *key, + const char *value, const char *subsection) +{ + char *cert = NULL; + int ret = 0; + + if (value == NULL) { + DBG("value is null"); + return 0; + } + + cert = load_cert_from_path(value); + if (!cert) + return -1; + + ret = vici_add_kv(section, key, (const char *)cert, subsection); + g_free(cert); + return ret; +} + +int vici_add_cert_kvl(VICISection *section, const char *key, + const char *value, const char *subsection) +{ + char *cert = NULL; + int ret = 0; + + cert = load_cert_from_path(value); + if (!cert) + return -1; + + ret = vici_add_kvl(section, key, (const char *)cert, subsection); + g_free(cert); + return ret; +} + +static void *add_element(struct request *r, enum vici_element type, + unsigned int size) +{ + unsigned int newlen; + void *ret, *new; + + if (r->used + size + 1 > r->allocated) { + newlen = r->allocated; + while (newlen < r->used + size + 1) { + newlen *= 2; + } + new = realloc(r->sndbuf, newlen); + if (!new) { + r->err = -errno; + return NULL; + } + r->sndbuf = new; + r->allocated = newlen; + } + r->sndbuf[r->used++] = type; + ret = r->sndbuf + r->used; + r->used += size; + return ret; +} + +static void section_start(struct request *r, const char *name) +{ + uint8_t nlen; + char *pos; + + nlen = strlen(name); + pos = add_element(r, VICI_SECTION_START, 1 + nlen); + if (pos) { + pos[0] = nlen; + memcpy(pos + 1, name, nlen); + } +} + +static void section_end(struct request *r) +{ + add_element(r, VICI_SECTION_END, 0); +} + +static void key_value(struct request *r, const char *name, + const void *buf, unsigned int buflen) +{ + uint8_t nlen; + uint16_t vlen; + char *pos; + + nlen = strlen(name); + pos = add_element(r, VICI_KEY_VALUE, 1 + nlen + sizeof(vlen) + buflen); + if (pos) { + pos[0] = nlen; + memcpy(pos + 1, name, nlen); + vlen = htons(buflen); + memcpy(pos + 1 + nlen, &vlen, sizeof(vlen)); + memcpy(pos + 1 + nlen + sizeof(vlen), buf, buflen); + } +} + + +static void list_start(struct request *r, const char *name) +{ + uint8_t nlen; + char *pos; + + nlen = strlen(name); + pos = add_element(r, VICI_LIST_START, 1 + nlen); + if (pos) { + pos[0] = nlen; + memcpy(pos + 1, name, nlen); + } +} + +static void list_item(struct request *r, const void *buf, + unsigned int buflen) +{ + uint16_t vlen; + char *pos; + + pos = add_element(r, VICI_LIST_ITEM, sizeof(vlen) + buflen); + if (pos) { + vlen = htons(buflen); + memcpy(pos, &vlen, sizeof(vlen)); + memcpy(pos + sizeof(vlen), buf, buflen); + } +} + +static void list_end(struct request *r) +{ + add_element(r, VICI_LIST_END, 0); +} + +static void destroy_vici_request(gpointer data) +{ + struct request *req = (struct request *)data; + if(!req) + return; + + g_free(req->sndbuf); + g_free(req); +} + +static int create_vici_request(enum vici_packet_type type, VICIClientCmd cmd, + struct request **rp) +{ + struct request *req = NULL; + + if (cmd >= VICI_CMD_MAX || !rp) + return -EINVAL; + + req = g_try_new0(struct request, 1); + if (!req) { + connman_error("g_try_new0 failed"); + return -ENOMEM; + } + + req->used = 2; + req->used += strlen(vici_cmd_str[cmd]); + req->allocated = MIN(32, req->used); + req->sndbuf = g_try_new0(char, req->allocated); + if (!req->sndbuf) { + connman_error("g_try_new0 failed"); + g_free(req); + return -ENOMEM; + } + + req->sndbuf[0] = type; + req->sndbuf[1] = req->used - 2; /* except for type and name length */ + memcpy(req->sndbuf + 2, vici_cmd_str[cmd], req->used - 2); + req->hdr_len = req->used; + req->cmd = cmd; + + *rp = req; + + return 0; +} + +static void write_section_kvs(VICISection *section, struct request *req) +{ + GHashTableIter iter; + gpointer key, value; + + if (section == NULL || req == NULL) + return; + + g_hash_table_iter_init (&iter, section->kvs); + while (g_hash_table_iter_next (&iter, &key, &value)) { + if (!key || !value) + continue; + key_value(req, (const char*)key, (const void *)value, strlen((char *)value)); + } + + return; +} + +static void write_list_item(gpointer data, gpointer user_data) +{ + struct request *req = NULL; + char *value = NULL; + + if (!data || !user_data) + return; + + value = (char *)data; + req = (struct request *)user_data; + list_item(req, value, strlen(value)); + + return; +} + +static void write_section_kvls(VICISection *section, struct request *req) +{ + GHashTableIter iter; + gpointer key, value; + + if (section == NULL || req == NULL) + return; + + g_hash_table_iter_init (&iter, section->kvls); + while (g_hash_table_iter_next (&iter, &key, &value)) { + if (!key || !value) + continue; + + list_start(req, key); + g_slist_foreach((GSList *)value, (GFunc)write_list_item, (gpointer)req); + list_end(req); + } + + return; +} + +static void write_section(struct request *req, VICISection *section) +{ + GHashTableIter iter; + gpointer key, value; + + if (req == NULL || section == NULL) + return; + + if (section->name) + section_start(req, section->name); + + write_section_kvs(section, req); + write_section_kvls(section, req); + + g_hash_table_iter_init(&iter, section->subsection); + while (g_hash_table_iter_next (&iter, &key, &value)) { + if (!key || !value) + continue; + write_section(req, (VICISection *)value); + } + + if (section->name) + section_end(req); + return; +} + +static int check_socket(int sock) +{ + struct pollfd p_fd; + int res = 0; + + p_fd.fd = sock; + p_fd.events = POLLIN | POLLOUT | POLLERR | POLLHUP | POLLNVAL; + res = poll((struct pollfd *) &p_fd, 1, 1); + + if (res < 0) { + connman_error("Polling error from socket\n"); + return -1; + } else if (res == 0) { + connman_error( "poll timeout. socket is busy\n"); + return 1; + } else { + + if (p_fd.revents & POLLERR) { + connman_error("Error! POLLERR from socket[%d]\n", sock); + return -1; + } else if (p_fd.revents & POLLHUP) { + connman_error("Error! POLLHUP from socket[%d]\n", sock); + return -1; + } else if (p_fd.revents & POLLNVAL) { + connman_error("Error! POLLNVAL from socket[%d]\n", sock); + return -1; + } else if (p_fd.revents & POLLIN) { + return 0; + } else if (p_fd.revents & POLLOUT) { + return 0; + } + } + + connman_error("Unknown poll event [%d]\n", p_fd.revents); + return -1; +} + +static int write_socket(int sock, char *data, int data_len) +{ + int wbytes = 0; + int left_len = data_len; + char *ptr = data; + int res = 0; + + if (sock < SOCK_FD_MIN || !data || data_len < 0) + return -1; + + res = check_socket(sock); + if (res < 0) + return -1; + else if (res > 0) + return -2; + + errno = 0; + while (left_len) { + wbytes = write(sock, ptr, left_len); + if (wbytes <= 0) { + connman_error("Failed to write data into socket[%d].\n", sock); + break; + }else if (wbytes < left_len) { + left_len -= wbytes; + ptr += wbytes; + } else if (wbytes == left_len) { + left_len = 0; + } else { + connman_error("Unknown error occurred.\n"); + break; + } + } + + if (left_len) + return -1; + else + return 0; +} + +int send_vici_command(struct request *req, VICIClient *vici_client) +{ + unsigned int size = 0; + int sock_fd = 0; + int res = 0; + + if (req == NULL || vici_client == NULL) { + connman_error("request is NULL\n"); + return -EINVAL; + } + sock_fd = vici_client->client_sock_fd; + + size = htonl(req->used); + res = write_socket(sock_fd, (char *)&size, sizeof(size)); + if (res != 0) { + connman_error("failed to send size with network byte order\n"); + return -EIO; + } + + res = write_socket(sock_fd, req->sndbuf, req->used); + if (res != 0) { + connman_error("failed to send pkt\n"); + return -EIO; + } + + if(req->cmd != VICI_CMD_REGISTER_CHILD_UPDOWN) + vici_client->request_list = g_slist_append(vici_client->request_list, req); + + return res; +} + +static void print_vici_element(int elem_type, char *value, int sections) +{ + int i = 0; + + + switch (elem_type) { + case VICI_SECTION_START: + for (i = 0; i < sections - 1; i++) + DBG("\t"); + DBG("%s = {\n", value); + break; + case VICI_SECTION_END: + for (i = 0; i < sections; i++) + DBG("\t"); + DBG("}\n"); + break; + case VICI_KEY_VALUE: + for (i = 0; i < sections; i++) + DBG("\t"); + DBG("%s\n", value); + break; + case VICI_LIST_START: + for (i = 0; i < sections; i++) + DBG("\t"); + DBG("%s = [", value); + break; + case VICI_LIST_ITEM: + DBG("%s, ", value); + break; + case VICI_LIST_END: + DBG("]\n"); + break; + default: + break; + } + return; +} + +static void debug_vici_message(char *buf, unsigned int size) +{ + char temp[255]; + unsigned int pos = 0; + int len = 0; + int sections = 0; + int type = -1; + + if (buf == NULL || size == 0) + return; + + pos = 1; + while (pos < size) { + + type = buf[pos]; + pos++; + switch (type) { + case VICI_SECTION_START: + { + len = buf[pos]; + pos++; + g_strlcpy(temp, (const gchar *)&buf[pos], len + 1); + pos += len; + sections++; + } + break; + case VICI_SECTION_END: + { + sections--; + } + break; + case VICI_KEY_VALUE: + { + int key_len = 0; + int value_len = 0; + + key_len = buf[pos]; + pos++; + g_strlcpy(temp, (const gchar *)&buf[pos], key_len + 1); + temp[key_len] = '='; + pos += (key_len + 1); + value_len = buf[pos]; + pos++; + g_strlcpy(temp + key_len + 1, (const gchar *)&buf[pos], value_len + 1); + pos += value_len; + } + break; + case VICI_LIST_START: + { + len = buf[pos]; + pos++; + g_strlcpy(temp, (const gchar *)&buf[pos], len + 1); + pos += len; + } + break; + case VICI_LIST_ITEM: + { + pos++; + len = buf[pos]; + pos++; + g_strlcpy(temp, (const gchar *)&buf[pos], len + 1); + pos += len; + } + break; + case VICI_LIST_END: + break; + default: + break; + } + print_vici_element(type, temp, sections); + } + return; +} + +static unsigned int extract_key_value(char *buf, unsigned int pos, char **key, char **value) +{ + int key_len = 0; + int value_len = 0; + + key_len = buf[pos]; + pos++; + *key = g_strndup((const gchar *)&buf[pos], key_len); + pos+=(key_len + 1); + value_len = buf[pos]; + pos++; + *value = g_strndup((const gchar *)&buf[pos], value_len); + pos+=value_len; + return pos; +} + +static gboolean extract_request_result(char *buf, unsigned int size, char **err) +{ + gboolean success = FALSE; + unsigned int pos = 0; + int type = -1; + + pos = 1; + while (pos < size) { + + type = buf[pos];//3 + pos++; + if (type == VICI_KEY_VALUE) { + char *key = NULL; + char *value = NULL; + pos = extract_key_value(buf, pos, &key, &value); + DBG("pos : %d size : %d\n", pos, size); + + /* TODO :remove this after debug */ + DBG("key : %s value : %s\n", key, value); + if (g_strcmp0(key, "success") == 0) + (g_strcmp0(value, "yes") == 0)?(success = TRUE):(success = FALSE); + + if (g_strcmp0(key, "errmsg")) + *err = g_strdup(value); + g_free(key); + g_free(value); + } + } + return success; +} + +static int handle_vici_result(gboolean success, int cmd, char * err) +{ + int ret = 0; + if (success) + return 0; + + g_free(err); + + switch (cmd) { + case VICI_CMD_LOAD_CONN: + ret = EINVAL; + break; + case VICI_CMD_LOAD_SHARED: + ret = EINVAL; + break; + case VICI_CMD_LOAD_CERT: + ret = EINVAL; + break; + case VICI_CMD_LOAD_AUTH: + ret = 0; + break; + case VICI_CMD_LOAD_KEY: + ret = EINVAL; + break; + case VICI_CMD_INITIATE: + ret = ECONNABORTED; + break; + case VICI_CMD_TERMINATE: + ret = EINVAL; + break; + default: + break; + } + + DBG(" %s failed with %d!\n", vici_cmd_str[cmd], ret); + return ret; +} + +static int process_vici_response(struct request * req) +{ + char *err = NULL; + gboolean success = FALSE; + int ret = 0; + + if (!req) + return -1; + + if (!req->rcvbuf || req->rcvbuf[0] != VICI_CMD_RESPONSE) + return -1; + + //TODO: remove below when there's no further problem. + debug_vici_message(req->rcvbuf, req->rcv_pkt_size); + + success = extract_request_result(req->rcvbuf, req->rcv_pkt_size, &err); + ret = handle_vici_result(success, req->cmd, err); + + return ret; +} + +int vici_send_request(VICIClient *vici_client, VICIClientCmd cmd, VICISection *root) +{ + struct request *req = NULL; + int ret; + + DBG("%s", vici_cmd_str[cmd]); + ret = create_vici_request(VICI_CMD_REQUEST, cmd, &req); + if (ret < 0) { + connman_error("error on create_request\n"); + return ret; + } + + write_section(req, root); + //TODO: remove below when there's no further problem. + debug_vici_message(req->sndbuf + req->hdr_len - 1, req->used - req->hdr_len + 1); + + ret = send_vici_command(req, vici_client); + if (ret < 0) { + destroy_vici_request(req); + connman_error("error on send_command\n"); + } + + return ret; +} + + +int vici_set_event_cb(VICIClient *vici_client, vici_event_cb cb, gpointer user_data) +{ + struct request *req = NULL; + int ret; + + DBG("%s",vici_cmd_str[VICI_EVENT_CHILD_UP]); + ret = create_vici_request(VICI_EVENT_REGISTER, VICI_CMD_REGISTER_CHILD_UPDOWN, &req); + if (ret < 0) { + connman_error("error on create_request\n"); + return ret; + } + + ret = send_vici_command(req, vici_client); + if (ret < 0) { + connman_error("error on send_command\n"); + } + + destroy_vici_request(req); + vici_client->event_cb = cb; + vici_client->event_user_data = user_data; + + return ret; + +} + +static int get_socket_from_source(GIOChannel *source, GIOCondition condition) +{ + int sock = -1; + /* check socket */ + sock = g_io_channel_unix_get_fd(source); + if (sock < SOCK_FD_MIN) + return -1; + + if ((condition & G_IO_ERR) || (condition & G_IO_HUP) || (condition & G_IO_NVAL)) { + connman_error("G_IO_ERR/G_IO_HUP/G_IO_NVAL received sock [%d] condition [%d]\n", sock, condition); + //TODO: handle the breaking socket + return -1; + } + return sock; +} + +static int read_socket(int sock, char *data, unsigned int data_len) +{ + int rbytes = 0; + int total_rbytes = 0; + + if (sock < SOCK_FD_MIN || !data || data_len <= 0) + return -1; + + while (data_len > 0) { + errno = 0; + rbytes = read(sock, data, data_len); + if (rbytes <= 0) + return -1; + + total_rbytes += rbytes; + data += rbytes; + data_len -= rbytes; + } + + return total_rbytes; +} + +static int recv_vici_pkt(int sock, struct _VICIClient *vici_client) +{ + if(!vici_client) + return -1; + + if (vici_client->rcv_pkt_size == 0) { + unsigned int pkt_size = 0; + if (read_socket(sock, (char *)&pkt_size, sizeof(pkt_size)) < 0) + return -1; + + vici_client->rcv_pkt_size = ntohl(pkt_size); + /* TODO :REMOVE THIS AFTER DEBUG */ + DBG("rcv_pkt_size [%d] will be recved\n", vici_client->rcv_pkt_size); + } else { + + DBG("rcv_pkt_size [%d] is recved\n", vici_client->rcv_pkt_size); + char *buf = NULL; + buf = g_try_malloc0(vici_client->rcv_pkt_size); + if (buf == NULL) + return -1; + + if (read_socket(sock, buf, vici_client->rcv_pkt_size) < 0) { + g_free(buf); + return -1; + } + vici_client->rcvbuf = buf; + } + + return 0; +} + +static struct request *pop_vici_request(VICIClient *vici_client) +{ + GSList *list = NULL; + + if (!vici_client) + return NULL; + + list = vici_client->request_list; + if(!list) + return NULL; + + return list->data; +} + +static void process_vici_reply(VICIClient *vici_client) +{ + struct request *req; + int ret = 0; + + if (!vici_client) + return; + + /* get first request */ + req = pop_vici_request(vici_client); + if (!req) + return; + + req->rcvbuf = vici_client->rcvbuf; + req->rcv_pkt_size = vici_client->rcv_pkt_size; + + ret = process_vici_response(req); + vici_client->request_list = g_slist_remove(vici_client->request_list, req); + destroy_vici_request(req); + + /* TODO :remove this after debug */ + DBG("left request reply : %d", g_slist_length(vici_client->request_list)); + + if (ret != 0 || g_slist_length(vici_client->request_list) == 0) + vici_client->reply_cb(ret, vici_client->reply_user_data); + +} + +static int extract_event_name(char *buf, unsigned int size, char *temp) +{ + int pos = 1; + int name_len = 0; + name_len = buf[pos]; + pos++; + DBG("event len: %d", name_len); + while(pos < size && pos - 2 < name_len) { + temp[pos - 2] = buf[pos]; + pos++; + } + temp[pos] = '\0'; + DBG("event name: %s", temp); + return pos; +} + +static char *vici_get_value(char *buf, unsigned int pos, unsigned int size, char *search_key) +{ + int type = -1; + + pos = 1; + while (pos < size) { + + type = buf[pos];//3 + pos++; + if (type == VICI_KEY_VALUE) { + char *key = NULL; + char *value = NULL; + pos = extract_key_value(buf, pos, &key, &value); + if (g_strcmp0(search_key, key) == 0) { + g_free(key); + return value; + } + + g_free(key); + g_free(value); + } + } + return NULL; +} + +static void process_child_updown(VICIClient *vici_client,char *buf, unsigned int size) +{ + char *state = NULL; + + state = vici_get_value(buf, 0, size, "state"); + if (g_strcmp0(state, "ESTABLISHED") == 0) { + DBG("ESTABLISHED"); + vici_client->event_cb(VICI_EVENT_CHILD_UP, vici_client->event_user_data); + } else if (g_strcmp0(state, "DELETING") == 0) { + DBG("DELETING"); + vici_client->event_cb(VICI_EVENT_CHILD_DOWN, vici_client->event_user_data); + } else { + DBG("Unknown event"); + } + g_free(state); + return; +} + +static void process_vici_event(VICIClient *vici_client) +{ + char *buf = NULL; + unsigned int size = 0; + unsigned int pos = 0; + char temp[256] = {0,}; + if (!vici_client || !(vici_client->rcvbuf) || vici_client->rcv_pkt_size == 0) + return; + + buf = vici_client->rcvbuf; + size = vici_client->rcv_pkt_size; + + pos = extract_event_name(buf, size, temp); + /* TODO: remove below after debug */ + /* add parser */ + if (g_strcmp0(temp, "child-updown") == 0) + process_child_updown(vici_client, buf + pos -1, size - pos); +} + +static void process_vici_packet(VICIClient *vici_client, char *buf) +{ + + if (!vici_client || !buf) + return; + + if (buf[0] == VICI_CMD_RESPONSE) { + DBG("VICI_CMD_RESPONSE\n"); + process_vici_reply(vici_client); + } else if (buf[0] == VICI_EVENT_CONFIRM) { + DBG("VICI_EVENT_CONFIRM\n"); + } else if (buf[0] == VICI_EVENT) { + DBG("VICI_EVENT"); + process_vici_event(vici_client); + } else { + DBG("Not handled [%u]", buf[0]); + } + return; +} + +static gboolean process_vici_msg(GIOChannel *source, + GIOCondition condition, + gpointer user_data) +{ + VICIClient *vici_client = NULL; + int sock = 0; + + vici_client = (VICIClient *)user_data; + if (!vici_client) + return FALSE; + + sock = get_socket_from_source(source, condition); + if (sock < 0) + return FALSE; + + + if(recv_vici_pkt(sock, vici_client) < 0) + return FALSE; + + if (!vici_client->rcvbuf) { + return TRUE; + } + + process_vici_packet(vici_client, vici_client->rcvbuf); + g_free(vici_client->rcvbuf); + vici_client->rcvbuf = NULL; + vici_client->rcv_pkt_size = 0; + + return TRUE; +} + +static int str_to_socket_addr(const char *uri, struct sockaddr_un *addr) +{ + memset(addr, 0, sizeof(*addr)); + addr->sun_family = AF_UNIX; + strncpy(addr->sun_path, uri, sizeof(addr->sun_path)); + + addr->sun_path[sizeof(addr->sun_path)-1] = '\0'; + + return offsetof(struct sockaddr_un, sun_path) + strlen(addr->sun_path); +} + +static int connect_socket(const char *uri) +{ + struct sockaddr_un addr; + int len, fd; + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + connman_error("socket() failed"); + return -errno; + } + + len = str_to_socket_addr(uri, &addr); + if (len == -1) { + connman_error("str_to_socket_addr failed"); + close(fd); + return -1; + } + + if (connect(fd, (struct sockaddr*)&addr, len) < 0) { + connman_error("connect failed. errno %d/%s", errno, strerror(errno)); + close(fd); + return -errno; + } + + return fd; +} + +static int initialize_vici_source(VICIClient *vici_client) +{ + GIOChannel *vici_channel; + if (!vici_client) { + return -ENOMEM; + } + + vici_client->client_sock_fd = connect_socket(VICI_DEFAULT_URI); + if (vici_client->client_sock_fd < 0) { + connman_error("connect_socket failed"); + return -EIO; + } + + vici_channel = g_io_channel_unix_new(vici_client->client_sock_fd); + if (!vici_channel) { + connman_error("g_io_channel_unix_new failed"); + close(vici_client->client_sock_fd); + return -ENOMEM; + } + + vici_client->client_watch = g_io_add_watch_full(vici_channel, + G_PRIORITY_LOW, + G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL, + (GIOFunc)process_vici_msg, + (gpointer)vici_client, + NULL); + g_io_channel_unref(vici_channel); + return 0; +} + +int vici_initialize(VICIClient **vici_client) +{ + int ret = 0; + + *vici_client = g_try_new0(VICIClient, 1); + if (!*vici_client) { + connman_error("out of memory"); + return -ENOMEM; + } + + ret = initialize_vici_source(*vici_client); + if (ret != 0) { + g_free(*vici_client); + return ret; + } + + DBG("connected"); + return 0; +} + +void vici_set_request_reply_cb(VICIClient *vici_client, vici_request_reply_cb reply_cb, gpointer user_data) +{ + vici_client->reply_cb = reply_cb; + vici_client->reply_user_data = user_data; +} + +int vici_deinitialize(VICIClient *vici_client) +{ + if (vici_client->client_watch > 0) { + g_source_remove(vici_client->client_watch); + vici_client->client_watch = 0; + } + + close(vici_client->client_sock_fd); + g_slist_free_full(vici_client->request_list, destroy_vici_request); + g_free(vici_client->rcvbuf); + g_free(vici_client); + + return 0; +} diff --git a/vpn/plugins/vici-client.h b/vpn/plugins/vici-client.h new file mode 100644 index 00000000..a33a8e46 --- /dev/null +++ b/vpn/plugins/vici-client.h @@ -0,0 +1,84 @@ +/* + * + * ConnMan VPN daemon + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __VICI_CLIENT_H +#define __VICI_CLIENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* strongswan VICI plugin client part*/ +struct _VICIClient; +typedef struct _VICIClient VICIClient; + +struct _VICISection; +typedef struct _VICISection VICISection; + +typedef enum { + VICI_CMD_LOAD_CONN, + VICI_CMD_LOAD_SHARED, + VICI_CMD_LOAD_CERT, + VICI_CMD_LOAD_AUTH, + VICI_CMD_UNLOAD_AUTH, + VICI_CMD_LOAD_KEY, + VICI_CMD_INITIATE, + VICI_CMD_TERMINATE, + VICI_CMD_REGISTER_CHILD_UPDOWN, + VICI_CMD_MAX, +} VICIClientCmd; + +typedef enum { + VICI_EVENT_CHILD_UP, + VICI_EVENT_CHILD_DOWN, + VICI_EVENT_MAX, +} VICIClientEvent; +#define VICI_DEFAULT_URI "/var/run/charon.vici" + +typedef int (*vici_add_element)(VICISection *sect, const char *key, + const char *value, const char *subsection); + +typedef void (*vici_request_reply_cb)(int err, void *user_data); +typedef void (*vici_event_cb)(VICIClientEvent event, void *user_data); + +VICISection* vici_create_section(const char *name); +int add_subsection(const char* name, VICISection* child, VICISection* section); +void vici_destroy_section(VICISection *sect); +int vici_add_kv(VICISection *sect, const char *key, + const char *value, const char *subsection); +int vici_add_kvl(VICISection *sect, const char *key, + const char *value, const char *subsection); +int vici_add_list(VICISection* section, char *key, + GSList *list, const char* subsection); +int vici_add_cert_kv(VICISection *section, const char *key, + const char *value, const char *subsection); +int vici_add_cert_kvl(VICISection *section, const char *key, + const char *value, const char *subsection); + +int vici_initialize(VICIClient **vici_client); +int vici_deinitialize(VICIClient *vici_client); +void vici_set_request_reply_cb(VICIClient *vici_client, vici_request_reply_cb reply_cb, gpointer user_data); +int vici_send_request(VICIClient *vici_client, VICIClientCmd cmd, VICISection *root); +int vici_set_event_cb(VICIClient *vici_client, vici_event_cb cb, gpointer user_data); + +#ifdef __cplusplus +} +#endif + +#endif /* __VICI_CLIENT_H */ diff --git a/vpn/plugins/vpn.c b/vpn/plugins/vpn.c index 9a423850..f6e24c4c 100644..100755 --- a/vpn/plugins/vpn.c +++ b/vpn/plugins/vpn.c @@ -336,6 +336,56 @@ static DBusMessage *vpn_notify(struct connman_task *task, return NULL; } +#if defined TIZEN_EXT +static void vpn_event(struct vpn_provider *provider, int state) +{ + struct vpn_driver_data *vpn_driver_data; + const char *name; + + name = vpn_provider_get_driver_name(provider); + if (!name) { + DBG("Cannot find VPN driver for provider %p", provider); + vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE); + return; + } + + vpn_driver_data = g_hash_table_lookup(driver_hash, name); + if (!vpn_driver_data) { + DBG("Cannot find VPN driver data for name %s", name); + vpn_provider_set_state(provider, VPN_PROVIDER_STATE_FAILURE); + return; + } + + DBG("provider %p driver %s state %d", provider, name, state); + + switch (state) { + case VPN_STATE_CONNECT: + vpn_provider_set_state(provider, + VPN_PROVIDER_STATE_CONNECT); + break; + case VPN_STATE_READY: + vpn_provider_set_state(provider, + VPN_PROVIDER_STATE_READY); + break; + + case VPN_STATE_UNKNOWN: + case VPN_STATE_IDLE: + case VPN_STATE_DISCONNECT: + case VPN_STATE_FAILURE: + vpn_provider_set_state(provider, + VPN_PROVIDER_STATE_DISCONNECT); + break; + + case VPN_STATE_AUTH_FAILURE: + vpn_provider_indicate_error(provider, + VPN_PROVIDER_ERROR_AUTH_FAILED); + break; + } + + return; +} +#endif + static int vpn_create_tun(struct vpn_provider *provider, int flags) { struct vpn_data *data = vpn_provider_get_data(provider); @@ -487,6 +537,12 @@ static int vpn_connect(struct vpn_provider *provider, goto exist_err; } + +#if defined TIZEN_EXT + if(vpn_driver_data->vpn_driver->set_event_cb) + vpn_driver_data->vpn_driver->set_event_cb(vpn_event, provider); +#endif + ret = vpn_driver_data->vpn_driver->connect(provider, data->task, data->if_name, cb, dbus_sender, user_data); diff --git a/vpn/plugins/vpn.h b/vpn/plugins/vpn.h index cb94bdcd..1888d5ff 100644..100755 --- a/vpn/plugins/vpn.h +++ b/vpn/plugins/vpn.h @@ -40,9 +40,16 @@ enum vpn_state { VPN_STATE_AUTH_FAILURE = 6, }; +#if defined TIZEN_EXT +typedef void (*vpn_event_callback)(struct vpn_provider *provider, int state); +#endif + struct vpn_driver { int flags; int (*notify) (DBusMessage *msg, struct vpn_provider *provider); +#if defined TIZEN_EXT + void (*set_event_cb) (vpn_event_callback event_cb, struct vpn_provider *provider); +#endif int (*connect) (struct vpn_provider *provider, struct connman_task *task, const char *if_name, vpn_provider_connect_cb_t cb, const char *dbus_sender, diff --git a/vpn/plugins/vpnc.c b/vpn/plugins/vpnc.c index af9dbe76..af9dbe76 100644..100755 --- a/vpn/plugins/vpnc.c +++ b/vpn/plugins/vpnc.c diff --git a/vpn/vpn-agent.c b/vpn/vpn-agent.c index b0b582b7..b0b582b7 100644..100755 --- a/vpn/vpn-agent.c +++ b/vpn/vpn-agent.c diff --git a/vpn/vpn-agent.h b/vpn/vpn-agent.h index c7328d7f..c7328d7f 100644..100755 --- a/vpn/vpn-agent.h +++ b/vpn/vpn-agent.h diff --git a/vpn/vpn-config.c b/vpn/vpn-config.c index c88a99ab..5f0e749a 100644..100755 --- a/vpn/vpn-config.c +++ b/vpn/vpn-config.c @@ -203,7 +203,11 @@ static int load_provider(GKeyFile *keyfile, const char *group, struct vpn_config *config, enum what action) { struct vpn_config_provider *config_provider; +#if !defined TIZEN_EXT const char *ident, *host, *domain; +#else + const char *ident, *host, *domain, *name; +#endif int err; /* Strip off "provider_" prefix */ @@ -229,8 +233,14 @@ static int load_provider(GKeyFile *keyfile, const char *group, host = get_string(config_provider, "Host"); domain = get_string(config_provider, "Domain"); +#if !defined TIZEN_EXT if (host && domain) { char *id = __vpn_provider_create_identifier(host, domain); +#else + name = get_string(config_provider, "Name"); + if (host && domain && name) { + char *id = __vpn_provider_create_identifier(host, domain, name); +#endif struct vpn_provider *provider; provider = __vpn_provider_lookup(id); @@ -252,7 +262,11 @@ static int load_provider(GKeyFile *keyfile, const char *group, DBG("provider identifier %s", id); } else { +#if !defined TIZEN_EXT DBG("invalid values host %s domain %s", host, domain); +#else + DBG("invalid values host %s domain %s name %s", host, domain, name); +#endif err = -EINVAL; goto err; } diff --git a/vpn/vpn-dbus.conf b/vpn/vpn-dbus.conf index 0f0c8da4..7b7b6d19 100644..100755 --- a/vpn/vpn-dbus.conf +++ b/vpn/vpn-dbus.conf @@ -4,7 +4,12 @@ <policy user="root"> <allow own="net.connman.vpn"/> <allow send_destination="net.connman.vpn"/> - <allow send_interface="net.connman.vpn.Agent"/> + <allow send_interface="net.connman.vpn.Agent"/> + </policy> + <policy user="network_fw"> + <allow own="net.connman.vpn"/> + <allow send_destination="net.connman.vpn"/> + <allow send_interface="net.connman.vpn.Agent"/> </policy> <policy at_console="true"> <allow send_destination="net.connman.vpn"/> diff --git a/vpn/vpn-ipconfig.c b/vpn/vpn-ipconfig.c index c096fa37..c096fa37 100644..100755 --- a/vpn/vpn-ipconfig.c +++ b/vpn/vpn-ipconfig.c diff --git a/vpn/vpn-manager.c b/vpn/vpn-manager.c index 021d625f..021d625f 100644..100755 --- a/vpn/vpn-manager.c +++ b/vpn/vpn-manager.c diff --git a/vpn/vpn-polkit.conf b/vpn/vpn-polkit.conf index a1dc6177..237d21be 100644..100755 --- a/vpn/vpn-polkit.conf +++ b/vpn/vpn-polkit.conf @@ -5,6 +5,10 @@ <allow own="net.connman.vpn"/> <allow send_interface="net.connman.vpn.Agent"/> </policy> + <policy user="network_fw"> + <allow own="net.connman.vpn"/> + <allow send_interface="net.connman.vpn.Agent"/> + </policy> <policy context="default"> <allow send_destination="net.connman.vpn"/> </policy> diff --git a/vpn/vpn-polkit.policy b/vpn/vpn-polkit.policy index 0c427220..0c427220 100644..100755 --- a/vpn/vpn-polkit.policy +++ b/vpn/vpn-polkit.policy diff --git a/vpn/vpn-provider.c b/vpn/vpn-provider.c index d2b3e3aa..67239e40 100644..100755 --- a/vpn/vpn-provider.c +++ b/vpn/vpn-provider.c @@ -1803,6 +1803,7 @@ static void provider_create_all_from_type(const char *provider_type) g_strfreev(providers); } +#if !defined TIZEN_EXT char *__vpn_provider_create_identifier(const char *host, const char *domain) { char *ident; @@ -1815,6 +1816,20 @@ char *__vpn_provider_create_identifier(const char *host, const char *domain) return ident; } +#else +char *__vpn_provider_create_identifier(const char *host, const char *domain, const char *name) +{ + char *ident; + + ident = g_strdup_printf("%s_%s_%s", host, domain, name); + if (!ident) + return NULL; + + provider_dbus_ident(ident); + + return ident; +} +#endif int __vpn_provider_create(DBusMessage *msg) { @@ -1868,7 +1883,11 @@ int __vpn_provider_create(DBusMessage *msg) if (!type || !name) return -EOPNOTSUPP; +#if !defined TIZEN_EXT ident = __vpn_provider_create_identifier(host, domain); +#else + ident = __vpn_provider_create_identifier(host, domain, name); +#endif DBG("ident %s", ident); provider = __vpn_provider_lookup(ident); @@ -2057,7 +2076,11 @@ int __vpn_provider_create_from_config(GHashTable *settings, goto fail; } +#if !defined TIZEN_EXT ident = __vpn_provider_create_identifier(host, domain); +#else + ident = __vpn_provider_create_identifier(host, domain, name); +#endif DBG("ident %s", ident); provider = __vpn_provider_lookup(ident); diff --git a/vpn/vpn-provider.h b/vpn/vpn-provider.h index bdc5f5c1..bdc5f5c1 100644..100755 --- a/vpn/vpn-provider.h +++ b/vpn/vpn-provider.h diff --git a/vpn/vpn-rtnl.c b/vpn/vpn-rtnl.c index a7565dba..a7565dba 100644..100755 --- a/vpn/vpn-rtnl.c +++ b/vpn/vpn-rtnl.c diff --git a/vpn/vpn-rtnl.h b/vpn/vpn-rtnl.h index aa640a66..aa640a66 100644..100755 --- a/vpn/vpn-rtnl.h +++ b/vpn/vpn-rtnl.h diff --git a/vpn/vpn.h b/vpn/vpn.h index 8bf86bd1..26b13d70 100644..100755 --- a/vpn/vpn.h +++ b/vpn/vpn.h @@ -71,8 +71,11 @@ int __vpn_ipconfig_init(void); void __vpn_ipconfig_cleanup(void); #include "vpn-provider.h" - +#if !defined TIZEN_EXT char *__vpn_provider_create_identifier(const char *host, const char *domain); +#else +char *__vpn_provider_create_identifier(const char *host, const char *domain, const char *name); +#endif bool __vpn_provider_check_routes(struct vpn_provider *provider); int __vpn_provider_append_user_route(struct vpn_provider *provider, int family, const char *network, diff --git a/vpn/vpn.ver b/vpn/vpn.ver index b8877064..b8877064 100644..100755 --- a/vpn/vpn.ver +++ b/vpn/vpn.ver |