From 2327c123dc570500e547568d06b742bb8b3208da Mon Sep 17 00:00:00 2001 From: "jk7744.park" Date: Sat, 24 Oct 2015 16:36:40 +0900 Subject: [PATCH] tizen 2.4 release --- AUTHORS | 44 + ChangeLog | 262 ++ HACKING | 144 - Makefile.am | 288 +- Makefile.plugins | 182 +- README | 173 +- TODO | 171 +- acinclude.m4 | 36 +- bootstrap-configure | 5 +- client/agent.c | 910 ++++ client/agent.h | 42 + client/commands.c | 2853 +++++++++++++ client/commands.h | 43 + client/dbus_helpers.c | 456 ++ client/dbus_helpers.h | 96 + client/input.c | 289 ++ client/input.h | 48 + client/main.c | 228 +- client/peers.c | 122 + client/peers.h | 38 + client/services.c | 156 + client/services.h | 38 + client/vpnconnections.c | 111 + client/vpnconnections.h | 38 + configure.ac | 101 +- connman.manifest | 13 +- doc/Makefile.am | 38 - doc/advanced-configuration.txt | 6 +- doc/agent-api.txt | 70 +- doc/backtrace.txt | 0 doc/behavior-api.txt | 0 doc/clock-api.txt | 0 doc/config-format.txt | 104 +- doc/connman-docs.xml | 121 - doc/connman-introduction.xml | 15 - doc/connman.8 | 79 + doc/connman.conf.5 | 135 + doc/counter-api.txt | 0 doc/gtk-doc.make | 173 - doc/ipconfig-api.txt | 0 doc/manager-api.txt | 87 +- doc/overview-api.txt | 75 +- doc/peer-api.txt | 103 + doc/plugin-api.txt | 140 + doc/rfc1035.txt | 3077 -------------- doc/rfc2131.txt | 2523 ----------- doc/rfc2132.txt | 1907 --------- doc/service-api.txt | 56 +- doc/session-api.txt | 225 +- doc/session-overview.txt | 187 +- doc/session-policy-format.txt | 83 + doc/technology-api.txt | 25 +- doc/version.xml.in | 1 - doc/vpn-connection-api.txt | 181 + doc/vpn-manager-api.txt | 50 + doc/vpn-overview.txt | 60 + gdbus/client.c | 153 +- gdbus/gdbus.h | 14 +- gdbus/mainloop.c | 12 +- gdbus/object.c | 25 +- gdbus/polkit.c | 0 gdbus/watch.c | 22 +- gdhcp/client.c | 1218 +++--- gdhcp/common.c | 197 +- gdhcp/common.h | 14 +- gdhcp/gdhcp.h | 57 +- gdhcp/ipv4ll.c | 23 +- gdhcp/ipv4ll.h | 2 +- gdhcp/server.c | 224 +- gsupplicant/dbus.c | 294 +- gsupplicant/dbus.h | 15 +- gsupplicant/gsupplicant.h | 131 +- gsupplicant/supplicant.c | 4192 ++++++++++++------ gweb/giognutls.c | 36 +- gweb/giognutls.h | 4 +- gweb/gionotls.c | 4 +- gweb/gresolv.c | 115 +- gweb/gresolv.h | 7 +- gweb/gweb.c | 437 +- gweb/gweb.h | 33 +- include/agent.h | 82 + include/dbus.h | 59 +- include/device.h | 49 +- include/inet.h | 14 +- tizen/rtctimer.h => include/inotify.h | 22 +- include/ipaddress.h | 60 + include/ipconfig.h | 21 +- include/log.h | 21 +- include/{types.h => machine.h} | 20 +- include/network.h | 48 +- include/notifier.h | 6 +- include/option.h | 0 include/peer.h | 118 + include/plugin.h | 0 include/provider.h | 32 +- include/provision.h | 53 + include/proxy.h | 0 include/resolver.h | 2 - include/rtnl.h | 0 include/service.h | 30 +- include/session.h | 110 + include/setting.h | 4 +- include/storage.h | 0 include/task.h | 0 include/technology.h | 14 +- include/timeserver.h | 0 include/utsname.h | 0 include/version.h.in | 0 include/vpn-dbus.h | 58 + packaging/connman.spec | 153 +- plugins/bluetooth.c | 74 +- plugins/bluetooth_legacy.c | 482 ++- plugins/connman-nmcompat.conf | 0 plugins/dundee.c | 174 +- plugins/ethernet.c | 265 +- plugins/gadget.c | 445 ++ plugins/hh2serial-gps.c | 22 +- plugins/iospm.c | 11 +- plugins/l2tp.c | 530 --- plugins/loopback.c | 18 +- plugins/mcc.h | 0 plugins/neard.c | 628 +++ plugins/nmcompat.c | 30 +- plugins/ofono.c | 813 ++-- plugins/openconnect.c | 281 -- plugins/pacrunner.c | 63 +- plugins/polkit.c | 0 plugins/polkit.policy | 4 +- plugins/pptp.c | 336 -- plugins/session_policy_local.c | 823 ++++ plugins/telephony.c | 392 +- plugins/tist.c | 26 +- plugins/vpn.c | 2012 +++++++-- plugins/wifi.c | 2150 +++++++--- resources/usr/sbin/connman.service | 7 - .../usr/share/dbus-1/services/net.connman.service | 4 - .../dbus-1/system-services/net.connman.service | 5 + scripts/connman.in | 2 +- scripts/libppp-plugin.c | 52 +- scripts/openconnect-script.c | 49 +- scripts/openvpn-script.c | 51 +- src/6to4.c | 26 +- src/agent-connman.c | 813 ++++ src/agent.c | 1076 +++-- src/bridge.c | 16 +- src/clock.c | 119 +- src/config.c | 1398 +++++-- src/connection.c | 524 ++- src/connman-dbus.conf | 15 +- src/connman-polkit.conf | 8 +- src/connman.h | 466 ++- src/connman.service.in | 9 +- src/connman_tv.service.in | 12 + src/counter.c | 17 +- src/dbus.c | 340 +- src/detect.c | 12 +- src/device.c | 632 +-- src/dhcp.c | 667 +-- src/dhcpv6.c | 2001 +++++++-- src/dnsproxy.c | 290 +- src/eduroam.config | 5 + src/error.c | 2 +- src/firewall.c | 460 ++ src/inet.c | 1446 ++++--- src/inotify.c | 261 ++ src/ipaddress.c | 228 + src/ipconfig.c | 1031 ++--- src/ippool.c | 69 +- src/iptables.c | 1587 ++++--- src/ipv6pd.c | 385 ++ src/log.c | 65 +- src/machine.c | 125 + src/main.c | 484 ++- src/main.conf | 41 +- src/manager.c | 247 +- src/nat.c | 85 +- src/net.connman.service.in | 5 + src/network.c | 925 ++-- src/notifier.c | 82 +- src/ntp.c | 220 +- src/peer.c | 1205 ++++++ src/peer_service.c | 429 ++ src/plugin.c | 66 +- src/provider.c | 1059 +---- src/proxy.c | 28 +- src/resolver.c | 137 +- src/rfkill.c | 42 +- src/rtnl.c | 284 +- src/service.c | 4426 +++++++++++--------- src/session.c | 2286 +++++----- src/shared/netlink.c | 666 +++ src/shared/netlink.h | 53 + src/shared/util.c | 90 + src/shared/util.h | 50 + src/stats.c | 58 +- src/storage.c | 138 +- src/task.c | 43 +- src/technology.c | 1446 +++++-- src/tethering.c | 280 +- src/timeserver.c | 166 +- src/timezone.c | 36 +- src/util.c | 88 + src/utsname.c | 8 +- src/wispr.c | 206 +- src/wpad.c | 26 +- test/{connect-vpn => connect-provider} | 0 test/disable-tethering | 2 +- test/enable-tethering | 32 +- test/monitor-vpn | 81 + test/p2p-on-supplicant | 649 +++ test/{disconnect-vpn => remove-provider} | 2 - test/set-clock | 32 + test/set-ipv6-method | 5 +- test/simple-agent | 141 +- test/test-connman | 27 +- test/test-supplicant | 71 - test/vpn-connect | 24 + test/vpn-disconnect | 24 + test/vpn-get | 48 + test/vpn-property | 72 + tizen/rtctimer.c | 355 -- tools/dbus-test.c | 4 +- tools/dhcp-server-test.c | 2 +- tools/dhcp-test.c | 4 +- tools/dnsproxy-test.c | 466 +++ tools/iptables-test.c | 1904 +-------- tools/iptables-unit.c | 556 +++ {unit => tools}/manager-api.c | 44 +- tools/netlink-test.c | 123 + tools/polkit-test.c | 2 +- tools/private-network-test.c | 2 +- tools/resolv-test.c | 12 +- {unit => tools}/session-api.c | 180 +- unit/test-session.c => tools/session-test.c | 291 +- unit/test-connman.h => tools/session-test.h | 74 +- unit/utils.c => tools/session-utils.c | 146 +- tools/stats-tool.c | 80 +- tools/supplicant-dbus.c | 62 +- tools/supplicant-dbus.h | 0 tools/supplicant-test.c | 4 +- tools/supplicant.c | 317 +- tools/supplicant.h | 0 tools/tap-test.c | 4 +- tools/web-test.c | 24 +- tools/wispr.c | 104 +- tools/wpad-test.c | 20 +- unit/test-ippool.c | 220 +- unit/test-nat.c | 165 - vpn/connman-task.te | 16 + vpn/connman-vpn.service.in | 13 + vpn/main.c | 359 ++ vpn/net.connman.vpn.service.in | 5 + vpn/plugins/l2tp.c | 811 ++++ vpn/plugins/openconnect.c | 582 +++ {plugins => vpn/plugins}/openvpn.c | 229 +- vpn/plugins/pptp.c | 622 +++ vpn/plugins/vpn.c | 608 +++ {plugins => vpn/plugins}/vpn.h | 35 +- {plugins => vpn/plugins}/vpnc.c | 129 +- vpn/vpn-agent.c | 145 + vpn/vpn-agent.h | 46 + vpn/vpn-config.c | 581 +++ vpn/vpn-dbus.conf | 15 + vpn/vpn-ipconfig.c | 453 ++ vpn/vpn-manager.c | 189 + vpn/vpn-polkit.conf | 11 + vpn/vpn-polkit.policy | 29 + vpn/vpn-provider.c | 2739 ++++++++++++ vpn/vpn-provider.h | 144 + vpn/vpn-rtnl.c | 1181 ++++++ vpn/vpn-rtnl.h | 65 + vpn/vpn.h | 118 + vpn/vpn.ver | 8 + 273 files changed, 51447 insertions(+), 27933 deletions(-) mode change 100644 => 100755 AUTHORS mode change 100644 => 100755 ChangeLog delete mode 100644 HACKING mode change 100644 => 100755 Makefile.am mode change 100644 => 100755 Makefile.plugins mode change 100644 => 100755 README mode change 100644 => 100755 TODO mode change 100644 => 100755 acinclude.m4 create mode 100755 client/agent.c create mode 100755 client/agent.h create mode 100755 client/commands.c create mode 100755 client/commands.h create mode 100755 client/dbus_helpers.c create mode 100755 client/dbus_helpers.h create mode 100755 client/input.c create mode 100755 client/input.h mode change 100644 => 100755 client/main.c create mode 100755 client/peers.c create mode 100755 client/peers.h create mode 100755 client/services.c create mode 100755 client/services.h create mode 100755 client/vpnconnections.c create mode 100755 client/vpnconnections.h mode change 100644 => 100755 configure.ac delete mode 100644 doc/Makefile.am mode change 100644 => 100755 doc/advanced-configuration.txt mode change 100644 => 100755 doc/agent-api.txt mode change 100644 => 100755 doc/backtrace.txt mode change 100644 => 100755 doc/behavior-api.txt mode change 100644 => 100755 doc/clock-api.txt mode change 100644 => 100755 doc/config-format.txt delete mode 100644 doc/connman-docs.xml delete mode 100644 doc/connman-introduction.xml create mode 100755 doc/connman.8 create mode 100755 doc/connman.conf.5 mode change 100644 => 100755 doc/counter-api.txt delete mode 100644 doc/gtk-doc.make mode change 100644 => 100755 doc/ipconfig-api.txt mode change 100644 => 100755 doc/manager-api.txt mode change 100644 => 100755 doc/overview-api.txt create mode 100755 doc/peer-api.txt mode change 100644 => 100755 doc/plugin-api.txt delete mode 100644 doc/rfc1035.txt delete mode 100644 doc/rfc2131.txt delete mode 100644 doc/rfc2132.txt mode change 100644 => 100755 doc/service-api.txt mode change 100644 => 100755 doc/session-api.txt mode change 100644 => 100755 doc/session-overview.txt create mode 100755 doc/session-policy-format.txt mode change 100644 => 100755 doc/technology-api.txt delete mode 100644 doc/version.xml.in create mode 100755 doc/vpn-connection-api.txt create mode 100755 doc/vpn-manager-api.txt create mode 100755 doc/vpn-overview.txt mode change 100644 => 100755 gdbus/client.c mode change 100644 => 100755 gdbus/gdbus.h mode change 100644 => 100755 gdbus/mainloop.c mode change 100644 => 100755 gdbus/object.c mode change 100644 => 100755 gdbus/polkit.c mode change 100644 => 100755 gdbus/watch.c mode change 100644 => 100755 gdhcp/common.c mode change 100644 => 100755 gdhcp/common.h mode change 100644 => 100755 gdhcp/gdhcp.h mode change 100644 => 100755 gdhcp/ipv4ll.c mode change 100644 => 100755 gdhcp/ipv4ll.h mode change 100644 => 100755 gdhcp/server.c mode change 100644 => 100755 gsupplicant/dbus.c mode change 100644 => 100755 gsupplicant/dbus.h mode change 100644 => 100755 gsupplicant/gsupplicant.h mode change 100644 => 100755 gsupplicant/supplicant.c mode change 100644 => 100755 gweb/giognutls.c mode change 100644 => 100755 gweb/giognutls.h mode change 100644 => 100755 gweb/gionotls.c mode change 100644 => 100755 gweb/gresolv.c mode change 100644 => 100755 gweb/gresolv.h mode change 100644 => 100755 gweb/gweb.c mode change 100644 => 100755 gweb/gweb.h create mode 100755 include/agent.h mode change 100644 => 100755 include/dbus.h mode change 100644 => 100755 include/device.h mode change 100644 => 100755 include/inet.h rename tizen/rtctimer.h => include/inotify.h (62%) mode change 100644 => 100755 create mode 100755 include/ipaddress.h mode change 100644 => 100755 include/ipconfig.h mode change 100644 => 100755 include/log.h rename include/{types.h => machine.h} (69%) mode change 100644 => 100755 mode change 100644 => 100755 include/network.h mode change 100644 => 100755 include/notifier.h mode change 100644 => 100755 include/option.h create mode 100755 include/peer.h mode change 100644 => 100755 include/plugin.h mode change 100644 => 100755 include/provider.h create mode 100755 include/provision.h mode change 100644 => 100755 include/proxy.h mode change 100644 => 100755 include/resolver.h mode change 100644 => 100755 include/rtnl.h mode change 100644 => 100755 include/service.h create mode 100755 include/session.h mode change 100644 => 100755 include/setting.h mode change 100644 => 100755 include/storage.h mode change 100644 => 100755 include/task.h mode change 100644 => 100755 include/technology.h mode change 100644 => 100755 include/timeserver.h mode change 100644 => 100755 include/utsname.h mode change 100644 => 100755 include/version.h.in create mode 100755 include/vpn-dbus.h mode change 100644 => 100755 packaging/connman.spec mode change 100644 => 100755 plugins/bluetooth.c mode change 100644 => 100755 plugins/bluetooth_legacy.c mode change 100644 => 100755 plugins/connman-nmcompat.conf mode change 100644 => 100755 plugins/dundee.c mode change 100644 => 100755 plugins/ethernet.c create mode 100755 plugins/gadget.c mode change 100644 => 100755 plugins/hh2serial-gps.c mode change 100644 => 100755 plugins/iospm.c delete mode 100644 plugins/l2tp.c mode change 100644 => 100755 plugins/loopback.c mode change 100644 => 100755 plugins/mcc.h create mode 100755 plugins/neard.c mode change 100644 => 100755 plugins/nmcompat.c mode change 100644 => 100755 plugins/ofono.c delete mode 100644 plugins/openconnect.c mode change 100644 => 100755 plugins/pacrunner.c mode change 100644 => 100755 plugins/polkit.c mode change 100644 => 100755 plugins/polkit.policy delete mode 100644 plugins/pptp.c create mode 100755 plugins/session_policy_local.c mode change 100644 => 100755 plugins/telephony.c mode change 100644 => 100755 plugins/tist.c mode change 100644 => 100755 plugins/vpn.c mode change 100644 => 100755 plugins/wifi.c delete mode 100755 resources/usr/sbin/connman.service delete mode 100644 resources/usr/share/dbus-1/services/net.connman.service create mode 100644 resources/usr/share/dbus-1/system-services/net.connman.service mode change 100644 => 100755 scripts/connman.in mode change 100644 => 100755 scripts/libppp-plugin.c mode change 100644 => 100755 scripts/openconnect-script.c mode change 100644 => 100755 scripts/openvpn-script.c mode change 100644 => 100755 src/6to4.c create mode 100755 src/agent-connman.c mode change 100644 => 100755 src/agent.c mode change 100644 => 100755 src/bridge.c mode change 100644 => 100755 src/clock.c mode change 100644 => 100755 src/config.c mode change 100644 => 100755 src/connection.c mode change 100644 => 100755 src/connman-dbus.conf mode change 100644 => 100755 src/connman-polkit.conf mode change 100644 => 100755 src/connman.h mode change 100644 => 100755 src/connman.service.in create mode 100644 src/connman_tv.service.in mode change 100644 => 100755 src/counter.c mode change 100644 => 100755 src/dbus.c mode change 100644 => 100755 src/detect.c mode change 100644 => 100755 src/device.c mode change 100644 => 100755 src/dhcp.c mode change 100644 => 100755 src/dhcpv6.c mode change 100644 => 100755 src/dnsproxy.c create mode 100755 src/eduroam.config mode change 100644 => 100755 src/error.c create mode 100755 src/firewall.c mode change 100644 => 100755 src/inet.c create mode 100755 src/inotify.c create mode 100755 src/ipaddress.c mode change 100644 => 100755 src/ipconfig.c mode change 100644 => 100755 src/ippool.c mode change 100644 => 100755 src/iptables.c create mode 100755 src/ipv6pd.c mode change 100644 => 100755 src/log.c create mode 100755 src/machine.c mode change 100644 => 100755 src/main.c mode change 100644 => 100755 src/main.conf mode change 100644 => 100755 src/manager.c mode change 100644 => 100755 src/nat.c create mode 100755 src/net.connman.service.in mode change 100644 => 100755 src/network.c mode change 100644 => 100755 src/notifier.c mode change 100644 => 100755 src/ntp.c create mode 100755 src/peer.c create mode 100755 src/peer_service.c mode change 100644 => 100755 src/plugin.c mode change 100644 => 100755 src/provider.c mode change 100644 => 100755 src/proxy.c mode change 100644 => 100755 src/resolver.c mode change 100644 => 100755 src/rfkill.c mode change 100644 => 100755 src/rtnl.c mode change 100644 => 100755 src/service.c mode change 100644 => 100755 src/session.c create mode 100755 src/shared/netlink.c create mode 100755 src/shared/netlink.h create mode 100755 src/shared/util.c create mode 100755 src/shared/util.h mode change 100644 => 100755 src/stats.c mode change 100644 => 100755 src/storage.c mode change 100644 => 100755 src/task.c mode change 100644 => 100755 src/technology.c mode change 100644 => 100755 src/tethering.c mode change 100644 => 100755 src/timeserver.c mode change 100644 => 100755 src/timezone.c create mode 100755 src/util.c mode change 100644 => 100755 src/utsname.c mode change 100644 => 100755 src/wispr.c mode change 100644 => 100755 src/wpad.c rename test/{connect-vpn => connect-provider} (100%) create mode 100755 test/monitor-vpn create mode 100755 test/p2p-on-supplicant rename test/{disconnect-vpn => remove-provider} (99%) create mode 100755 test/set-clock delete mode 100755 test/test-supplicant create mode 100755 test/vpn-connect create mode 100755 test/vpn-disconnect create mode 100755 test/vpn-get create mode 100755 test/vpn-property delete mode 100644 tizen/rtctimer.c mode change 100644 => 100755 tools/dbus-test.c mode change 100644 => 100755 tools/dhcp-server-test.c mode change 100644 => 100755 tools/dhcp-test.c create mode 100755 tools/dnsproxy-test.c mode change 100644 => 100755 tools/iptables-test.c create mode 100755 tools/iptables-unit.c rename {unit => tools}/manager-api.c (89%) mode change 100644 => 100755 create mode 100755 tools/netlink-test.c mode change 100644 => 100755 tools/polkit-test.c mode change 100644 => 100755 tools/private-network-test.c mode change 100644 => 100755 tools/resolv-test.c rename {unit => tools}/session-api.c (58%) mode change 100644 => 100755 rename unit/test-session.c => tools/session-test.c (67%) mode change 100644 => 100755 rename unit/test-connman.h => tools/session-test.h (66%) mode change 100644 => 100755 rename unit/utils.c => tools/session-utils.c (65%) mode change 100644 => 100755 mode change 100644 => 100755 tools/stats-tool.c mode change 100644 => 100755 tools/supplicant-dbus.c mode change 100644 => 100755 tools/supplicant-dbus.h mode change 100644 => 100755 tools/supplicant-test.c mode change 100644 => 100755 tools/supplicant.c mode change 100644 => 100755 tools/supplicant.h mode change 100644 => 100755 tools/tap-test.c mode change 100644 => 100755 tools/web-test.c mode change 100644 => 100755 tools/wispr.c mode change 100644 => 100755 tools/wpad-test.c mode change 100644 => 100755 unit/test-ippool.c delete mode 100644 unit/test-nat.c create mode 100755 vpn/connman-task.te create mode 100755 vpn/connman-vpn.service.in create mode 100755 vpn/main.c create mode 100755 vpn/net.connman.vpn.service.in create mode 100755 vpn/plugins/l2tp.c create mode 100755 vpn/plugins/openconnect.c rename {plugins => vpn/plugins}/openvpn.c (57%) mode change 100644 => 100755 create mode 100755 vpn/plugins/pptp.c create mode 100755 vpn/plugins/vpn.c rename {plugins => vpn/plugins}/vpn.h (60%) mode change 100644 => 100755 rename {plugins => vpn/plugins}/vpnc.c (67%) mode change 100644 => 100755 create mode 100755 vpn/vpn-agent.c create mode 100755 vpn/vpn-agent.h create mode 100755 vpn/vpn-config.c create mode 100755 vpn/vpn-dbus.conf create mode 100755 vpn/vpn-ipconfig.c create mode 100755 vpn/vpn-manager.c create mode 100755 vpn/vpn-polkit.conf create mode 100755 vpn/vpn-polkit.policy create mode 100755 vpn/vpn-provider.c create mode 100755 vpn/vpn-provider.h create mode 100755 vpn/vpn-rtnl.c create mode 100755 vpn/vpn-rtnl.h create mode 100755 vpn/vpn.h create mode 100755 vpn/vpn.ver diff --git a/AUTHORS b/AUTHORS old mode 100644 new mode 100755 index 33404c4..9f807f9 --- a/AUTHORS +++ b/AUTHORS @@ -46,3 +46,47 @@ Lucas De Marchi Elena Tebesoi Mikel Astiz Paulo Pizarro +Ross Burton +Tudor Marcu +Ceara Chewning +Johannes Berg +Justin Maggard +Yann E. Morin +Constantin Musca +Terry Simons +Luciano Coelho +Peter Meerwald +Chengyi Zhao +Tysen Moore +Bastien Nocera +Michael Ikey Doherty +Mateusz Potrola +Jaehyun Kim +Zhang Zhengguang +Sjoerd Simons +Alban Crequy +Philippe Coval +Hannu Mallat +Glenn Schmottlach +Jonathan Liu +Andrew LeCain +Maneesh Jain +Eduardo Abinader +Guoqiang Liu +Eric Bouxirot +Alexandru Costache +Pasi Sjöholm +Mario Schuknecht +Slava Monich +Aaron McCarthy +Saurav Babu +David Lechner +Jason Abele +Erik Larsson +Chris Hiszpanski +Tomáš Čech +Philip Withnall +Andreas Oberritter +Arman Uguray +Vinicius Costa Gomes +Marcus Folkesson diff --git a/ChangeLog b/ChangeLog old mode 100644 new mode 100755 index a069a74..11e08cd --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,265 @@ +ver 1.29: + Fix issue with IPv6 autoconfiguration when disabled. + Fix issue with IPv6 temporary route handling. + Fix issue with IPv6 timers for nameservers. + Fix issue with DHPCv6 and route configuration. + Fix issue with DHCPv6 source port and buggy servers. + Fix issue with DHCPv6 rapid commit option length. + Fix issue with DHCPv6 rapid commit error handling. + Fix issue with handling invalid WiFi passphrases. + Fix issue with connecting Ethernet devices. + Add support for Ethernet and VLAN usage. + +ver 1.28: + Fix issue with DHCPv6 re-transmission timer. + Fix issue with DHCP service ID option byte order. + Fix issue with IPv6 connections and SLAAC/DHCPv6. + Fix issue with telephony and IPv6 autoconfiguration. + Fix issue with Bluetooth technology setting changes. + Fix issue with WiFi autoscan interval calculation. + Fix issue with WiFi and missing BSS signal strength. + Add support for IPv4 information for WiFi Display. + +ver 1.27: + Fix issue with memory leak in IP configuration. + Fix issue with providing random numbers for DHCP. + Fix issue with handling IN_MOVED_TO inotify events. + Fix issue with channel selection for WiFi scanning. + Add support for handling Bluetooth GN and PANU roles. + +ver 1.26: + Fix issue with missing WiFi security provisioning support. + Fix issue with immutable setting and provisioned services. + Fix issue with scheduling DNS cache cleanup procedure. + Fix issue with IPv6 Privacy setting on service removal. + Fix issue with DHCPv6 CONFIRM message sending procedure. + Fix issue with DHCPv6 lease expiration handling support. + Fix issue with DHCPv4 networks and broadcast flag handling. + Fix issue with DHCPv4 networks without gateway configuration. + Fix issue with P2P Peer authorization handling. + Fix issue with P2P Peer service registration. + Add support for WiFi Display information elements. + Add support for systemd-hostnamed integration. + +ver 1.25: + Fix issue with handling rebind timer for DHCPv6. + Fix issue with handling DHCP renew transaction. + Fix issue with user supplied proxy settings and DHCP. + Fix issue with extra status codes from captive portals. + Fix issue with service idle state reset on failure. + Fix issue with DNS label compression handling. + Add support for experimental P2P Peer service. + +ver 1.24: + Fix issue with handling slave interfaces. + Fix issue with handling DHCPv4 broadcast flag. + Fix issue with handling DHCPv4 lease expiration. + Fix issue with handling WiFi auto-scanning timeout. + Fix issue with handling domain and DNS server changes. + Fix issue with double free and agent messages. + +ver 1.23: + Fix issue with memory leak in technology handling. + Fix issue with not removing host route of OpenVPN. + Fix issue with double free in DHCP cleanup handling. + Fix issue with handling DHCP method from oFono. + Fix issue with IPv6-PD when disabling tethering. + Fix issue with DNS proxy when disabling tethering. + Fix issue with Bluetooth start and stop interaction. + Fix issue with Bluetooth PAN networks on adapter change. + +ver 1.22: + Fix issue with WPS state synchronization. + Fix issue with DNS servers and default service. + Fix issue with DHCP client and rebooting state. + Add support for NTP exponential backoff handling. + Add support for NTP kiss-of-death packet handling. + Add support for Ethernet gadget networking. + +ver 1.21: + Fix issue with WiFi networks and zero SSID length. + Fix issue with security details for hidden WiFi networks. + Fix issue with handling IPv6 proxy address resolving. + Fix issue with enabling Bluetooth controllers. + +ver 1.20: + Fix issue with invalid cache of DNS proxy support. + Fix issue with stopping DHCP for failed connections. + Fix issue with not stopping IPv4 Link-Local state machine. + Fix issue with service type handling for unknown interfaces. + Fix issue with using interface names instead of indexes. + Fix issue with resetting network retry counter on failure. + Fix issue with using nameservers when its type is not enabled. + Fix issue with fallback nameservers not being used. + Add support for NTP version 3 protocol. + +ver 1.19: + Fix issue with not correctly storing IPv4 method. + Fix issue with changing the default service too early. + Fix issue with service reference count and WISPr checks. + Fix issue with service auto-connect handling and ordering. + Fix issue with host and domain names when service changes. + Fix issue with proxy result and WISPr handling. + Fix issue with proxy reset when disconnecting. + Fix issue with handling fallback nameservers. + Add support for multiple agents. + +ver 1.18: + Fix issue with alignment calculation for iptables. + Fix issue with WEP key index parameter handling. + Fix issue with handling of 802.1x credentials. + Fix issue with command line parameter parsing. + Add support for completion handling in client tool. + +ver 1.17: + Fix issue with handling consecutive WiFi scanning. + Fix issue with WiFi handling and RFKILL soft block. + Fix issue with handling external RFKILL events. + Fix issue with handling USB gadget devices. + Fix issue with network reference handling. + Fix issue with byte order and DHCP discover options. + Fix issue with DHCP retry handling during IPv4-LL. + Fix issue with DHCPv6 rebind handling. + Add support for DHCPv6 decline message handling. + Add support for DHCPv6 duplicate address detection. + +ver 1.16: + Fix issue with missing signals during connection changes. + Fix issue with missing notification of proxy properties. + Fix issue with missing DHCPv6 domain list option. + Fix issue with missing DHCPv6 release message. + Fix issue with missing DHCPv6 error handling. + Fix issue with wrong IPCMv6 checksum calculation. + Fix issue with wrong service disconnect state. + Fix issue with failure to enable offline mode. + Add support for Netfilter Accounting (NFACCT). + Add support for IPv6 prefix delegation handling. + +ver 1.15: + Fix issue with missing cleanup for IPv4-LL handling. + Fix issue with missing property update for domain names. + Fix issue with scanning for all stored hidden WiFi networks. + Fix issue with time server polling for non-default service. + Fix issue with persistent storage of time configuration. + +ver 1.14: + Fix issue with WiFi scanning race condition and power cycle. + Add support for configuring allowed tethering technologies. + Add support for persistent tethering configurations. + Add support for DHCPv6 max retransmission duration option. + Add support for DHCPv6 elapsed time option. + Add support for DHCPv6 confirm messages. + +ver 1.13: + Fix issue with auto-scanning of known hidden SSIDs. + Fix issue with not correctly terminated auto-scanning. + Fix issue with missing enforcing of immutable services. + Fix issue with missing handling of multiple connection attempts. + Fix issue with missing WISPr restart after nameserver change. + Fix issue with missing provisioning for IP address method. + Fix issue with missing IP configuration signal on disconnect. + Fix issue with DNS proxy and memory leaks on request timeouts. + Fix issue with DNS proxy and handling partial TCP messages. + Fix issue with DNS proxy and handling of EDNS0 buffers. + Fix issue with DNS proxy and handling of IPv6 loopback. + Fix issue with DNS proxy listening on all interfaces. + Fix issue with CDMA network creation. + +ver 1.12: + Fix issue with overwriting gateway address. + Fix issue with missing IP address validation. + Fix issue with parsing of IPv6 configuration settings. + Fix issue with DHCP server address stored in host order. + Fix issue with resolver query failures and pending results. + Fix issue with wrongly reported max scan SSID parameter. + Fix issue with handling errors from WiFi fast scanning. + Add support for WiFi provisioning via NFC. + Add support for VPN daemon provisioning. + Add support for Ethernet provisioning. + +ver 1.11: + Fix issue with agent reference counting imbalance. + Fix issue with handling max number of SSID for scanning. + Fix issue with missing notification of online state changes. + Fix issue with not properly triggering auto-connect behavior. + Fix issue with disabling IPv6 in lower up interface states. + Fix issue with spurious error messages for interface handling. + Fix issue with wrong answer count in DNS responses. + Fix issue with crash in DNS lookup function. + Add support for BlueZ 5.x network interfaces. + Remove deprecated WiMAX support. + +ver 1.10: + Fix issue with not skipping service if settings loading fails. + Fix issue with not clearing address before starting DHCP. + Fix issue with not handling removal of GPRS context. + Fix issue with not closing UDP socket on error condition. + Fix issue with race condition when removing WiFi device. + Add support for separate VPN daemon. + +ver 1.9: + Fix issue with WISPr portal context handling. + Fix issue with DNS lookup from wrong queue. + Fix issue with DNS data reception after disconnect. + Fix issue with missing DNS host part length checking. + Fix issue with RFKILL and technology interaction. + Fix issue with tethering and disabled technologies. + Add support for single connected technology setting. + +ver 1.8: + Fix issue with NTP transmit time calculation. + Fix issue with WiFi Tethering and newer kernels. + Fix issue with Netlink messages from Wireless Extensions. + Fix issue with IPv6 nameserver refresh beeing applied to IPv4. + Fix issue with overwriting DNS proxy address information. + Fix issue with missing handling of RFKILL hard blocking. + Add support for disabling internal backtrace functionality. + +ver 1.7: + Fix issue with IPv4 address removal when setting interface down. + Fix issue with wrong error when setting tethering support option. + Fix issue with errors reported twice via agent to the client. + Fix issue with missing serialization of agent callbacks. + Add initial version of command line client tool. + +ver 1.6: + Fix issue with Bluetooth networking support. + Fix issue with technology enabling method returns. + Fix issue with wrong IP address for fixed configurations. + Fix issue with IP address setting when interface is down. + Fix issue with handling duplicate hidden WiFi networks. + Fix issue with missing scanning for hidden WiFi networks. + Fix issue with missing update of service properties. + Fix issue with missing clearing of service errors. + Add manual pages for daemon and configuration file. + +ver 1.5: + Fix issue with detecting Bluetooth networks when powered off. + Fix issue with connection attempts of non-favorite services. + Fix issue with connection attempts of disabled IP configurations. + Fix issue with missing auto-connection after changing IP method. + Fix issue with setting service state when changing IPv4 method. + Fix issue with IPv6 usage and static/manual configuration. + Add support for configuration option to disable hostname updates. + Add support for storing WiFi Tethering identifier and passphrase. + Add support for signaling changes of error property. + +ver 1.4: + Fix issue with WiFi scanning in Tethering mode. + Fix issue with WISPr operation and disconnects. + Fix issue with DHCP client and restart behavior. + Fix issue with DNS resolving and failing IPv6 records. + Fix issue with incorrect NTP leap-not-in-sync flag. + Fix issue with incorrect NTP transmit time value. + Fix issue with failing NTP server due to routing. + Fix issue with missing gateway change notification. + Fix issue with stale network interfaces at startup. + Fix issue with pending method reply and agent errors. + Add support for providing previous WPS PIN to agent. + Add support for WPA supplicant based auto-scanning. + Add support for per device regulatory domain setting. + Add support for provisioning hidden WiFi networks. + ver 1.3: Fix issue with default configuration values. Fix issue with timeserver canonical name entries. diff --git a/HACKING b/HACKING deleted file mode 100644 index 05fb69c..0000000 --- a/HACKING +++ /dev/null @@ -1,144 +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. - - -Generating source code documentation -==================================== - -The source code is annotated using the gtk-doc style documentation. This -allows an easy way of generating API documentation. The "bootstrap-configure" -script will use the "--enable-gtk-doc" configure to enable the generation of -the documentation. - -To make the gtk-doc process work, the gtk-doc tools need to be installed. -Every distribution should provide a package for this, but the naming of the -package might be different: - - Debian - # apt-get install gtk-doc-tools - - Ubuntu - # apt-get install gtk-doc-utils - - Fedora - # yum install gtk-doc - -In case "bootstrap-configure" is not used, the manual steps for generating -the documentation files are like this: - - Configuring the repository - # ./configure --enable-gtk-doc - - Generate the documentation - # cd doc && make - - View documentation - # firefox doc/html/index.html - diff --git a/Makefile.am b/Makefile.am old mode 100644 new mode 100755 index f5bf62a..afe412c --- a/Makefile.am +++ b/Makefile.am @@ -1,19 +1,23 @@ AM_MAKEFLAGS = --no-print-directory +noinst_LTLIBRARIES = + includedir = @includedir@/connman -include_HEADERS = include/types.h include/log.h include/plugin.h \ +include_HEADERS = include/log.h include/plugin.h \ include/notifier.h include/service.h \ include/resolver.h include/ipconfig.h \ include/device.h include/network.h include/inet.h \ - include/storage.h + include/storage.h include/provision.h \ + include/session.h include/ipaddress.h include/agent.h \ + include/inotify.h include/peer.h include/machine.h nodist_include_HEADERS = include/version.h noinst_HEADERS = include/rtnl.h include/task.h \ include/dbus.h include/option.h \ - include/provider.h \ + include/provider.h include/vpn-dbus.h \ include/utsname.h include/timeserver.h include/proxy.h \ include/technology.h include/setting.h @@ -21,7 +25,10 @@ local_headers = $(foreach file,$(include_HEADERS) $(nodist_include_HEADERS) \ $(noinst_HEADERS), include/connman/$(notdir $(file))) -gdbus_sources = gdbus/gdbus.h gdbus/mainloop.c gdbus/watch.c \ +noinst_LTLIBRARIES += gdbus/libgdbus-internal.la + +gdbus_libgdbus_internal_la_SOURCES = gdbus/gdbus.h \ + gdbus/mainloop.c gdbus/watch.c \ gdbus/object.c gdbus/client.c gdbus/polkit.c gdhcp_sources = gdhcp/gdhcp.h gdhcp/common.h gdhcp/common.c gdhcp/client.c \ @@ -35,6 +42,9 @@ else gweb_sources += gweb/giognutls.h gweb/gionotls.c endif +shared_sources = src/shared/util.h src/shared/util.c \ + src/shared/netlink.h src/shared/netlink.c + if DATAFILES if NMCOMPAT @@ -45,13 +55,30 @@ dbusconfdir = @DBUS_CONFDIR@ dbusconf_DATA = src/connman.conf $(nmcompat_conf) +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 + +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 +service_files = src/connman.service src/net.connman.service \ + vpn/connman-vpn.service \ + vpn/net.connman.vpn.service + plugin_LTLIBRARIES = plugin_objects = @@ -62,25 +89,21 @@ builtin_libadd = builtin_cflags = noinst_PROGRAMS = +bin_PROGRAMS = unit_objects = -sbin_PROGRAMS = src/connmand +MANUAL_PAGES = -if TIZEN_RTC -tizen_rtc_timer_sources = tizen/rtctimer.h tizen/rtctimer.c -else -tizen_rtc_timer_sources = -endif +sbin_PROGRAMS = src/connmand -src_connmand_SOURCES = $(gdbus_sources) $(gdhcp_sources) $(gweb_sources) \ - $(tizen_rtc_timer_sources) \ - $(builtin_sources) src/connman.ver \ +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 \ src/device.c src/network.c src/connection.c \ src/manager.c src/service.c \ - src/clock.c src/timezone.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/inet.c \ src/dhcp.c src/dhcpv6.c src/rtnl.c src/proxy.c \ @@ -89,51 +112,132 @@ src_connmand_SOURCES = $(gdbus_sources) $(gdhcp_sources) $(gweb_sources) \ 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/ippool.c src/bridge.c src/nat.c src/ipaddress.c \ + src/inotify.c src/firewall.c src/ipv6pd.c src/peer.c \ + src/peer_service.c src/machine.c src/util.c -src_connmand_LDADD = $(builtin_libadd) @GLIB_LIBS@ @DBUS_LIBS@ \ - @XTABLES_LIBS@ @GNUTLS_LIBS@ -lresolv -ldl +src_connmand_LDADD = gdbus/libgdbus-internal.la $(builtin_libadd) \ + @GLIB_LIBS@ @DBUS_LIBS@ @XTABLES_LIBS@ @GNUTLS_LIBS@ \ + -lresolv -ldl -lrt src_connmand_LDFLAGS = -Wl,--export-dynamic \ -Wl,--version-script=$(srcdir)/src/connman.ver -BUILT_SOURCES = $(local_headers) src/builtin.h +if VPN +vpn_plugin_LTLIBRARIES = + +vpn_plugin_objects = + +builtin_vpn_modules = +builtin_vpn_sources = +builtin_vpn_libadd = +builtin_vpn_cflags = + +sbin_PROGRAMS += vpn/connman-vpnd + +vpn_connman_vpnd_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 \ + vpn/vpn-config.c + +vpn_connman_vpnd_LDADD = gdbus/libgdbus-internal.la $(builtin_vpn_libadd) \ + @GLIB_LIBS@ @DBUS_LIBS@ @GNUTLS_LIBS@ \ + -lresolv -ldl -CLEANFILES = src/connman.conf $(BUILT_SOURCES) +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 + +if VPN +BUILT_SOURCES += vpn/builtin.h +endif + +CLEANFILES = src/connman.conf $(BUILT_SOURCES) $(service_files) statedir = $(localstatedir)/run/connman +vpn_statedir = $(localstatedir)/run/connman-vpn + +if VPN +vpn_plugindir = $(libdir)/connman/plugins-vpn +endif plugindir = $(libdir)/connman/plugins scriptdir = $(libdir)/connman/scripts storagedir = $(localstatedir)/lib/connman +vpn_storagedir = $(localstatedir)/lib/connman-vpn configdir = ${sysconfdir}/connman if MAINTAINER_MODE +if VPN +build_vpn_plugindir = $(abs_top_srcdir)/vpn/plugins/.libs +endif build_plugindir = $(abs_top_srcdir)/plugins/.libs build_scriptdir = $(abs_top_srcdir)/scripts else build_plugindir = $(plugindir) build_scriptdir = $(scriptdir) +if VPN +build_vpn_plugindir = $(vpn_plugindir) +endif endif AM_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @XTABLES_CFLAGS@ \ @GNUTLS_CFLAGS@ $(builtin_cflags) \ -DCONNMAN_PLUGIN_BUILTIN \ -DSTATEDIR=\""$(statedir)"\" \ + -DVPN_STATEDIR=\""$(vpn_statedir)"\" \ -DPLUGINDIR=\""$(build_plugindir)"\" \ -DSCRIPTDIR=\""$(build_scriptdir)"\" \ -DSTORAGEDIR=\""$(storagedir)\"" \ - -DSYSCONFDIR=\""$(sysconfdir)\"" \ + -DVPN_STORAGEDIR=\""$(vpn_storagedir)\"" \ -DCONFIGDIR=\""$(configdir)\"" -INCLUDES = -I$(builddir)/include -I$(builddir)/src -I$(srcdir)/gdbus +if VPN +AM_CPPFLAGS = -I$(builddir)/include -I$(srcdir)/gdbus +else +AM_CPPFLAGS = -I$(builddir)/include -I$(builddir)/src -I$(srcdir)/gdbus +endif + +src_connmand_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @XTABLES_CFLAGS@ \ + @GNUTLS_CFLAGS@ $(builtin_cflags) \ + -DCONNMAN_PLUGIN_BUILTIN \ + -DSTATEDIR=\""$(statedir)"\" \ + -DPLUGINDIR=\""$(build_plugindir)"\" \ + -DSCRIPTDIR=\""$(build_scriptdir)"\" \ + -DSTORAGEDIR=\""$(storagedir)\"" \ + -DVPN_STORAGEDIR=\""$(vpn_storagedir)\"" \ + -DCONFIGDIR=\""$(configdir)\"" \ + -I$(builddir)/src EXTRA_DIST = src/genbuiltin src/connman-dbus.conf src/connman-polkit.conf \ - plugins/connman-nmcompat.conf + plugins/connman-nmcompat.conf \ + $(service_files_sources) scripts/connman.in +if VPN +vpn_connman_vpnd_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ \ + $(builtin_vpn_cflags) \ + -DCONNMAN_PLUGIN_BUILTIN \ + -DVPN_STATEDIR=\""$(vpn_statedir)"\" \ + -DPLUGINDIR=\""$(build_vpn_plugindir)"\" \ + -DSCRIPTDIR=\""$(build_scriptdir)"\" \ + -DSTORAGEDIR=\""$(storagedir)\"" \ + -DVPN_STORAGEDIR=\""$(vpn_storagedir)\"" \ + -DCONFIGDIR=\""$(configdir)\"" \ + -I$(builddir)/vpn + +endif + +EXTRA_DIST += vpn/vpn-dbus.conf vpn/vpn-polkit.conf script_DATA = script_PROGRAMS = @@ -142,12 +246,32 @@ script_LTLIBRARIES = include Makefile.plugins if CLIENT -noinst_PROGRAMS += client/cm +bin_PROGRAMS += client/connmanctl + +MANUAL_PAGES = doc/connmanctl.1 + +client_connmanctl_SOURCES = client/dbus_helpers.h client/dbus_helpers.c \ + client/services.h client/services.c \ + client/commands.h client/commands.c \ + client/input.h client/input.c \ + client/agent.h client/agent.c \ + client/peers.h client/peers.c \ + client/vpnconnections.h client/vpnconnections.c \ + client/main.c -client_cm_SOURCES = client/main.c -client_cm_LDADD = @DBUS_LIBS@ +client_connmanctl_LDADD = gdbus/libgdbus-internal.la @DBUS_LIBS@ @GLIB_LIBS@ \ + -lreadline -ldl -lncurses endif +noinst_PROGRAMS += unit/test-ippool + +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 + +TESTS = unit/test-ippool + if WISPR noinst_PROGRAMS += tools/wispr @@ -162,12 +286,14 @@ noinst_PROGRAMS += tools/supplicant-test \ tools/dbus-test tools/polkit-test \ tools/iptables-test tools/tap-test tools/wpad-test \ tools/stats-tool tools/private-network-test \ - unit/test-session unit/test-ippool unit/test-nat + tools/session-test tools/iptables-unit \ + tools/dnsproxy-test tools/netlink-test -tools_supplicant_test_SOURCES = $(gdbus_sources) tools/supplicant-test.c \ +tools_supplicant_test_SOURCES = tools/supplicant-test.c \ tools/supplicant-dbus.h tools/supplicant-dbus.c \ tools/supplicant.h tools/supplicant.c -tools_supplicant_test_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ +tools_supplicant_test_LDADD = gdbus/libgdbus-internal.la \ + @GLIB_LIBS@ @DBUS_LIBS@ tools_web_test_SOURCES = $(gweb_sources) tools/web-test.c tools_web_test_LDADD = @GLIB_LIBS@ @GNUTLS_LIBS@ -lresolv @@ -186,44 +312,53 @@ tools_dhcp_test_LDADD = @GLIB_LIBS@ tools_dhcp_server_test_SOURCES = $(gdhcp_sources) tools/dhcp-server-test.c tools_dhcp_server_test_LDADD = @GLIB_LIBS@ -tools_dbus_test_SOURCES = $(gdbus_sources) tools/dbus-test.c -tools_dbus_test_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ +tools_dbus_test_SOURCES = tools/dbus-test.c +tools_dbus_test_LDADD = gdbus/libgdbus-internal.la @GLIB_LIBS@ @DBUS_LIBS@ tools_polkit_test_LDADD = @DBUS_LIBS@ -tools_iptables_test_LDADD = @GLIB_LIBS@ @XTABLES_LIBS@ +tools_iptables_test_SOURCES = src/log.c src/iptables.c tools/iptables-test.c +tools_iptables_test_LDADD = @GLIB_LIBS@ @XTABLES_LIBS@ -ldl tools_private_network_test_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ -unit_test_session_SOURCES = $(gdbus_sources) src/log.c src/dbus.c \ - unit/test-session.c unit/utils.c unit/manager-api.c \ - unit/session-api.c unit/test-connman.h -unit_test_session_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ -ldl -unit_objects += $(unit_test_session_OBJECTS) - -unit_test_ippool_SOURCES = $(gdbus_sources) src/log.c src/dbus.c \ - src/ippool.c unit/test-ippool.c -unit_test_ippool_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ -ldl -unit_objects += $(unit_test_ippool_OBJECTS) - -unit_test_nat_SOURCES = $(gdbus_sources) src/log.c src/dbus.c \ - src/iptables.c src/nat.c unit/test-nat.c -unit_test_nat_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ @XTABLES_LIBS@ -ldl -unit_objects += $(unit_nat_ippool_OBJECTS) +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 \ + @GLIB_LIBS@ @DBUS_LIBS@ -ldl + +tools_iptables_unit_CFLAGS = @DBUS_CFLAGS@ @GLIB_CFLAGS@ @XTABLES_CFLAGS@ \ + -DIPTABLES_SAVE=\""${IPTABLES_SAVE}"\" +tools_iptables_unit_SOURCES = src/log.c \ + src/iptables.c src/firewall.c src/nat.c tools/iptables-unit.c +tools_iptables_unit_LDADD = gdbus/libgdbus-internal.la \ + @GLIB_LIBS@ @DBUS_LIBS@ @XTABLES_LIBS@ -ldl + +tools_dnsproxy_test_SOURCES = tools/dnsproxy-test.c +tools_dnsproxy_test_LDADD = @GLIB_LIBS@ + +tools_netlink_test_SOURCES =$(shared_sources) tools/netlink-test.c +tools_netlink_test_LDADD = @GLIB_LIBS@ + endif test_scripts = test/get-state test/list-services \ test/monitor-services test/test-clock \ test/simple-agent test/show-introspection test/test-compat \ test/test-manager test/test-connman test/monitor-connman \ - test/connect-vpn test/disconnect-vpn \ + test/connect-provider test/remove-provider \ test/test-counter test/set-ipv4-method test/set-ipv6-method \ test/get-services test/get-proxy-autoconfig test/set-proxy \ test/enable-tethering test/disable-tethering test/backtrace \ - test/test-session test/test-supplicant \ + test/test-session test/p2p-on-supplicant \ test/test-new-supplicant test/service-move-before \ test/set-global-timeservers test/get-global-timeservers \ - test/set-nameservers test/set-domains + test/set-nameservers test/set-domains test/set-timeservers \ + test/set-clock + +test_scripts += test/vpn-connect test/vpn-disconnect test/vpn-get \ + test/monitor-vpn test/vpn-property if TEST testdir = $(pkglibdir)/test @@ -233,25 +368,37 @@ endif EXTRA_DIST += $(test_scripts) EXTRA_DIST += doc/overview-api.txt doc/behavior-api.txt \ + doc/coding-style.txt doc/wifi-p2p-overview.txt \ + doc/vpn-agent-api.txt doc/peer-api.txt \ doc/ipconfig-api.txt doc/plugin-api.txt \ doc/manager-api.txt doc/agent-api.txt \ doc/service-api.txt doc/technology-api.txt \ doc/counter-api.txt doc/config-format.txt \ doc/clock-api.txt doc/session-api.txt \ doc/session-overview.txt doc/backtrace.txt \ - doc/advanced-configuration.txt + doc/advanced-configuration.txt \ + doc/vpn-config-format.txt \ + doc/vpn-connection-api.txt \ + doc/vpn-manager-api.txt doc/vpn-overview.txt \ + doc/session-policy-format.txt +EXTRA_DIST += src/main.conf \ + src/eduroam.config + +MANUAL_PAGES += doc/connman.8 doc/connman.conf.5 + +dist_man_MANS = $(MANUAL_PAGES) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = connman.pc -DISTCHECK_CONFIGURE_FLAGS = --disable-gtk-doc \ - --disable-datafiles \ +DISTCHECK_CONFIGURE_FLAGS = --disable-datafiles \ --enable-hh2serial-gps \ --enable-openconnect \ --enable-openvpn \ --enable-vpnc \ + --enable-session-policy-local \ --enable-nmcompat \ --enable-polkit @@ -259,12 +406,15 @@ DISTCLEANFILES = $(pkgconfig_DATA) MAINTAINERCLEANFILES = Makefile.in \ aclocal.m4 configure config.h.in config.sub config.guess \ - ltmain.sh depcomp compile missing install-sh mkinstalldirs + ltmain.sh depcomp compile missing install-sh mkinstalldirs test-driver src/builtin.h: src/genbuiltin $(builtin_sources) $(AM_V_GEN)$(srcdir)/src/genbuiltin $(builtin_modules) > $@ +vpn/builtin.h: src/genbuiltin $(builtin_vpn_sources) + $(AM_V_GEN)$(srcdir)/src/genbuiltin $(builtin_vpn_modules) > $@ + src/connman.conf: src/connman-dbus.conf src/connman-polkit.conf if POLKIT $(AM_V_GEN)cp $(srcdir)/src/connman-polkit.conf $@ @@ -272,6 +422,38 @@ else $(AM_V_GEN)cp $(srcdir)/src/connman-dbus.conf $@ endif +if VPN +vpn/connman-vpn-dbus.conf: vpn/vpn-dbus.conf vpn/vpn-polkit.conf +if POLKIT + $(AM_V_GEN)cp $(srcdir)/vpn/vpn-polkit.conf $@ +else + $(AM_V_GEN)cp $(srcdir)/vpn/vpn-dbus.conf $@ +endif +endif + +if SELINUX +if VPN +EXTRA_DIST += connman-task.pp +CLEANFILES += connman-task.pp +endif + +connman-task.pp: vpn/connman-task.te + make -f /usr/share/selinux/devel/Makefile +endif + +EXTRA_DIST += vpn/connman-task.te + +do_subst = $(AM_V_GEN)$(SED) \ + -e 's,[@]prefix[@],$(prefix),g' \ + -e 's,[@]sbindir[@],$(sbindir),g' \ + -e 's,[@]sysconfdir[@],$(sysconfdir),g' + +%.service: %.service.in Makefile + $(do_subst) < $< > $@ + +scripts/connman: scripts/connman.in Makefile + $(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 old mode 100644 new mode 100755 index 74a1c4a..83ad8fb --- a/Makefile.plugins +++ b/Makefile.plugins @@ -3,9 +3,6 @@ plugin_cflags = -fvisibility=hidden -I$(srcdir)/gdbus \ @DBUS_CFLAGS@ @GLIB_CFLAGS@ plugin_ldflags = -no-undefined -module -avoid-version -script_cflags = -fvisibility=hidden -I$(srcdir)/gdbus \ - @DBUS_CFLAGS@ - if LOOPBACK builtin_modules += loopback builtin_sources += plugins/loopback.c @@ -16,6 +13,11 @@ builtin_modules += ethernet builtin_sources += plugins/ethernet.c endif +if GADGET +builtin_modules += gadget +builtin_sources += plugins/gadget.c +endif + gsupplicant_sources = gsupplicant/gsupplicant.h gsupplicant/dbus.h \ gsupplicant/supplicant.c gsupplicant/dbus.c @@ -25,6 +27,8 @@ builtin_sources += plugins/wifi.c $(gsupplicant_sources) endif if BLUETOOTH +builtin_modules += bluetooth_legacy +builtin_sources += plugins/bluetooth_legacy.c builtin_modules += bluetooth builtin_sources += plugins/bluetooth.c endif @@ -41,11 +45,6 @@ plugins_hh2serial_gps_la_LDFLAGS = $(plugin_ldflags) endif endif -if TELEPHONY -builtin_modules += telephony -builtin_sources += plugins/telephony.c -endif - if OFONO builtin_modules += ofono builtin_sources += plugins/mcc.h plugins/ofono.c @@ -56,110 +55,130 @@ 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 + if OPENCONNECT if OPENCONNECT_BUILTIN -builtin_modules += openconnect -builtin_sources += plugins/openconnect.c -builtin_vpn_sources = plugins/vpn.c plugins/vpn.h -builtin_cflags += -DOPENCONNECT=\"@OPENCONNECT@\" +builtin_vpn_modules += openconnect +builtin_vpn_sources += vpn/plugins/openconnect.c +builtin_vpn_source = vpn/plugins/vpn.c vpn/plugins/vpn.h +builtin_vpn_cflags += -DOPENCONNECT=\"@OPENCONNECT@\" else -plugin_LTLIBRARIES += plugins/openconnect.la -plugin_objects += $(plugins_openconnect_la_OBJECTS) -plugins_openconnect_la_SOURCES = plugins/vpn.h plugins/vpn.c \ - plugins/openconnect.c -plugins_openconnect_la_CFLAGS = $(plugin_cflags) -DOPENCONNECT=\"@OPENCONNECT@\" \ - -DSTATEDIR=\""$(statedir)"\" \ +vpn_plugin_LTLIBRARIES += vpn/plugins/openconnect.la +vpn_plugin_objects += $(plugins_openconnect_la_OBJECTS) +vpn_plugins_openconnect_la_SOURCES = vpn/plugins/vpn.h vpn/plugins/vpn.c \ + vpn/plugins/openconnect.c +vpn_plugins_openconnect_la_CFLAGS = $(plugin_cflags) \ + -DOPENCONNECT=\"@OPENCONNECT@\" \ + -DVPN_STATEDIR=\""$(vpn_statedir)"\" \ -DSCRIPTDIR=\""$(build_scriptdir)"\" -plugins_openconnect_la_LDFLAGS = $(plugin_ldflags) +vpn_plugins_openconnect_la_LDFLAGS = $(plugin_ldflags) endif endif if OPENVPN if OPENVPN_BUILTIN -builtin_modules += openvpn -builtin_sources += plugins/openvpn.c -builtin_vpn_sources = plugins/vpn.c plugins/vpn.h -builtin_cflags += -DOPENVPN=\"@OPENVPN@\" +builtin_vpn_modules += openvpn +builtin_vpn_sources += vpn/plugins/openvpn.c +builtin_vpn_source = vpn/plugins/vpn.c vpn/plugins/vpn.h +builtin_vpn_cflags += -DOPENVPN=\"@OPENVPN@\" else -plugin_LTLIBRARIES += plugins/openvpn.la -plugin_objects += $(plugins_openvpn_la_OBJECTS) -plugins_openvpn_la_SOURCES = plugins/vpn.h plugins/vpn.c \ - plugins/openvpn.c -plugins_openvpn_la_CFLAGS = $(plugin_cflags) -DOPENVPN=\"@OPENVPN@\" \ - -DSTATEDIR=\""$(statedir)"\" \ +vpn_plugin_LTLIBRARIES += vpn/plugins/openvpn.la +vpn_plugin_objects += $(plugins_openvpn_la_OBJECTS) +vpn_plugins_openvpn_la_SOURCES = vpn/plugins/vpn.h vpn/plugins/vpn.c \ + vpn/plugins/openvpn.c +vpn_plugins_openvpn_la_CFLAGS = $(plugin_cflags) -DOPENVPN=\"@OPENVPN@\" \ + -DVPN_STATEDIR=\""$(vpn_statedir)"\" \ -DSCRIPTDIR=\""$(build_scriptdir)"\" -plugins_openvpn_la_LDFLAGS = $(plugin_ldflags) +vpn_plugins_openvpn_la_LDFLAGS = $(plugin_ldflags) endif endif if VPNC if VPNC_BUILTIN -builtin_modules += vpnc -builtin_sources += plugins/vpnc.c -builtin_vpn_sources = plugins/vpn.c plugins/vpn.h -builtin_cflags += -DVPNC=\"@VPNC@\" +builtin_vpn_modules += vpnc +builtin_vpn_sources += vpn/plugins/vpnc.c +builtin_vpn_source = vpn/plugins/vpn.c vpn/plugins/vpn.h +builtin_vpn_cflags += -DVPNC=\"@VPNC@\" else -plugin_LTLIBRARIES += plugins/vpnc.la -plugin_objects += $(plugins_vpnc_la_OBJECTS) -plugins_vpnc_la_SOURCES = plugins/vpn.h plugins/vpn.c \ - plugins/vpnc.c -plugins_vpnc_la_CFLAGS = $(plugin_cflags) -DVPNC=\"@VPNC@\" \ - -DSTATEDIR=\""$(statedir)"\" \ +vpn_plugin_LTLIBRARIES += vpn/plugins/vpnc.la +vpn_plugin_objects += $(plugins_vpnc_la_OBJECTS) +vpn_plugins_vpnc_la_SOURCES = vpn/plugins/vpn.h vpn/plugins/vpn.c \ + vpn/plugins/vpnc.c +vpn_plugins_vpnc_la_CFLAGS = $(plugin_cflags) -DVPNC=\"@VPNC@\" \ + -DVPN_STATEDIR=\""$(vpn_statedir)"\" \ -DSCRIPTDIR=\""$(build_scriptdir)"\" -plugins_vpnc_la_LDFLAGS = $(plugin_ldflags) +vpn_plugins_vpnc_la_LDFLAGS = $(plugin_ldflags) endif endif if L2TP if L2TP_BUILTIN -builtin_modules += l2tp -builtin_sources += plugins/l2tp.c -builtin_vpn_sources = plugins/vpn.c plugins/vpn.h -builtin_cflags += -DL2TP=\"@L2TP@\" +builtin_vpn_modules += l2tp +builtin_vpn_sources += vpn/plugins/l2tp.c +builtin_vpn_source = vpn/plugins/vpn.c vpn/plugins/vpn.h +builtin_vpn_cflags += -DL2TP=\"@L2TP@\" else -plugin_LTLIBRARIES += plugins/l2tp.la -plugin_objects += $(plugins_l2tp_la_OBJECTS) -plugins_l2tp_la_SOURCES = plugins/vpn.h plugins/vpn.c \ - plugins/l2tp.c -plugins_l2tp_la_CFLAGS = $(plugin_cflags) -DL2TP=\"@L2TP@\" \ - -DSTATEDIR=\""$(statedir)"\" \ +vpn_plugin_LTLIBRARIES += vpn/plugins/l2tp.la +vpn_plugin_objects += $(plugins_l2tp_la_OBJECTS) +vpn_plugins_l2tp_la_SOURCES = vpn/plugins/vpn.h vpn/plugins/vpn.c \ + vpn/plugins/l2tp.c +vpn_plugins_l2tp_la_CFLAGS = $(plugin_cflags) -DL2TP=\"@L2TP@\" \ + -DVPN_STATEDIR=\""$(vpn_statedir)"\" \ -DSCRIPTDIR=\""$(build_scriptdir)"\" -plugins_l2tp_la_LDFLAGS = $(plugin_ldflags) +vpn_plugins_l2tp_la_LDFLAGS = $(plugin_ldflags) endif endif if PPTP if PPTP_BUILTIN -builtin_modules += pptp -builtin_sources += plugins/pptp.c -builtin_vpn_sources = plugins/vpn.c plugins/vpn.h -builtin_cflags += -DPPPD=\"@PPPD@\" -DPPTP=\"@PPTP@\" +builtin_vpn_modules += pptp +builtin_vpn_sources += vpn/plugins/pptp.c +builtin_vpn_source = vpn/plugins/vpn.c vpn/plugins/vpn.h +builtin_vpn_cflags += -DPPPD=\"@PPPD@\" -DPPTP=\"@PPTP@\" else -plugin_LTLIBRARIES += plugins/pptp.la -plugin_objects += $(plugins_pptp_la_OBJECTS) -plugins_pptp_la_SOURCES = plugins/vpn.h plugins/vpn.c \ - plugins/pptp.c -plugins_pptp_la_CFLAGS = $(plugin_cflags) -DPPPD=\"@PPPD@\" \ +vpn_plugin_LTLIBRARIES += vpn/plugins/pptp.la +vpn_plugin_objects += $(plugins_pptp_la_OBJECTS) +vpn_plugins_pptp_la_SOURCES = vpn/plugins/vpn.h vpn/plugins/vpn.c \ + vpn/plugins/pptp.c +vpn_plugins_pptp_la_CFLAGS = $(plugin_cflags) -DPPPD=\"@PPPD@\" \ -DPPTP=\"@PPTP@\" \ - -DSTATEDIR=\""$(statedir)"\" \ + -DVPN_STATEDIR=\""$(vpn_statedir)"\" \ -DSCRIPTDIR=\""$(build_scriptdir)"\" -plugins_pptp_la_LDFLAGS = $(plugin_ldflags) +vpn_plugins_pptp_la_LDFLAGS = $(plugin_ldflags) endif endif if PPTP script_LTLIBRARIES += scripts/libppp-plugin.la -scripts_libppp_plugin_la_LDFLAGS = $(script_cflags) @DBUS_CFLAGS@ +scripts_libppp_plugin_la_LDFLAGS = $(plugin_ldflags) scripts_libppp_plugin_la_LIBADD = @DBUS_LIBS@ else if L2TP script_LTLIBRARIES += scripts/libppp-plugin.la -scripts_libppp_plugin_la_LDFLAGS = $(script_cflags) @DBUS_CFLAGS@ +scripts_libppp_plugin_la_LDFLAGS = $(plugin_ldflags) scripts_libppp_plugin_la_LIBADD = @DBUS_LIBS@ endif endif -builtin_sources += $(builtin_vpn_sources) +if VPN +builtin_vpn_sources += $(builtin_vpn_source) +endif +endif if PACRUNNER builtin_modules += pacrunner @@ -174,6 +193,10 @@ if DATAFILES policydir = @POLKIT_DATADIR@ policy_DATA = plugins/net.connman.policy + +if VPN +policy_DATA += vpn/net.connman.vpn.policy +endif endif endif @@ -219,9 +242,36 @@ plugins_tist_la_LDFLAGS = $(plugin_ldflags) endif endif +if SESSION_POLICY_LOCAL +if SESSION_POLICY_LOCAL_BUILTIN +builtin_modules += session_policy_local +builtin_sources += plugins/session_policy_local.c +else +plugin_LTLIBRARIES += plugins/session_policy_local.la +plugin_objects += $(plugins_session_policy_local_la_OBJECTS) +plugins_session_policy_local_la_CFLAGS = $(plugin_cflags) \ + -DSTORAGEDIR=\""$(storagedir)\"" +plugins_session_policy_local_la_LDFLAGS = $(plugin_ldflags) +endif +endif + +if NEARD +builtin_modules += neard +builtin_sources += plugins/neard.c +endif + EXTRA_DIST += plugins/polkit.policy plugins/net.connman.policy: plugins/polkit.policy if POLKIT $(AM_V_GEN)cp $< $@ endif + +EXTRA_DIST += vpn/vpn-polkit.policy + +if VPN +vpn/net.connman.vpn.policy: vpn/vpn-polkit.policy +if POLKIT + $(AM_V_GEN)cp $< $@ +endif +endif diff --git a/README b/README old mode 100644 new mode 100755 index 6215e96..531f396 --- a/README +++ b/README @@ -31,6 +31,11 @@ Also plugins with additional features are available: - PACrunner proxy handling - PolicyKit authorization support +Note that when ConnMan starts, it clears all network interfaces that are +going to be used. If this is not desired, network interfaces can be ignored +either by setting NetworkInterfaceBlacklist in the main.conf config file or +by using the -I command line option. + Compilation and installation ============================ @@ -39,9 +44,10 @@ In order to compile Connection Manager you need following software packages: - GCC compiler - GLib library - D-Bus library - - IP-Tables library + - IP-Tables library (for tethering support) - GnuTLS library (optional) - PolicyKit (optional) + - readline (command line client) To configure run: ./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var @@ -65,6 +71,14 @@ For a working system, certain configuration options need to be enabled: enabled. This option can be used to build a small daemon for a specific system if Ethernet support is not required. + --disable-gadget + + Disable support for USB Ethernet Gadget devices + + By default USB Ethernet Gadget technology support is built-in and + enabled. This option can be used to build a small daemon + for a specific system if USB Ethernet Gadget support is not required. + --disable-wifi Disable support for WiFi devices @@ -176,6 +190,110 @@ For a working system, certain configuration options need to be enabled: written to use NetworkManager to detect online/offline status and have not yet been converted to use ConnMan. + --disable-client + + Disable support for the command line client + + By default the command line client is enabled and uses the + readline library. For specific systems where ConnMan is + configured by other means, the command line client can be + disabled and the dependency on readline is removed. + + --enable-selinux + + Enable support for compiling SElinux type enforcement rules + + The TE rules are needed if host environment is in enforcing + mode. Without this option, the VPN client process cannot + send notification to connman-vpnd via net.connman.Task + interface. The compiled connman-task.pp module needs to + also installed using this command + # semodule -i connman-task.pp + in order to enable the dbus access. + + +Activating debugging +==================== + +One can activate debugging prints in ConnMan using -d command line option. +If the -d option has no parameters, then debugging is activated for all +source code files. If the -d option has parameters, they tell which source +code files have debugging activated. One can use wild cards in file names. +Example: + -d Activate all normal debug prints + -d src/service.c This prints debugging info from src/service.c + file only + -d src/network.c:src/ipconfig.c + This activates debug prints in src/network.c + and src/ipconfig.c files. + -d 'src/n*.c' This would activate debug print from all the C source + files starting with letter 'n' in src directory. + Note the quotation marks around option, that is to + prevent shell expansion. + -d '*/n*.c:*/i*.c' Activate debug prints for all C source files starting + with letters 'n' or 'i' in any sub-directory. + +Some components of ConnMan have environment variable activated debug prints. +If the environment variable is set, then corresponding component will print +some extra debugging information. +Following environment variables can be used: + CONNMAN_DHCP_DEBUG DHCPv4 related debug information + CONNMAN_DHCPV6_DEBUG DHCPv6 related debug information + CONNMAN_IPTABLES_DEBUG Extra information when iptables is used + CONNMAN_RESOLV_DEBUG Name resolver debug prints. These debug prints + are used when ConnMan resolves host names for + its own use. + Note that the DNS proxy debug prints do not + use this environment variable. For that, one + can use "-d src/dnsproxy.c" command line option. + CONNMAN_SUPPLICANT_DEBUG Debugging prints for communication between + connmand and wpa_supplicant processes. + CONNMAN_WEB_DEBUG Debug information when ConnMan does Internet + connectivity check in Wispr and 6to4 components. + +Example: + CONNMAN_WEB_DEBUG=1 src/connmand -n + +If timing conditions are relevant then it is recommended command to +get log traces as follows: + connmand -d 2>&1 | ts '[%H:%M:%.S]' | tee connman.log + +The 'ts' program is normaly avialable in the moreutils package. + + +Kernel configuration +==================== + +In order to support tethering, the following kernel configuration options +need to be enabled either as modules (m) or builtin (y): + +CONFIG_BRIDGE +CONFIG_IP_NF_TARGET_MASQUERADE + +In order to enable CONFIG_IP_NF_TARGET_MASQUERADE, the following options need +to be enabled also as modules (m) or builtin (y): + +CONFIG_NETFILTER +CONFIG_NF_CONNTRACK_IPV4 +CONFIG_NF_NAT_IPV4 + +For routing and statistic support in Sessions, the following options +need to be enabled as modules (m) or builtin (y): + +CONFIG_IP_NF_IPTABLES +CONFIG_IP_MULTIPLE_TABLES +CONFIG_NETFILTER_NETLINK_ACCT +CONFIG_NETFILTER_XT_MATCH_NFACCT +CONFIG_NETFILTER_XT_CONNMARK +CONFIG_NETFILTER_XT_TARGET_CONNMARK +CONFIG_NETFILTER_XT_MATCH_CONNMARK + +In order to support USB gadget tethering, the following kernel configuration +options need to be enabled: + +CONFIG_USB_GADGET +CONFIG_USB_ETH + wpa_supplicant configuration ============================ @@ -187,14 +305,20 @@ CONFIG_WPS=y CONFIG_AP=y CONFIG_CTRL_IFACE_DBUS_NEW=y -and, add: +add: CONFIG_BGSCAN_SIMPLE=y This last option will enable the support of background scanning while being connected, which is necessary when roaming on wifi. -It is recommended to use wpa_supplicant 0.8.x or 1.x or later. +It is recommended to use wpa_supplicant 2.x or later. + +If wpa_supplicant is configured to D-Bus autostart, then ConnMan will +trigger the autostart of wpa_supplicant. However please keep in mind +that this trigger only happens once. If wpa_supplicant stops or crashes, +ConnMan does not periodically try to autostart it. It is up to systemd or +similar service management tool to autostart it. VPN @@ -222,6 +346,46 @@ network. While the same setup works well for a WiFi or ethernet uplink. +Online check +============ + +ConnMan tries to detect if it has Internet connection or not when +a service is connected. If the online check succeeds the service +enters Online state, if not it stays in Ready state. The online +check is also used to detect whether ConnMan is behind a captive +portal like when you are in hotel and need to pay for connectivity. + +The online check is done by trying to fetch status.html document +from ipv4.connman.net (for IPv4 connectivity) and ipv6.connman.net +(for IPv6 connectivity). The used URL looks like this +http://ipv{4|6}.connman.net/online/status.html + +During the online check procedure, ConnMan will temporarily install +a host route to both the ipv4.connman.net and ipv6.connman.net so that +the online check query can be directed via the correct network +interface which the connected service is using. This host route is +automatically removed when the online check is done. + +ConnMan sends this very minimal information in http header when doing +the online check request (example): + Host: ipv4.connman.net + User-Agent: ConnMan/1.23 wispr + Connection: close + +Currently following information is returned from connman.net if +the connection is successfull (200 OK http response code is returned): + Server: nginx + Date: Mon, 09 Jun 2014 09:25:42 GMT + Content-Type: text/html + Connection: close + X-ConnMan-Status: online + +The X-ConnMan-Status field is used in portal detection, if it is missing +ConnMan will call RequestBrowser method in net.connman.Agent dbus +interface to handle the portal login if the portal does not support WISPr. +See doc/agent-api.txt for more details. + + Information =========== @@ -229,4 +393,7 @@ Mailing list: connman@connman.net For additional information about the project visit ConnMan web site: + https://01.org/connman http://www.connman.net + +You can report bugs at https://01.org/jira/browse/CM diff --git a/TODO b/TODO old mode 100644 new mode 100755 index 97bec13..dac2ea2 --- a/TODO +++ b/TODO @@ -12,26 +12,10 @@ Background Core ==== -- Session API implementation - - Priority: High - Complexity: C4 - Owner: Daniel Wagner - Owner: Patrik Flykt - - The session API should provide a connection abstraction in order to - prioritize applications network accesses, prevent or allow network - and bearer roaming, or provide applications with a way to request - for periodic network connections. On-demand connections will be - implemented through this API as well. - See http://www.mail-archive.com/connman@connman.net/msg01653.html - - - Personal firewall Priority: Low Complexity: C8 - Owner: Tomasz Bursztyka Discuss and implement a basic and safe firewalling strategy into Connman. Provide a D-Bus API for personal firewalling. @@ -46,24 +30,106 @@ Core security integration. -- Favorite service migration removal +- Check logging produced by connman_info() - Priority: Medium - Complexity: C1 - When: 12/2012 + Priority: Medium + Complexity: C1 + + Check that logging produced by connman_info() contains meaningful messages + and get rid of the unnecessary ones. + + +- Remove --nobacktrace option + + Priority: Medium + Complexity: C1 + When: 2.0 + + Remove the --nobacktrace option or change it to --backtrace depending on + the level of systemd integration or other factors. + + +- Clean up data structure usage + + Priority: Medium + Complexity: C4 + + Use hash tables, queues and lists in the code. Check on the currently used + data structures and see if something can be simplified. - Remove service migration code that moves services from default.profile - to the current directory-based structure. + +- Unit tests for DHCP, DNS and HTTP + + Priority: Low + Complexity: C4 + + Create unit tests for these components starting with DHCP. Use gtest + from GLib for this task similarly to what has been done for OBEX in Bluez + and oFono in general. + + +- Support other time sources than NTP + + Priority: Low + Complexity: C2 + + Support other time sources like cellular, GPS in addition to NTP. + + +- Get interface names from src/device.c + + Priority: Low + Complexity: C2 + + Instead of using ioctls in connman_inet_ifindex and connman_inet_ifname, + utilize the information already provided by netlink in src/device.c. + + +- Simplify gateway selection code + + Priority: Low + Complexity: C4 + + The service list is always sorted according to preference with the + first service always owning the default route. See if update_order and + find_default_gateway in src/connection.c can be modified to use the + sorted service list instead of walking through the gateway_hash. + + +- Support D-Bus ObjectManager + + Priority: Medium + Complexity: C4 + + Support D-Bus ObjectManager by using functionality already present in + ./gdbus. Method calls and signals are already registered with gdbus, but + properties and replies especially in Agent are still handled with plain + dbus library function calls. + + With this, Manager API is removed, and a WiFi P2P API based on + ObjectManager common to Linux desktops can be implemented. WiFi ==== +- Clean up WiFi data structure usage + + Priority: Medium + Complexity: C2 + + Struct wifi_data is passed as a pointer in some of the wifi plugin + callbacks. For example removing a WiFi USB stick causes RTNL and + wpa_supplicant to call the wifi plugin at the same time causing the + freeing of the wifi data structure. Fix up the code to have proper + reference counting or other handling in place for the shared wifi data + and the members in the data structure. + + - EAP-AKA/SIM Priority: Medium Complexity: C2 - Owner: Samuel Ortiz This EAP is needed for SIM card based network authentication. ConnMan here plays a minor role: Once wpa_supplicant is set up for @@ -77,23 +143,25 @@ WiFi Complexity: C1 -- WiFi p2p - - Priority: Medium - Complexity: C2 - - -- Previous WPS pin code sending - - Priority: Medium - Complexity: C2 +- Removing wpa_supplicant 0.7.x legacy support - Provide previous WPS pin code in PreviousPassphrase field if WPS was used. + Priority: Low + Complexity: C1 + Removing global country property setter in gsupplicant, and removing + wifi's technology set_regdom implementation. Removing autoscan fallback. + (Note: should be done around the end 2012) Bluetooth ========= +- Remove Bluez 4.x support + + Priority: Low + Complexity: C1 + + Remove plugins/bluetooth-legacy.c support in about 6 month (July 2013) or + when Bluez 4.x usage becomes minimal. Cellular ======== @@ -106,20 +174,39 @@ VPN Priority: Medium Complexity: C4 - Owner: Jukka Rissanen + + +- L2TP & PPTP compatibility prefix removal + + Priority: Medium + Complexity: C1 + When: connman 2.0 + + The VPN config file provisioning patchset contains code that makes + PPP options to be marked by "PPPD." prefix. The code supports also + old "L2TP." and "PPTP." prefix for PPP options. Remove the compatibility + code and only allow "PPPD." prefix for PPP options. + + +- Update VPNC and OpenVPN with Agent support + + Priority: Medium + Complexity: C2 + + Update VPNC and OpenVPN with VPN Agent support to request possible user + ids and passphrases. Tools ===== -- Command line tool +- Add Clock API and MoveBefore/MoveAfter support to connmanctl Priority: Low - Complexity: C4 - Owner: Patrik Flykt + Complexity: C2 - For platforms not running python, it could prove useful to provide them - with a native single binary command line tool. + The connmanctl command line tool should support Clock API and Service API + MoveBefore/MoveAfter. User Interface @@ -129,7 +216,7 @@ User Interface Priority: Low Complexity: C4 - Owner: Alok Barsode A GNOME3 shell user interface would make it easier for mainstream distros - users to use ConnMan. + users to use ConnMan. Continue/restart the work at + https://github.com/connectivity/gnome-extension-connman diff --git a/acinclude.m4 b/acinclude.m4 old mode 100644 new mode 100755 index 0a59871..9e8e0dc --- a/acinclude.m4 +++ b/acinclude.m4 @@ -12,7 +12,7 @@ AC_DEFUN([AC_PROG_CC_PIE], [ AC_DEFUN([COMPILER_FLAGS], [ if (test "${CFLAGS}" = ""); then - CFLAGS="-Wall -O2 -D_FORTIFY_SOURCE=2" + CFLAGS="-Wall -O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2" fi if (test "$USE_MAINTAINER_MODE" = "yes"); then CFLAGS+=" -Werror -Wextra" @@ -25,37 +25,3 @@ AC_DEFUN([COMPILER_FLAGS], [ CFLAGS="$CFLAGS -DG_DISABLE_DEPRECATED" fi ]) - -AC_DEFUN([GTK_DOC_CHECK], -[ - AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first - AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first - dnl for overriding the documentation installation directory - AC_ARG_WITH([html-dir], - AS_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),, - [with_html_dir='${datadir}/gtk-doc/html']) - HTML_DIR="$with_html_dir" - AC_SUBST([HTML_DIR]) - - dnl enable/disable documentation building - AC_ARG_ENABLE([gtk-doc], - AS_HELP_STRING([--enable-gtk-doc], - [use gtk-doc to build documentation [[default=no]]]),, - [enable_gtk_doc=no]) - - if test x$enable_gtk_doc = xyes; then - ifelse([$1],[], - [PKG_CHECK_EXISTS([gtk-doc],, - AC_MSG_ERROR([gtk-doc not installed and --enable-gtk-doc requested]))], - [PKG_CHECK_EXISTS([gtk-doc >= $1],, - AC_MSG_ERROR([You need to have gtk-doc >= $1 installed to build gtk-doc]))]) - fi - - AC_MSG_CHECKING([whether to build gtk-doc documentation]) - AC_MSG_RESULT($enable_gtk_doc) - - AC_PATH_PROGS(GTKDOC_CHECK,gtkdoc-check,) - - AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes]) - AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [test -n "$LIBTOOL"]) -]) diff --git a/bootstrap-configure b/bootstrap-configure index 69c00d0..070c676 100755 --- a/bootstrap-configure +++ b/bootstrap-configure @@ -4,10 +4,6 @@ if [ -f config.status ]; then make maintainer-clean fi -if [ ! -f doc/gtk-doc.make ]; then - gtkdocize --copy --docdir doc -fi - ./bootstrap && \ ./configure --enable-maintainer-mode \ --enable-debug \ @@ -19,5 +15,6 @@ fi --enable-openconnect=builtin \ --enable-openvpn=builtin \ --enable-vpnc=builtin \ + --enable-session-policy-local=builtin \ --enable-nmcompat \ --enable-polkit $* diff --git a/client/agent.c b/client/agent.c new file mode 100755 index 0000000..d020889 --- /dev/null +++ b/client/agent.c @@ -0,0 +1,910 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "input.h" +#include "dbus_helpers.h" +#include "agent.h" + +#define AGENT_INTERFACE "net.connman.Agent" +#define VPN_AGENT_INTERFACE "net.connman.vpn.Agent" + +static DBusConnection *agent_connection; + +struct agent_input_data { + const char *attribute; + bool requested; + char *prompt; + connmanctl_input_func_t func; +}; + +struct agent_data { + struct agent_input_data *input; + char *interface; + bool registered; + DBusMessage *message; + DBusMessage *reply; + DBusMessageIter iter; + DBusMessageIter dict; + GDBusMethodFunction pending_function; +}; + +static void request_input_ssid_return(char *input, void *user_data); +static void request_input_passphrase_return(char *input, void *user_data); +static void request_input_string_return(char *input, void *user_data); + +enum requestinput { + SSID = 0, + IDENTITY = 1, + PASSPHRASE = 2, + WPS = 3, + WISPR_USERNAME = 4, + WISPR_PASSPHRASE = 5, + REQUEST_INPUT_MAX = 6, +}; + +static struct agent_input_data agent_input_handler[] = { + { "Name", false, "Hidden SSID name? ", request_input_ssid_return }, + { "Identity", false, "EAP username? ", request_input_string_return }, + { "Passphrase", false, "Passphrase? ", + request_input_passphrase_return }, + { "WPS", false, "WPS PIN (empty line for pushbutton)? " , + request_input_string_return }, + { "Username", false, "WISPr username? ", request_input_string_return }, + { "Password", false, "WISPr password? ", request_input_string_return }, + { }, +}; + +static struct agent_data agent_request = { + agent_input_handler, + AGENT_INTERFACE, +}; + +static struct agent_input_data vpnagent_input_handler[] = { + { "OpenConnect.Cookie", false, "OpenConnect Cookie? ", + request_input_string_return }, + { "OpenConnect.ServerCert", false, + "OpenConnect server certificate hash? ", + request_input_string_return }, + { "OpenConnect.VPNHost", false, "OpenConnect VPN server? ", + request_input_string_return }, + { "Username", false, "VPN username? ", request_input_string_return }, + { "Password", false, "VPN password? ", request_input_string_return }, + { }, +}; + +static struct agent_data vpn_agent_request = { + vpnagent_input_handler, + VPN_AGENT_INTERFACE, +}; + +static int confirm_input(char *input) +{ + int i; + + if (!input) + return -1; + + for (i = 0; input[i] != '\0'; i++) + if (isspace(input[i]) == 0) + break; + + if (strcasecmp(&input[i], "yes") == 0 || + strcasecmp(&input[i], "y") == 0) + return 1; + + if (strcasecmp(&input[i], "no") == 0 || + strcasecmp(&input[i], "n") == 0) + return 0; + + return -1; +} + +static char *strip_path(char *path) +{ + char *name = strrchr(path, '/'); + if (name) + name++; + else + name = path; + + return name; +} + +static char *agent_path(void) +{ + static char *path = NULL; + + if (!path) + path = g_strdup_printf("/net/connman/connmanctl%d", getpid()); + + return path; +} + +static void pending_message_remove(struct agent_data *request) +{ + if (request->message) { + dbus_message_unref(request->message); + request->message = NULL; + } + + if (request->reply) { + dbus_message_unref(request->reply); + request->reply = NULL; + } +} + +static void pending_command_complete(char *message) +{ + struct agent_data *next_request = NULL; + DBusMessage *pending_message; + GDBusMethodFunction pending_function; + + __connmanctl_save_rl(); + + fprintf(stdout, "%s", message); + + __connmanctl_redraw_rl(); + + if (__connmanctl_is_interactive() == true) + __connmanctl_command_mode(); + else + __connmanctl_agent_mode("", NULL, NULL); + + if (agent_request.message) + next_request = &agent_request; + else if (vpn_agent_request.message) + next_request = &vpn_agent_request; + + if (!next_request) + return; + + pending_message = next_request->message; + pending_function = next_request->pending_function; + next_request->pending_function = NULL; + + pending_function(agent_connection, next_request->message, + next_request); + + dbus_message_unref(pending_message); +} + +static bool handle_message(DBusMessage *message, struct agent_data *request, + GDBusMethodFunction function) +{ + if (!agent_request.pending_function && + !vpn_agent_request.pending_function) + return true; + + request->message = dbus_message_ref(message); + request->pending_function = function; + + return false; +} + +static DBusMessage *agent_release(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct agent_data *request = user_data; + + if (handle_message(message, request, agent_release) == false) + return NULL; + + g_dbus_unregister_interface(connection, agent_path(), + request->interface); + request->registered = false; + + pending_message_remove(request); + + if (strcmp(request->interface, AGENT_INTERFACE) == 0) + pending_command_complete("Agent unregistered by ConnMan\n"); + else + pending_command_complete("VPN Agent unregistered by ConnMan " + "VPNd\n"); + + if (__connmanctl_is_interactive() == false) + __connmanctl_quit(); + + return dbus_message_new_method_return(message); +} + +static DBusMessage *agent_cancel(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct agent_data *request = user_data; + + if (handle_message(message, request, agent_cancel) == false) + return NULL; + + pending_message_remove(request); + + if (strcmp(request->interface, AGENT_INTERFACE) == 0) + pending_command_complete("Agent request cancelled by " + "ConnMan\n"); + else + pending_command_complete("VPN Agent request cancelled by " + "ConnMan VPNd\n"); + + return dbus_message_new_method_return(message); +} + +static void request_browser_return(char *input, void *user_data) +{ + struct agent_data *request = user_data; + + switch (confirm_input(input)) { + case 1: + g_dbus_send_reply(agent_connection, request->message, + DBUS_TYPE_INVALID); + break; + case 0: + g_dbus_send_error(agent_connection, request->message, + "net.connman.Agent.Error.Canceled", NULL); + break; + default: + return; + } + + pending_message_remove(request); + pending_command_complete(""); +} + +static DBusMessage *agent_request_browser(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct agent_data *request = user_data; + DBusMessageIter iter; + char *service, *url; + + if (handle_message(message, request, agent_request_browser) == false) + return NULL; + + dbus_message_iter_init(message, &iter); + + dbus_message_iter_get_basic(&iter, &service); + dbus_message_iter_next(&iter); + dbus_message_iter_get_basic(&iter, &url); + + __connmanctl_save_rl(); + fprintf(stdout, "Agent RequestBrowser %s\n", strip_path(service)); + fprintf(stdout, " %s\n", url); + __connmanctl_redraw_rl(); + + request->message = dbus_message_ref(message); + __connmanctl_agent_mode("Connected (yes/no)? ", + request_browser_return, request); + + return NULL; +} + +static void report_error_return(char *input, void *user_data) +{ + struct agent_data *request = user_data; + + switch (confirm_input(input)) { + case 1: + if (strcmp(request->interface, AGENT_INTERFACE) == 0) + g_dbus_send_error(agent_connection, request->message, + "net.connman.Agent.Error.Retry", NULL); + else + g_dbus_send_error(agent_connection, request->message, + "net.connman.vpn.Agent.Error.Retry", + NULL); + break; + case 0: + g_dbus_send_reply(agent_connection, request->message, + DBUS_TYPE_INVALID); + break; + default: + return; + } + + pending_message_remove(request); + pending_command_complete(""); +} + +static DBusMessage *agent_report_error(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct agent_data *request = user_data; + DBusMessageIter iter; + char *path, *service, *error; + + if (handle_message(message, request, agent_report_error) == false) + return NULL; + + dbus_message_iter_init(message, &iter); + + dbus_message_iter_get_basic(&iter, &path); + service = strip_path(path); + + dbus_message_iter_next(&iter); + dbus_message_iter_get_basic(&iter, &error); + + __connmanctl_save_rl(); + if (strcmp(request->interface, AGENT_INTERFACE) == 0) + fprintf(stdout, "Agent ReportError %s\n", service); + else + fprintf(stdout, "VPN Agent ReportError %s\n", service); + fprintf(stdout, " %s\n", error); + __connmanctl_redraw_rl(); + + request->message = dbus_message_ref(message); + __connmanctl_agent_mode("Retry (yes/no)? ", report_error_return, + request); + + return NULL; +} + +static DBusMessage *agent_report_peer_error(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct agent_data *request = user_data; + char *path, *peer, *error; + DBusMessageIter iter; + + if (handle_message(message, request, + agent_report_peer_error) == false) + return NULL; + + dbus_message_iter_init(message, &iter); + + dbus_message_iter_get_basic(&iter, &path); + peer = strip_path(path); + + dbus_message_iter_next(&iter); + dbus_message_iter_get_basic(&iter, &error); + + __connmanctl_save_rl(); + fprintf(stdout, "Agent ReportPeerError %s\n", peer); + fprintf(stdout, " %s\n", error); + __connmanctl_redraw_rl(); + + request->message = dbus_message_ref(message); + __connmanctl_agent_mode("Retry (yes/no)? ", + report_error_return, request); + return NULL; +} + +static void request_input_next(struct agent_data *request) +{ + int i; + + for (i = 0; request->input[i].attribute; i++) { + if (request->input[i].requested == true) { + if (request->input[i].func) + __connmanctl_agent_mode(request->input[i].prompt, + request->input[i].func, + request); + else + request->input[i].requested = false; + return; + } + } + + dbus_message_iter_close_container(&request->iter, &request->dict); + + g_dbus_send_message(agent_connection, request->reply); + request->reply = NULL; + + pending_message_remove(request); + pending_command_complete(""); + + __connmanctl_redraw_rl(); +} + +static void request_input_append(struct agent_data *request, + const char *attribute, char *value) +{ + __connmanctl_dbus_append_dict_entry(&request->dict, attribute, + DBUS_TYPE_STRING, &value); +} + +static void request_input_ssid_return(char *input, + void *user_data) +{ + struct agent_data *request = user_data; + int len = 0; + + if (input) + len = strlen(input); + + if (len > 0 && len <= 32) { + request->input[SSID].requested = false; + request_input_append(request, request->input[SSID].attribute, + input); + + request_input_next(request); + } +} + +static void request_input_passphrase_return(char *input, void *user_data) +{ + struct agent_data *request = user_data; + int len = 0; + + /* TBD passphrase length checking */ + + if (input) + len = strlen(input); + + if (len == 0 && request->input[WPS].requested == false) + return; + + request->input[PASSPHRASE].requested = false; + + if (len > 0) { + request_input_append(request, + request->input[PASSPHRASE].attribute, input); + + request->input[WPS].requested = false; + } + + request_input_next(request); +} + +static void request_input_string_return(char *input, void *user_data) +{ + struct agent_data *request = user_data; + int i; + + for (i = 0; request->input[i].attribute; i++) { + if (request->input[i].requested == true) { + request_input_append(request, + request->input[i].attribute, input); + request->input[i].requested = false; + break; + } + } + + request_input_next(request); +} + +static void parse_agent_request(struct agent_data *request, + DBusMessageIter *iter) +{ + DBusMessageIter dict, entry, variant, dict_entry; + DBusMessageIter field_entry, field_value; + char *field, *argument, *value; + char *attr_type = NULL; + int i; + + dbus_message_iter_recurse(iter, &dict); + + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + + dbus_message_iter_recurse(&dict, &entry); + + dbus_message_iter_get_basic(&entry, &field); + + dbus_message_iter_next(&entry); + + dbus_message_iter_recurse(&entry, &variant); + dbus_message_iter_recurse(&variant, &dict_entry); + + while (dbus_message_iter_get_arg_type(&dict_entry) + == DBUS_TYPE_DICT_ENTRY) { + dbus_message_iter_recurse(&dict_entry, &field_entry); + + dbus_message_iter_get_basic(&field_entry, &argument); + + dbus_message_iter_next(&field_entry); + + dbus_message_iter_recurse(&field_entry, &field_value); + + if (strcmp(argument, "Type") == 0) { + dbus_message_iter_get_basic(&field_value, + &value); + attr_type = g_strdup(value); + } + + dbus_message_iter_next(&dict_entry); + } + + for (i = 0; request->input[i].attribute; i++) { + if (strcmp(field, request->input[i].attribute) == 0) { + request->input[i].requested = true; + break; + } + } + + g_free(attr_type); + attr_type = NULL; + + dbus_message_iter_next(&dict); + } +} + +static DBusMessage *agent_request_input(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct agent_data *request = user_data; + DBusMessageIter iter, dict; + char *service, *str; + + if (handle_message(message, request, agent_request_input) == false) + return NULL; + + dbus_message_iter_init(message, &iter); + + dbus_message_iter_get_basic(&iter, &str); + service = strip_path(str); + + dbus_message_iter_next(&iter); + dbus_message_iter_recurse(&iter, &dict); + + __connmanctl_save_rl(); + if (strcmp(request->interface, AGENT_INTERFACE) == 0) + fprintf(stdout, "Agent RequestInput %s\n", service); + else + fprintf(stdout, "VPN Agent RequestInput %s\n", service); + __connmanctl_dbus_print(&dict, " ", " = ", "\n"); + fprintf(stdout, "\n"); + + parse_agent_request(request, &iter); + + request->reply = dbus_message_new_method_return(message); + dbus_message_iter_init_append(request->reply, &request->iter); + + dbus_message_iter_open_container(&request->iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + &request->dict); + + request_input_next(request); + + return NULL; +} + +static void request_authorization_return(char *input, void *user_data) +{ + struct agent_data *request = user_data; + + switch (confirm_input(input)) { + case 1: + request->reply = dbus_message_new_method_return( + request->message); + dbus_message_iter_init_append(request->reply, &request->iter); + + dbus_message_iter_open_container(&request->iter, + DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + &request->dict); + dbus_message_iter_close_container(&request->iter, + &request->dict); + g_dbus_send_message(agent_connection, request->reply); + request->reply = NULL; + break; + case 0: + g_dbus_send_error(agent_connection, request->message, + "net.connman.Agent.Error.Rejected", NULL); + break; + default: + g_dbus_send_error(agent_connection, request->message, + "net.connman.Agent.Error.Canceled", NULL); + break; + } + + pending_message_remove(request); + pending_command_complete(""); +} + +static DBusMessage * +agent_request_peer_authorization(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + struct agent_data *request = user_data; + DBusMessageIter iter, dict; + char *peer, *str; + bool input; + int i; + + if (handle_message(message, request, agent_request_peer_authorization) + == false) + return NULL; + + dbus_message_iter_init(message, &iter); + + dbus_message_iter_get_basic(&iter, &str); + peer = strip_path(str); + + dbus_message_iter_next(&iter); + dbus_message_iter_recurse(&iter, &dict); + + __connmanctl_save_rl(); + fprintf(stdout, "Agent RequestPeerAuthorization %s\n", peer); + __connmanctl_dbus_print(&dict, " ", " = ", "\n"); + fprintf(stdout, "\n"); + + parse_agent_request(request, &iter); + + for (input = false, i = 0; request->input[i].attribute; i++) { + if (request->input[i].requested == true) { + input = true; + break; + } + } + + if (!input) { + request->message = dbus_message_ref(message); + __connmanctl_agent_mode("Accept connection (yes/no)? ", + request_authorization_return, request); + return NULL; + } + + request->reply = dbus_message_new_method_return(message); + dbus_message_iter_init_append(request->reply, &request->iter); + + dbus_message_iter_open_container(&request->iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + &request->dict); + + request_input_next(request); + + return NULL; +} + +static const GDBusMethodTable agent_methods[] = { + { GDBUS_ASYNC_METHOD("Release", NULL, NULL, agent_release) }, + { GDBUS_ASYNC_METHOD("Cancel", NULL, NULL, agent_cancel) }, + { GDBUS_ASYNC_METHOD("RequestBrowser", + GDBUS_ARGS({ "service", "o" }, + { "url", "s" }), + NULL, agent_request_browser) }, + { GDBUS_ASYNC_METHOD("ReportError", + GDBUS_ARGS({ "service", "o" }, + { "error", "s" }), + NULL, agent_report_error) }, + { GDBUS_ASYNC_METHOD("ReportPeerError", + GDBUS_ARGS({ "peer", "o" }, + { "error", "s" }), + NULL, agent_report_peer_error) }, + { GDBUS_ASYNC_METHOD("RequestInput", + GDBUS_ARGS({ "service", "o" }, + { "fields", "a{sv}" }), + GDBUS_ARGS({ "fields", "a{sv}" }), + agent_request_input) }, + { GDBUS_ASYNC_METHOD("RequestPeerAuthorization", + GDBUS_ARGS({ "peer", "o" }, + { "fields", "a{sv}" }), + GDBUS_ARGS({ "fields", "a{sv}" }), + agent_request_peer_authorization) }, + { }, +}; + +static int agent_register_return(DBusMessageIter *iter, const char *error, + void *user_data) +{ + DBusConnection *connection = user_data; + + if (error) { + g_dbus_unregister_interface(connection, agent_path(), + AGENT_INTERFACE); + fprintf(stderr, "Error registering Agent: %s\n", error); + return 0; + } + + agent_request.registered = true; + fprintf(stdout, "Agent registered\n"); + + return -EINPROGRESS; +} + +static void append_path(DBusMessageIter *iter, void *user_data) +{ + const char *path = user_data; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path); +} + +int __connmanctl_agent_register(DBusConnection *connection) +{ + char *path = agent_path(); + int result; + + if (agent_request.registered == true) { + fprintf(stderr, "Agent already registered\n"); + return -EALREADY; + } + + agent_connection = connection; + + if (!g_dbus_register_interface(connection, path, + AGENT_INTERFACE, agent_methods, + NULL, NULL, &agent_request, NULL)) { + fprintf(stderr, "Error: Failed to register Agent callbacks\n"); + return 0; + } + + result = __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, + CONNMAN_PATH, "net.connman.Manager", "RegisterAgent", + agent_register_return, connection, append_path, path); + + if (result != -EINPROGRESS) { + g_dbus_unregister_interface(connection, agent_path(), + AGENT_INTERFACE); + + fprintf(stderr, "Error: Failed to register Agent\n"); + } + + return result; +} + +static int agent_unregister_return(DBusMessageIter *iter, const char *error, + void *user_data) +{ + if (error) { + fprintf(stderr, "Error unregistering Agent: %s\n", error); + return 0; + } + + agent_request.registered = false; + fprintf(stdout, "Agent unregistered\n"); + + return 0; +} + +int __connmanctl_agent_unregister(DBusConnection *connection) +{ + char *path = agent_path(); + int result; + + if (agent_request.registered == false) { + fprintf(stderr, "Agent not registered\n"); + return -EALREADY; + } + + g_dbus_unregister_interface(connection, agent_path(), AGENT_INTERFACE); + + result = __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, + CONNMAN_PATH, "net.connman.Manager", "UnregisterAgent", + agent_unregister_return, NULL, append_path, path); + + if (result != -EINPROGRESS) + fprintf(stderr, "Error: Failed to unregister Agent\n"); + + return result; +} + +static const GDBusMethodTable vpn_agent_methods[] = { + { GDBUS_ASYNC_METHOD("Release", NULL, NULL, agent_release) }, + { GDBUS_ASYNC_METHOD("Cancel", NULL, NULL, agent_cancel) }, + { GDBUS_ASYNC_METHOD("ReportError", + GDBUS_ARGS({ "service", "o" }, + { "error", "s" }), + NULL, agent_report_error) }, + { GDBUS_ASYNC_METHOD("RequestInput", + GDBUS_ARGS({ "service", "o" }, + { "fields", "a{sv}" }), + GDBUS_ARGS({ "fields", "a{sv}" }), + agent_request_input) }, + { }, +}; + +static int vpn_agent_register_return(DBusMessageIter *iter, const char *error, + void *user_data) +{ + DBusConnection *connection = user_data; + + if (error) { + g_dbus_unregister_interface(connection, agent_path(), + VPN_AGENT_INTERFACE); + fprintf(stderr, "Error registering VPN Agent: %s\n", error); + return 0; + } + + vpn_agent_request.registered = true; + fprintf(stdout, "VPN Agent registered\n"); + + return -EINPROGRESS; +} + +int __connmanctl_vpn_agent_register(DBusConnection *connection) +{ + char *path = agent_path(); + int result; + + if (vpn_agent_request.registered == true) { + fprintf(stderr, "VPN Agent already registered\n"); + return -EALREADY; + } + + agent_connection = connection; + + if (!g_dbus_register_interface(connection, path, + VPN_AGENT_INTERFACE, vpn_agent_methods, + NULL, NULL, &vpn_agent_request, NULL)) { + fprintf(stderr, "Error: Failed to register VPN Agent " + "callbacks\n"); + return 0; + } + + result = __connmanctl_dbus_method_call(connection, VPN_SERVICE, + VPN_PATH, "net.connman.vpn.Manager", "RegisterAgent", + vpn_agent_register_return, connection, append_path, + path); + + if (result != -EINPROGRESS) { + g_dbus_unregister_interface(connection, agent_path(), + VPN_AGENT_INTERFACE); + + fprintf(stderr, "Error: Failed to register VPN Agent\n"); + } + + return result; +} + +static int vpn_agent_unregister_return(DBusMessageIter *iter, + const char *error, void *user_data) +{ + if (error) { + fprintf(stderr, "Error unregistering VPN Agent: %s\n", error); + return 0; + } + + vpn_agent_request.registered = false; + fprintf(stdout, "VPN Agent unregistered\n"); + + return 0; +} + +int __connmanctl_vpn_agent_unregister(DBusConnection *connection) +{ + char *path = agent_path(); + int result; + + if (vpn_agent_request.registered == false) { + fprintf(stderr, "VPN Agent not registered\n"); + return -EALREADY; + } + + g_dbus_unregister_interface(connection, agent_path(), + VPN_AGENT_INTERFACE); + + result = __connmanctl_dbus_method_call(connection, VPN_SERVICE, + VPN_PATH, "net.connman.vpn.Manager", "UnregisterAgent", + vpn_agent_unregister_return, NULL, append_path, path); + + if (result != -EINPROGRESS) + fprintf(stderr, "Error: Failed to unregister VPN Agent\n"); + + return result; +} diff --git a/client/agent.h b/client/agent.h new file mode 100755 index 0000000..669a593 --- /dev/null +++ b/client/agent.h @@ -0,0 +1,42 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __CONNMANCTL_AGENT_H +#define __CONNMANCTL_AGENT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int __connmanctl_agent_register(DBusConnection *connection); +int __connmanctl_agent_unregister(DBusConnection *connection); + +int __connmanctl_vpn_agent_register(DBusConnection *connection); +int __connmanctl_vpn_agent_unregister(DBusConnection *connection); + +#ifdef __cplusplus +} +#endif + +#endif /* __CONNMANCTL_AGENT_H */ diff --git a/client/commands.c b/client/commands.c new file mode 100755 index 0000000..9208016 --- /dev/null +++ b/client/commands.c @@ -0,0 +1,2853 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2012-2014 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "dbus_helpers.h" +#include "input.h" +#include "services.h" +#include "peers.h" +#include "commands.h" +#include "agent.h" +#include "vpnconnections.h" + +static DBusConnection *connection; +static GHashTable *service_hash; +static GHashTable *peer_hash; +static GHashTable *technology_hash; +static char *session_notify_path; +static char *session_path; +static bool session_connected; + +struct connman_option { + const char *name; + const char val; + const char *desc; +}; + +static char *ipv4[] = { + "Method", + "Address", + "Netmask", + "Gateway", + NULL +}; + +static char *ipv6[] = { + "Method", + "Address", + "PrefixLength", + "Gateway", + NULL +}; + +static int cmd_help(char *args[], int num, struct connman_option *options); + +static bool check_dbus_name(const char *name) +{ + /* + * Valid dbus chars should be [A-Z][a-z][0-9]_ + * and should not start with number. + */ + unsigned int i; + + if (!name || name[0] == '\0') + return false; + + for (i = 0; name[i] != '\0'; i++) + if (!((name[i] >= 'A' && name[i] <= 'Z') || + (name[i] >= 'a' && name[i] <= 'z') || + (name[i] >= '0' && name[i] <= '9') || + name[i] == '_')) + return false; + + return true; +} + +static int parse_boolean(char *arg) +{ + if (!arg) + return -1; + + if (strcasecmp(arg, "no") == 0 || + strcasecmp(arg, "false") == 0 || + strcasecmp(arg, "off" ) == 0 || + strcasecmp(arg, "disable" ) == 0 || + strcasecmp(arg, "n") == 0 || + strcasecmp(arg, "f") == 0 || + strcasecmp(arg, "0") == 0) + return 0; + + if (strcasecmp(arg, "yes") == 0 || + strcasecmp(arg, "true") == 0 || + strcasecmp(arg, "on") == 0 || + strcasecmp(arg, "enable" ) == 0 || + strcasecmp(arg, "y") == 0 || + strcasecmp(arg, "t") == 0 || + strcasecmp(arg, "1") == 0) + return 1; + + return -1; +} + +static int parse_args(char *arg, struct connman_option *options) +{ + int i; + + if (!arg) + return -1; + + for (i = 0; options[i].name; i++) { + if (strcmp(options[i].name, arg) == 0 || + (strncmp(arg, "--", 2) == 0 && + strcmp(&arg[2], options[i].name) == 0)) + return options[i].val; + } + + return '?'; +} + +static int enable_return(DBusMessageIter *iter, const char *error, + void *user_data) +{ + char *tech = user_data; + char *str; + + str = strrchr(tech, '/'); + if (str) + str++; + else + str = tech; + + if (!error) + fprintf(stdout, "Enabled %s\n", str); + else + fprintf(stderr, "Error %s: %s\n", str, error); + + g_free(user_data); + + return 0; +} + +static int cmd_enable(char *args[], int num, struct connman_option *options) +{ + char *tech; + dbus_bool_t b = TRUE; + + if (num > 2) + return -E2BIG; + + if (num < 2) + return -EINVAL; + + if (check_dbus_name(args[1]) == false) + return -EINVAL; + + if (strcmp(args[1], "offline") == 0) { + tech = g_strdup(args[1]); + return __connmanctl_dbus_set_property(connection, "/", + "net.connman.Manager", enable_return, tech, + "OfflineMode", DBUS_TYPE_BOOLEAN, &b); + } + + tech = g_strdup_printf("/net/connman/technology/%s", args[1]); + return __connmanctl_dbus_set_property(connection, tech, + "net.connman.Technology", enable_return, tech, + "Powered", DBUS_TYPE_BOOLEAN, &b); +} + +static int disable_return(DBusMessageIter *iter, const char *error, + void *user_data) +{ + char *tech = user_data; + char *str; + + str = strrchr(tech, '/'); + if (str) + str++; + else + str = tech; + + if (!error) + fprintf(stdout, "Disabled %s\n", str); + else + fprintf(stderr, "Error %s: %s\n", str, error); + + g_free(user_data); + + return 0; +} + +static int cmd_disable(char *args[], int num, struct connman_option *options) +{ + char *tech; + dbus_bool_t b = FALSE; + + if (num > 2) + return -E2BIG; + + if (num < 2) + return -EINVAL; + + if (check_dbus_name(args[1]) == false) + return -EINVAL; + + if (strcmp(args[1], "offline") == 0) { + tech = g_strdup(args[1]); + return __connmanctl_dbus_set_property(connection, "/", + "net.connman.Manager", disable_return, tech, + "OfflineMode", DBUS_TYPE_BOOLEAN, &b); + } + + tech = g_strdup_printf("/net/connman/technology/%s", args[1]); + return __connmanctl_dbus_set_property(connection, tech, + "net.connman.Technology", disable_return, tech, + "Powered", DBUS_TYPE_BOOLEAN, &b); +} + +static int state_print(DBusMessageIter *iter, const char *error, + void *user_data) +{ + DBusMessageIter entry; + + if (error) { + fprintf(stderr, "Error: %s", error); + return 0; + } + + dbus_message_iter_recurse(iter, &entry); + __connmanctl_dbus_print(&entry, " ", " = ", "\n"); + fprintf(stdout, "\n"); + + return 0; +} + +static int cmd_state(char *args[], int num, struct connman_option *options) +{ + if (num > 1) + return -E2BIG; + + return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, + CONNMAN_PATH, "net.connman.Manager", "GetProperties", + state_print, NULL, NULL, NULL); +} + +static int services_list(DBusMessageIter *iter, const char *error, + void *user_data) +{ + if (!error) { + __connmanctl_services_list(iter); + fprintf(stdout, "\n"); + } else { + fprintf(stderr, "Error: %s\n", error); + } + + return 0; +} + +static int peers_list(DBusMessageIter *iter, + const char *error, void *user_data) +{ + if (!error) { + __connmanctl_peers_list(iter); + fprintf(stdout, "\n"); + } else + fprintf(stderr, "Error: %s\n", error); + + return 0; +} + +static int object_properties(DBusMessageIter *iter, + const char *error, void *user_data) +{ + char *path = user_data; + char *str; + DBusMessageIter dict; + + if (!error) { + fprintf(stdout, "%s\n", path); + + dbus_message_iter_recurse(iter, &dict); + __connmanctl_dbus_print(&dict, " ", " = ", "\n"); + + fprintf(stdout, "\n"); + + } else { + str = strrchr(path, '/'); + if (str) + str++; + else + str = path; + + fprintf(stderr, "Error %s: %s\n", str, error); + } + + g_free(user_data); + + return 0; +} + +static int cmd_services(char *args[], int num, struct connman_option *options) +{ + char *service_name = NULL; + char *path; + int c; + + if (num > 3) + return -E2BIG; + + c = parse_args(args[1], options); + switch (c) { + case -1: + break; + case 'p': + if (num < 3) + return -EINVAL; + service_name = args[2]; + break; + default: + if (num > 2) + return -E2BIG; + service_name = args[1]; + break; + } + + if (!service_name) { + return __connmanctl_dbus_method_call(connection, + CONNMAN_SERVICE, CONNMAN_PATH, + "net.connman.Manager", "GetServices", + services_list, NULL, NULL, NULL); + } + + if (check_dbus_name(service_name) == false) + return -EINVAL; + + path = g_strdup_printf("/net/connman/service/%s", service_name); + return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path, + "net.connman.Service", "GetProperties", + object_properties, path, NULL, NULL); +} + +static int cmd_peers(char *args[], int num, struct connman_option *options) +{ + char *peer_name = NULL; + char *path; + + if (num > 2) + return -E2BIG; + + if (num == 2) + peer_name = args[1]; + + if (!peer_name) { + return __connmanctl_dbus_method_call(connection, + CONNMAN_SERVICE, CONNMAN_PATH, + "net.connman.Manager", "GetPeers", + peers_list, NULL, NULL, NULL); + } + + if (check_dbus_name(peer_name) == false) + return -EINVAL; + + path = g_strdup_printf("/net/connman/peer/%s", peer_name); + return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, + path, "net.connman.Peer", "GetProperties", + object_properties, path, NULL, NULL); +} + +static int technology_print(DBusMessageIter *iter, const char *error, + void *user_data) +{ + DBusMessageIter array; + + if (error) { + fprintf(stderr, "Error: %s\n", error); + return 0; + } + + dbus_message_iter_recurse(iter, &array); + while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) { + DBusMessageIter entry, dict; + const char *path; + + dbus_message_iter_recurse(&array, &entry); + dbus_message_iter_get_basic(&entry, &path); + fprintf(stdout, "%s\n", path); + + dbus_message_iter_next(&entry); + + dbus_message_iter_recurse(&entry, &dict); + __connmanctl_dbus_print(&dict, " ", " = ", "\n"); + fprintf(stdout, "\n"); + + dbus_message_iter_next(&array); + } + + return 0; +} + +static int cmd_technologies(char *args[], int num, + struct connman_option *options) +{ + if (num > 1) + return -E2BIG; + + return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, + CONNMAN_PATH, "net.connman.Manager", "GetTechnologies", + technology_print, NULL, NULL, NULL); +} + +struct tether_enable { + char *path; + dbus_bool_t enable; +}; + +static int tether_set_return(DBusMessageIter *iter, const char *error, + void *user_data) +{ + struct tether_enable *tether = user_data; + char *str; + + str = strrchr(tether->path, '/'); + if (str) + str++; + else + str = tether->path; + + if (!error) { + fprintf(stdout, "%s tethering for %s\n", + tether->enable ? "Enabled" : "Disabled", + str); + } else + fprintf(stderr, "Error %s %s tethering: %s\n", + tether->enable ? + "enabling" : "disabling", str, error); + + g_free(tether->path); + g_free(user_data); + + return 0; +} + +static int tether_set(char *technology, int set_tethering) +{ + struct tether_enable *tether = g_new(struct tether_enable, 1); + + switch(set_tethering) { + case 1: + tether->enable = TRUE; + break; + case 0: + tether->enable = FALSE; + break; + default: + g_free(tether); + return 0; + } + + tether->path = g_strdup_printf("/net/connman/technology/%s", + technology); + + return __connmanctl_dbus_set_property(connection, tether->path, + "net.connman.Technology", tether_set_return, + tether, "Tethering", DBUS_TYPE_BOOLEAN, + &tether->enable); +} + +struct tether_properties { + int ssid_result; + int passphrase_result; + int set_tethering; +}; + +static int tether_update(struct tether_properties *tether) +{ + if (tether->ssid_result == 0 && tether->passphrase_result == 0) + return tether_set("wifi", tether->set_tethering); + + if (tether->ssid_result != -EINPROGRESS && + tether->passphrase_result != -EINPROGRESS) { + g_free(tether); + return 0; + } + + return -EINPROGRESS; +} + +static int tether_set_ssid_return(DBusMessageIter *iter, const char *error, + void *user_data) +{ + struct tether_properties *tether = user_data; + + if (!error) { + fprintf(stdout, "Wifi SSID set\n"); + tether->ssid_result = 0; + } else { + fprintf(stderr, "Error setting wifi SSID: %s\n", error); + tether->ssid_result = -EINVAL; + } + + return tether_update(tether); +} + +static int tether_set_passphrase_return(DBusMessageIter *iter, + const char *error, void *user_data) +{ + struct tether_properties *tether = user_data; + + if (!error) { + fprintf(stdout, "Wifi passphrase set\n"); + tether->passphrase_result = 0; + } else { + fprintf(stderr, "Error setting wifi passphrase: %s\n", error); + tether->passphrase_result = -EINVAL; + } + + return tether_update(tether); +} + +static int tether_set_ssid(char *ssid, char *passphrase, int set_tethering) +{ + struct tether_properties *tether = g_new(struct tether_properties, 1); + + tether->set_tethering = set_tethering; + + tether->ssid_result = __connmanctl_dbus_set_property(connection, + "/net/connman/technology/wifi", + "net.connman.Technology", + tether_set_ssid_return, tether, + "TetheringIdentifier", DBUS_TYPE_STRING, &ssid); + + tether->passphrase_result =__connmanctl_dbus_set_property(connection, + "/net/connman/technology/wifi", + "net.connman.Technology", + tether_set_passphrase_return, tether, + "TetheringPassphrase", DBUS_TYPE_STRING, &passphrase); + + if (tether->ssid_result != -EINPROGRESS && + tether->passphrase_result != -EINPROGRESS) { + g_free(tether); + return -ENXIO; + } + + return -EINPROGRESS; +} + +static int cmd_tether(char *args[], int num, struct connman_option *options) +{ + char *ssid, *passphrase; + int set_tethering; + + if (num < 3) + return -EINVAL; + + passphrase = args[num - 1]; + ssid = args[num - 2]; + + set_tethering = parse_boolean(args[2]); + + if (strcmp(args[1], "wifi") == 0) { + + if (num > 5) + return -E2BIG; + + if (num == 5 && set_tethering == -1) + return -EINVAL; + + if (num == 4) + set_tethering = -1; + + if (num > 3) + return tether_set_ssid(ssid, passphrase, set_tethering); + } + + if (num > 3) + return -E2BIG; + + if (set_tethering == -1) + return -EINVAL; + + if (check_dbus_name(args[1]) == false) + return -EINVAL; + + return tether_set(args[1], set_tethering); +} + +static int scan_return(DBusMessageIter *iter, const char *error, + void *user_data) +{ + char *path = user_data; + + if (!error) { + char *str = strrchr(path, '/'); + str++; + fprintf(stdout, "Scan completed for %s\n", str); + } else + fprintf(stderr, "Error %s: %s\n", path, error); + + g_free(user_data); + + return 0; +} + +static int cmd_scan(char *args[], int num, struct connman_option *options) +{ + char *path; + + if (num > 2) + return -E2BIG; + + if (num < 2) + return -EINVAL; + + if (check_dbus_name(args[1]) == false) + return -EINVAL; + + path = g_strdup_printf("/net/connman/technology/%s", args[1]); + return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path, + "net.connman.Technology", "Scan", + scan_return, path, NULL, NULL); +} + +static int connect_return(DBusMessageIter *iter, const char *error, + void *user_data) +{ + char *path = user_data; + + if (!error) { + char *str = strrchr(path, '/'); + str++; + fprintf(stdout, "Connected %s\n", str); + } else + fprintf(stderr, "Error %s: %s\n", path, error); + + g_free(user_data); + + return 0; +} + +static int cmd_connect(char *args[], int num, struct connman_option *options) +{ + const char *iface = "net.connman.Service"; + char *path; + + if (num > 2) + return -E2BIG; + + if (num < 2) + return -EINVAL; + + if (check_dbus_name(args[1]) == false) + return -EINVAL; + + if (g_strstr_len(args[1], 5, "peer_") == args[1]) { + iface = "net.connman.Peer"; + path = g_strdup_printf("/net/connman/peer/%s", args[1]); + } else + path = g_strdup_printf("/net/connman/service/%s", args[1]); + + return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path, + iface, "Connect", connect_return, path, NULL, NULL); +} + +static int disconnect_return(DBusMessageIter *iter, const char *error, + void *user_data) +{ + char *path = user_data; + + if (!error) { + char *str = strrchr(path, '/'); + str++; + fprintf(stdout, "Disconnected %s\n", str); + } else + fprintf(stderr, "Error %s: %s\n", path, error); + + g_free(user_data); + + return 0; +} + +static int cmd_disconnect(char *args[], int num, struct connman_option *options) +{ + const char *iface = "net.connman.Service"; + char *path; + + if (num > 2) + return -E2BIG; + + if (num < 2) + return -EINVAL; + + if (check_dbus_name(args[1]) == false) + return -EINVAL; + + if (g_strstr_len(args[1], 5, "peer_") == args[1]) { + iface = "net.connman.Peer"; + path = g_strdup_printf("/net/connman/peer/%s", args[1]); + } else + path = g_strdup_printf("/net/connman/service/%s", args[1]); + + return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, + path, iface, "Disconnect", + disconnect_return, path, NULL, NULL); +} + +static int config_return(DBusMessageIter *iter, const char *error, + void *user_data) +{ + char *service_name = user_data; + + if (error) + fprintf(stderr, "Error %s: %s\n", service_name, error); + + g_free(user_data); + + return 0; +} + +struct config_append { + char **opts; + int values; +}; + +static void config_append_ipv4(DBusMessageIter *iter, + void *user_data) +{ + struct config_append *append = user_data; + char **opts = append->opts; + int i = 0; + + if (!opts) + return; + + while (opts[i] && ipv4[i]) { + __connmanctl_dbus_append_dict_entry(iter, ipv4[i], + DBUS_TYPE_STRING, &opts[i]); + i++; + } + + append->values = i; +} + +static void config_append_ipv6(DBusMessageIter *iter, void *user_data) +{ + struct config_append *append = user_data; + char **opts = append->opts; + + if (!opts) + return; + + append->values = 1; + + if (g_strcmp0(opts[0], "auto") == 0) { + char *str; + + switch (parse_boolean(opts[1])) { + case 0: + append->values = 2; + + str = "disabled"; + __connmanctl_dbus_append_dict_entry(iter, "Privacy", + DBUS_TYPE_STRING, &str); + break; + + case 1: + append->values = 2; + + str = "enabled"; + __connmanctl_dbus_append_dict_entry(iter, "Privacy", + DBUS_TYPE_STRING, &str); + break; + + default: + if (opts[1]) { + append->values = 2; + + if (g_strcmp0(opts[1], "prefered") != 0 && + g_strcmp0(opts[1], + "preferred") != 0) { + fprintf(stderr, "Error %s: %s\n", + opts[1], + strerror(EINVAL)); + return; + } + + str = "prefered"; + __connmanctl_dbus_append_dict_entry(iter, + "Privacy", DBUS_TYPE_STRING, + &str); + } + break; + } + } else if (g_strcmp0(opts[0], "manual") == 0) { + int i = 1; + + while (opts[i] && ipv6[i]) { + if (i == 2) { + int value = atoi(opts[i]); + __connmanctl_dbus_append_dict_entry(iter, + ipv6[i], DBUS_TYPE_BYTE, + &value); + } else { + __connmanctl_dbus_append_dict_entry(iter, + ipv6[i], DBUS_TYPE_STRING, + &opts[i]); + } + i++; + } + + append->values = i; + + } else if (g_strcmp0(opts[0], "off") != 0) { + fprintf(stderr, "Error %s: %s\n", opts[0], strerror(EINVAL)); + + return; + } + + __connmanctl_dbus_append_dict_entry(iter, "Method", DBUS_TYPE_STRING, + &opts[0]); +} + +static void config_append_str(DBusMessageIter *iter, void *user_data) +{ + struct config_append *append = user_data; + char **opts = append->opts; + int i = 0; + + if (!opts) + return; + + while (opts[i]) { + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, + &opts[i]); + i++; + } + + append->values = i; +} + +static void append_servers(DBusMessageIter *iter, void *user_data) +{ + struct config_append *append = user_data; + char **opts = append->opts; + int i = 1; + + if (!opts) + return; + + while (opts[i] && g_strcmp0(opts[i], "--excludes") != 0) { + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, + &opts[i]); + i++; + } + + append->values = i; +} + +static void append_excludes(DBusMessageIter *iter, void *user_data) +{ + struct config_append *append = user_data; + char **opts = append->opts; + int i = append->values; + + if (!opts || !opts[i] || + g_strcmp0(opts[i], "--excludes") != 0) + return; + + i++; + while (opts[i]) { + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, + &opts[i]); + i++; + } + + append->values = i; +} + +static void config_append_proxy(DBusMessageIter *iter, void *user_data) +{ + struct config_append *append = user_data; + char **opts = append->opts; + + if (!opts) + return; + + if (g_strcmp0(opts[0], "manual") == 0) { + __connmanctl_dbus_append_dict_string_array(iter, "Servers", + append_servers, append); + + __connmanctl_dbus_append_dict_string_array(iter, "Excludes", + append_excludes, append); + + } else if (g_strcmp0(opts[0], "auto") == 0) { + if (opts[1]) { + __connmanctl_dbus_append_dict_entry(iter, "URL", + DBUS_TYPE_STRING, &opts[1]); + append->values++; + } + + } else if (g_strcmp0(opts[0], "direct") != 0) + return; + + __connmanctl_dbus_append_dict_entry(iter, "Method",DBUS_TYPE_STRING, + &opts[0]); + + append->values++; +} + +static int cmd_config(char *args[], int num, struct connman_option *options) +{ + int result = 0, res = 0, index = 2, oldindex = 0; + int c; + char *service_name, *path; + char **opt_start; + dbus_bool_t val; + struct config_append append; + + service_name = args[1]; + if (!service_name) + return -EINVAL; + + if (check_dbus_name(service_name) == false) + return -EINVAL; + + while (index < num && args[index]) { + c = parse_args(args[index], options); + opt_start = &args[index + 1]; + append.opts = opt_start; + append.values = 0; + + res = 0; + + oldindex = index; + path = g_strdup_printf("/net/connman/service/%s", service_name); + + switch (c) { + case 'a': + switch (parse_boolean(*opt_start)) { + case 1: + val = TRUE; + break; + case 0: + val = FALSE; + break; + default: + res = -EINVAL; + break; + } + + index++; + + if (res == 0) { + res = __connmanctl_dbus_set_property(connection, + path, "net.connman.Service", + config_return, + g_strdup(service_name), + "AutoConnect", + DBUS_TYPE_BOOLEAN, &val); + } + break; + case 'i': + res = __connmanctl_dbus_set_property_dict(connection, + path, "net.connman.Service", + config_return, g_strdup(service_name), + "IPv4.Configuration", DBUS_TYPE_STRING, + config_append_ipv4, &append); + index += append.values; + break; + + case 'v': + res = __connmanctl_dbus_set_property_dict(connection, + path, "net.connman.Service", + config_return, g_strdup(service_name), + "IPv6.Configuration", DBUS_TYPE_STRING, + config_append_ipv6, &append); + index += append.values; + break; + + case 'n': + res = __connmanctl_dbus_set_property_array(connection, + path, "net.connman.Service", + config_return, g_strdup(service_name), + "Nameservers.Configuration", + DBUS_TYPE_STRING, config_append_str, + &append); + index += append.values; + break; + + case 't': + res = __connmanctl_dbus_set_property_array(connection, + path, "net.connman.Service", + config_return, g_strdup(service_name), + "Timeservers.Configuration", + DBUS_TYPE_STRING, config_append_str, + &append); + index += append.values; + break; + + case 'd': + res = __connmanctl_dbus_set_property_array(connection, + path, "net.connman.Service", + config_return, g_strdup(service_name), + "Domains.Configuration", + DBUS_TYPE_STRING, config_append_str, + &append); + index += append.values; + break; + + case 'x': + res = __connmanctl_dbus_set_property_dict(connection, + path, "net.connman.Service", + config_return, g_strdup(service_name), + "Proxy.Configuration", + DBUS_TYPE_STRING, config_append_proxy, + &append); + index += append.values; + break; + case 'r': + res = __connmanctl_dbus_method_call(connection, + CONNMAN_SERVICE, path, + "net.connman.Service", "Remove", + config_return, g_strdup(service_name), + NULL, NULL); + break; + default: + res = -EINVAL; + break; + } + + g_free(path); + + if (res < 0) { + if (res == -EINPROGRESS) + result = -EINPROGRESS; + else + printf("Error '%s': %s\n", args[oldindex], + strerror(-res)); + } else + index += res; + + index++; + } + + return result; +} + +static DBusHandlerResult monitor_changed(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + DBusMessageIter iter; + const char *interface, *path; + + interface = dbus_message_get_interface(message); + if (!interface) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (strncmp(interface, "net.connman.", 12) != 0) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (!strcmp(interface, "net.connman.Agent") || + !strcmp(interface, "net.connman.vpn.Agent") || + !strcmp(interface, "net.connman.Session") || + !strcmp(interface, "net.connman.Notification")) + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + interface = strrchr(interface, '.'); + if (interface && *interface != '\0') + interface++; + + path = strrchr(dbus_message_get_path(message), '/'); + if (path && *path != '\0') + path++; + + __connmanctl_save_rl(); + + if (dbus_message_is_signal(message, "net.connman.Manager", + "ServicesChanged")) { + + fprintf(stdout, "%-12s %-20s = {\n", interface, + "ServicesChanged"); + dbus_message_iter_init(message, &iter); + __connmanctl_services_list(&iter); + fprintf(stdout, "\n}\n"); + + __connmanctl_redraw_rl(); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } else if (dbus_message_is_signal(message, "net.connman.Manager", + "PeersChanged")) { + fprintf(stdout, "%-12s %-20s = {\n", interface, + "PeersChanged"); + dbus_message_iter_init(message, &iter); + __connmanctl_peers_list(&iter); + fprintf(stdout, "\n}\n"); + + __connmanctl_redraw_rl(); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } else if (dbus_message_is_signal(message, "net.connman.vpn.Manager", + "ConnectionAdded") || + dbus_message_is_signal(message, + "net.connman.vpn.Manager", + "ConnectionRemoved")) { + interface = "vpn.Manager"; + path = dbus_message_get_member(message); + + } else if (dbus_message_is_signal(message, "net.connman.Manager", + "TechnologyAdded") || + dbus_message_is_signal(message, "net.connman.Manager", + "TechnologyRemoved")) + path = dbus_message_get_member(message); + + fprintf(stdout, "%-12s %-20s ", interface, path); + dbus_message_iter_init(message, &iter); + + __connmanctl_dbus_print(&iter, "", " = ", " = "); + fprintf(stdout, "\n"); + + __connmanctl_redraw_rl(); + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static struct { + char *interface; + bool enabled; +} monitor[] = { + { "Service", false }, + { "Technology", false }, + { "Manager", false }, + { "vpn.Manager", false }, + { "vpn.Connection", false }, + { NULL, }, +}; + +static void monitor_add(char *interface) +{ + bool add_filter = true, found = false; + int i; + char *rule; + DBusError err; + + for (i = 0; monitor[i].interface; i++) { + if (monitor[i].enabled == true) + add_filter = false; + + if (g_strcmp0(interface, monitor[i].interface) == 0) { + if (monitor[i].enabled == true) + return; + + monitor[i].enabled = true; + found = true; + } + } + + if (found == false) + return; + + if (add_filter == true) + dbus_connection_add_filter(connection, monitor_changed, + NULL, NULL); + + dbus_error_init(&err); + rule = g_strdup_printf("type='signal',interface='net.connman.%s'", + interface); + dbus_bus_add_match(connection, rule, &err); + g_free(rule); + + if (dbus_error_is_set(&err)) + fprintf(stderr, "Error: %s\n", err.message); +} + +static void monitor_del(char *interface) +{ + bool del_filter = true, found = false; + int i; + char *rule; + + + for (i = 0; monitor[i].interface; i++) { + if (g_strcmp0(interface, monitor[i].interface) == 0) { + if (monitor[i].enabled == false) + return; + + monitor[i].enabled = false; + found = true; + } + + if (monitor[i].enabled == true) + del_filter = false; + } + + if (found == false) + return; + + rule = g_strdup_printf("type='signal',interface='net.connman.%s'", + interface); + dbus_bus_remove_match(connection, rule, NULL); + g_free(rule); + + if (del_filter == true) + dbus_connection_remove_filter(connection, monitor_changed, + NULL); +} + +static int cmd_monitor(char *args[], int num, struct connman_option *options) +{ + bool add = true; + int c; + + if (num > 3) + return -E2BIG; + + if (num == 3) { + switch (parse_boolean(args[2])) { + case 0: + add = false; + break; + + default: + break; + } + } + + c = parse_args(args[1], options); + switch (c) { + case -1: + monitor_add("Service"); + monitor_add("Technology"); + monitor_add("Manager"); + monitor_add("vpn.Manager"); + monitor_add("vpn.Connection"); + break; + + case 's': + if (add == true) + monitor_add("Service"); + else + monitor_del("Service"); + break; + + case 'c': + if (add == true) + monitor_add("Technology"); + else + monitor_del("Technology"); + break; + + case 'm': + if (add == true) + monitor_add("Manager"); + else + monitor_del("Manager"); + break; + + case 'M': + if (add == true) + monitor_add("vpn.Manager"); + else + monitor_del("vpn.Manager"); + break; + + case 'C': + if (add == true) + monitor_add("vpn.Connection"); + else + monitor_del("vpn.Connection"); + break; + + default: + switch(parse_boolean(args[1])) { + case 0: + monitor_del("Service"); + monitor_del("Technology"); + monitor_del("Manager"); + monitor_del("vpn.Manager"); + monitor_del("vpn.Connection"); + break; + + case 1: + monitor_add("Service"); + monitor_add("Technology"); + monitor_add("Manager"); + monitor_add("vpn.Manager"); + monitor_add("vpn.Connection"); + break; + + default: + return -EINVAL; + } + } + + if (add == true) + return -EINPROGRESS; + + return 0; +} + +static int cmd_agent(char *args[], int num, struct connman_option *options) +{ + if (!__connmanctl_is_interactive()) { + fprintf(stderr, "Error: Not supported in non-interactive " + "mode\n"); + return 0; + } + + if (num > 2) + return -E2BIG; + + if (num < 2) + return -EINVAL; + + switch(parse_boolean(args[1])) { + case 0: + __connmanctl_agent_unregister(connection); + break; + + case 1: + if (__connmanctl_agent_register(connection) == -EINPROGRESS) + return -EINPROGRESS; + + break; + + default: + return -EINVAL; + break; + } + + return 0; +} + +static int vpnconnections_properties(DBusMessageIter *iter, const char *error, + void *user_data) +{ + char *path = user_data; + char *str; + DBusMessageIter dict; + + if (!error) { + fprintf(stdout, "%s\n", path); + + dbus_message_iter_recurse(iter, &dict); + __connmanctl_dbus_print(&dict, " ", " = ", "\n"); + + fprintf(stdout, "\n"); + + } else { + str = strrchr(path, '/'); + if (str) + str++; + else + str = path; + + fprintf(stderr, "Error %s: %s\n", str, error); + } + + g_free(user_data); + + return 0; +} + +static int vpnconnections_list(DBusMessageIter *iter, const char *error, + void *user_data) +{ + if (!error) + __connmanctl_vpnconnections_list(iter); + else + fprintf(stderr, "Error: %s\n", error); + + return 0; +} + +static int cmd_vpnconnections(char *args[], int num, + struct connman_option *options) +{ + char *vpnconnection_name, *path; + + if (num > 2) + return -E2BIG; + + vpnconnection_name = args[1]; + + if (!vpnconnection_name) + return __connmanctl_dbus_method_call(connection, + VPN_SERVICE, VPN_PATH, + "net.connman.vpn.Manager", "GetConnections", + vpnconnections_list, NULL, + NULL, NULL); + + if (check_dbus_name(vpnconnection_name) == false) + return -EINVAL; + + path = g_strdup_printf("/net/connman/vpn/connection/%s", + vpnconnection_name); + return __connmanctl_dbus_method_call(connection, VPN_SERVICE, path, + "net.connman.vpn.Connection", "GetProperties", + vpnconnections_properties, path, NULL, NULL); + +} + +static int cmd_vpnagent(char *args[], int num, struct connman_option *options) +{ + if (!__connmanctl_is_interactive()) { + fprintf(stderr, "Error: Not supported in non-interactive " + "mode\n"); + return 0; + } + + if (num > 2) + return -E2BIG; + + if (num < 2) + return -EINVAL; + + switch(parse_boolean(args[1])) { + case 0: + __connmanctl_vpn_agent_unregister(connection); + break; + + case 1: + if (__connmanctl_vpn_agent_register(connection) == + -EINPROGRESS) + return -EINPROGRESS; + + break; + + default: + return -EINVAL; + break; + } + + return 0; +} + +static DBusMessage *session_release(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + __connmanctl_save_rl(); + + fprintf(stdout, "Session %s released\n", session_path); + + __connmanctl_redraw_rl(); + + g_free(session_path); + session_path = NULL; + session_connected = false; + + return g_dbus_create_reply(message, DBUS_TYPE_INVALID); +} + +static DBusMessage *session_update(DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + DBusMessageIter iter, dict; + + __connmanctl_save_rl(); + + fprintf(stdout, "Session Update = {\n"); + + dbus_message_iter_init(message, &iter); + dbus_message_iter_recurse(&iter, &dict); + + __connmanctl_dbus_print(&dict, "", " = ", "\n"); + fprintf(stdout, "\n}\n"); + + dbus_message_iter_recurse(&iter, &dict); + + while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { + DBusMessageIter entry, variant; + char *field, *state; + + dbus_message_iter_recurse(&dict, &entry); + + dbus_message_iter_get_basic(&entry, &field); + + if (dbus_message_iter_get_arg_type(&entry) + == DBUS_TYPE_STRING + && !strcmp(field, "State")) { + + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &variant); + if (dbus_message_iter_get_arg_type(&variant) + != DBUS_TYPE_STRING) + break; + + dbus_message_iter_get_basic(&variant, &state); + + if (!session_connected && (!strcmp(state, "connected") + || !strcmp(state, "online"))) { + + fprintf(stdout, "Session %s connected\n", + session_path); + session_connected = true; + + break; + } + + if (!strcmp(state, "disconnected") && + session_connected) { + + fprintf(stdout, "Session %s disconnected\n", + session_path); + session_connected = false; + } + break; + } + + dbus_message_iter_next(&dict); + } + + __connmanctl_redraw_rl(); + + return g_dbus_create_reply(message, DBUS_TYPE_INVALID); +} + +static const GDBusMethodTable notification_methods[] = { + { GDBUS_METHOD("Release", NULL, NULL, session_release) }, + { GDBUS_METHOD("Update", GDBUS_ARGS({"settings", "a{sv}"}), + NULL, session_update) }, + { }, +}; + +static int session_notify_add(const char *path) +{ + if (session_notify_path) + return 0; + + if (!g_dbus_register_interface(connection, path, + "net.connman.Notification", + notification_methods, NULL, NULL, + NULL, NULL)) { + fprintf(stderr, "Error: Failed to register VPN Agent " + "callbacks\n"); + return -EIO; + } + + session_notify_path = g_strdup(path); + + return 0; +} + +static void session_notify_remove(void) +{ + if (!session_notify_path) + return; + + g_dbus_unregister_interface(connection, session_notify_path, + "net.connman.Notification"); + + g_free(session_notify_path); + session_notify_path = NULL; +} + +static int session_connect_cb(DBusMessageIter *iter, const char *error, + void *user_data) +{ + if (error) { + fprintf(stderr, "Error: %s", error); + return 0; + } + + return -EINPROGRESS; +} + + +static int session_connect(void) +{ + return __connmanctl_dbus_method_call(connection, "net.connman", + session_path, "net.connman.Session", "Connect", + session_connect_cb, NULL, NULL, NULL); +} + +static int session_disconnect_cb(DBusMessageIter *iter, const char *error, + void *user_data) +{ + if (error) + fprintf(stderr, "Error: %s", error); + + return 0; +} + +static int session_disconnect(void) +{ + return __connmanctl_dbus_method_call(connection, "net.connman", + session_path, "net.connman.Session", "Disconnect", + session_disconnect_cb, NULL, NULL, NULL); +} + +static int session_create_cb(DBusMessageIter *iter, const char *error, + void *user_data) +{ + gboolean connect = GPOINTER_TO_INT(user_data); + char *str; + + if (error) { + fprintf(stderr, "Error creating session: %s", error); + session_notify_remove(); + return 0; + } + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH) { + fprintf(stderr, "Error creating session: No session path\n"); + return -EINVAL; + } + + g_free(session_path); + + dbus_message_iter_get_basic(iter, &str); + session_path = g_strdup(str); + + fprintf(stdout, "Session %s created\n", session_path); + + if (connect) + return session_connect(); + + return -EINPROGRESS; +} + +static void session_create_append(DBusMessageIter *iter, void *user_data) +{ + const char *notify_path = user_data; + + __connmanctl_dbus_append_dict(iter, NULL, NULL); + + dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, + ¬ify_path); +} + +static int session_create(gboolean connect) +{ + int res; + char *notify_path; + + notify_path = g_strdup_printf("/net/connman/connmanctl%d", getpid()); + session_notify_add(notify_path); + + res = __connmanctl_dbus_method_call(connection, "net.connman", "/", + "net.connman.Manager", "CreateSession", + session_create_cb, GINT_TO_POINTER(connect), + session_create_append, notify_path); + + g_free(notify_path); + + if (res < 0 && res != -EINPROGRESS) + session_notify_remove(); + + return res; +} + +static int session_destroy_cb(DBusMessageIter *iter, const char *error, + void *user_data) +{ + if (error) { + fprintf(stderr, "Error destroying session: %s", error); + return 0; + } + + fprintf(stdout, "Session %s ended\n", session_path); + + g_free(session_path); + session_path = NULL; + session_connected = false; + + return 0; +} + +static void session_destroy_append(DBusMessageIter *iter, void *user_data) +{ + const char *path = user_data; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path); +} + +static int session_destroy(void) +{ + return __connmanctl_dbus_method_call(connection, "net.connman", "/", + "net.connman.Manager", "DestroySession", + session_destroy_cb, NULL, + session_destroy_append, session_path); +} + +static int session_config_return(DBusMessageIter *iter, const char *error, + void *user_data) +{ + char *property_name = user_data; + + if (error) + fprintf(stderr, "Error setting session %s: %s\n", + property_name, error); + + return 0; +} + +static void session_config_append_array(DBusMessageIter *iter, + void *user_data) +{ + struct config_append *append = user_data; + char **opts = append->opts; + int i = 1; + + if (!opts) + return; + + while (opts[i] && strncmp(opts[i], "--", 2) != 0) { + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, + &opts[i]); + i++; + } + + append->values = i; +} + +static int session_config(char *args[], int num, + struct connman_option *options) +{ + int index = 0, res = 0; + struct config_append append; + char c; + + while (index < num && args[index]) { + append.opts = &args[index]; + append.values = 0; + + c = parse_args(args[index], options); + + switch (c) { + case 'b': + res = __connmanctl_dbus_session_change_array(connection, + session_path, session_config_return, + "AllowedBearers", "AllowedBearers", + session_config_append_array, &append); + break; + case 't': + if (!args[index + 1]) { + res = -EINVAL; + break; + } + + res = __connmanctl_dbus_session_change(connection, + session_path, session_config_return, + "ConnectionType", "ConnectionType", + DBUS_TYPE_STRING, &args[index + 1]); + append.values = 2; + break; + + default: + res = -EINVAL; + } + + if (res < 0 && res != -EINPROGRESS) { + printf("Error '%s': %s\n", args[index], + strerror(-res)); + return 0; + } + + index += append.values; + } + + return 0; +} + +static int cmd_session(char *args[], int num, struct connman_option *options) +{ + char *command; + + if (num < 2) + return -EINVAL; + + command = args[1]; + + switch(parse_boolean(command)) { + case 0: + if (!session_path) + return -EALREADY; + return session_destroy(); + + case 1: + if (session_path) + return -EALREADY; + return session_create(FALSE); + + default: + if (!strcmp(command, "connect")) { + if (!session_path) + return session_create(TRUE); + + return session_connect(); + + } else if (!strcmp(command, "disconnect")) { + + if (!session_path) { + fprintf(stdout, "Session does not exist\n"); + return 0; + } + + return session_disconnect(); + } else if (!strcmp(command, "config")) { + if (!session_path) { + fprintf(stdout, "Session does not exist\n"); + return 0; + } + + if (num == 2) + return -EINVAL; + + return session_config(&args[2], num - 2, options); + } + + } + + return -EINVAL; +} + +static int cmd_exit(char *args[], int num, struct connman_option *options) +{ + return 1; +} + +static char *lookup_service(const char *text, int state) +{ + static int len = 0; + static GHashTableIter iter; + gpointer key, value; + + if (state == 0) { + g_hash_table_iter_init(&iter, service_hash); + len = strlen(text); + } + + while (g_hash_table_iter_next(&iter, &key, &value)) { + const char *service = key; + if (strncmp(text, service, len) == 0) + return strdup(service); + } + + return NULL; +} + +static char *lookup_service_arg(const char *text, int state) +{ + if (__connmanctl_input_calc_level() > 1) { + __connmanctl_input_lookup_end(); + return NULL; + } + + return lookup_service(text, state); +} + +static char *lookup_peer(const char *text, int state) +{ + static GHashTableIter iter; + gpointer key, value; + static int len = 0; + + if (state == 0) { + g_hash_table_iter_init(&iter, peer_hash); + len = strlen(text); + } + + while (g_hash_table_iter_next(&iter, &key, &value)) { + const char *peer = key; + if (strncmp(text, peer, len) == 0) + return strdup(peer); + } + + return NULL; +} + +static char *lookup_peer_arg(const char *text, int state) +{ + if (__connmanctl_input_calc_level() > 1) { + __connmanctl_input_lookup_end(); + return NULL; + } + + return lookup_peer(text, state); +} + +static char *lookup_technology(const char *text, int state) +{ + static int len = 0; + static GHashTableIter iter; + gpointer key, value; + + if (state == 0) { + g_hash_table_iter_init(&iter, technology_hash); + len = strlen(text); + } + + while (g_hash_table_iter_next(&iter, &key, &value)) { + const char *technology = key; + if (strncmp(text, technology, len) == 0) + return strdup(technology); + } + + return NULL; +} + +static char *lookup_technology_arg(const char *text, int state) +{ + if (__connmanctl_input_calc_level() > 1) { + __connmanctl_input_lookup_end(); + return NULL; + } + + return lookup_technology(text, state); +} + +static char *lookup_technology_offline(const char *text, int state) +{ + static int len = 0; + static bool end = false; + char *str; + + if (__connmanctl_input_calc_level() > 1) { + __connmanctl_input_lookup_end(); + return NULL; + } + + if (state == 0) { + len = strlen(text); + end = false; + } + + if (end) + return NULL; + + str = lookup_technology(text, state); + if (str) + return str; + + end = true; + + if (strncmp(text, "offline", len) == 0) + return strdup("offline"); + + return NULL; +} + +static char *lookup_on_off(const char *text, int state) +{ + char *onoff[] = { "on", "off", NULL }; + static int idx = 0; + static int len = 0; + + char *str; + + if (!state) { + idx = 0; + len = strlen(text); + } + + while (onoff[idx]) { + str = onoff[idx]; + idx++; + + if (!strncmp(text, str, len)) + return strdup(str); + } + + return NULL; +} + +static char *lookup_tether(const char *text, int state) +{ + int level; + + level = __connmanctl_input_calc_level(); + if (level < 2) + return lookup_technology(text, state); + + if (level == 2) + return lookup_on_off(text, state); + + __connmanctl_input_lookup_end(); + + return NULL; +} + +static char *lookup_agent(const char *text, int state) +{ + if (__connmanctl_input_calc_level() > 1) { + __connmanctl_input_lookup_end(); + return NULL; + } + + return lookup_on_off(text, state); +} + +static struct connman_option service_options[] = { + {"properties", 'p', "[] (obsolete)"}, + { NULL, } +}; + +static struct connman_option config_options[] = { + {"nameservers", 'n', " [] []"}, + {"timeservers", 't', " [] [...]"}, + {"domains", 'd', " [] [...]"}, + {"ipv6", 'v', "off|auto [enable|disable|preferred]|\n" + "\t\t\tmanual
"}, + {"proxy", 'x', "direct|auto |manual [] [...]\n" + "\t\t\t[exclude [] [...]]"}, + {"autoconnect", 'a', "yes|no"}, + {"ipv4", 'i', "off|dhcp|manual
"}, + {"remove", 'r', " Remove service"}, + { NULL, } +}; + +static struct connman_option monitor_options[] = { + {"services", 's', "[off] Monitor only services"}, + {"tech", 'c', "[off] Monitor only technologies"}, + {"manager", 'm', "[off] Monitor only manager interface"}, + {"vpnmanager", 'M', "[off] Monitor only VPN manager " + "interface"}, + {"vpnconnection", 'C', "[off] Monitor only VPN " + "connections" }, + { NULL, } +}; + +static struct connman_option session_options[] = { + {"bearers", 'b', " [ [...]]"}, + {"type", 't', "local|internet|any"}, + { NULL, } +}; + +static char *lookup_options(struct connman_option *options, const char *text, + int state) +{ + static int idx = 0; + static int len = 0; + const char *str; + + if (state == 0) { + idx = 0; + len = strlen(text); + } + + while (options[idx].name) { + str = options[idx].name; + idx++; + + if (str && strncmp(text, str, len) == 0) + return strdup(str); + } + + return NULL; +} + +static char *lookup_monitor(const char *text, int state) +{ + int level; + + level = __connmanctl_input_calc_level(); + + if (level < 2) + return lookup_options(monitor_options, text, state); + + if (level == 2) + return lookup_on_off(text, state); + + __connmanctl_input_lookup_end(); + return NULL; +} + +static char *lookup_config(const char *text, int state) +{ + if (__connmanctl_input_calc_level() < 2) + return lookup_service(text, state); + + return lookup_options(config_options, text, state); +} + +static char *lookup_session(const char *text, int state) +{ + return lookup_options(session_options, text, state); +} + +static int peer_service_cb(DBusMessageIter *iter, const char *error, + void *user_data) +{ + bool registration = GPOINTER_TO_INT(user_data); + + if (error) + fprintf(stderr, "Error %s peer service: %s\n", + registration ? "registering" : "unregistering", error); + else + fprintf(stdout, "Peer service %s\n", + registration ? "registered" : "unregistered"); + + return 0; +} + +struct _peer_service { + unsigned char *bjr_query; + int bjr_query_len; + unsigned char *bjr_response; + int bjr_response_len; + unsigned char *wfd_ies; + int wfd_ies_len; + char *upnp_service; + int version; + int master; +}; + +static void append_dict_entry_fixed_array(DBusMessageIter *iter, + const char *property, void *value, int length) +{ + DBusMessageIter dict_entry, variant, array; + + dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, + NULL, &dict_entry); + dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING, + &property); + dbus_message_iter_open_container(&dict_entry, DBUS_TYPE_VARIANT, + DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING, + &variant); + dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, + DBUS_TYPE_BYTE_AS_STRING, &array); + dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE, + value, length); + dbus_message_iter_close_container(&variant, &array); + dbus_message_iter_close_container(&dict_entry, &variant); + dbus_message_iter_close_container(iter, &dict_entry); +} + +static void append_peer_service_dict(DBusMessageIter *iter, void *user_data) +{ + struct _peer_service *service = user_data; + + if (service->bjr_query && service->bjr_response) { + append_dict_entry_fixed_array(iter, "BonjourQuery", + &service->bjr_query, service->bjr_query_len); + append_dict_entry_fixed_array(iter, "BonjourResponse", + &service->bjr_response, service->bjr_response_len); + } else if (service->upnp_service && service->version) { + __connmanctl_dbus_append_dict_entry(iter, "UpnpVersion", + DBUS_TYPE_INT32, &service->version); + __connmanctl_dbus_append_dict_entry(iter, "UpnpService", + DBUS_TYPE_STRING, &service->upnp_service); + } else if (service->wfd_ies) { + append_dict_entry_fixed_array(iter, "WiFiDisplayIEs", + &service->wfd_ies, service->wfd_ies_len); + } +} + +static void peer_service_append(DBusMessageIter *iter, void *user_data) +{ + struct _peer_service *service = user_data; + dbus_bool_t master; + + __connmanctl_dbus_append_dict(iter, append_peer_service_dict, service); + + if (service->master < 0) + return; + + master = service->master == 1 ? TRUE : FALSE; + dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &master); +} + +static struct _peer_service *fill_in_peer_service(unsigned char *bjr_query, + int bjr_query_len, unsigned char *bjr_response, + int bjr_response_len, char *upnp_service, + int version, unsigned char *wfd_ies, + int wfd_ies_len) +{ + struct _peer_service *service; + + service = dbus_malloc0(sizeof(*service)); + + if (bjr_query_len && bjr_response_len) { + service->bjr_query = dbus_malloc0(bjr_query_len); + memcpy(service->bjr_query, bjr_query, bjr_query_len); + service->bjr_query_len = bjr_query_len; + + service->bjr_response = dbus_malloc0(bjr_response_len); + memcpy(service->bjr_response, bjr_response, bjr_response_len); + service->bjr_response_len = bjr_response_len; + } else if (upnp_service && version) { + service->upnp_service = strdup(upnp_service); + service->version = version; + } else if (wfd_ies && wfd_ies_len) { + service->wfd_ies = dbus_malloc0(wfd_ies_len); + memcpy(service->wfd_ies, wfd_ies, wfd_ies_len); + service->wfd_ies_len = wfd_ies_len; + } else { + dbus_free(service); + service = NULL; + } + + return service; +} + +static void free_peer_service(struct _peer_service *service) +{ + dbus_free(service->bjr_query); + dbus_free(service->bjr_response); + dbus_free(service->wfd_ies); + free(service->upnp_service); + dbus_free(service); +} + +static int peer_service_register(unsigned char *bjr_query, int bjr_query_len, + unsigned char *bjr_response, int bjr_response_len, + char *upnp_service, int version, + unsigned char *wfd_ies, int wfd_ies_len, int master) +{ + struct _peer_service *service; + bool registration = true; + int ret; + + service = fill_in_peer_service(bjr_query, bjr_query_len, bjr_response, + bjr_response_len, upnp_service, version, + wfd_ies, wfd_ies_len); + if (!service) + return -EINVAL; + + service->master = master; + + ret = __connmanctl_dbus_method_call(connection, "net.connman", "/", + "net.connman.Manager", "RegisterPeerService", + peer_service_cb, GINT_TO_POINTER(registration), + peer_service_append, service); + + free_peer_service(service); + + return ret; +} + +static int peer_service_unregister(unsigned char *bjr_query, int bjr_query_len, + unsigned char *bjr_response, int bjr_response_len, + char *upnp_service, int version, + unsigned char *wfd_ies, int wfd_ies_len) +{ + struct _peer_service *service; + bool registration = false; + int ret; + + service = fill_in_peer_service(bjr_query, bjr_query_len, bjr_response, + bjr_response_len, upnp_service, version, + wfd_ies, wfd_ies_len); + if (!service) + return -EINVAL; + + service->master = -1; + + ret = __connmanctl_dbus_method_call(connection, "net.connman", "/", + "net.connman.Manager", "UnregisterPeerService", + peer_service_cb, GINT_TO_POINTER(registration), + peer_service_append, service); + + free_peer_service(service); + + return ret; +} + +static int parse_spec_array(char *command, unsigned char spec[1024]) +{ + int length, pos, end; + char b[3] = {}; + char *e; + + end = strlen(command); + for (e = NULL, length = pos = 0; command[pos] != '\0'; length++) { + if (pos+2 > end) + return -EINVAL; + + b[0] = command[pos]; + b[1] = command[pos+1]; + + spec[length] = strtol(b, &e, 16); + if (e && *e != '\0') + return -EINVAL; + + pos += 2; + } + + return length; +} + +static int cmd_peer_service(char *args[], int num, + struct connman_option *options) +{ + unsigned char bjr_query[1024] = {}; + unsigned char bjr_response[1024] = {}; + unsigned char wfd_ies[1024] = {}; + char *upnp_service = NULL; + int bjr_query_len = 0, bjr_response_len = 0; + int version = 0, master = 0, wfd_ies_len = 0; + int limit; + + if (num < 4) + return -EINVAL; + + if (!strcmp(args[2], "wfd_ies")) { + wfd_ies_len = parse_spec_array(args[3], wfd_ies); + if (wfd_ies_len == -EINVAL) + return -EINVAL; + limit = 5; + goto master; + } + + if (num < 6) + return -EINVAL; + + limit = 7; + if (!strcmp(args[2], "bjr_query")) { + if (strcmp(args[4], "bjr_response")) + return -EINVAL; + bjr_query_len = parse_spec_array(args[3], bjr_query); + bjr_response_len = parse_spec_array(args[5], bjr_response); + + if (bjr_query_len == -EINVAL || bjr_response_len == -EINVAL) + return -EINVAL; + } else if (!strcmp(args[2], "upnp_service")) { + char *e = NULL; + + if (strcmp(args[4], "upnp_version")) + return -EINVAL; + upnp_service = args[3]; + version = strtol(args[5], &e, 10); + if (*e != '\0') + return -EINVAL; + } + +master: + if (num == limit) { + master = parse_boolean(args[6]); + if (master < 0) + return -EINVAL; + } + + if (!strcmp(args[1], "register")) { + return peer_service_register(bjr_query, bjr_query_len, + bjr_response, bjr_response_len, upnp_service, + version, wfd_ies, wfd_ies_len, master); + } else if (!strcmp(args[1], "unregister")) { + return peer_service_unregister(bjr_query, bjr_query_len, + bjr_response, bjr_response_len, upnp_service, + version, wfd_ies, wfd_ies_len); + } + + return -EINVAL; +} + +static const struct { + const char *cmd; + const char *argument; + struct connman_option *options; + int (*func) (char *args[], int num, struct connman_option *options); + const char *desc; + __connmanctl_lookup_cb cb; +} cmd_table[] = { + { "state", NULL, NULL, cmd_state, + "Shows if the system is online or offline", NULL }, + { "technologies", NULL, NULL, cmd_technologies, + "Display technologies", NULL }, + { "enable", "|offline", NULL, cmd_enable, + "Enables given technology or offline mode", + lookup_technology_offline }, + { "disable", "|offline", NULL, cmd_disable, + "Disables given technology or offline mode", + lookup_technology_offline }, + { "tether", " on|off\n" + " wifi [on|off] ", + NULL, cmd_tether, + "Enable, disable tethering, set SSID and passphrase for wifi", + lookup_tether }, + { "services", "[]", service_options, cmd_services, + "Display services", lookup_service_arg }, + { "peers", "[peer]", NULL, cmd_peers, + "Display peers", lookup_peer_arg }, + { "scan", "", NULL, cmd_scan, + "Scans for new services for given technology", + lookup_technology_arg }, + { "connect", "", NULL, cmd_connect, + "Connect a given service or peer", lookup_service_arg }, + { "disconnect", "", NULL, cmd_disconnect, + "Disconnect a given service or peer", lookup_service_arg }, + { "config", "", config_options, cmd_config, + "Set service configuration options", lookup_config }, + { "monitor", "[off]", monitor_options, cmd_monitor, + "Monitor signals from interfaces", lookup_monitor }, + { "agent", "on|off", NULL, cmd_agent, + "Agent mode", lookup_agent }, + {"vpnconnections", "[]", NULL, cmd_vpnconnections, + "Display VPN connections", NULL }, + { "vpnagent", "on|off", NULL, cmd_vpnagent, + "VPN Agent mode", lookup_agent }, + { "session", "on|off|connect|disconnect|config", session_options, + cmd_session, "Enable or disable a session", lookup_session }, + { "peer_service", "register|unregister \n" + "Where specs are:\n" + "\tbjr_query bjr_response \n" + "\tupnp_service upnp_version \n" + "\twfd_ies \n", NULL, + cmd_peer_service, "(Un)Register a Peer Service", NULL }, + { "help", NULL, NULL, cmd_help, + "Show help", NULL }, + { "exit", NULL, NULL, cmd_exit, + "Exit", NULL }, + { "quit", NULL, NULL, cmd_exit, + "Quit", NULL }, + { NULL, }, +}; + +static int cmd_help(char *args[], int num, struct connman_option *options) +{ + bool interactive = __connmanctl_is_interactive(); + int i, j; + + if (interactive == false) + fprintf(stdout, "Usage: connmanctl [[command] [args]]\n"); + + for (i = 0; cmd_table[i].cmd; i++) { + const char *cmd = cmd_table[i].cmd; + const char *argument = cmd_table[i].argument; + const char *desc = cmd_table[i].desc; + + printf("%-16s%-22s%s\n", cmd? cmd: "", + argument? argument: "", + desc? desc: ""); + + if (cmd_table[i].options) { + for (j = 0; cmd_table[i].options[j].name; + j++) { + const char *options_desc = + cmd_table[i].options[j].desc ? + cmd_table[i].options[j].desc: ""; + + printf(" --%-16s%s\n", + cmd_table[i].options[j].name, + options_desc); + } + } + } + + if (interactive == false) + fprintf(stdout, "\nNote: arguments and output are considered " + "EXPERIMENTAL for now.\n"); + + return 0; +} + +__connmanctl_lookup_cb __connmanctl_get_lookup_func(const char *text) +{ + int i, cmdlen, textlen; + + if (!text) + return NULL; + + textlen = strlen(text); + + for (i = 0; cmd_table[i].cmd; i++) { + cmdlen = strlen(cmd_table[i].cmd); + + if (textlen > cmdlen && text[cmdlen] != ' ') + continue; + + if (strncmp(cmd_table[i].cmd, text, cmdlen) == 0) + return cmd_table[i].cb; + } + + return NULL; +} + +int __connmanctl_commands(DBusConnection *dbus_conn, char *argv[], int argc) +{ + int i, result; + + connection = dbus_conn; + + for (i = 0; cmd_table[i].cmd; i++) { + if (g_strcmp0(cmd_table[i].cmd, argv[0]) == 0 && + cmd_table[i].func) { + result = cmd_table[i].func(argv, argc, + cmd_table[i].options); + if (result < 0 && result != -EINPROGRESS) + fprintf(stderr, "Error '%s': %s\n", argv[0], + strerror(-result)); + return result; + } + } + + fprintf(stderr, "Error '%s': Unknown command\n", argv[0]); + return -EINVAL; +} + +char *__connmanctl_lookup_command(const char *text, int state) +{ + static int i = 0; + static int len = 0; + + if (state == 0) { + i = 0; + len = strlen(text); + } + + while (cmd_table[i].cmd) { + const char *command = cmd_table[i].cmd; + + i++; + + if (strncmp(text, command, len) == 0) + return strdup(command); + } + + return NULL; +} + +static char *get_path(char *full_path) +{ + char *path; + + path = strrchr(full_path, '/'); + if (path && *path != '\0') + path++; + else + path = full_path; + + return path; +} + +static void add_service_id(const char *path) +{ + g_hash_table_replace(service_hash, g_strdup(path), + GINT_TO_POINTER(TRUE)); +} + +static void remove_service_id(const char *path) +{ + g_hash_table_remove(service_hash, path); +} + +static void services_added(DBusMessageIter *iter) +{ + DBusMessageIter array; + char *path = NULL; + + while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) { + + dbus_message_iter_recurse(iter, &array); + if (dbus_message_iter_get_arg_type(&array) != + DBUS_TYPE_OBJECT_PATH) + return; + + dbus_message_iter_get_basic(&array, &path); + add_service_id(get_path(path)); + + dbus_message_iter_next(iter); + } +} + +static void update_services(DBusMessageIter *iter) +{ + DBusMessageIter array; + char *path; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return; + + dbus_message_iter_recurse(iter, &array); + services_added(&array); + + dbus_message_iter_next(iter); + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return; + + dbus_message_iter_recurse(iter, &array); + while (dbus_message_iter_get_arg_type(&array) == + DBUS_TYPE_OBJECT_PATH) { + dbus_message_iter_get_basic(&array, &path); + remove_service_id(get_path(path)); + + dbus_message_iter_next(&array); + } +} + +static int populate_service_hash(DBusMessageIter *iter, const char *error, + void *user_data) +{ + if (error) { + fprintf(stderr, "Error getting services: %s", error); + return 0; + } + + update_services(iter); + return 0; +} + +static void add_peer_id(const char *path) +{ + g_hash_table_replace(peer_hash, g_strdup(path), GINT_TO_POINTER(TRUE)); +} + +static void remove_peer_id(const char *path) +{ + g_hash_table_remove(peer_hash, path); +} + +static void peers_added(DBusMessageIter *iter) +{ + DBusMessageIter array; + char *path = NULL; + + while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) { + + dbus_message_iter_recurse(iter, &array); + if (dbus_message_iter_get_arg_type(&array) != + DBUS_TYPE_OBJECT_PATH) + return; + + dbus_message_iter_get_basic(&array, &path); + add_peer_id(get_path(path)); + + dbus_message_iter_next(iter); + } +} + +static void update_peers(DBusMessageIter *iter) +{ + DBusMessageIter array; + char *path; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return; + + dbus_message_iter_recurse(iter, &array); + peers_added(&array); + + dbus_message_iter_next(iter); + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return; + + dbus_message_iter_recurse(iter, &array); + while (dbus_message_iter_get_arg_type(&array) == + DBUS_TYPE_OBJECT_PATH) { + dbus_message_iter_get_basic(&array, &path); + remove_peer_id(get_path(path)); + + dbus_message_iter_next(&array); + } +} + +static int populate_peer_hash(DBusMessageIter *iter, + const char *error, void *user_data) +{ + if (error) { + fprintf(stderr, "Error getting peers: %s", error); + return 0; + } + + update_peers(iter); + return 0; +} + +static void add_technology_id(const char *path) +{ + g_hash_table_replace(technology_hash, g_strdup(path), + GINT_TO_POINTER(TRUE)); +} + +static void remove_technology_id(const char *path) +{ + g_hash_table_remove(technology_hash, path); +} + +static void remove_technology(DBusMessageIter *iter) +{ + char *path = NULL; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH) + return; + + dbus_message_iter_get_basic(iter, &path); + remove_technology_id(get_path(path)); +} + +static void add_technology(DBusMessageIter *iter) +{ + char *path = NULL; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH) + return; + + dbus_message_iter_get_basic(iter, &path); + add_technology_id(get_path(path)); +} + +static void update_technologies(DBusMessageIter *iter) +{ + DBusMessageIter array; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return; + + dbus_message_iter_recurse(iter, &array); + + while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) { + DBusMessageIter object_path; + + dbus_message_iter_recurse(&array, &object_path); + + add_technology(&object_path); + + dbus_message_iter_next(&array); + } +} + +static int populate_technology_hash(DBusMessageIter *iter, const char *error, + void *user_data) +{ + if (error) { + fprintf(stderr, "Error getting technologies: %s", error); + return 0; + } + + update_technologies(iter); + + return 0; +} + +static DBusHandlerResult monitor_completions_changed( + DBusConnection *connection, + DBusMessage *message, void *user_data) +{ + bool *enabled = user_data; + DBusMessageIter iter; + DBusHandlerResult handled; + + if (*enabled) + handled = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + else + handled = DBUS_HANDLER_RESULT_HANDLED; + + if (dbus_message_is_signal(message, "net.connman.Manager", + "ServicesChanged")) { + dbus_message_iter_init(message, &iter); + update_services(&iter); + return handled; + } + + if (dbus_message_is_signal(message, "net.connman.Manager", + "PeersChanged")) { + dbus_message_iter_init(message, &iter); + update_peers(&iter); + return handled; + } + + if (dbus_message_is_signal(message, "net.connman.Manager", + "TechnologyAdded")) { + dbus_message_iter_init(message, &iter); + add_technology(&iter); + return handled; + } + + if (dbus_message_is_signal(message, "net.connman.Manager", + "TechnologyRemoved")) { + dbus_message_iter_init(message, &iter); + remove_technology(&iter); + return handled; + } + + if (!g_strcmp0(dbus_message_get_interface(message), + "net.connman.Manager")) + return handled; + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +void __connmanctl_monitor_completions(DBusConnection *dbus_conn) +{ + bool *manager_enabled = NULL; + DBusError err; + int i; + + for (i = 0; monitor[i].interface; i++) { + if (!strcmp(monitor[i].interface, "Manager")) { + manager_enabled = &monitor[i].enabled; + break; + } + } + + if (!dbus_conn) { + g_hash_table_destroy(service_hash); + g_hash_table_destroy(technology_hash); + + dbus_bus_remove_match(connection, + "type='signal',interface='net.connman.Manager'", NULL); + dbus_connection_remove_filter(connection, + monitor_completions_changed, + manager_enabled); + return; + } + + connection = dbus_conn; + + service_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); + + peer_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); + + technology_hash = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, NULL); + + __connmanctl_dbus_method_call(connection, + CONNMAN_SERVICE, CONNMAN_PATH, + "net.connman.Manager", "GetServices", + populate_service_hash, NULL, NULL, NULL); + + __connmanctl_dbus_method_call(connection, + CONNMAN_SERVICE, CONNMAN_PATH, + "net.connman.Manager", "GetPeers", + populate_peer_hash, NULL, NULL, NULL); + + __connmanctl_dbus_method_call(connection, + CONNMAN_SERVICE, CONNMAN_PATH, + "net.connman.Manager", "GetTechnologies", + populate_technology_hash, NULL, NULL, NULL); + + dbus_connection_add_filter(connection, + monitor_completions_changed, manager_enabled, + NULL); + + dbus_error_init(&err); + dbus_bus_add_match(connection, + "type='signal',interface='net.connman.Manager'", &err); + + if (dbus_error_is_set(&err)) + fprintf(stderr, "Error: %s\n", err.message); +} diff --git a/client/commands.h b/client/commands.h new file mode 100755 index 0000000..d5d1bec --- /dev/null +++ b/client/commands.h @@ -0,0 +1,43 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __CONNMANCTL_COMMANDS_H +#define __CONNMANCTL_COMMANDS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef char *(*__connmanctl_lookup_cb)(const char *text, int state); + +int __connmanctl_commands(DBusConnection *connection, char *argv[], int argc); +char *__connmanctl_lookup_command(const char *text, int state); +void __connmanctl_monitor_completions(DBusConnection *dbus_conn); +__connmanctl_lookup_cb __connmanctl_get_lookup_func(const char *text); + +#ifdef __cplusplus +} +#endif + +#endif /* __CONNMANCTL_COMMANDS_H */ diff --git a/client/dbus_helpers.c b/client/dbus_helpers.c new file mode 100755 index 0000000..d905746 --- /dev/null +++ b/client/dbus_helpers.c @@ -0,0 +1,456 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include +#include + +#include "input.h" +#include "dbus_helpers.h" + +#define TIMEOUT 120000 + +void __connmanctl_dbus_print(DBusMessageIter *iter, const char *pre, + const char *dict, const char *sep) +{ + int arg_type; + dbus_bool_t b; + unsigned char c; + dbus_uint16_t u16; + dbus_uint32_t u; + dbus_int32_t i; + double d; + + char *str; + DBusMessageIter entry; + + if (!pre) + pre = ""; + + while ((arg_type = dbus_message_iter_get_arg_type(iter)) + != DBUS_TYPE_INVALID) { + + fprintf(stdout, "%s", pre); + + switch (arg_type) { + case DBUS_TYPE_STRUCT: + fprintf(stdout, "{ "); + dbus_message_iter_recurse(iter, &entry); + __connmanctl_dbus_print(&entry, "", "=", " "); + fprintf(stdout, " }"); + break; + + case DBUS_TYPE_ARRAY: + fprintf(stdout, "[ "); + + dbus_message_iter_recurse(iter, &entry); + __connmanctl_dbus_print(&entry, "", "=", ", "); + + fprintf(stdout, " ]"); + break; + + case DBUS_TYPE_DICT_ENTRY: + + dbus_message_iter_recurse(iter, &entry); + __connmanctl_dbus_print(&entry, "", dict, dict); + break; + + case DBUS_TYPE_STRING: + case DBUS_TYPE_OBJECT_PATH: + dbus_message_iter_get_basic(iter, &str); + fprintf(stdout, "%s", str); + break; + + case DBUS_TYPE_VARIANT: + dbus_message_iter_recurse(iter, &entry); + __connmanctl_dbus_print(&entry, pre, dict, sep); + break; + + case DBUS_TYPE_BOOLEAN: + dbus_message_iter_get_basic(iter, &b); + if (!b) + fprintf(stdout, "False"); + else + fprintf(stdout, "True"); + break; + + case DBUS_TYPE_BYTE: + dbus_message_iter_get_basic(iter, &c); + fprintf(stdout, "%d", c); + break; + + case DBUS_TYPE_UINT16: + dbus_message_iter_get_basic(iter, &u16); + fprintf(stdout, "%u", u16); + break; + + case DBUS_TYPE_UINT32: + dbus_message_iter_get_basic(iter, &u); + fprintf(stdout, "%d", u); + break; + + case DBUS_TYPE_INT32: + dbus_message_iter_get_basic(iter, &i); + fprintf(stdout, "%d", i); + break; + + case DBUS_TYPE_DOUBLE: + dbus_message_iter_get_basic(iter, &d); + fprintf(stdout, "%f", d); + break; + + default: + fprintf(stdout, "", arg_type); + break; + } + + if (dbus_message_iter_has_next(iter)) + fprintf(stdout, "%s", sep); + + dbus_message_iter_next(iter); + } +} + +struct dbus_callback { + connmanctl_dbus_method_return_func_t cb; + void *user_data; +}; + +static void dbus_method_reply(DBusPendingCall *call, void *user_data) +{ + struct dbus_callback *callback = user_data; + int res = 0; + DBusMessage *reply; + DBusMessageIter iter; + + __connmanctl_save_rl(); + + reply = dbus_pending_call_steal_reply(call); + if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { + DBusError err; + + dbus_error_init(&err); + dbus_set_error_from_message(&err, reply); + + callback->cb(NULL, err.message, callback->user_data); + + dbus_error_free(&err); + goto end; + } + + dbus_message_iter_init(reply, &iter); + res = callback->cb(&iter, NULL, callback->user_data); + +end: + __connmanctl_redraw_rl(); + if (__connmanctl_is_interactive() == false && res != -EINPROGRESS) + __connmanctl_quit(); + + g_free(callback); + dbus_message_unref(reply); +} + +static int send_method_call(DBusConnection *connection, + DBusMessage *message, connmanctl_dbus_method_return_func_t cb, + void *user_data) +{ + int res = -ENXIO; + DBusPendingCall *call; + struct dbus_callback *callback; + + if (!dbus_connection_send_with_reply(connection, message, &call, TIMEOUT)) + goto end; + + if (!call) + goto end; + + if (cb) { + callback = g_new0(struct dbus_callback, 1); + callback->cb = cb; + callback->user_data = user_data; + dbus_pending_call_set_notify(call, dbus_method_reply, + callback, NULL); + res = -EINPROGRESS; + } + +end: + dbus_message_unref(message); + return res; +} + +static int append_variant(DBusMessageIter *iter, const char *property, + int type, void *value) +{ + DBusMessageIter variant; + char *type_str; + + switch(type) { + case DBUS_TYPE_BOOLEAN: + type_str = DBUS_TYPE_BOOLEAN_AS_STRING; + break; + case DBUS_TYPE_BYTE: + type_str = DBUS_TYPE_BYTE_AS_STRING; + break; + case DBUS_TYPE_STRING: + type_str = DBUS_TYPE_STRING_AS_STRING; + break; + case DBUS_TYPE_INT32: + type_str = DBUS_TYPE_INT32_AS_STRING; + break; + default: + return -EOPNOTSUPP; + } + + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property); + dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, type_str, + &variant); + dbus_message_iter_append_basic(&variant, type, value); + dbus_message_iter_close_container(iter, &variant); + + return 0; +} + +int __connmanctl_dbus_method_call(DBusConnection *connection, + const char *service, const char *path, const char *interface, + const char *method, connmanctl_dbus_method_return_func_t cb, + void *user_data, connmanctl_dbus_append_func_t append_func, + void *append_data) +{ + DBusMessage *message; + DBusMessageIter iter; + + message = dbus_message_new_method_call(service, path, interface, + method); + + if (!message) + return -ENOMEM; + + if (append_func) { + dbus_message_iter_init_append(message, &iter); + append_func(&iter, append_data); + } + + return send_method_call(connection, message, cb, user_data); +} + +int __connmanctl_dbus_set_property(DBusConnection *connection, + const char *path, const char *interface, + connmanctl_dbus_method_return_func_t cb, void * user_data, + const char *property, int type, void *value) +{ + DBusMessage *message; + DBusMessageIter iter; + + message = dbus_message_new_method_call("net.connman", path, + interface, "SetProperty"); + + if (!message) + return -ENOMEM; + + dbus_message_iter_init_append(message, &iter); + + if (append_variant(&iter, property, type, value) < 0) { + dbus_message_unref(message); + return -EINVAL; + } + + return send_method_call(connection, message, cb, user_data); +} + +void __connmanctl_dbus_append_dict(DBusMessageIter *iter, + connmanctl_dbus_append_func_t append_fn, void *append_data) +{ + DBusMessageIter dict; + + dbus_message_iter_open_container(iter, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict); + + if (append_fn) + append_fn(&dict, append_data); + + dbus_message_iter_close_container(iter, &dict); +} + +void __connmanctl_dbus_append_dict_entry(DBusMessageIter *iter, + const char *property, int type, void *value) +{ + DBusMessageIter dict_entry; + + dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL, + &dict_entry); + + append_variant(&dict_entry, property, type, value); + + dbus_message_iter_close_container(iter, &dict_entry); +} + +int __connmanctl_dbus_set_property_dict(DBusConnection *connection, + const char *path, const char *interface, + connmanctl_dbus_method_return_func_t cb, void *user_data, + const char *property, int type, + connmanctl_dbus_append_func_t append_fn, + void *append_user_data) +{ + DBusMessage *message; + DBusMessageIter iter, variant, dict; + + message = dbus_message_new_method_call("net.connman", path, + interface, "SetProperty"); + + if (!message) + return -ENOMEM; + + dbus_message_iter_init_append(message, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property); + dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, + DBUS_TYPE_ARRAY_AS_STRING + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + &variant); + + dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING + DBUS_TYPE_STRING_AS_STRING + DBUS_TYPE_VARIANT_AS_STRING + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, + &dict); + + append_fn(&dict, append_user_data); + + dbus_message_iter_close_container(&variant, &dict); + dbus_message_iter_close_container(&iter, &variant); + + return send_method_call(connection, message, cb, user_data); +} + +static void append_variant_array(DBusMessageIter *iter, const char *property, + connmanctl_dbus_append_func_t append_fn, + void *append_user_data) +{ + DBusMessageIter variant, array; + + dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property); + dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT, + DBUS_TYPE_ARRAY_AS_STRING + DBUS_TYPE_STRING_AS_STRING, + &variant); + + dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY, + DBUS_TYPE_STRING_AS_STRING, &array); + + append_fn(&array, append_user_data); + + dbus_message_iter_close_container(&variant, &array); + dbus_message_iter_close_container(iter, &variant); +} + +void __connmanctl_dbus_append_dict_string_array(DBusMessageIter *iter, + const char *property, connmanctl_dbus_append_func_t append_fn, + void *append_user_data) +{ + DBusMessageIter dict_entry; + + dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL, + &dict_entry); + + append_variant_array(&dict_entry, property, append_fn, + append_user_data); + + dbus_message_iter_close_container(iter, &dict_entry); +} + +int __connmanctl_dbus_set_property_array(DBusConnection *connection, + const char *path, const char *interface, + connmanctl_dbus_method_return_func_t cb, void *user_data, + const char *property, int type, + connmanctl_dbus_append_func_t append_fn, + void *append_user_data) +{ + DBusMessage *message; + DBusMessageIter iter; + + if (type != DBUS_TYPE_STRING) + return -EOPNOTSUPP; + + message = dbus_message_new_method_call("net.connman", path, + interface, "SetProperty"); + + if (!message) + return -ENOMEM; + + dbus_message_iter_init_append(message, &iter); + + append_variant_array(&iter, property, append_fn, append_user_data); + + return send_method_call(connection, message, cb, user_data); +} + +int __connmanctl_dbus_session_change(DBusConnection *connection, + const char *session_path, + connmanctl_dbus_method_return_func_t cb, void * user_data, + const char *property, int type, void *value) +{ + DBusMessage *message; + DBusMessageIter iter; + + message = dbus_message_new_method_call("net.connman", session_path, + "net.connman.Session", "Change"); + + if (!message) + return -ENOMEM; + + dbus_message_iter_init_append(message, &iter); + + if (append_variant(&iter, property, type, value) < 0) { + dbus_message_unref(message); + return -EINVAL; + } + + return send_method_call(connection, message, cb, user_data); +} + +int __connmanctl_dbus_session_change_array(DBusConnection *connection, + const char *session_path, + connmanctl_dbus_method_return_func_t cb, void *user_data, + const char *property, + connmanctl_dbus_append_func_t append_fn, + void *append_user_data) +{ + DBusMessage *message; + DBusMessageIter iter; + + message = dbus_message_new_method_call("net.connman", session_path, + "net.connman.Session", "Change"); + + if (!message) + return -ENOMEM; + + dbus_message_iter_init_append(message, &iter); + + append_variant_array(&iter, property, append_fn, append_user_data); + + return send_method_call(connection, message, cb, user_data); +} diff --git a/client/dbus_helpers.h b/client/dbus_helpers.h new file mode 100755 index 0000000..395808a --- /dev/null +++ b/client/dbus_helpers.h @@ -0,0 +1,96 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __CONNMANCTL_DBUS_HELPERS_H +#define __CONNMANCTL_DBUS_HELPERS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define CONNMAN_SERVICE "net.connman" +#define CONNMAN_PATH "/" +#define VPN_SERVICE CONNMAN_SERVICE ".vpn" +#define VPN_PATH "/" + +void __connmanctl_dbus_print(DBusMessageIter *iter, const char *pre, + const char *dict, const char *sep); + +typedef int (*connmanctl_dbus_method_return_func_t)(DBusMessageIter *iter, + const char *error, void *user_data); + +typedef void (*connmanctl_dbus_append_func_t)(DBusMessageIter *iter, + void *user_data); + +int __connmanctl_dbus_method_call(DBusConnection *connection, + const char *service, const char *path, const char *interface, + const char *method, connmanctl_dbus_method_return_func_t cb, + void * user_data, connmanctl_dbus_append_func_t append_fn, + void *append_data); + +int __connmanctl_dbus_set_property(DBusConnection *connection, + const char *path, const char *interface, + connmanctl_dbus_method_return_func_t cb, void * user_data, + const char *property, int type, void *value); + +void __connmanctl_dbus_append_dict(DBusMessageIter *iter, + connmanctl_dbus_append_func_t append_fn, void *append_data); + +void __connmanctl_dbus_append_dict_entry(DBusMessageIter *iter, + const char *property, int type, void *value); + +int __connmanctl_dbus_set_property_dict(DBusConnection *connection, + const char *path, const char *interface, + connmanctl_dbus_method_return_func_t cb, void * user_data, + const char *property, int type, + connmanctl_dbus_append_func_t append_fn, + void *append_user_data); + +void __connmanctl_dbus_append_dict_string_array(DBusMessageIter *iter, + const char *property, connmanctl_dbus_append_func_t append_fn, + void *append_user_data); +int __connmanctl_dbus_set_property_array(DBusConnection *connection, + const char *path, const char *interface, + connmanctl_dbus_method_return_func_t cb, void *user_data, + const char *property, int type, + connmanctl_dbus_append_func_t append_fn, + void *append_user_data); + +int __connmanctl_dbus_session_change(DBusConnection *connection, + const char *session_path, + connmanctl_dbus_method_return_func_t cb, void * user_data, + const char *property, int type, void *value); + +int __connmanctl_dbus_session_change_array(DBusConnection *connection, + const char *session_path, + connmanctl_dbus_method_return_func_t cb, void *user_data, + const char *property, + connmanctl_dbus_append_func_t append_fn, + void *append_user_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/client/input.c b/client/input.c new file mode 100755 index 0000000..4e5e496 --- /dev/null +++ b/client/input.c @@ -0,0 +1,289 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2012-2014 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include "input.h" +#include "commands.h" + +static DBusConnection *connection; +static GMainLoop *main_loop; +static bool interactive = false; + +static bool save_input; +static char *saved_line; +static int saved_point; + +void __connmanctl_quit(void) +{ + if (main_loop) + g_main_loop_quit(main_loop); +} + +bool __connmanctl_is_interactive(void) +{ + return interactive; +} + +void __connmanctl_save_rl(void) +{ + save_input = !RL_ISSTATE(RL_STATE_DONE); + + if (save_input) { + saved_point = rl_point; + saved_line = rl_copy_text(0, rl_end); + rl_save_prompt(); + rl_replace_line("", 0); + rl_redisplay(); + } +} + +void __connmanctl_redraw_rl(void) +{ + if (save_input) { + rl_restore_prompt(); + rl_replace_line(saved_line, 0); + rl_point = saved_point; + rl_redisplay(); + free(saved_line); + } + + save_input = 0; +} + +static void rl_handler(char *input) +{ + char **args, **trim_args; + int num, len, err, i; + + if (!input) { + rl_newline(1, '\n'); + g_main_loop_quit(main_loop); + return; + } + + args = g_strsplit(input, " ", 0); + num = g_strv_length(args); + + trim_args = g_new0(char *, num + 1); + for (i = 0, len = 0; i < num; i++) { + if (*args[i] != '\0') { + trim_args[len] = args[i]; + len++; + } + } + + if (len > 0) { + + add_history(input); + + err = __connmanctl_commands(connection, trim_args, len); + + if (err > 0) + g_main_loop_quit(main_loop); + } + + g_strfreev(args); + g_free(trim_args); +} + +static gboolean input_handler(GIOChannel *channel, GIOCondition condition, + gpointer user_data) +{ + if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) { + g_main_loop_quit(main_loop); + return FALSE; + } + + rl_callback_read_char(); + return TRUE; +} + +static char **complete_agent(const char *text, int start, int end) +{ + rl_attempted_completion_over = 1; + + return NULL; +} + +/* Return how many parameters we have typed */ +int __connmanctl_input_calc_level(void) +{ + int count = 0; + char *ptr; + + ptr = rl_line_buffer; + + while (*ptr) { + if (*ptr == ' ') { + if (*(ptr + 1) == ' ') { + ptr++; + continue; + } else + count++; + } + ptr++; + } + + return count; +} + +void __connmanctl_input_lookup_end(void) +{ + rl_attempted_completion_over = 1; +} + +static char **complete_command(const char *text, int start, int end) +{ + if (start == 0) { + return rl_completion_matches(text, + __connmanctl_lookup_command); + + } else { + __connmanctl_lookup_cb cb; + char **str = NULL; + + cb = __connmanctl_get_lookup_func(rl_line_buffer); + if (cb) + str = rl_completion_matches(text, cb); + else + rl_attempted_completion_over = 1; + + return str; + } +} + +static struct { + connmanctl_input_func_t cb; + void *user_data; +} agent_handler; + +static void rl_agent_handler(char *input) +{ + agent_handler.cb(input, agent_handler.user_data); +} + +void __connmanctl_agent_mode(const char *prompt, + connmanctl_input_func_t input_handler, void *user_data) +{ + agent_handler.cb = input_handler; + agent_handler.user_data = user_data; + + if (input_handler) + rl_callback_handler_install(prompt, rl_agent_handler); + else { + rl_set_prompt(prompt); + rl_callback_handler_remove(); + rl_redisplay(); + } + rl_attempted_completion_function = complete_agent; +} + +void __connmanctl_command_mode(void) +{ + rl_callback_handler_install("connmanctl> ", rl_handler); + rl_attempted_completion_function = complete_command; +} + +int __connmanctl_input_init(int argc, char *argv[]) +{ + char *help[] = { + "help", + NULL + }; + guint source = 0; + int err; + DBusError dbus_err; + GIOChannel *channel; + + dbus_error_init(&dbus_err); + connection = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, &dbus_err); + + if (dbus_error_is_set(&dbus_err)) { + fprintf(stderr, "Error: %s\n", dbus_err.message); + dbus_error_free(&dbus_err); + return 1; + } + + if (argc < 2) { + interactive = true; + + channel = g_io_channel_unix_new(fileno(stdin)); + source = g_io_add_watch(channel, + G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL, + input_handler, NULL); + g_io_channel_unref(channel); + + __connmanctl_monitor_completions(connection); + + __connmanctl_command_mode(); + + err = -EINPROGRESS; + } else { + interactive = false; + + if (strcmp(argv[1], "--help") == 0 || + strcmp(argv[1], "-h") == 0) + err = __connmanctl_commands(connection, help, 1); + else + err = __connmanctl_commands(connection, argv + 1, + argc - 1); + } + + if (err == -EINPROGRESS) { + main_loop = g_main_loop_new(NULL, FALSE); + g_main_loop_run(main_loop); + + err = 0; + } + + if (interactive) { + g_source_remove(source); + __connmanctl_monitor_completions(NULL); + + rl_callback_handler_remove(); +#if !defined TIZEN_EXT + rl_message(""); +#endif + } + + dbus_connection_unref(connection); + if (main_loop) + g_main_loop_unref(main_loop); + + if (err < 0) + err = -err; + else + err = 0; + + return err; +} diff --git a/client/input.h b/client/input.h new file mode 100755 index 0000000..c7256a4 --- /dev/null +++ b/client/input.h @@ -0,0 +1,48 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2012-2014 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __CONNMANCTL_INPUT_H +#define __CONNMANCTL_INPUT_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void __connmanctl_quit(void); +bool __connmanctl_is_interactive(void); +void __connmanctl_save_rl(void); +void __connmanctl_redraw_rl(void); +int __connmanctl_input_calc_level(void); +void __connmanctl_input_lookup_end(void); +typedef void (* connmanctl_input_func_t) (char *input, void *user_data); +void __connmanctl_agent_mode(const char *prompt, + connmanctl_input_func_t input_handler, void *user_data); +void __connmanctl_command_mode(void); +int __connmanctl_input_init(int argc, char *argv[]); + +#ifdef __cplusplus +} +#endif + +#endif /* __CONNMANCTL_INPUT_H */ diff --git a/client/main.c b/client/main.c old mode 100644 new mode 100755 index 4a88d6e..6d3c57f --- a/client/main.c +++ b/client/main.c @@ -2,11 +2,12 @@ * * Connection Manager * - * Copyright (C) 2007-2012 Intel Corporation. All rights reserved. + * Copyright (C) 2012-2013 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. + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -19,226 +20,9 @@ * */ -#ifdef HAVE_CONFIG_H -#include -#endif - -#include -#include -#include -#include - -#include - -#define CONNMAN_SERVICE "net.connman" - -#define CONNMAN_MANAGER_INTERFACE CONNMAN_SERVICE ".Manager" -#define CONNMAN_MANAGER_PATH "/" - -struct service_data { - const char *path; - const char *name; - dbus_bool_t favorite; -}; - -static DBusMessage *get_services(DBusConnection *connection) -{ - DBusMessage *message, *reply; - DBusError error; - - message = dbus_message_new_method_call(CONNMAN_SERVICE, - CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, - "GetServices"); - if (message == NULL) - return NULL; - - dbus_error_init(&error); - - reply = dbus_connection_send_with_reply_and_block(connection, - message, -1, &error); - if (reply == NULL) { - if (dbus_error_is_set(&error) == TRUE) { - fprintf(stderr, "%s\n", error.message); - dbus_error_free(&error); - } else - fprintf(stderr, "Failed to get properties\n"); - dbus_message_unref(message); - return NULL; - } - - dbus_message_unref(message); - - return reply; -} - -static DBusMessage *lookup_service(DBusConnection *connection, - const char *pattern) -{ - DBusMessage *message, *reply; - DBusError error; - - message = dbus_message_new_method_call(CONNMAN_SERVICE, - CONNMAN_MANAGER_PATH, - CONNMAN_MANAGER_INTERFACE, - "LookupService"); - if (message == NULL) - return NULL; - - dbus_message_append_args(message, DBUS_TYPE_STRING, &pattern, - DBUS_TYPE_INVALID); - - dbus_error_init(&error); - - reply = dbus_connection_send_with_reply_and_block(connection, - message, -1, &error); - if (reply == NULL) { - if (dbus_error_is_set(&error) == TRUE) { - fprintf(stderr, "%s\n", error.message); - dbus_error_free(&error); - } else - fprintf(stderr, "Failed to get properties\n"); - dbus_message_unref(message); - return NULL; - } - - dbus_message_unref(message); - - return reply; -} - -static void extract_properties(DBusMessageIter *dict, - struct service_data *service) -{ - while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) { - DBusMessageIter entry, value; - const char *key; - - dbus_message_iter_recurse(dict, &entry); - dbus_message_iter_get_basic(&entry, &key); - - dbus_message_iter_next(&entry); - - dbus_message_iter_recurse(&entry, &value); - - //type = dbus_message_iter_get_arg_type(&value); - //dbus_message_iter_get_basic(&value, &val); - - if (strcmp(key, "Name") == 0) - dbus_message_iter_get_basic(&value, &service->name); - else if (strcmp(key, "Favorite") == 0) - dbus_message_iter_get_basic(&value, &service->favorite); - - dbus_message_iter_next(dict); - } -} - -static void extract_services(DBusMessage *message) -{ - DBusMessageIter iter, array; - - dbus_message_iter_init(message, &iter); - dbus_message_iter_recurse(&iter, &array); - - while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) { - DBusMessageIter entry, dict; - struct service_data service; - const char *path; - - dbus_message_iter_recurse(&array, &entry); - dbus_message_iter_get_basic(&entry, &path); - - service.path = strrchr(path, '/') + 1; - - dbus_message_iter_next(&entry); - - dbus_message_iter_recurse(&entry, &dict); - extract_properties(&dict, &service); - - printf("%c %-20s { %-50s }\n", - service.favorite == TRUE ? '*' : ' ', - service.name, service.path); - - dbus_message_iter_next(&array); - } -} - -static int cmd_list_services(DBusConnection *connection) -{ - DBusMessage *message; - - message = get_services(connection); - if (message == NULL) - return -1; - - extract_services(message); - - dbus_message_unref(message); - - return 0; -} - -static int cmd_show_service(DBusConnection *connection, const char *pattern) -{ - DBusMessage *message; - const char *path; - - message = lookup_service(connection, pattern); - if (message == NULL) - return -1; - - dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &path, - DBUS_TYPE_INVALID); - - printf("Service: %s\n", path); - - dbus_message_unref(message); - - return 0; -} - -static void usage(const char *program) -{ - printf("ConnMan utility ver %s\n\n", VERSION); - - printf("Usage:\n" - "\t%s [options]\n\n", program); - - printf("Commands:\n" - "\thelp\n" - "\tlist\n" - "\tshow \n" - "\n"); -} +#include "input.h" int main(int argc, char *argv[]) { - DBusConnection *conn; - - if (argc > 1 && strcmp(argv[1], "help") == 0) { - usage(argv[0]); - exit(0); - } - - conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); - if (!conn) { - fprintf(stderr, "Can't get on system bus\n"); - exit(1); - } - - if (argc > 1) { - if (strcmp(argv[1], "list") == 0) - cmd_list_services(conn); - else if (strcmp(argv[1], "show") == 0) { - if (argc > 2) - cmd_show_service(conn, argv[2]); - else - usage(argv[0]); - } - } else - usage(argv[0]); - - dbus_connection_unref(conn); - - return 0; + return __connmanctl_input_init(argc, argv); } diff --git a/client/peers.c b/client/peers.c new file mode 100755 index 0000000..bf1aa0e --- /dev/null +++ b/client/peers.c @@ -0,0 +1,122 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2014 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "peers.h" + +static void print_peer(char *path, DBusMessageIter *iter) +{ + char *name = "", *state = ""; + char *str, *property; + DBusMessageIter entry, val; + int count = 0; + + while (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) { + dbus_message_iter_recurse(iter, &entry); + dbus_message_iter_get_basic(&entry, &property); + + if (strcmp(property, "Name") == 0) { + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &val); + dbus_message_iter_get_basic(&val, &name); + } else if (strcmp(property, "State") == 0) { + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &val); + dbus_message_iter_get_basic(&val, &state); + } + + dbus_message_iter_next(iter); + count++; + } + + str = strrchr(path, '/'); + if (str) + str++; + else + str = path; + + if (count > 0) + fprintf(stdout, "%s %s %s", name, state, str); + else + fprintf(stdout, "%s %s", "unchanged", str); +} + +static void list_peer_array(DBusMessageIter *iter) +{ + DBusMessageIter array, dict; + char *path = NULL; + + while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) { + dbus_message_iter_recurse(iter, &array); + if (dbus_message_iter_get_arg_type(&array) + != DBUS_TYPE_OBJECT_PATH) + return; + + dbus_message_iter_get_basic(&array, &path); + + dbus_message_iter_next(&array); + if (dbus_message_iter_get_arg_type(&array) + == DBUS_TYPE_ARRAY) { + dbus_message_iter_recurse(&array, &dict); + print_peer(path, &dict); + } + + if (dbus_message_iter_has_next(iter)) + fprintf(stdout, "\n"); + + dbus_message_iter_next(iter); + } +} + +void __connmanctl_peers_list(DBusMessageIter *iter) +{ + DBusMessageIter array; + char *path; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return; + + dbus_message_iter_recurse(iter, &array); + list_peer_array(&array); + + dbus_message_iter_next(iter); + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return; + + fprintf(stdout, "\n}, {"); + + dbus_message_iter_recurse(iter, &array); + while (dbus_message_iter_get_arg_type(&array) + == DBUS_TYPE_OBJECT_PATH) { + dbus_message_iter_get_basic(&array, &path); + fprintf(stdout, "\n%s %s", "removed", path); + + dbus_message_iter_next(&array); + } + +} diff --git a/client/peers.h b/client/peers.h new file mode 100755 index 0000000..fdf7ce7 --- /dev/null +++ b/client/peers.h @@ -0,0 +1,38 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2014 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __CONNMANCTL_PEERS_H +#define __CONNMANCTL_PEERS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void __connmanctl_peers_list(DBusMessageIter *iter); + +#ifdef __cplusplus +} +#endif + +#endif /* __CONNMANCTL_PEERS_H */ diff --git a/client/services.c b/client/services.c new file mode 100755 index 0000000..0c18669 --- /dev/null +++ b/client/services.c @@ -0,0 +1,156 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2012-2013 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include + +#include "services.h" + +static void print_service(char *path, DBusMessageIter *iter) +{ + char *name = "", *str = NULL; + int autoconn = 0, favorite = 0, count = 0; + char *property; + char state = ' '; + DBusMessageIter entry, val; + + while (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) { + + dbus_message_iter_recurse(iter, &entry); + dbus_message_iter_get_basic(&entry, &property); + if (strcmp(property, "Name") == 0) { + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &val); + dbus_message_iter_get_basic(&val, &name); + + } else if (strcmp(property, "State") == 0) { + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &val); + dbus_message_iter_get_basic(&val, &str); + + if (str) { + if (strcmp(str, "online") == 0) + state = 'O'; + else if (strcmp(str, "ready") == 0) + state = 'R'; + else if (!strcmp(str, "association")) + state = 'a'; + else if (!strcmp(str, "configuration")) + state = 'c'; + else if (!strcmp(str, "disconnect")) + state = 'd'; + } + + } else if (strcmp(property, "AutoConnect") == 0) { + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &val); + dbus_message_iter_get_basic(&val, &autoconn); + + } else if (strcmp(property, "Favorite") == 0) { + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &val); + dbus_message_iter_get_basic(&val, &favorite); + } + + count++; + dbus_message_iter_next(iter); + } + + str = strrchr(path, '/'); + if (str) + str++; + else + str = path; + + if (count > 0) + fprintf(stdout, "%c%c%c %-20s %s", favorite != 0 ? '*' : ' ', + autoconn != 0 ? 'A' : ' ', state, name, str); + else + fprintf(stdout, "%-24s %s", "unchanged", str); + +} + +static void list_service_array(DBusMessageIter *iter) +{ + DBusMessageIter array, dict; + char *path = NULL; + + while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) { + + dbus_message_iter_recurse(iter, &array); + if (dbus_message_iter_get_arg_type(&array) + != DBUS_TYPE_OBJECT_PATH) + return; + + dbus_message_iter_get_basic(&array, &path); + + dbus_message_iter_next(&array); + if (dbus_message_iter_get_arg_type(&array) + == DBUS_TYPE_ARRAY) { + dbus_message_iter_recurse(&array, &dict); + print_service(path, &dict); + } + + if (dbus_message_iter_has_next(iter)) + fprintf(stdout, "\n"); + + dbus_message_iter_next(iter); + } +} + +void __connmanctl_services_list(DBusMessageIter *iter) +{ + DBusMessageIter array; + char *path; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return; + + dbus_message_iter_recurse(iter, &array); + list_service_array(&array); + + dbus_message_iter_next(iter); + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return; + + fprintf(stdout, "\n}, {"); + + dbus_message_iter_recurse(iter, &array); + while (dbus_message_iter_get_arg_type(&array) + == DBUS_TYPE_OBJECT_PATH) { + dbus_message_iter_get_basic(&array, &path); + fprintf(stdout, "\n%-24s %s", "removed", path); + + dbus_message_iter_next(&array); + } + +} diff --git a/client/services.h b/client/services.h new file mode 100755 index 0000000..9b555fe --- /dev/null +++ b/client/services.h @@ -0,0 +1,38 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2012-2013 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __CONNMANCTL_SERVICES_H +#define __CONNMANCTL_SERVICES_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void __connmanctl_services_list(DBusMessageIter *iter); + +#ifdef __cplusplus +} +#endif + +#endif /* __CONNMANCTL_SERVICES_H */ diff --git a/client/vpnconnections.c b/client/vpnconnections.c new file mode 100755 index 0000000..d7bcbfe --- /dev/null +++ b/client/vpnconnections.c @@ -0,0 +1,111 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include + +#include "vpnconnections.h" + +static void print_connection(char *path, DBusMessageIter *iter) +{ + char *name = ""; + char state = ' '; + char *str; + char *property; + DBusMessageIter entry, val; + + while (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) { + + dbus_message_iter_recurse(iter, &entry); + dbus_message_iter_get_basic(&entry, &property); + if (strcmp(property, "Name") == 0) { + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &val); + dbus_message_iter_get_basic(&val, &name); + + } else if (strcmp(property, "State") == 0) { + dbus_message_iter_next(&entry); + dbus_message_iter_recurse(&entry, &val); + dbus_message_iter_get_basic(&val, &str); + + if (str) { + if (strcmp(str, "ready") == 0) + state = 'R'; + else if (strcmp(str, "configuration") == 0) + state = 'C'; + else if (strcmp(str, "failure") == 0) + state = 'F'; + } + } + + dbus_message_iter_next(iter); + } + + str = strrchr(path, '/'); + if (str) + str++; + else + str = path; + + fprintf(stdout, " %c %-20s %s", state, name, str); +} + +void __connmanctl_vpnconnections_list(DBusMessageIter *iter) +{ + DBusMessageIter array, entry, dict; + char *path = NULL; + + if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY) + return; + + dbus_message_iter_recurse(iter, &array); + + while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) { + + dbus_message_iter_recurse(&array, &entry); + if (dbus_message_iter_get_arg_type(&entry) + != DBUS_TYPE_OBJECT_PATH) + return; + + dbus_message_iter_get_basic(&entry, &path); + + dbus_message_iter_next(&entry); + if (dbus_message_iter_get_arg_type(&entry) + == DBUS_TYPE_ARRAY) { + dbus_message_iter_recurse(&entry, &dict); + print_connection(path, &dict); + } + + if (dbus_message_iter_has_next(&array)) + fprintf(stdout, "\n"); + + dbus_message_iter_next(&array); + } + + fprintf(stdout, "\n"); +} diff --git a/client/vpnconnections.h b/client/vpnconnections.h new file mode 100755 index 0000000..a915c84 --- /dev/null +++ b/client/vpnconnections.h @@ -0,0 +1,38 @@ +/* + * + * Connection Manager + * + * Copyright (C) 2013 Intel Corporation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __CONNMANCTL_VPNCONNECTIONS_H +#define __CONNMANCTL_VPNCONNECTIONS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void __connmanctl_vpnconnections_list(DBusMessageIter *iter); + +#ifdef __cplusplus +} +#endif + +#endif /* __CONNMANCTL_VPNCONNECTIONS_H */ diff --git a/configure.ac b/configure.ac old mode 100644 new mode 100755 index fa69daa..35d8f98 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.60) -AC_INIT(connman, 1.3) +AC_INIT(connman, 1.29) AM_INIT_AUTOMAKE([foreign subdir-objects color-tests]) AC_CONFIG_HEADERS([config.h]) @@ -38,8 +38,6 @@ AC_ARG_ENABLE(optimization, AC_HELP_STRING([--disable-optimization], fi ]) -GTK_DOC_CHECK - AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [enable compiling with debugging information]), [ if (test "${enableval}" = "yes" && @@ -57,30 +55,17 @@ AC_ARG_ENABLE(pie, AC_HELP_STRING([--enable-pie], fi ]) -AC_ARG_ENABLE(threads, - AC_HELP_STRING([--enable-threads], [enable threading support]), - [enable_threads=${enableval}], [enable_threads="no"]) - AC_ARG_ENABLE(hh2serial-gps, AC_HELP_STRING([--enable-hh2serial-gps], [enable hh2serial GPS support]), [enable_hh2serial_gps=${enableval}], [enable_hh2serial_gps="no"]) AM_CONDITIONAL(HH2SERIAL_GPS, test "${enable_hh2serial_gps}" != "no") AM_CONDITIONAL(HH2SERIAL_GPS_BUILTIN, test "${enable_hh2serial_gps}" = "builtin") -AC_ARG_ENABLE(tizen-ext, - AC_HELP_STRING([--enable-tizen-ext], [enable TIZEN extensions]), - [if (test "${enableval}" = "yes"); then - CFLAGS="$CFLAGS -DTIZEN_EXT" - LIBS="$LIBS -lsmack" - fi]) - -AC_ARG_ENABLE(tizen-rtc-timer, - AC_HELP_STRING([--enable-tizen-rtc-timer], [enable TIZEN RTC timer]), - [if (test "${enableval}" = "yes"); then - CFLAGS="$CFLAGS -DTIZEN_RTC_TIMER" - [enable_tizen_rtc_timer="yes"] - fi]) -AM_CONDITIONAL(TIZEN_RTC, test "${enable_tizen_rtc_timer}" = "yes") +AC_ARG_ENABLE(telephony, + AC_HELP_STRING([--enable-telephony], [enable Telephony support]), + [enable_telephony=${enableval}], [enable_telephony="yes"]) +AM_CONDITIONAL(TELEPHONY, test "${enable_telephony}" != "no") +AM_CONDITIONAL(TELEPHONY_BUILTIN, test "${enable_telephony}" = "builtin") AC_ARG_WITH(openconnect, AC_HELP_STRING([--with-openconnect=PROGRAM], [specify location of openconnect binary]), [path_openconnect=${withval}]) @@ -142,6 +127,9 @@ fi AM_CONDITIONAL(VPNC, test "${enable_vpnc}" != "no") AM_CONDITIONAL(VPNC_BUILTIN, test "${enable_vpnc}" = "builtin") +AC_ARG_WITH(l2tp, AC_HELP_STRING([--with-l2tp=PROGRAM], + [specify location of l2tp binary]), [path_l2tp=${withval}]) + AC_ARG_ENABLE(l2tp, AC_HELP_STRING([--enable-l2tp], [enable l2tp support]), [enable_l2tp=${enableval}], [enable_l2tp="no"]) @@ -164,6 +152,9 @@ fi AM_CONDITIONAL(L2TP, test "${enable_l2tp}" != "no") AM_CONDITIONAL(L2TP_BUILTIN, test "${enable_l2tp}" = "builtin") +AC_ARG_WITH(pptp, AC_HELP_STRING([--with-pptp=PROGRAM], + [specify location of pptp binary]), [path_pptp=${withval}]) + AC_ARG_ENABLE(pptp, AC_HELP_STRING([--enable-pptp], [enable pptp support]), [enable_pptp=${enableval}], [enable_pptp="no"]) @@ -209,6 +200,12 @@ AC_ARG_ENABLE(tist, AM_CONDITIONAL(TIST, test "${enable_tist}" != "no") AM_CONDITIONAL(TIST_BUILTIN, test "${enable_tist}" = "builtin") +AC_ARG_ENABLE(session-policy-local, + AC_HELP_STRING([--enable-session-policy-local], [enable local file Session policy configuration support]), + [enable_session_policy_local=${enableval}], [enable_session_policy_local="no"]) +AM_CONDITIONAL(SESSION_POLICY_LOCAL, test "${enable_session_policy_local}" != "no") +AM_CONDITIONAL(SESSION_POLICY_LOCAL_BUILTIN, test "${enable_session_policy_local}" = "builtin") + AC_ARG_WITH(stats-max-file-size, AC_HELP_STRING([--with-stats-max-file-size=SIZE], [Maximal size of a statistics round robin file]), [stats_max_file_size=${withval}]) @@ -225,14 +222,6 @@ PKG_CHECK_MODULES(GLIB, glib-2.0 >= 2.28, dummy=yes, AC_SUBST(GLIB_CFLAGS) AC_SUBST(GLIB_LIBS) -if (test "${enable_threads}" = "yes"); then - AC_DEFINE(NEED_THREADS, 1, [Define if threading support is required]) - PKG_CHECK_MODULES(GTHREAD, gthread-2.0 >= 2.16, dummy=yes, - AC_MSG_ERROR(GThread >= 2.16 is required)) - GLIB_CFLAGS="$GLIB_CFLAGS $GTHREAD_CFLAGS" - GLIB_LIBS="$GLIB_LIBS $GTHREAD_LIBS" -fi - PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.4, dummy=yes, AC_MSG_ERROR(D-Bus >= 1.4 is required)) AC_SUBST(DBUS_CFLAGS) @@ -267,7 +256,7 @@ if (test -n "${path_systemdunit}"); then fi AM_CONDITIONAL(SYSTEMD, test -n "${path_systemdunit}") -PKG_CHECK_MODULES(XTABLES, xtables, dummy=yes, +PKG_CHECK_MODULES(XTABLES, xtables >= 1.4.11, dummy=yes, AC_MSG_ERROR(Xtables library is required)) AC_SUBST(XTABLES_CFLAGS) AC_SUBST(XTABLES_LIBS) @@ -294,6 +283,11 @@ if (test "${enable_polkit}" != "no"); then fi AM_CONDITIONAL(POLKIT, test "${enable_polkit}" != "no") +AC_ARG_ENABLE(selinux, AC_HELP_STRING([--enable-selinux], + [enable selinux support]), + [enable_selinux=${enableval}], [enable_selinux="no"]) +AM_CONDITIONAL(SELINUX, test "${enable_selinux}" != "no") + AC_ARG_ENABLE(loopback, AC_HELP_STRING([--disable-loopback], [disable loopback support]), [enable_loopback=${enableval}]) @@ -304,6 +298,11 @@ AC_ARG_ENABLE(ethernet, AC_HELP_STRING([--disable-ethernet], [enable_ethernet=${enableval}]) AM_CONDITIONAL(ETHERNET, test "${enable_ethernet}" != "no") +AC_ARG_ENABLE(gadget, AC_HELP_STRING([--disable-gadget], + [disable USB Gadget support]), + [enable_gadget=${enableval}]) +AM_CONDITIONAL(GADGET, test "${enable_gadget}" != "no") + AC_ARG_ENABLE(wifi, AC_HELP_STRING([--disable-wifi], [disable WiFi support]), [enable_wifi=${enableval}]) @@ -314,11 +313,6 @@ AC_ARG_ENABLE(bluetooth, AC_HELP_STRING([--disable-bluetooth], [enable_bluetooth=${enableval}]) AM_CONDITIONAL(BLUETOOTH, test "${enable_bluetooth}" != "no") -AC_ARG_ENABLE(telephony, AC_HELP_STRING([--disable-telephony], - [disable telephony support]), - [enable_telephony=${enableval}]) -AM_CONDITIONAL(TELEPHONY, test "${enable_telephony}" != "no") - AC_ARG_ENABLE(ofono, AC_HELP_STRING([--disable-ofono], [disable oFono support]), [enable_ofono=${enableval}]) @@ -334,6 +328,11 @@ AC_ARG_ENABLE(pacrunner, AC_HELP_STRING([--disable-pacrunner], [enable_pacrunner=${enableval}]) AM_CONDITIONAL(PACRUNNER, test "${enable_pacrunner}" != "no") +AC_ARG_ENABLE(neard, AC_HELP_STRING([--disable-neard], + [disable Neard support]), + [enable_neard=${enableval}]) +AM_CONDITIONAL(NEARD, test "${enable_neard}" != "no") + AC_ARG_ENABLE(wispr, AC_HELP_STRING([--disable-wispr], [disable WISPr support]), [enable_wispr=${enableval}]) @@ -344,9 +343,18 @@ AC_ARG_ENABLE(tools, AC_HELP_STRING([--disable-tools], [enable_tools=${enableval}]) AM_CONDITIONAL(TOOLS, test "${enable_tools}" != "no") +if (test "${enable_tools}" != "no"); then + AC_PATH_PROGS(IPTABLES_SAVE, [iptables-save], [], + $PATH:/sbin:/usr/sbin) + IPTABLES_SAVE=$ac_cv_path_IPTABLES_SAVE +else + IPTABLES_SAVE="" +fi +AC_SUBST(IPTABLES_SAVE) + AC_ARG_ENABLE(client, AC_HELP_STRING([--disable-client], [disable command line client]), - [disable_client=${enableval}]) + [enable_client=${enableval}]) AM_CONDITIONAL(CLIENT, test "${enable_client}" != "no") if (test "${enable_wispr}" != "no"); then @@ -372,17 +380,20 @@ if (test "${enable_wifi}" != "no"); then $PATH:/sbin:/usr/sbin) fi -AC_ARG_ENABLE(linklocaladdr, AC_HELP_STRING([--disable-linklocaladdr], - [disable link local address when dhcp failed]), [ - if (test "${enableval}" = "no"); then - CFLAGS="$CFLAGS -DDISABLE_LINK_LOCAL_ADDR" - fi -]) - AC_ARG_ENABLE(datafiles, AC_HELP_STRING([--disable-datafiles], [don't install configuration and data files]), [enable_datafiles=${enableval}]) AM_CONDITIONAL(DATAFILES, test "${enable_datafiles}" != "no") -AC_OUTPUT(Makefile include/version.h src/connman.service - scripts/connman doc/version.xml connman.pc) +if (test "${enable_client}" != "no"); then + AC_CHECK_HEADERS(readline/readline.h, dummy=yes, + AC_MSG_ERROR(readline header files are required)) +fi + +AM_CONDITIONAL(VPN, test "${enable_openconnect}" != "no" -o \ + "${enable_openvpn}" != "no" -o \ + "${enable_vpnc}" != "no" -o \ + "${enable_l2tp}" != "no" -o \ + "${enable_pptp}" != "no") + +AC_OUTPUT(Makefile include/version.h connman.pc src/connman.service src/connman_tv.service) diff --git a/connman.manifest b/connman.manifest index e8b8e16..f296822 100644 --- a/connman.manifest +++ b/connman.manifest @@ -10,21 +10,32 @@ + + + + + + + + + + + - + diff --git a/doc/Makefile.am b/doc/Makefile.am deleted file mode 100644 index ce3e433..0000000 --- a/doc/Makefile.am +++ /dev/null @@ -1,38 +0,0 @@ - -DOC_MODULE = connman - -DOC_MAIN_SGML_FILE = $(DOC_MODULE)-docs.xml - -DOC_SOURCE_DIR = ../src - -SCAN_OPTIONS = --rebuild-sections --source-dir=../include - -MKDB_OPTIONS = --sgml-mode --output-format=xml --tmpl-dir=. \ - --ignore-files=connman \ - --source-dir=../include \ - --source-suffixes=c,h - -MKTMPL_OPTIONS = --output-dir=. - -HFILE_GLOB = $(top_srcdir)/include/*.h -CFILE_GLOB = $(top_srcdir)/src/*.c $(top_srcdir)/src/*.h - -IGNORE_HFILES = connman connman.h - -HTML_IMAGES = - -content_files = connman-introduction.xml - -INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/gdbus \ - $(GTHREAD_CFLAGS) $(GMODULE_CFLAGS) $(GLIB_CFLAGS) $(DBUS_CFLAGS) - -GTKDOC_LIBS = $(DBUS_LIBS) $(GLIB_LIBS) $(GMODULE_LIBS) $(GTHREAD_LIBS) - -MAINTAINERCLEANFILES = Makefile.in \ - $(DOC_MODULE).types $(DOC_MODULE)-*.txt *.sgml *.bak - -if ENABLE_GTK_DOC -include $(top_srcdir)/doc/gtk-doc.make -else -EXTRA_DIST = $(DOC_MAIN_SGML_FILE) connman-introduction.xml -endif diff --git a/doc/advanced-configuration.txt b/doc/advanced-configuration.txt old mode 100644 new mode 100755 index 3c08c8f..12c2250 --- a/doc/advanced-configuration.txt +++ b/doc/advanced-configuration.txt @@ -5,7 +5,7 @@ Advanced configuration interface Configuration basics ==================== -The default configuration method for all servers is automatic or something +The default configuration method for all services is automatic or something like DHCP. In almost every case that should be just good enough, but if it is not, Connection Manager supports manual configuration for Ethernet and IP settings. @@ -44,12 +44,12 @@ configuration this call could be used: "Netmask": "255.255.255.0" }) The configuration itself is a dictionary with various fields. Not all of -them need to present. A lot of combinations are valid. +them need to be present. A lot of combinations are valid. For example the "Method" field has valid settings of "off", "fixed", "manual" and "dhcp". The "fixed" value however can not be set by any user program. It is an internal value that some 3G cards require. Switching to "off" will -remove and IP configuration from the interface. The "manual" method allows +remove any IP configuration from the interface. The "manual" method allows for static address configuration. And "dhcp" will use DHCP to retrieve all required information automatically. diff --git a/doc/agent-api.txt b/doc/agent-api.txt old mode 100644 new mode 100755 index 91371af..2ddd19a --- a/doc/agent-api.txt +++ b/doc/agent-api.txt @@ -23,6 +23,16 @@ Methods void Release() Possible Errors: net.connman.Agent.Error.Retry + void ReportPeerError(object peer, string error) + + This method gets called when an error has to be + reported to the user about a peer connection. + + A special return value can be used to trigger a + retry of the failed transaction. + + Possible Errors: net.connman.Agent.Error.Retry + void RequestBrowser(object service, string url) This method gets called when it is required @@ -58,6 +68,25 @@ Methods void Release() Possible Errors: net.connman.Agent.Error.Canceled net.connman.Agent.Error.LaunchBrowser + dict RequestPeerAuthorization(object peer, dict fields) [experimental] + + This method gets called when trying to connect to a + peer or when an incoming peer connection is requested, + for which some extra input is required. In this case, + it will only deal with WPS input as well as accepting + or rejecting an incoming connection. + + The return value should be a dictionary where the + keys are the field names and the values are the + actual fields. Alternatively an error indicating that + the request got canceled or rejected can be returned. + + The dictionary arguments contains field names with + their input parameters. + + Possible Errors: net.connman.Agent.Error.Canceled + net.connman.Agent.Error.Rejected + void Cancel() This method gets called to indicate that the agent @@ -94,7 +123,9 @@ Fields string Name provided as an informational argument when connecting with it does not work anymore, for instance when it has been changed on the AP. Such argument appears when - a RequestInput is raised after a retry. + a RequestInput is raised after a retry. In case of WPS + association through PIN method: when retrying, the + previous wpspin will be provided. string WPS @@ -105,6 +136,9 @@ Fields string Name method, or a pin code if user wants to use the pin method. + In case of a RequestPeerAuthorization, this field will + be set as mandatory. + string Username Username for WISPr authentication. This field will be @@ -197,6 +231,23 @@ Examples Requesting a passphrase for WPA2 network ==> { "WPS" : "123456" } + Requesting a passphrase for a WPA2 network with WPS alternative + after an error on the previous one: + + RequestInput("/service3", + { "Passphrase" : { "Type" : "psk", + "Requirement" : "mandatory", + "Alternates" : [ "WPS" ] + }, + "WPS" : { "Type" : "wpspin", + "Requirement" : "alternate" + } + "PreviousPassphrase" : + { "Type" : "wpspin", + "Requirement : "informational", + "Value" : "123456" + } + Requesting passphrase for a WPA-Enterprise network: RequestInput("/service4", @@ -235,3 +286,20 @@ Examples Requesting a passphrase for WPA2 network } ==> { "Username" : "foo", "Password": "secret" } + + Requesting a answer about an inconming peer connection: + + RequestPeerAuthorization("/peer3", {}) + + ==> { } + + Requesting the WPS details when connecting to a peer: + + RequestPeerAuthorization("/peer4", + { "WPS": + { "Type" : "wpspin", + "Requirement" : "mandatory" + } + } + + ==> { "WPS" : "" } diff --git a/doc/backtrace.txt b/doc/backtrace.txt old mode 100644 new mode 100755 diff --git a/doc/behavior-api.txt b/doc/behavior-api.txt old mode 100644 new mode 100755 diff --git a/doc/clock-api.txt b/doc/clock-api.txt old mode 100644 new mode 100755 diff --git a/doc/config-format.txt b/doc/config-format.txt old mode 100644 new mode 100755 index 4f76832..b16f4e4 --- a/doc/config-format.txt +++ b/doc/config-format.txt @@ -5,40 +5,74 @@ Connman uses configuration files to provision existing services. Connman will be looking for its configuration files at STORAGEDIR which by default points to /var/lib/connman/. Configuration file names must not include other characters than letters or numbers and must have a .config suffix. -Those configuration files are text files with a simple format and we typically -have one file per provisioned network. +Those configuration files are text files with a simple key-value pair format, +organized into sections. Values do not comprise leading or trailing whitespace. +We typically have one file per provisioned network. If the config file is removed, then Connman tries to remove the -provisioned service. If individual service entry inside config is removed, -then the corresponding provisioned service is removed. If service -entry is changed, then corresponding service is removed and then -immediately re-provisioned. +provisioned services. If an individual service inside a config is removed, +then the corresponding provisioned service is removed. If a service section +is changed, then the corresponding service is removed and immediately +re-provisioned. -Global entry [global] -===================== +Global section [global] +======================= -These files can have an optional global entry describing the actual file. -The 2 allowed fields for that entry are: +These files can have an optional global section describing the actual file. +The two allowed fields for this section are: - Name: Name of the network. - Description: Description of the network. -- Protected: Configuration protection against being removed, modified or -overwritten by a Manager.ProvisionService() call. If unset, this value defaults -to TRUE, i.e. configs are protected by default. -Service entry [service_*] -========================= +Service sections [service_*] +============================ Each provisioned service must start with the [service_*] tag. Replace * with an identifier unique to the config file. Allowed fields: -- Type: Service type. We currently only support wifi. +- Type: Service type. We currently only support wifi and ethernet. +- IPv4: The IPv4 address, netmask and gateway. Format of the entry + is network/netmask/gateway. The mask length can be used instead + of netmask. The gateway can be omitted if necessary. + The IPv4 field can also contain the string "off" or "dhcp". + If the setting is "off", then no IPv4 address is set to the interface. + If the setting is "dhcp", then DHCPv4 address resolution is activated. + Example: 192.168.1.2/24/192.168.1.1 + 192.168.200.100/255.255.255.0/192.168.200.1 + 10.0.0.2/24 +- IPv6: The IPv6 address, prefix length and gateway. Format of the entry + is network/prefixlen/gateway. For IPv6 addresses only prefix length is + accepted. The gateway can be omitted if necessary. + The IPv6 field can also contain the string "off" or "auto". + If the setting is "off", then no IPv6 address is set to the interface. + If the setting is "auto", then SLAAC or DHCPv6 is used. + Example: 2001:db8::2/64/2001:db8::1 + 2001:db8::1:2:3:4/64 +- IPv6.Privacy: IPv6 privacy option. Value can be either "disabled", + "enabled" or "preferred" (or the misspelled "prefered"). See use_tempaddr + variable description in Linux kernel Documentation/networking/ip-sysctl.txt + file. +- MAC: MAC address of the interface where this setting should be applied. + The MAC address is optional and if it is missing, then the first found + interface is used. The byte values must have prefix 0 added, + the bytes must be separated by ":" char and its length must be + exactly 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 = 17 characters. +- Nameservers: Comma separated list of nameservers +- SearchDomains: Comma separated list of DNS search domains +- Timeservers: Comma separated list of timeservers +- Domain: Domain name to be used + +If IPv4 address is missing then DHCP is used. If IPv6 address is missing, +then SLAAC or DHCPv6 is used. + +The following options are valid if Type is "wifi" - Name: A string representation of an 802.11 SSID. If the SSID field is present, the Name field is ignored. -- SSID: A hexadecimal representation of an 802.11 SSID. If the SSID field is - omitted, the Name field is used instead. +- SSID: A hexadecimal representation of an 802.11 SSID. Use this format to + encode special characters including starting or ending spaces. If the SSID + field is omitted, the Name field is used instead. - EAP: EAP type. We currently only support tls, ttls or peap. - CACertFile: File path to CA certificate file (PEM/DER). - ClientCertFile: File path to client certificate file (PEM/DER). @@ -53,20 +87,25 @@ Allowed fields: Prefix the value with "EAP-" to indicate the usage of an EAP-based inner authentication method (should only be used with EAP = TTLS). - Passphrase: RSN/WPA/WPA2 Passphrase +- Security: The security type of the network. Possible values are 'psk' + (WPA/WPA2 PSK), 'ieee8021x' (WPA EAP), 'none' and 'wep'. When not set, the + default value is 'ieee8021x' if an EAP type is configured, 'psk' if a + passphrase is present and 'none' otherwise. +- Hidden: If set to true, then this AP is hidden. If missing or set to false, + then AP is not hidden. -Example -======= +Examples +======== This is a configuration file for a network providing EAP-TLS, EAP-TTLS and -EAP-PEAP services. -The respective SSIDs are tls_ssid, ttls_ssid and peap_ssid and the file name -is example.config. +EAP-PEAP services. The respective SSIDs are tls_ssid, ttls_ssid and peap_ssid +and the file name is example.config. + Please note that the SSID entry is for hexadecimal encoded SSID (e.g. "SSID = 746c735f73736964"). If your SSID does not contain any exotic character then you should use the Name entry instead (e.g. "Name = tls_ssid"). - example@example:[~]$ cat /var/lib/connman/example.config [global] Name = Example @@ -97,3 +136,20 @@ EAP = peap CACertFile = /home/user/.cert/ca.pem Phase2 = MSCHAPV2 Identity = user + +[service_home_ethernet] +Type = ethernet +IPv4 = 192.168.1.42/255.255.255.0/192.168.1.1 +IPv6 = 2001:db8::42/64/2001:db8::1 +MAC = 01:02:03:04:05:06 +Nameservers = 10.2.3.4,192.168.1.99 +SearchDomains = my.home,isp.net +Timeservers = 10.172.2.1,ntp.my.isp.net +Domain = my.home + +[service_home_wifi] +Type = wifi +Name = my_home_wifi +Passphrase = secret +IPv4 = 192.168.2.2/255.255.255.0/192.168.2.1 +MAC = 06:05:04:03:02:01 diff --git a/doc/connman-docs.xml b/doc/connman-docs.xml deleted file mode 100644 index d4059a4..0000000 --- a/doc/connman-docs.xml +++ /dev/null @@ -1,121 +0,0 @@ - - -]> - - - Connection Manager Reference Manual - Version &version; - - - Marcel - Holtmann - -
- marcel@holtmann.org -
-
-
-
- - - 2007-2008 - Intel Corporation. All rights reserved. - - - - - Permission is granted to copy, distribute and/or modify this - document under the terms of the GNU Free - Documentation License, Version 1.1 or any later - version published by the Free Software Foundation with no - Invariant Sections, no Front-Cover Texts, and no Back-Cover - Texts. You may obtain a copy of the GNU Free - Documentation License from the Free Software - Foundation by visiting their Web site or by writing - to: - -
- The Free Software Foundation, Inc., - 59 Temple Place - Suite 330, - Boston, MA 02111-1307, - USA -
-
-
-
- - - Design Overview - - - This part presents the design documentation for Connection Manager. - - - - - - - Manager interface - - - - - - - Device interface - - - - - - - Network interface - - - - - - - Service interface - - - - - - - Connection interface - - - - - - - Plugin API Reference - - - This part presents the function reference for Connection Manager. - - - - - - - - - - - - - License - - - - - - - Index - -
diff --git a/doc/connman-introduction.xml b/doc/connman-introduction.xml deleted file mode 100644 index 4672c2c..0000000 --- a/doc/connman-introduction.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - Introduction - - - About - - - - - - diff --git a/doc/connman.8 b/doc/connman.8 new file mode 100755 index 0000000..7297cf8 --- /dev/null +++ b/doc/connman.8 @@ -0,0 +1,79 @@ +.\" connman(8) manual page +.\" +.\" Copyright (C) 2012 Intel Corporation +.\" +.TH CONNMAN "8" "21 August 2012" +.SH NAME +ConnMan \- network management daemon +.SH SYNOPSIS +.B connmand [\-\-version] | [\-\-help] +.PP +.B connmand [\-\-config=] [\-\-debug=::...] [\-\-device=,,...] [\-\-nodevice=,,..] [\-\-wifi=,,...] [\-\-plugin=,,...] [\-\-noplugin=,,...] [\-\-nodaemon] [\-\-nodnsproxy] +.SH DESCRIPTION +The \fIConnMan\fP provides a daemon for managing internet connections +within devices running the Linux operating system. The Connection Manager is +designed to be slim and to use as few resources as possible. +It is a fully modular system that can be extended, through plug-ins, +to support all kinds of wired or wireless technologies. +Also, configuration methods, like DHCP and domain name resolving, +are implemented using plug-ins. +The plug-in approach allows for easy adaption and modification for various +use cases. +.P +.SH OPTIONS +The following options are supported: +.TP +.I "\-\-version" +Print the ConnMan software version and exit. +.TP +.I "\-\-help" +Print ConnMan's available options and exit. +.TP +.I "\-\-config=" +Specify configuration file to set up various settings for ConnMan. If not +specified, the default value of '/connman/main.conf' +is used; where is dependent on your distribution (usually +it's /etc). See \fBconnman.conf\fP(5) for more information on configuration +file. The use of config file is optional and sane default values +are used if config file is missing. +.TP +.I "\-\-debug=::..." +Sets how much information ConnMan sends to the log destination (usually +syslog's "daemon" facility). If the file options are omitted, then debugging +information from all the source files are printed. If file options are +present, then only debug prints from that source file are printed. +Example: --debug=src/service.c:plugins/wifi.c +.TP +.I "\-\-device=,,..." +Only manage these network interfaces. By default all network interfaces +are managed. +.TP +.I "\-\-nodevice=,,..." +Never manage these network interfaces. +.TP +.I "\-\-plugin=,,..." +Load these plugins only. The option can be a pattern containing +"*" and "?" characters. +.TP +.I "\-\-noplugin=,,..." +Never load these plugins. The option can be a pattern containing +"*" and "?" characters. +.TP +.I "\-\-wifi=,,..." +Wifi driver that WiFi/Supplicant should use. If omitted, then the value +of "nl80211,wext" is used by default. +.TP +.I "\-\-nodaemon" +Do not daemonize. This is useful for debugging, and directs log output to +the controlling terminal in addition to syslog. +.TP +.I "\-\-nodnsproxy" +Do not act as a DNS proxy. By default ConnMan will direct all DNS traffic +to itself by setting nameserver to 127.0.0.1 in \fBresolv.conf\fP(5) file. +If this is not desired and you want that all programs call directly some +DNS server, then you can use the --nodnsproxy option. +If this option is used, then ConnMan is not able to cache the DNS queries +because the DNS traffic is not going through ConnMan and that can cause +some extra network traffic. +.SH SEE ALSO +.BR connman.conf (5). diff --git a/doc/connman.conf.5 b/doc/connman.conf.5 new file mode 100755 index 0000000..c1ca75c --- /dev/null +++ b/doc/connman.conf.5 @@ -0,0 +1,135 @@ +.\" connman.conf(5) manual page +.\" +.\" Copyright (C) 2012 Intel Corporation +.\" +.TH "connman.conf" "5" "21 August 2012" "" +.SH NAME +main.conf \- ConnMan configuration file +.SH SYNOPSIS +/etc/connman/main.conf +.br +or +.br +\fI\fP/connman/main.conf +.br +where depends on your distribution or build. +.SH DESCRIPTION +.P +.I main.conf +is a configuration file for ConnMan. The configuration file is +optional but it can be used to set up various aspects of ConnMan's +behavior. The location of the file may be changed through use of +the "\-\-config=" argument for \fBconnman\fP (8). +.SH "FILE FORMAT" +.P +The configuration file format is key file format. +It consists of sections (groups) of key-value pairs. +Lines beginning with a '#' and blank lines are considered comments. +Sections are started by a header line containing the section enclosed +in '[' and ']', and ended implicitly by the start of the next section +or the end of the file. Each key-value pair must be contained in a section. +.P +Description of sections and available keys follows: +.SS [General] +This section is the only mandatory section of the configuration file. +.TP +.B InputRequestTimeout=\fPsecs\fP +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. +.TP +.B BrowserLaunchTimeout=\fPsecs\fP +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. +.TP +.B BackgroundScanning=\fPtrue|false\fP +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. +.TP +.B FallbackTimeservers=\fPserver1,server2,...\fP +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. +.TP +.B FallbackNameservers=\fPserver1,server2,...\fP +List of fallback nameservers separated by "," appended +to the list of nameservers given by the service. The +nameserver entries must be in numeric format, host +names are ignored. +.TP +.B DefaultAutoConnectTechnologies=\fPtechnology1,technology2,...\fP +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. +.TP +.B PreferredTechnologies=\fPtechnology1,technology2,...\fP +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. +.TP +.B NetworkInterfaceBlacklist=\fPinterface1,interface2,...\fP +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. +.TP +.B AllowHostnameUpdates=\fPtrue|false\fP +Allow connman to change the system hostname. This can +happen for example if we receive DHCP hostname option. +Default value is true. +.TP +.B SingleConnectedTechnology=\fPtrue|false\fP +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. +.TP +.B TetheringTechnologies=\fPtechnology1,technology2,...\fP +List of technologies that are allowed to enable tethering separated by ",". +The default value is wifi,bluetooth,gadget. Only those technologies listed +here are used for tethering. If one wants to tether ethernet, +then add "ethernet" in the list. +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. +.TP +.B PersistentTetheringMode=\fPtrue|false\fP +Restore earlier tethering status when returning from offline mode, +re-enabling a technology, and after restarts and reboots. +Default value is false. +.TP +.B Enable6to4=\fPtrue|false\fP +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). +.SH "SEE ALSO" +.BR Connman (8) diff --git a/doc/counter-api.txt b/doc/counter-api.txt old mode 100644 new mode 100755 diff --git a/doc/gtk-doc.make b/doc/gtk-doc.make deleted file mode 100644 index 354ffb7..0000000 --- a/doc/gtk-doc.make +++ /dev/null @@ -1,173 +0,0 @@ -# -*- mode: makefile -*- - -#################################### -# Everything below here is generic # -#################################### - -if GTK_DOC_USE_LIBTOOL -GTKDOC_CC = $(LIBTOOL) --mode=compile $(CC) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -GTKDOC_LD = $(LIBTOOL) --mode=link $(CC) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -else -GTKDOC_CC = $(CC) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -GTKDOC_LD = $(CC) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -endif - -# We set GPATH here; this gives us semantics for GNU make -# which are more like other make's VPATH, when it comes to -# whether a source that is a target of one rule is then -# searched for in VPATH/GPATH. -# -GPATH = $(srcdir) - -TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE) - -EXTRA_DIST = \ - $(content_files) \ - $(HTML_IMAGES) \ - $(DOC_MAIN_SGML_FILE) \ - $(DOC_MODULE)-sections.txt \ - $(DOC_MODULE)-overrides.txt - -DOC_STAMPS=scan-build.stamp tmpl-build.stamp sgml-build.stamp html-build.stamp \ - $(srcdir)/tmpl.stamp $(srcdir)/sgml.stamp $(srcdir)/html.stamp - -SCANOBJ_FILES = \ - $(DOC_MODULE).args \ - $(DOC_MODULE).hierarchy \ - $(DOC_MODULE).interfaces \ - $(DOC_MODULE).prerequisites \ - $(DOC_MODULE).signals - -REPORT_FILES = \ - $(DOC_MODULE)-undocumented.txt \ - $(DOC_MODULE)-undeclared.txt \ - $(DOC_MODULE)-unused.txt - -CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) - -if ENABLE_GTK_DOC -all-local: html-build.stamp -else -all-local: -endif - -docs: html-build.stamp - -#### scan #### - -scan-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB) - @echo 'gtk-doc: Scanning header files' - @-chmod -R u+w $(srcdir) - cd $(srcdir) && \ - gtkdoc-scan --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --ignore-headers="$(IGNORE_HFILES)" $(SCAN_OPTIONS) $(EXTRA_HFILES) - if grep -l '^..*$$' $(srcdir)/$(DOC_MODULE).types > /dev/null 2>&1 ; then \ - CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" CFLAGS="$(GTKDOC_CFLAGS)" LDFLAGS="$(GTKDOC_LIBS)" gtkdoc-scangobj $(SCANGOBJ_OPTIONS) --module=$(DOC_MODULE) --output-dir=$(srcdir) ; \ - else \ - cd $(srcdir) ; \ - for i in $(SCANOBJ_FILES) ; do \ - test -f $$i || touch $$i ; \ - done \ - fi - touch scan-build.stamp - -$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp - @true - -#### templates #### - -tmpl-build.stamp: $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt - @echo 'gtk-doc: Rebuilding template files' - @-chmod -R u+w $(srcdir) - cd $(srcdir) && gtkdoc-mktmpl --module=$(DOC_MODULE) $(MKTMPL_OPTIONS) - touch tmpl-build.stamp - -tmpl.stamp: tmpl-build.stamp - @true - -tmpl/*.sgml: - @true - - -#### xml #### - -sgml-build.stamp: tmpl.stamp $(HFILE_GLOB) $(CFILE_GLOB) $(DOC_MODULE)-sections.txt $(srcdir)/tmpl/*.sgml $(expand_content_files) - @echo 'gtk-doc: Building XML' - @-chmod -R u+w $(srcdir) - cd $(srcdir) && \ - gtkdoc-mkdb --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --output-format=xml --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) $(MKDB_OPTIONS) - touch sgml-build.stamp - -sgml.stamp: sgml-build.stamp - @true - -#### html #### - -html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) - @echo 'gtk-doc: Building HTML' - @-chmod -R u+w $(srcdir) - rm -rf $(srcdir)/html - mkdir $(srcdir)/html - cd $(srcdir)/html && gtkdoc-mkhtml $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE) - test "x$(HTML_IMAGES)" = "x" || ( cd $(srcdir) && cp $(HTML_IMAGES) html ) - @echo 'gtk-doc: Fixing cross-references' - cd $(srcdir) && gtkdoc-fixxref --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) - touch html-build.stamp - -############## - -clean-local: - rm -f *~ *.bak - rm -rf .libs - -distclean-local: - cd $(srcdir) && \ - rm -rf xml $(REPORT_FILES) \ - $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt - -maintainer-clean-local: clean - cd $(srcdir) && rm -rf xml html - -install-data-local: - -installfiles=`echo $(srcdir)/html/*`; \ - if test "$$installfiles" = '$(srcdir)/html/*'; \ - then echo '-- Nothing to install' ; \ - else \ - $(mkinstalldirs) $(DESTDIR)$(TARGET_DIR); \ - for i in $$installfiles; do \ - echo '-- Installing '$$i ; \ - $(INSTALL_DATA) $$i $(DESTDIR)$(TARGET_DIR); \ - done; \ - echo '-- Installing $(srcdir)/html/index.sgml' ; \ - $(INSTALL_DATA) $(srcdir)/html/index.sgml $(DESTDIR)$(TARGET_DIR) || :; \ - which gtkdoc-rebase >/dev/null && \ - gtkdoc-rebase --relative --dest-dir=$(DESTDIR) --html-dir=$(DESTDIR)$(TARGET_DIR) ; \ - fi - - -uninstall-local: - rm -f $(DESTDIR)$(TARGET_DIR)/* - -# -# Require gtk-doc when making dist -# -if ENABLE_GTK_DOC -dist-check-gtkdoc: -else -dist-check-gtkdoc: - @echo "*** gtk-doc must be installed and enabled in order to make dist" - @false -endif - -dist-hook: dist-check-gtkdoc dist-hook-local - mkdir $(distdir)/tmpl - mkdir $(distdir)/xml - mkdir $(distdir)/html - -cp $(srcdir)/tmpl/*.sgml $(distdir)/tmpl - -cp $(srcdir)/xml/*.xml $(distdir)/xml - cp $(srcdir)/html/* $(distdir)/html - -cp $(srcdir)/$(DOC_MODULE).types $(distdir)/ - -cp $(srcdir)/$(DOC_MODULE)-sections.txt $(distdir)/ - cd $(distdir) && rm -f $(DISTCLEANFILES) - -gtkdoc-rebase --online --relative --html-dir=$(distdir)/html - -.PHONY : dist-hook-local docs diff --git a/doc/ipconfig-api.txt b/doc/ipconfig-api.txt old mode 100644 new mode 100755 diff --git a/doc/manager-api.txt b/doc/manager-api.txt old mode 100644 new mode 100755 index 3bd201d..31e137c --- a/doc/manager-api.txt +++ b/doc/manager-api.txt @@ -39,7 +39,14 @@ Methods dict GetProperties() Possible Errors: [service].Error.InvalidArguments - object ConnectProvider(dict provider) + array{object,dict} GetPeers() [experimental] + + Returns a sorted list of tuples with peer object path + and dictionary of peer properties + + Possible Errors: [service].Error.InvalidArguments + + object ConnectProvider(dict provider) [deprecated] Connect to a VPN specified by the given provider properties. @@ -58,8 +65,16 @@ Methods dict GetProperties() When 'SessionMode' property is enabled, this method call is disallowed. + This API is deprecated and should not be used. + The VPN configuration API is provided by ConnMan + VPN daemon and user should use that one instead. + Possible Errors: [service].Error.InvalidArguments + void RemoveProvider(object path) [deprecated] + + Remove a VPN specified by the object path. + void RegisterAgent(object path) Register new agent for handling user requests. @@ -141,6 +156,44 @@ Methods dict GetProperties() Possible Errors: [service].Error.InvalidArguments + void RegisterPeerService(dict specification, boolean master) + [experimental] + + Registers a local P2P Peer service + + Even if p2p techonology is not available, it will be + possible to register peer services, since a p2p + enabled WiFi device might appear at anytime. The + registered peer services will automatically be enabled + for the p2p WiFi device; the application does not need + to do any re-registration. + + A Peer service belongs to the process that registers + it, thus if that process dies, its Peer services will + be destroyed as well. + + The specification dict follows the format described + in the Peer API document. + + ConnMan will be able to determine in most cases + whether to be the P2P Group Owner or not. If the + service for some reason must belong to a group that + this device manages, the "master" property can be + set. Do not enable the "master" property unless it + is absolutely sure that this is needed for the + provided peer service. + + Possible Errors: [service].Error.InvalidArguments + [service].Error.AlreadyExists + [service].Error.NotSupported + + void UnregisterPeerService(dict specification) [experimental] + + Unregisters an existing local P2P Peer service + + Possible Errors: [service].Error.InvalidArguments + [service].Error.NotRegistered + Signals TechnologyAdded(object path, dict properties) Signal that is sent when a new technology is added. @@ -150,7 +203,7 @@ Signals TechnologyAdded(object path, dict properties) TechnologyRemoved(object path) - Signal that is sent when a modem has been removed. + Signal that is sent when a technology has been removed. The object path is no longer accessible after this signal and only emitted for reference. @@ -178,6 +231,28 @@ Signals TechnologyAdded(object path, dict properties) required to watch the PropertyChanged signal of the service object. + PeersChanged(array{object, dict}, array{object}) [experimental] + + Signals a list of peers that have been changed via the + first array. And a list of peer that have been removed + via the second array. + + The list of changed peers is sorted. The dictionary + with the properties might be empty in case none of the + properties have changed. Or only contains the + properties that have changed. + + For newly added peers the whole set of properties will + be present. + + The list of removed peers can be empty. + + This signal will only be triggered when the sort order + of the peer list or the number of peers changes. It + will not be emitted if only a property of the peer + object changes. For that it is required to watch the + PropertyChanged signal of the peer object. + PropertyChanged(string name, variant value) This signal indicates a changed value of the given @@ -224,11 +299,9 @@ Properties string State [readonly] the limited usage of WiFi or Bluetooth devices might be allowed in some situations. - boolean SessionMode [readwrite] [experminental] + boolean SessionMode [readwrite] [experminental][deprecated] - This disables the auto connect feature. It should be - enabled when the Session API is used. When SessionMode - is enabled, 'ConnectService' and 'ConnectProvider' - method calls are disallowed. + This property exists only for compatibility reasons + and does not affect ConnMan in any way. The default value is false. diff --git a/doc/overview-api.txt b/doc/overview-api.txt old mode 100644 new mode 100755 index 14fec14..f126887 --- a/doc/overview-api.txt +++ b/doc/overview-api.txt @@ -99,13 +99,11 @@ delete/remove button. | | Ethernet is special here since the unplugging of the network cable will -remove the favorite selection. +remove the service from the list +---------------------------------------+ | Ethernet with cable | order=1 - favorite=yes +---------------------------------------+ - | Ethernet without cable | order=0 - favorite=no - +---------------------------------------+ | Guest (strength 90, none) | order=0 +---------------------------------------+ | | @@ -143,14 +141,13 @@ A working connection is considered top priority. +---------------------------------------+ | | -Another possible user interaction would be to unplug the Ethernet cable and -in this case the favorite setting will be removed and the service falls back -down in the list. +Another possible user interaction would be to disconnect the Ethernet service +and in this case the service falls back down in the list. +---------------------------------------+ | My WiFi AP (strength 80, rsn) | order=1 - connected=yes +---------------------------------------+ - | Ethernet | order=0 + | Ethernet | order=1 - connected=no +---------------------------------------+ | Guest (strength 90, none) | order=0 +---------------------------------------+ @@ -174,15 +171,11 @@ and are sorted above all others. +---------------------------------------+ | | -Unplugging the Ethernet cable will remove the favorite setting, but due to -the basic ordering of services it will be at the top of the services with an -order number of 0 (directly after all favorite services). +Unplugging the Ethernet cable will remove the Ethernet service. +---------------------------------------+ | My WiFi AP (strength 80, rsn) | order=1 - connected=no +---------------------------------------+ - | Ethernet | order=0 - connected=no - +---------------------------------------+ | Guest (strength 90, none) | order=0 +---------------------------------------+ | | @@ -197,7 +190,7 @@ included in this list. They will only show up once a carrier is detected. The service interface is not meant for basic device configuration task. So switching a device on and off (via RFKILL for example) should be done via -the device interface. +the technology interface. See "Technology interfaces" chapter in this document. Due to limited screen size of small devices and the big amount of WiFi access points that are deployed right now it might be sensible to not show @@ -219,6 +212,19 @@ In case of WiFi this will be the SSID value. The SSID is a binary array and will be converted into printable form. Unprintable characters are replaced with spaces. +In addition to WiFi naming, WiFi networks are subject to a grouping policy +performed around SSID and security type. This means that one service will be +seen for N WiFi networks providing the same SSID and the same security metod. +For instance, if 5 APs are servicing an SSID called "TEST" with WPA2 +authentication and 3 APs are servicing the same SSID with open authentication +method, the user will see only two services listed with the name "TEST" +differentiated by their security type, which are "psk" and "none". Such +policy is also applied to hidden networks, where hidden services will have an +empty name and will be differentiated by the security type. The user has then +to select the one with the right security and the Agent API will request any +required information such as the SSID for the network (See "Application +basics" below). + For Bluetooth the device alias is used. The alias is different since it can be overwritten by the user via the Bluetooth service. The identification is still done based on its address, but the display name might change. In @@ -376,9 +382,14 @@ will result in an error if no cable is plugged in. All connection attempts can fail for one reason or another. Application should be able to handle such errors and will also be notified of changes via signals. -In future versions Connection Manager will interact with an agent to confirm -certain transactions with the user. This functionality is currently not -implemented. +Connection Manager will interact with an agent via the Agent API to confirm +certain transactions with the user. If Connection Manager needs extra +information, it will ask the user for exactly the information it requires, +i.e. passphrase, network's name (for hidden WiFi networks) and more depending +on the use case (e.g. WPS, EAP). Therefore an application environment using +Connection Manager should implement one dedicated Connection Manager agent +according to the Agent API in order to interact with the user. Please see +agent-api.txt for implementation details. To monitor the current status of a service the state property can be used. It gives detailed information about the current progress. @@ -390,3 +401,35 @@ gives detailed information about the current progress. All state changes are also sent via the PropertyChanged signal on the service interface. This allows asynchronous monitoring without having to poll Connection Manager for changes. + + +Technology interfaces +===================== + +When ConnMan is started first time, all technologies except ethernet are +powered off by default. The reason is that the user needs to decide which +technologies are relevant to him and what bearers the user wants to use. +User can use the Technology Powered property to turn on or off a given +technology. See doc/technology-api.txt document for details. + +User can activate offline (flight) mode via Manager OfflineMode property. +While in offline mode, all the technologies including ethernet are +powered off. During the offline mode, the user can temporarily activate +individual technologies by using the Technology Powered property or by +using the rfkill command or Fn-Fx key combination found in some laptops. + +If the host supports rfkill switch, then all the radios can be turned off +by the kernel when the switch is activated. ConnMan will notice this and +remove corresponding technologies from D-Bus. Technologies cannot be +activated while rfkill switch is turned on. When rfkill switch is turned +off (radios are activated), then ConnMan restores the original Powered +status for each activated technology. + +User can use the rfkill command from command line or indirectly via +some UI component to activate/deactivate individual radios found in +the host. ConnMan will listen these rfkill events and set the Powered +property accordingly. ConnMan will not save the rfkill status it has +received. This means that after restarting ConnMan, the original and +saved technology status is used when deciding which technologies should +be powered. If the user uses the Technology D-Bus API to set the Powered +property, then that information is saved and used when ConnMan is restarted. diff --git a/doc/peer-api.txt b/doc/peer-api.txt new file mode 100755 index 0000000..b871f4d --- /dev/null +++ b/doc/peer-api.txt @@ -0,0 +1,103 @@ +Peer hierarchy [EXPERIMENTAL] +============================= + +Service net.connman +Interface net.connman.Peer +Object path [variable prefix]/{peer0,peer1,...} + +Methods dict GetProperties() [deprecated] + + Returns properties for the peer object. See the + properties sections for available properties. + + Usage of this method is highly discouraged. Use + the Manager.GetPeers() method instead. + + Possible Errors: [service].Error.InvalidArguments + + void Connect() [experimental] + + Connect this peer. + + This method call will only return in case of an error + or when the peer is fully connected. So setting a + longer D-Bus timeout might be a really good idea. + + Possible Errors: [service].Error.InvalidArguments + + void Disconnect() [experimental] + + Disconnect this peer. If the peer is not connected, an + error message will be generated. + + Possible Errors: [service].Error.InvalidArguments + +Signals PropertyChanged(string name, variant value) [experimental] + + This signal indicates a changed value of the given + property. + +Properties string State [readonly] [experimental] + + The peer state information. + + Valid state are "idle", "failure", "association", + "configuration", "ready" and "disconnect". + + string Name [readonly] [experimental] + + Name of the peer. + + dict IPv4 [readonly] [experimental] + + string Local [readonly] + + The current peer's local configured IPv4 + address. + + string Remote [readonly] + + The current peer's remote configured IPv4 + address. + + array{dict} Services [readonly] [experimental] + + Array of P2P service specifications consisting of + either UpnpService and UpnpVersion or BonjourQuery + and BonjourResponse, but not a mix of these. The + dict members have the following format: + + String UpnpService [readonly] + + The UPNP service URI. + + int32 UpnpVersion [readonly] + + The UPNP version in use. + + array{byte} BonjourQuery [readonly] + + The bonjour service query data, provided + through a byte array. + + Note: a Peer object will never show this + information. When scanning, a device gets + only the bonjour response data. However, + this information is mandatory when a bonjour + service is given through Manager API + RegisterPeerService and + UnregisterPeerService. + + array{byte} BonjourResponse [readonly] + + The bonjour service response data, provided + through a byte array. + + Note: this will be the only bonjour related + information a Peer object will show. + + array{byte} WiFiDisplayIEs [readonly] + + The TLV formated byte array representing the + WiFi Display Informations Elements. + diff --git a/doc/plugin-api.txt b/doc/plugin-api.txt old mode 100644 new mode 100755 index b39c043..616938b --- a/doc/plugin-api.txt +++ b/doc/plugin-api.txt @@ -22,3 +22,143 @@ static void example_exit(void) CONNMAN_PLUGIN_DEFINE(example, "Example plugin", CONNMAN_VERSION, example_init, example_exit) + + +Infrastructure for plugins +========================== + +The Connection Manager provides a very good infrastructure for plugins to +interface with the core functionalities of ConnMan. The infrastructure is +well divided into the concepts of Technology, Device and Network, among +others. + +Technology infrastructure +========================= + +A Technology in ConnMan is an abstract representation of the different +kinds of technologies it supports such as WiFi, Ethernet, Bluetooth and +Celullar. The technologies support are added to ConnMan through plugins, such +as plugins/bluetooth.c for the Bluetooth Technology or plugins/wifi.c for the +WiFi Technology. Each new technology plugin needs to register itself as a +Technology with ConnMan. As an example we will take a look at the Bluetooth +plugin registration. As a first step 'struct connman_technology_driver' needs +to be defined: + + static struct connman_technology_driver tech_driver = { + .name = "bluetooth", + .type = CONNMAN_SERVICE_TYPE_BLUETOOTH, + .probe = bluetooth_tech_probe, + .remove = bluetooth_tech_remove, + .set_tethering = bluetooth_tech_set_tethering, + }; + +More functions can be defined depending on the purpose of the plugin. All +vtable's supported functions can be seen in include/technology.h. If a +completely new technology type is added 'enum connman_service_type' in +include/service.h needs to be extended accordingly. This inclusion comes in +the form of Service because ultimately a new technology introduces a new +Service. New technologies can also reuse existing Services types. + +To make the Connection Manager aware of the new Technology plugin we need to +register its driver by calling 'connman_technology_driver_register()' in the +plugin initialization function, bluetooth_init() in this example: + + connman_technology_driver_register(&tech_driver); + +In this document the error check is supressed for the sake of simplicity. +All plugins should check return values in driver registration functions. + +After this call ConnMan becomes aware of the new Technology plugin and will +call the probe() method when the new technology is recognized by the system. For +the Bluetooth plugin for example probe() would be called when a Bluetooth +adapter is recognized. A Technology is only probed if there exists at least +one device of such technology plugged into the system. + +Complementary, the technology must be unregistered on the plugin exit function +through 'connman_technology_driver_unregister()'. + +Device infrastructure +===================== + +A Device represents a real device of a given Technology, there could be many +devices per technology. To enable ConnMan to handle Devices a device driver +needs to be registered. Using the Bluetooth plugin as example it would have to +define a 'struct connman_device_driver': + + static struct connman_device_driver device_driver = { + .name = "bluetooth", + .type = CONNMAN_DEVICE_TYPE_BLUETOOTH, + .probe = bluetooth_device_probe, + .remove = bluetooth_device_remove, + .enable = bluetooth_device_enable, + .disable = bluetooth_device_disable, + }; + +And to register the driver: + + connman_device_driver_register(&device_driver); + +'connman_device_driver_register()' is called during the plugin initialization +process, not necessarily at the plugin init function. + +In this document the error check is supressed for the sake of simplicity. +All plugins should check return values in driver registration functions. + +Additionally code to handle the detection of new devices needs to be written +for each plugin, the bluetooth plugin does so by registering watchers for the +BlueZ D-Bus interface. Once a new Bluetooth Device appears the plugin needs to +notify ConnMan core by calling connman_device_create(), for the bluetooth +plugin the call would be: + + struct connman_device *device; + + device = connman_device_create("bluetooth", + CONNMAN_DEVICE_TYPE_BLUETOOTH) + +ConnMan core will then register the bluetooth device as a Device entity and +call the probe() function from the bluetooth plugin device driver. If a +Technology entity for the Device type doesn't exist it will be created and +Technology probe() function in the bluetooth technology driver is called. + +For the Bluetooth plugin a Device represents the local Bluetooth Adapter +plugged in the system. + +To learn how to use the connman_device_*() functions such as +connman_device_set_powered() and connman_device_ref() see src/device.c for +its API documentation. + +Network infrastructure +====================== + +The Connection Manager provides a mean to plugins handle the specifics of +establishing/handling a connection for each type of Technology. For the +bluetooth plugin a connman_network_driver needs to be registered: + + static struct connman_network_driver network_driver = { + .name = "bluetooth", + .type = CONNMAN_NETWORK_TYPE_BLUETOOTH_PAN, + .probe = bluetooth_pan_probe, + .remove = bluetooth_pan_remove, + .connect = bluetooth_pan_connect, + .disconnect = bluetooth_pan_disconnect, + }; + +And then call the register function: + + connman_network_driver_register(&network_driver); + +In this document the error check is supressed for the sake of simplicity. +All plugins should check return values in driver registration functions. + +The next step would be the probe of a Network entity, for the bluetooth +plugin this would happen when a new device that supports the PAN NAP role is +paired with the system. ConnMan then call connman_device_add_network() to +associate the new Network with the existing Device entity (the local Bluetooth +Adapter). + +Then in the vtable's connect method all the needed pieces to perform a +connection shall be perfomed. + +To learn how to use the connman_network_*() functions such as +connman_network_set_index() and connman_network_set_connected() see +src/network.c for its API documentation. diff --git a/doc/rfc1035.txt b/doc/rfc1035.txt deleted file mode 100644 index b1a9bf5..0000000 --- a/doc/rfc1035.txt +++ /dev/null @@ -1,3077 +0,0 @@ -Network Working Group P. Mockapetris -Request for Comments: 1035 ISI - November 1987 -Obsoletes: RFCs 882, 883, 973 - - DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION - - -1. STATUS OF THIS MEMO - -This RFC describes the details of the domain system and protocol, and -assumes that the reader is familiar with the concepts discussed in a -companion RFC, "Domain Names - Concepts and Facilities" [RFC-1034]. - -The domain system is a mixture of functions and data types which are an -official protocol and functions and data types which are still -experimental. Since the domain system is intentionally extensible, new -data types and experimental behavior should always be expected in parts -of the system beyond the official protocol. The official protocol parts -include standard queries, responses and the Internet class RR data -formats (e.g., host addresses). Since the previous RFC set, several -definitions have changed, so some previous definitions are obsolete. - -Experimental or obsolete features are clearly marked in these RFCs, and -such information should be used with caution. - -The reader is especially cautioned not to depend on the values which -appear in examples to be current or complete, since their purpose is -primarily pedagogical. Distribution of this memo is unlimited. - - Table of Contents - - 1. STATUS OF THIS MEMO 1 - 2. INTRODUCTION 3 - 2.1. Overview 3 - 2.2. Common configurations 4 - 2.3. Conventions 7 - 2.3.1. Preferred name syntax 7 - 2.3.2. Data Transmission Order 8 - 2.3.3. Character Case 9 - 2.3.4. Size limits 10 - 3. DOMAIN NAME SPACE AND RR DEFINITIONS 10 - 3.1. Name space definitions 10 - 3.2. RR definitions 11 - 3.2.1. Format 11 - 3.2.2. TYPE values 12 - 3.2.3. QTYPE values 12 - 3.2.4. CLASS values 13 - - - -Mockapetris [Page 1] - -RFC 1035 Domain Implementation and Specification November 1987 - - - 3.2.5. QCLASS values 13 - 3.3. Standard RRs 13 - 3.3.1. CNAME RDATA format 14 - 3.3.2. HINFO RDATA format 14 - 3.3.3. MB RDATA format (EXPERIMENTAL) 14 - 3.3.4. MD RDATA format (Obsolete) 15 - 3.3.5. MF RDATA format (Obsolete) 15 - 3.3.6. MG RDATA format (EXPERIMENTAL) 16 - 3.3.7. MINFO RDATA format (EXPERIMENTAL) 16 - 3.3.8. MR RDATA format (EXPERIMENTAL) 17 - 3.3.9. MX RDATA format 17 - 3.3.10. NULL RDATA format (EXPERIMENTAL) 17 - 3.3.11. NS RDATA format 18 - 3.3.12. PTR RDATA format 18 - 3.3.13. SOA RDATA format 19 - 3.3.14. TXT RDATA format 20 - 3.4. ARPA Internet specific RRs 20 - 3.4.1. A RDATA format 20 - 3.4.2. WKS RDATA format 21 - 3.5. IN-ADDR.ARPA domain 22 - 3.6. Defining new types, classes, and special namespaces 24 - 4. MESSAGES 25 - 4.1. Format 25 - 4.1.1. Header section format 26 - 4.1.2. Question section format 28 - 4.1.3. Resource record format 29 - 4.1.4. Message compression 30 - 4.2. Transport 32 - 4.2.1. UDP usage 32 - 4.2.2. TCP usage 32 - 5. MASTER FILES 33 - 5.1. Format 33 - 5.2. Use of master files to define zones 35 - 5.3. Master file example 36 - 6. NAME SERVER IMPLEMENTATION 37 - 6.1. Architecture 37 - 6.1.1. Control 37 - 6.1.2. Database 37 - 6.1.3. Time 39 - 6.2. Standard query processing 39 - 6.3. Zone refresh and reload processing 39 - 6.4. Inverse queries (Optional) 40 - 6.4.1. The contents of inverse queries and responses 40 - 6.4.2. Inverse query and response example 41 - 6.4.3. Inverse query processing 42 - - - - - - -Mockapetris [Page 2] - -RFC 1035 Domain Implementation and Specification November 1987 - - - 6.5. Completion queries and responses 42 - 7. RESOLVER IMPLEMENTATION 43 - 7.1. Transforming a user request into a query 43 - 7.2. Sending the queries 44 - 7.3. Processing responses 46 - 7.4. Using the cache 47 - 8. MAIL SUPPORT 47 - 8.1. Mail exchange binding 48 - 8.2. Mailbox binding (Experimental) 48 - 9. REFERENCES and BIBLIOGRAPHY 50 - Index 54 - -2. INTRODUCTION - -2.1. Overview - -The goal of domain names is to provide a mechanism for naming resources -in such a way that the names are usable in different hosts, networks, -protocol families, internets, and administrative organizations. - -From the user's point of view, domain names are useful as arguments to a -local agent, called a resolver, which retrieves information associated -with the domain name. Thus a user might ask for the host address or -mail information associated with a particular domain name. To enable -the user to request a particular type of information, an appropriate -query type is passed to the resolver with the domain name. To the user, -the domain tree is a single information space; the resolver is -responsible for hiding the distribution of data among name servers from -the user. - -From the resolver's point of view, the database that makes up the domain -space is distributed among various name servers. Different parts of the -domain space are stored in different name servers, although a particular -data item will be stored redundantly in two or more name servers. The -resolver starts with knowledge of at least one name server. When the -resolver processes a user query it asks a known name server for the -information; in return, the resolver either receives the desired -information or a referral to another name server. Using these -referrals, resolvers learn the identities and contents of other name -servers. Resolvers are responsible for dealing with the distribution of -the domain space and dealing with the effects of name server failure by -consulting redundant databases in other servers. - -Name servers manage two kinds of data. The first kind of data held in -sets called zones; each zone is the complete database for a particular -"pruned" subtree of the domain space. This data is called -authoritative. A name server periodically checks to make sure that its -zones are up to date, and if not, obtains a new copy of updated zones - - - -Mockapetris [Page 3] - -RFC 1035 Domain Implementation and Specification November 1987 - - -from master files stored locally or in another name server. The second -kind of data is cached data which was acquired by a local resolver. -This data may be incomplete, but improves the performance of the -retrieval process when non-local data is repeatedly accessed. Cached -data is eventually discarded by a timeout mechanism. - -This functional structure isolates the problems of user interface, -failure recovery, and distribution in the resolvers and isolates the -database update and refresh problems in the name servers. - -2.2. Common configurations - -A host can participate in the domain name system in a number of ways, -depending on whether the host runs programs that retrieve information -from the domain system, name servers that answer queries from other -hosts, or various combinations of both functions. The simplest, and -perhaps most typical, configuration is shown below: - - Local Host | Foreign - | - +---------+ +----------+ | +--------+ - | | user queries | |queries | | | - | User |-------------->| |---------|->|Foreign | - | Program | | Resolver | | | Name | - | |<--------------| |<--------|--| Server | - | | user responses| |responses| | | - +---------+ +----------+ | +--------+ - | A | - cache additions | | references | - V | | - +----------+ | - | cache | | - +----------+ | - -User programs interact with the domain name space through resolvers; the -format of user queries and user responses is specific to the host and -its operating system. User queries will typically be operating system -calls, and the resolver and its cache will be part of the host operating -system. Less capable hosts may choose to implement the resolver as a -subroutine to be linked in with every program that needs its services. -Resolvers answer user queries with information they acquire via queries -to foreign name servers and the local cache. - -Note that the resolver may have to make several queries to several -different foreign name servers to answer a particular user query, and -hence the resolution of a user query may involve several network -accesses and an arbitrary amount of time. The queries to foreign name -servers and the corresponding responses have a standard format described - - - -Mockapetris [Page 4] - -RFC 1035 Domain Implementation and Specification November 1987 - - -in this memo, and may be datagrams. - -Depending on its capabilities, a name server could be a stand alone -program on a dedicated machine or a process or processes on a large -timeshared host. A simple configuration might be: - - Local Host | Foreign - | - +---------+ | - / /| | - +---------+ | +----------+ | +--------+ - | | | | |responses| | | - | | | | Name |---------|->|Foreign | - | Master |-------------->| Server | | |Resolver| - | files | | | |<--------|--| | - | |/ | | queries | +--------+ - +---------+ +----------+ | - -Here a primary name server acquires information about one or more zones -by reading master files from its local file system, and answers queries -about those zones that arrive from foreign resolvers. - -The DNS requires that all zones be redundantly supported by more than -one name server. Designated secondary servers can acquire zones and -check for updates from the primary server using the zone transfer -protocol of the DNS. This configuration is shown below: - - Local Host | Foreign - | - +---------+ | - / /| | - +---------+ | +----------+ | +--------+ - | | | | |responses| | | - | | | | Name |---------|->|Foreign | - | Master |-------------->| Server | | |Resolver| - | files | | | |<--------|--| | - | |/ | | queries | +--------+ - +---------+ +----------+ | - A |maintenance | +--------+ - | +------------|->| | - | queries | |Foreign | - | | | Name | - +------------------|--| Server | - maintenance responses | +--------+ - -In this configuration, the name server periodically establishes a -virtual circuit to a foreign name server to acquire a copy of a zone or -to check that an existing copy has not changed. The messages sent for - - - -Mockapetris [Page 5] - -RFC 1035 Domain Implementation and Specification November 1987 - - -these maintenance activities follow the same form as queries and -responses, but the message sequences are somewhat different. - -The information flow in a host that supports all aspects of the domain -name system is shown below: - - Local Host | Foreign - | - +---------+ +----------+ | +--------+ - | | user queries | |queries | | | - | User |-------------->| |---------|->|Foreign | - | Program | | Resolver | | | Name | - | |<--------------| |<--------|--| Server | - | | user responses| |responses| | | - +---------+ +----------+ | +--------+ - | A | - cache additions | | references | - V | | - +----------+ | - | Shared | | - | database | | - +----------+ | - A | | - +---------+ refreshes | | references | - / /| | V | - +---------+ | +----------+ | +--------+ - | | | | |responses| | | - | | | | Name |---------|->|Foreign | - | Master |-------------->| Server | | |Resolver| - | files | | | |<--------|--| | - | |/ | | queries | +--------+ - +---------+ +----------+ | - A |maintenance | +--------+ - | +------------|->| | - | queries | |Foreign | - | | | Name | - +------------------|--| Server | - maintenance responses | +--------+ - -The shared database holds domain space data for the local name server -and resolver. The contents of the shared database will typically be a -mixture of authoritative data maintained by the periodic refresh -operations of the name server and cached data from previous resolver -requests. The structure of the domain data and the necessity for -synchronization between name servers and resolvers imply the general -characteristics of this database, but the actual format is up to the -local implementor. - - - - -Mockapetris [Page 6] - -RFC 1035 Domain Implementation and Specification November 1987 - - -Information flow can also be tailored so that a group of hosts act -together to optimize activities. Sometimes this is done to offload less -capable hosts so that they do not have to implement a full resolver. -This can be appropriate for PCs or hosts which want to minimize the -amount of new network code which is required. This scheme can also -allow a group of hosts can share a small number of caches rather than -maintaining a large number of separate caches, on the premise that the -centralized caches will have a higher hit ratio. In either case, -resolvers are replaced with stub resolvers which act as front ends to -resolvers located in a recursive server in one or more name servers -known to perform that service: - - Local Hosts | Foreign - | - +---------+ | - | | responses | - | Stub |<--------------------+ | - | Resolver| | | - | |----------------+ | | - +---------+ recursive | | | - queries | | | - V | | - +---------+ recursive +----------+ | +--------+ - | | queries | |queries | | | - | Stub |-------------->| Recursive|---------|->|Foreign | - | Resolver| | Server | | | Name | - | |<--------------| |<--------|--| Server | - +---------+ responses | |responses| | | - +----------+ | +--------+ - | Central | | - | cache | | - +----------+ | - -In any case, note that domain components are always replicated for -reliability whenever possible. - -2.3. Conventions - -The domain system has several conventions dealing with low-level, but -fundamental, issues. While the implementor is free to violate these -conventions WITHIN HIS OWN SYSTEM, he must observe these conventions in -ALL behavior observed from other hosts. - -2.3.1. Preferred name syntax - -The DNS specifications attempt to be as general as possible in the rules -for constructing domain names. The idea is that the name of any -existing object can be expressed as a domain name with minimal changes. - - - -Mockapetris [Page 7] - -RFC 1035 Domain Implementation and Specification November 1987 - - -However, when assigning a domain name for an object, the prudent user -will select a name which satisfies both the rules of the domain system -and any existing rules for the object, whether these rules are published -or implied by existing programs. - -For example, when naming a mail domain, the user should satisfy both the -rules of this memo and those in RFC-822. When creating a new host name, -the old rules for HOSTS.TXT should be followed. This avoids problems -when old software is converted to use domain names. - -The following syntax will result in fewer problems with many - -applications that use domain names (e.g., mail, TELNET). - - ::= | " " - - ::=