PageRenderTime 58ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/connman/client/commands.c

https://github.com/lpotter/connman
C | 2553 lines | 1986 code | 542 blank | 25 comment | 403 complexity | 08ddf5402f61f36c884d66115c961896 MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. *
  3. * Connection Manager
  4. *
  5. * Copyright (C) 2012-2014 Intel Corporation. All rights reserved.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. */
  22. #ifdef HAVE_CONFIG_H
  23. #include <config.h>
  24. #endif
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <errno.h>
  29. #include <stdbool.h>
  30. #include <sys/types.h>
  31. #include <unistd.h>
  32. #include <glib.h>
  33. #include <gdbus.h>
  34. #include "dbus_helpers.h"
  35. #include "input.h"
  36. #include "services.h"
  37. #include "peers.h"
  38. #include "commands.h"
  39. #include "agent.h"
  40. #include "vpnconnections.h"
  41. static DBusConnection *connection;
  42. static GHashTable *service_hash;
  43. static GHashTable *peer_hash;
  44. static GHashTable *technology_hash;
  45. static char *session_notify_path;
  46. static char *session_path;
  47. static bool session_connected;
  48. struct connman_option {
  49. const char *name;
  50. const char val;
  51. const char *desc;
  52. };
  53. static char *ipv4[] = {
  54. "Method",
  55. "Address",
  56. "Netmask",
  57. "Gateway",
  58. NULL
  59. };
  60. static char *ipv6[] = {
  61. "Method",
  62. "Address",
  63. "PrefixLength",
  64. "Gateway",
  65. NULL
  66. };
  67. static int cmd_help(char *args[], int num, struct connman_option *options);
  68. static bool check_dbus_name(const char *name)
  69. {
  70. /*
  71. * Valid dbus chars should be [A-Z][a-z][0-9]_
  72. * and should not start with number.
  73. */
  74. unsigned int i;
  75. if (!name || name[0] == '\0')
  76. return false;
  77. for (i = 0; name[i] != '\0'; i++)
  78. if (!((name[i] >= 'A' && name[i] <= 'Z') ||
  79. (name[i] >= 'a' && name[i] <= 'z') ||
  80. (name[i] >= '0' && name[i] <= '9') ||
  81. name[i] == '_'))
  82. return false;
  83. return true;
  84. }
  85. static int parse_boolean(char *arg)
  86. {
  87. if (!arg)
  88. return -1;
  89. if (strcasecmp(arg, "no") == 0 ||
  90. strcasecmp(arg, "false") == 0 ||
  91. strcasecmp(arg, "off" ) == 0 ||
  92. strcasecmp(arg, "disable" ) == 0 ||
  93. strcasecmp(arg, "n") == 0 ||
  94. strcasecmp(arg, "f") == 0 ||
  95. strcasecmp(arg, "0") == 0)
  96. return 0;
  97. if (strcasecmp(arg, "yes") == 0 ||
  98. strcasecmp(arg, "true") == 0 ||
  99. strcasecmp(arg, "on") == 0 ||
  100. strcasecmp(arg, "enable" ) == 0 ||
  101. strcasecmp(arg, "y") == 0 ||
  102. strcasecmp(arg, "t") == 0 ||
  103. strcasecmp(arg, "1") == 0)
  104. return 1;
  105. return -1;
  106. }
  107. static int parse_args(char *arg, struct connman_option *options)
  108. {
  109. int i;
  110. if (!arg)
  111. return -1;
  112. for (i = 0; options[i].name; i++) {
  113. if (strcmp(options[i].name, arg) == 0 ||
  114. (strncmp(arg, "--", 2) == 0 &&
  115. strcmp(&arg[2], options[i].name) == 0))
  116. return options[i].val;
  117. }
  118. return '?';
  119. }
  120. static int enable_return(DBusMessageIter *iter, const char *error,
  121. void *user_data)
  122. {
  123. char *tech = user_data;
  124. char *str;
  125. str = strrchr(tech, '/');
  126. if (str)
  127. str++;
  128. else
  129. str = tech;
  130. if (!error)
  131. fprintf(stdout, "Enabled %s\n", str);
  132. else
  133. fprintf(stderr, "Error %s: %s\n", str, error);
  134. g_free(user_data);
  135. return 0;
  136. }
  137. static int cmd_enable(char *args[], int num, struct connman_option *options)
  138. {
  139. char *tech;
  140. dbus_bool_t b = TRUE;
  141. if (num > 2)
  142. return -E2BIG;
  143. if (num < 2)
  144. return -EINVAL;
  145. if (check_dbus_name(args[1]) == false)
  146. return -EINVAL;
  147. if (strcmp(args[1], "offline") == 0) {
  148. tech = g_strdup(args[1]);
  149. return __connmanctl_dbus_set_property(connection, "/",
  150. "net.connman.Manager", enable_return, tech,
  151. "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
  152. }
  153. tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
  154. return __connmanctl_dbus_set_property(connection, tech,
  155. "net.connman.Technology", enable_return, tech,
  156. "Powered", DBUS_TYPE_BOOLEAN, &b);
  157. }
  158. static int disable_return(DBusMessageIter *iter, const char *error,
  159. void *user_data)
  160. {
  161. char *tech = user_data;
  162. char *str;
  163. str = strrchr(tech, '/');
  164. if (str)
  165. str++;
  166. else
  167. str = tech;
  168. if (!error)
  169. fprintf(stdout, "Disabled %s\n", str);
  170. else
  171. fprintf(stderr, "Error %s: %s\n", str, error);
  172. g_free(user_data);
  173. return 0;
  174. }
  175. static int cmd_disable(char *args[], int num, struct connman_option *options)
  176. {
  177. char *tech;
  178. dbus_bool_t b = FALSE;
  179. if (num > 2)
  180. return -E2BIG;
  181. if (num < 2)
  182. return -EINVAL;
  183. if (check_dbus_name(args[1]) == false)
  184. return -EINVAL;
  185. if (strcmp(args[1], "offline") == 0) {
  186. tech = g_strdup(args[1]);
  187. return __connmanctl_dbus_set_property(connection, "/",
  188. "net.connman.Manager", disable_return, tech,
  189. "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
  190. }
  191. tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
  192. return __connmanctl_dbus_set_property(connection, tech,
  193. "net.connman.Technology", disable_return, tech,
  194. "Powered", DBUS_TYPE_BOOLEAN, &b);
  195. }
  196. static int state_print(DBusMessageIter *iter, const char *error,
  197. void *user_data)
  198. {
  199. DBusMessageIter entry;
  200. if (error) {
  201. fprintf(stderr, "Error: %s", error);
  202. return 0;
  203. }
  204. dbus_message_iter_recurse(iter, &entry);
  205. __connmanctl_dbus_print(&entry, " ", " = ", "\n");
  206. fprintf(stdout, "\n");
  207. return 0;
  208. }
  209. static int cmd_state(char *args[], int num, struct connman_option *options)
  210. {
  211. if (num > 1)
  212. return -E2BIG;
  213. return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
  214. CONNMAN_PATH, "net.connman.Manager", "GetProperties",
  215. state_print, NULL, NULL, NULL);
  216. }
  217. static int services_list(DBusMessageIter *iter, const char *error,
  218. void *user_data)
  219. {
  220. if (!error) {
  221. __connmanctl_services_list(iter);
  222. fprintf(stdout, "\n");
  223. } else {
  224. fprintf(stderr, "Error: %s\n", error);
  225. }
  226. return 0;
  227. }
  228. static int peers_list(DBusMessageIter *iter,
  229. const char *error, void *user_data)
  230. {
  231. if (!error) {
  232. __connmanctl_peers_list(iter);
  233. fprintf(stdout, "\n");
  234. } else
  235. fprintf(stderr, "Error: %s\n", error);
  236. return 0;
  237. }
  238. static int object_properties(DBusMessageIter *iter,
  239. const char *error, void *user_data)
  240. {
  241. char *path = user_data;
  242. char *str;
  243. DBusMessageIter dict;
  244. if (!error) {
  245. fprintf(stdout, "%s\n", path);
  246. dbus_message_iter_recurse(iter, &dict);
  247. __connmanctl_dbus_print(&dict, " ", " = ", "\n");
  248. fprintf(stdout, "\n");
  249. } else {
  250. str = strrchr(path, '/');
  251. if (str)
  252. str++;
  253. else
  254. str = path;
  255. fprintf(stderr, "Error %s: %s\n", str, error);
  256. }
  257. g_free(user_data);
  258. return 0;
  259. }
  260. static int cmd_services(char *args[], int num, struct connman_option *options)
  261. {
  262. char *service_name = NULL;
  263. char *path;
  264. int c;
  265. if (num > 3)
  266. return -E2BIG;
  267. c = parse_args(args[1], options);
  268. switch (c) {
  269. case -1:
  270. break;
  271. case 'p':
  272. if (num < 3)
  273. return -EINVAL;
  274. service_name = args[2];
  275. break;
  276. default:
  277. if (num > 2)
  278. return -E2BIG;
  279. service_name = args[1];
  280. break;
  281. }
  282. if (!service_name) {
  283. return __connmanctl_dbus_method_call(connection,
  284. CONNMAN_SERVICE, CONNMAN_PATH,
  285. "net.connman.Manager", "GetServices",
  286. services_list, NULL, NULL, NULL);
  287. }
  288. if (check_dbus_name(service_name) == false)
  289. return -EINVAL;
  290. path = g_strdup_printf("/net/connman/service/%s", service_name);
  291. return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
  292. "net.connman.Service", "GetProperties",
  293. object_properties, path, NULL, NULL);
  294. }
  295. static int cmd_peers(char *args[], int num, struct connman_option *options)
  296. {
  297. char *peer_name = NULL;
  298. char *path;
  299. if (num > 2)
  300. return -E2BIG;
  301. if (num == 2)
  302. peer_name = args[1];
  303. if (!peer_name) {
  304. return __connmanctl_dbus_method_call(connection,
  305. CONNMAN_SERVICE, CONNMAN_PATH,
  306. "net.connman.Manager", "GetPeers",
  307. peers_list, NULL, NULL, NULL);
  308. }
  309. if (check_dbus_name(peer_name) == false)
  310. return -EINVAL;
  311. path = g_strdup_printf("/net/connman/peer/%s", peer_name);
  312. return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
  313. path, "net.connman.Peer", "GetProperties",
  314. object_properties, path, NULL, NULL);
  315. }
  316. static int technology_print(DBusMessageIter *iter, const char *error,
  317. void *user_data)
  318. {
  319. DBusMessageIter array;
  320. if (error) {
  321. fprintf(stderr, "Error: %s\n", error);
  322. return 0;
  323. }
  324. dbus_message_iter_recurse(iter, &array);
  325. while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
  326. DBusMessageIter entry, dict;
  327. const char *path;
  328. dbus_message_iter_recurse(&array, &entry);
  329. dbus_message_iter_get_basic(&entry, &path);
  330. fprintf(stdout, "%s\n", path);
  331. dbus_message_iter_next(&entry);
  332. dbus_message_iter_recurse(&entry, &dict);
  333. __connmanctl_dbus_print(&dict, " ", " = ", "\n");
  334. fprintf(stdout, "\n");
  335. dbus_message_iter_next(&array);
  336. }
  337. return 0;
  338. }
  339. static int cmd_technologies(char *args[], int num,
  340. struct connman_option *options)
  341. {
  342. if (num > 1)
  343. return -E2BIG;
  344. return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
  345. CONNMAN_PATH, "net.connman.Manager", "GetTechnologies",
  346. technology_print, NULL, NULL, NULL);
  347. }
  348. struct tether_enable {
  349. char *path;
  350. dbus_bool_t enable;
  351. };
  352. static int tether_set_return(DBusMessageIter *iter, const char *error,
  353. void *user_data)
  354. {
  355. struct tether_enable *tether = user_data;
  356. char *str;
  357. str = strrchr(tether->path, '/');
  358. if (str)
  359. str++;
  360. else
  361. str = tether->path;
  362. if (!error) {
  363. fprintf(stdout, "%s tethering for %s\n",
  364. tether->enable ? "Enabled" : "Disabled",
  365. str);
  366. } else
  367. fprintf(stderr, "Error %s %s tethering: %s\n",
  368. tether->enable ?
  369. "enabling" : "disabling", str, error);
  370. g_free(tether->path);
  371. g_free(user_data);
  372. return 0;
  373. }
  374. static int tether_set(char *technology, int set_tethering)
  375. {
  376. struct tether_enable *tether = g_new(struct tether_enable, 1);
  377. switch(set_tethering) {
  378. case 1:
  379. tether->enable = TRUE;
  380. break;
  381. case 0:
  382. tether->enable = FALSE;
  383. break;
  384. default:
  385. g_free(tether);
  386. return 0;
  387. }
  388. tether->path = g_strdup_printf("/net/connman/technology/%s",
  389. technology);
  390. return __connmanctl_dbus_set_property(connection, tether->path,
  391. "net.connman.Technology", tether_set_return,
  392. tether, "Tethering", DBUS_TYPE_BOOLEAN,
  393. &tether->enable);
  394. }
  395. struct tether_properties {
  396. int ssid_result;
  397. int passphrase_result;
  398. int set_tethering;
  399. };
  400. static int tether_update(struct tether_properties *tether)
  401. {
  402. if (tether->ssid_result == 0 && tether->passphrase_result == 0)
  403. return tether_set("wifi", tether->set_tethering);
  404. if (tether->ssid_result != -EINPROGRESS &&
  405. tether->passphrase_result != -EINPROGRESS) {
  406. g_free(tether);
  407. return 0;
  408. }
  409. return -EINPROGRESS;
  410. }
  411. static int tether_set_ssid_return(DBusMessageIter *iter, const char *error,
  412. void *user_data)
  413. {
  414. struct tether_properties *tether = user_data;
  415. if (!error) {
  416. fprintf(stdout, "Wifi SSID set\n");
  417. tether->ssid_result = 0;
  418. } else {
  419. fprintf(stderr, "Error setting wifi SSID: %s\n", error);
  420. tether->ssid_result = -EINVAL;
  421. }
  422. return tether_update(tether);
  423. }
  424. static int tether_set_passphrase_return(DBusMessageIter *iter,
  425. const char *error, void *user_data)
  426. {
  427. struct tether_properties *tether = user_data;
  428. if (!error) {
  429. fprintf(stdout, "Wifi passphrase set\n");
  430. tether->passphrase_result = 0;
  431. } else {
  432. fprintf(stderr, "Error setting wifi passphrase: %s\n", error);
  433. tether->passphrase_result = -EINVAL;
  434. }
  435. return tether_update(tether);
  436. }
  437. static int tether_set_ssid(char *ssid, char *passphrase, int set_tethering)
  438. {
  439. struct tether_properties *tether = g_new(struct tether_properties, 1);
  440. tether->set_tethering = set_tethering;
  441. tether->ssid_result = __connmanctl_dbus_set_property(connection,
  442. "/net/connman/technology/wifi",
  443. "net.connman.Technology",
  444. tether_set_ssid_return, tether,
  445. "TetheringIdentifier", DBUS_TYPE_STRING, &ssid);
  446. tether->passphrase_result =__connmanctl_dbus_set_property(connection,
  447. "/net/connman/technology/wifi",
  448. "net.connman.Technology",
  449. tether_set_passphrase_return, tether,
  450. "TetheringPassphrase", DBUS_TYPE_STRING, &passphrase);
  451. if (tether->ssid_result != -EINPROGRESS &&
  452. tether->passphrase_result != -EINPROGRESS) {
  453. g_free(tether);
  454. return -ENXIO;
  455. }
  456. return -EINPROGRESS;
  457. }
  458. static int cmd_tether(char *args[], int num, struct connman_option *options)
  459. {
  460. char *ssid, *passphrase;
  461. int set_tethering;
  462. if (num < 3)
  463. return -EINVAL;
  464. passphrase = args[num - 1];
  465. ssid = args[num - 2];
  466. set_tethering = parse_boolean(args[2]);
  467. if (strcmp(args[1], "wifi") == 0) {
  468. if (num > 5)
  469. return -E2BIG;
  470. if (num == 5 && set_tethering == -1)
  471. return -EINVAL;
  472. if (num == 4)
  473. set_tethering = -1;
  474. if (num > 3)
  475. return tether_set_ssid(ssid, passphrase, set_tethering);
  476. }
  477. if (num > 3)
  478. return -E2BIG;
  479. if (set_tethering == -1)
  480. return -EINVAL;
  481. if (check_dbus_name(args[1]) == false)
  482. return -EINVAL;
  483. return tether_set(args[1], set_tethering);
  484. }
  485. static int scan_return(DBusMessageIter *iter, const char *error,
  486. void *user_data)
  487. {
  488. char *path = user_data;
  489. if (!error) {
  490. char *str = strrchr(path, '/');
  491. str++;
  492. fprintf(stdout, "Scan completed for %s\n", str);
  493. } else
  494. fprintf(stderr, "Error %s: %s\n", path, error);
  495. g_free(user_data);
  496. return 0;
  497. }
  498. static int cmd_scan(char *args[], int num, struct connman_option *options)
  499. {
  500. char *path;
  501. if (num > 2)
  502. return -E2BIG;
  503. if (num < 2)
  504. return -EINVAL;
  505. if (check_dbus_name(args[1]) == false)
  506. return -EINVAL;
  507. path = g_strdup_printf("/net/connman/technology/%s", args[1]);
  508. return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
  509. "net.connman.Technology", "Scan",
  510. scan_return, path, NULL, NULL);
  511. }
  512. static int connect_return(DBusMessageIter *iter, const char *error,
  513. void *user_data)
  514. {
  515. char *path = user_data;
  516. if (!error) {
  517. char *str = strrchr(path, '/');
  518. str++;
  519. fprintf(stdout, "Connected %s\n", str);
  520. } else
  521. fprintf(stderr, "Error %s: %s\n", path, error);
  522. g_free(user_data);
  523. return 0;
  524. }
  525. static int cmd_connect(char *args[], int num, struct connman_option *options)
  526. {
  527. char *path;
  528. if (num > 2)
  529. return -E2BIG;
  530. if (num < 2)
  531. return -EINVAL;
  532. if (check_dbus_name(args[1]) == false)
  533. return -EINVAL;
  534. path = g_strdup_printf("/net/connman/service/%s", args[1]);
  535. return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
  536. "net.connman.Service", "Connect",
  537. connect_return, path, NULL, NULL);
  538. }
  539. static int disconnect_return(DBusMessageIter *iter, const char *error,
  540. void *user_data)
  541. {
  542. char *path = user_data;
  543. if (!error) {
  544. char *str = strrchr(path, '/');
  545. str++;
  546. fprintf(stdout, "Disconnected %s\n", str);
  547. } else
  548. fprintf(stderr, "Error %s: %s\n", path, error);
  549. g_free(user_data);
  550. return 0;
  551. }
  552. static int cmd_disconnect(char *args[], int num, struct connman_option *options)
  553. {
  554. char *path;
  555. if (num > 2)
  556. return -E2BIG;
  557. if (num < 2)
  558. return -EINVAL;
  559. if (check_dbus_name(args[1]) == false)
  560. return -EINVAL;
  561. path = g_strdup_printf("/net/connman/service/%s", args[1]);
  562. return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
  563. "net.connman.Service", "Disconnect",
  564. disconnect_return, path, NULL, NULL);
  565. }
  566. static int config_return(DBusMessageIter *iter, const char *error,
  567. void *user_data)
  568. {
  569. char *service_name = user_data;
  570. if (error)
  571. fprintf(stderr, "Error %s: %s\n", service_name, error);
  572. g_free(user_data);
  573. return 0;
  574. }
  575. struct config_append {
  576. char **opts;
  577. int values;
  578. };
  579. static void config_append_ipv4(DBusMessageIter *iter,
  580. void *user_data)
  581. {
  582. struct config_append *append = user_data;
  583. char **opts = append->opts;
  584. int i = 0;
  585. if (!opts)
  586. return;
  587. while (opts[i] && ipv4[i]) {
  588. __connmanctl_dbus_append_dict_entry(iter, ipv4[i],
  589. DBUS_TYPE_STRING, &opts[i]);
  590. i++;
  591. }
  592. append->values = i;
  593. }
  594. static void config_append_ipv6(DBusMessageIter *iter, void *user_data)
  595. {
  596. struct config_append *append = user_data;
  597. char **opts = append->opts;
  598. if (!opts)
  599. return;
  600. append->values = 1;
  601. if (g_strcmp0(opts[0], "auto") == 0) {
  602. char *str;
  603. switch (parse_boolean(opts[1])) {
  604. case 0:
  605. append->values = 2;
  606. str = "disabled";
  607. __connmanctl_dbus_append_dict_entry(iter, "Privacy",
  608. DBUS_TYPE_STRING, &str);
  609. break;
  610. case 1:
  611. append->values = 2;
  612. str = "enabled";
  613. __connmanctl_dbus_append_dict_entry(iter, "Privacy",
  614. DBUS_TYPE_STRING, &str);
  615. break;
  616. default:
  617. if (opts[1]) {
  618. append->values = 2;
  619. if (g_strcmp0(opts[1], "prefered") != 0 &&
  620. g_strcmp0(opts[1],
  621. "preferred") != 0) {
  622. fprintf(stderr, "Error %s: %s\n",
  623. opts[1],
  624. strerror(EINVAL));
  625. return;
  626. }
  627. str = "prefered";
  628. __connmanctl_dbus_append_dict_entry(iter,
  629. "Privacy", DBUS_TYPE_STRING,
  630. &str);
  631. }
  632. break;
  633. }
  634. } else if (g_strcmp0(opts[0], "manual") == 0) {
  635. int i = 1;
  636. while (opts[i] && ipv6[i]) {
  637. if (i == 2) {
  638. int value = atoi(opts[i]);
  639. __connmanctl_dbus_append_dict_entry(iter,
  640. ipv6[i], DBUS_TYPE_BYTE,
  641. &value);
  642. } else {
  643. __connmanctl_dbus_append_dict_entry(iter,
  644. ipv6[i], DBUS_TYPE_STRING,
  645. &opts[i]);
  646. }
  647. i++;
  648. }
  649. append->values = i;
  650. } else if (g_strcmp0(opts[0], "off") != 0) {
  651. fprintf(stderr, "Error %s: %s\n", opts[0], strerror(EINVAL));
  652. return;
  653. }
  654. __connmanctl_dbus_append_dict_entry(iter, "Method", DBUS_TYPE_STRING,
  655. &opts[0]);
  656. }
  657. static void config_append_str(DBusMessageIter *iter, void *user_data)
  658. {
  659. struct config_append *append = user_data;
  660. char **opts = append->opts;
  661. int i = 0;
  662. if (!opts)
  663. return;
  664. while (opts[i]) {
  665. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
  666. &opts[i]);
  667. i++;
  668. }
  669. append->values = i;
  670. }
  671. static void append_servers(DBusMessageIter *iter, void *user_data)
  672. {
  673. struct config_append *append = user_data;
  674. char **opts = append->opts;
  675. int i = 1;
  676. if (!opts)
  677. return;
  678. while (opts[i] && g_strcmp0(opts[i], "--excludes") != 0) {
  679. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
  680. &opts[i]);
  681. i++;
  682. }
  683. append->values = i;
  684. }
  685. static void append_excludes(DBusMessageIter *iter, void *user_data)
  686. {
  687. struct config_append *append = user_data;
  688. char **opts = append->opts;
  689. int i = append->values;
  690. if (!opts || !opts[i] ||
  691. g_strcmp0(opts[i], "--excludes") != 0)
  692. return;
  693. i++;
  694. while (opts[i]) {
  695. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
  696. &opts[i]);
  697. i++;
  698. }
  699. append->values = i;
  700. }
  701. static void config_append_proxy(DBusMessageIter *iter, void *user_data)
  702. {
  703. struct config_append *append = user_data;
  704. char **opts = append->opts;
  705. if (!opts)
  706. return;
  707. if (g_strcmp0(opts[0], "manual") == 0) {
  708. __connmanctl_dbus_append_dict_string_array(iter, "Servers",
  709. append_servers, append);
  710. __connmanctl_dbus_append_dict_string_array(iter, "Excludes",
  711. append_excludes, append);
  712. } else if (g_strcmp0(opts[0], "auto") == 0) {
  713. if (opts[1]) {
  714. __connmanctl_dbus_append_dict_entry(iter, "URL",
  715. DBUS_TYPE_STRING, &opts[1]);
  716. append->values++;
  717. }
  718. } else if (g_strcmp0(opts[0], "direct") != 0)
  719. return;
  720. __connmanctl_dbus_append_dict_entry(iter, "Method",DBUS_TYPE_STRING,
  721. &opts[0]);
  722. append->values++;
  723. }
  724. static int cmd_config(char *args[], int num, struct connman_option *options)
  725. {
  726. int result = 0, res = 0, index = 2, oldindex = 0;
  727. int c;
  728. char *service_name, *path;
  729. char **opt_start;
  730. dbus_bool_t val;
  731. struct config_append append;
  732. service_name = args[1];
  733. if (!service_name)
  734. return -EINVAL;
  735. if (check_dbus_name(service_name) == false)
  736. return -EINVAL;
  737. while (index < num && args[index]) {
  738. c = parse_args(args[index], options);
  739. opt_start = &args[index + 1];
  740. append.opts = opt_start;
  741. append.values = 0;
  742. res = 0;
  743. oldindex = index;
  744. path = g_strdup_printf("/net/connman/service/%s", service_name);
  745. switch (c) {
  746. case 'a':
  747. switch (parse_boolean(*opt_start)) {
  748. case 1:
  749. val = TRUE;
  750. break;
  751. case 0:
  752. val = FALSE;
  753. break;
  754. default:
  755. res = -EINVAL;
  756. break;
  757. }
  758. index++;
  759. if (res == 0) {
  760. res = __connmanctl_dbus_set_property(connection,
  761. path, "net.connman.Service",
  762. config_return,
  763. g_strdup(service_name),
  764. "AutoConnect",
  765. DBUS_TYPE_BOOLEAN, &val);
  766. }
  767. break;
  768. case 'i':
  769. res = __connmanctl_dbus_set_property_dict(connection,
  770. path, "net.connman.Service",
  771. config_return, g_strdup(service_name),
  772. "IPv4.Configuration", DBUS_TYPE_STRING,
  773. config_append_ipv4, &append);
  774. index += append.values;
  775. break;
  776. case 'v':
  777. res = __connmanctl_dbus_set_property_dict(connection,
  778. path, "net.connman.Service",
  779. config_return, g_strdup(service_name),
  780. "IPv6.Configuration", DBUS_TYPE_STRING,
  781. config_append_ipv6, &append);
  782. index += append.values;
  783. break;
  784. case 'n':
  785. res = __connmanctl_dbus_set_property_array(connection,
  786. path, "net.connman.Service",
  787. config_return, g_strdup(service_name),
  788. "Nameservers.Configuration",
  789. DBUS_TYPE_STRING, config_append_str,
  790. &append);
  791. index += append.values;
  792. break;
  793. case 't':
  794. res = __connmanctl_dbus_set_property_array(connection,
  795. path, "net.connman.Service",
  796. config_return, g_strdup(service_name),
  797. "Timeservers.Configuration",
  798. DBUS_TYPE_STRING, config_append_str,
  799. &append);
  800. index += append.values;
  801. break;
  802. case 'd':
  803. res = __connmanctl_dbus_set_property_array(connection,
  804. path, "net.connman.Service",
  805. config_return, g_strdup(service_name),
  806. "Domains.Configuration",
  807. DBUS_TYPE_STRING, config_append_str,
  808. &append);
  809. index += append.values;
  810. break;
  811. case 'x':
  812. res = __connmanctl_dbus_set_property_dict(connection,
  813. path, "net.connman.Service",
  814. config_return, g_strdup(service_name),
  815. "Proxy.Configuration",
  816. DBUS_TYPE_STRING, config_append_proxy,
  817. &append);
  818. index += append.values;
  819. break;
  820. case 'r':
  821. res = __connmanctl_dbus_method_call(connection,
  822. CONNMAN_SERVICE, path,
  823. "net.connman.Service", "Remove",
  824. config_return, g_strdup(service_name),
  825. NULL, NULL);
  826. break;
  827. default:
  828. res = -EINVAL;
  829. break;
  830. }
  831. g_free(path);
  832. if (res < 0) {
  833. if (res == -EINPROGRESS)
  834. result = -EINPROGRESS;
  835. else
  836. printf("Error '%s': %s\n", args[oldindex],
  837. strerror(-res));
  838. } else
  839. index += res;
  840. index++;
  841. }
  842. return result;
  843. }
  844. static DBusHandlerResult monitor_changed(DBusConnection *connection,
  845. DBusMessage *message, void *user_data)
  846. {
  847. DBusMessageIter iter;
  848. const char *interface, *path;
  849. interface = dbus_message_get_interface(message);
  850. if (!interface)
  851. return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  852. if (strncmp(interface, "net.connman.", 12) != 0)
  853. return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  854. if (!strcmp(interface, "net.connman.Agent") ||
  855. !strcmp(interface, "net.connman.vpn.Agent") ||
  856. !strcmp(interface, "net.connman.Session") ||
  857. !strcmp(interface, "net.connman.Notification"))
  858. return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  859. interface = strrchr(interface, '.');
  860. if (interface && *interface != '\0')
  861. interface++;
  862. path = strrchr(dbus_message_get_path(message), '/');
  863. if (path && *path != '\0')
  864. path++;
  865. __connmanctl_save_rl();
  866. if (dbus_message_is_signal(message, "net.connman.Manager",
  867. "ServicesChanged")) {
  868. fprintf(stdout, "%-12s %-20s = {\n", interface,
  869. "ServicesChanged");
  870. dbus_message_iter_init(message, &iter);
  871. __connmanctl_services_list(&iter);
  872. fprintf(stdout, "\n}\n");
  873. __connmanctl_redraw_rl();
  874. return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  875. } else if (dbus_message_is_signal(message, "net.connman.Manager",
  876. "PeersChanged")) {
  877. fprintf(stdout, "%-12s %-20s = {\n", interface,
  878. "PeersChanged");
  879. dbus_message_iter_init(message, &iter);
  880. __connmanctl_peers_list(&iter);
  881. fprintf(stdout, "\n}\n");
  882. __connmanctl_redraw_rl();
  883. return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  884. } else if (dbus_message_is_signal(message, "net.connman.vpn.Manager",
  885. "ConnectionAdded") ||
  886. dbus_message_is_signal(message,
  887. "net.connman.vpn.Manager",
  888. "ConnectionRemoved")) {
  889. interface = "vpn.Manager";
  890. path = dbus_message_get_member(message);
  891. } else if (dbus_message_is_signal(message, "net.connman.Manager",
  892. "TechnologyAdded") ||
  893. dbus_message_is_signal(message, "net.connman.Manager",
  894. "TechnologyRemoved"))
  895. path = dbus_message_get_member(message);
  896. fprintf(stdout, "%-12s %-20s ", interface, path);
  897. dbus_message_iter_init(message, &iter);
  898. __connmanctl_dbus_print(&iter, "", " = ", " = ");
  899. fprintf(stdout, "\n");
  900. __connmanctl_redraw_rl();
  901. return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
  902. }
  903. static struct {
  904. char *interface;
  905. bool enabled;
  906. } monitor[] = {
  907. { "Service", false },
  908. { "Technology", false },
  909. { "Manager", false },
  910. { "vpn.Manager", false },
  911. { "vpn.Connection", false },
  912. { NULL, },
  913. };
  914. static void monitor_add(char *interface)
  915. {
  916. bool add_filter = true, found = false;
  917. int i;
  918. char *rule;
  919. DBusError err;
  920. for (i = 0; monitor[i].interface; i++) {
  921. if (monitor[i].enabled == true)
  922. add_filter = false;
  923. if (g_strcmp0(interface, monitor[i].interface) == 0) {
  924. if (monitor[i].enabled == true)
  925. return;
  926. monitor[i].enabled = true;
  927. found = true;
  928. }
  929. }
  930. if (found == false)
  931. return;
  932. if (add_filter == true)
  933. dbus_connection_add_filter(connection, monitor_changed,
  934. NULL, NULL);
  935. dbus_error_init(&err);
  936. rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
  937. interface);
  938. dbus_bus_add_match(connection, rule, &err);
  939. g_free(rule);
  940. if (dbus_error_is_set(&err))
  941. fprintf(stderr, "Error: %s\n", err.message);
  942. }
  943. static void monitor_del(char *interface)
  944. {
  945. bool del_filter = true, found = false;
  946. int i;
  947. char *rule;
  948. for (i = 0; monitor[i].interface; i++) {
  949. if (g_strcmp0(interface, monitor[i].interface) == 0) {
  950. if (monitor[i].enabled == false)
  951. return;
  952. monitor[i].enabled = false;
  953. found = true;
  954. }
  955. if (monitor[i].enabled == true)
  956. del_filter = false;
  957. }
  958. if (found == false)
  959. return;
  960. rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
  961. interface);
  962. dbus_bus_remove_match(connection, rule, NULL);
  963. g_free(rule);
  964. if (del_filter == true)
  965. dbus_connection_remove_filter(connection, monitor_changed,
  966. NULL);
  967. }
  968. static int cmd_monitor(char *args[], int num, struct connman_option *options)
  969. {
  970. bool add = true;
  971. int c;
  972. if (num > 3)
  973. return -E2BIG;
  974. if (num == 3) {
  975. switch (parse_boolean(args[2])) {
  976. case 0:
  977. add = false;
  978. break;
  979. default:
  980. break;
  981. }
  982. }
  983. c = parse_args(args[1], options);
  984. switch (c) {
  985. case -1:
  986. monitor_add("Service");
  987. monitor_add("Technology");
  988. monitor_add("Manager");
  989. monitor_add("vpn.Manager");
  990. monitor_add("vpn.Connection");
  991. break;
  992. case 's':
  993. if (add == true)
  994. monitor_add("Service");
  995. else
  996. monitor_del("Service");
  997. break;
  998. case 'c':
  999. if (add == true)
  1000. monitor_add("Technology");
  1001. else
  1002. monitor_del("Technology");
  1003. break;
  1004. case 'm':
  1005. if (add == true)
  1006. monitor_add("Manager");
  1007. else
  1008. monitor_del("Manager");
  1009. break;
  1010. case 'M':
  1011. if (add == true)
  1012. monitor_add("vpn.Manager");
  1013. else
  1014. monitor_del("vpn.Manager");
  1015. break;
  1016. case 'C':
  1017. if (add == true)
  1018. monitor_add("vpn.Connection");
  1019. else
  1020. monitor_del("vpn.Connection");
  1021. break;
  1022. default:
  1023. switch(parse_boolean(args[1])) {
  1024. case 0:
  1025. monitor_del("Service");
  1026. monitor_del("Technology");
  1027. monitor_del("Manager");
  1028. monitor_del("vpn.Manager");
  1029. monitor_del("vpn.Connection");
  1030. break;
  1031. case 1:
  1032. monitor_add("Service");
  1033. monitor_add("Technology");
  1034. monitor_add("Manager");
  1035. monitor_add("vpn.Manager");
  1036. monitor_add("vpn.Connection");
  1037. break;
  1038. default:
  1039. return -EINVAL;
  1040. }
  1041. }
  1042. if (add == true)
  1043. return -EINPROGRESS;
  1044. return 0;
  1045. }
  1046. static int cmd_agent(char *args[], int num, struct connman_option *options)
  1047. {
  1048. if (!__connmanctl_is_interactive()) {
  1049. fprintf(stderr, "Error: Not supported in non-interactive "
  1050. "mode\n");
  1051. return 0;
  1052. }
  1053. if (num > 2)
  1054. return -E2BIG;
  1055. if (num < 2)
  1056. return -EINVAL;
  1057. switch(parse_boolean(args[1])) {
  1058. case 0:
  1059. __connmanctl_agent_unregister(connection);
  1060. break;
  1061. case 1:
  1062. if (__connmanctl_agent_register(connection) == -EINPROGRESS)
  1063. return -EINPROGRESS;
  1064. break;
  1065. default:
  1066. return -EINVAL;
  1067. break;
  1068. }
  1069. return 0;
  1070. }
  1071. static int vpnconnections_properties(DBusMessageIter *iter, const char *error,
  1072. void *user_data)
  1073. {
  1074. char *path = user_data;
  1075. char *str;
  1076. DBusMessageIter dict;
  1077. if (!error) {
  1078. fprintf(stdout, "%s\n", path);
  1079. dbus_message_iter_recurse(iter, &dict);
  1080. __connmanctl_dbus_print(&dict, " ", " = ", "\n");
  1081. fprintf(stdout, "\n");
  1082. } else {
  1083. str = strrchr(path, '/');
  1084. if (str)
  1085. str++;
  1086. else
  1087. str = path;
  1088. fprintf(stderr, "Error %s: %s\n", str, error);
  1089. }
  1090. g_free(user_data);
  1091. return 0;
  1092. }
  1093. static int vpnconnections_list(DBusMessageIter *iter, const char *error,
  1094. void *user_data)
  1095. {
  1096. if (!error)
  1097. __connmanctl_vpnconnections_list(iter);
  1098. else
  1099. fprintf(stderr, "Error: %s\n", error);
  1100. return 0;
  1101. }
  1102. static int cmd_vpnconnections(char *args[], int num,
  1103. struct connman_option *options)
  1104. {
  1105. char *vpnconnection_name, *path;
  1106. if (num > 2)
  1107. return -E2BIG;
  1108. vpnconnection_name = args[1];
  1109. if (!vpnconnection_name)
  1110. return __connmanctl_dbus_method_call(connection,
  1111. VPN_SERVICE, VPN_PATH,
  1112. "net.connman.vpn.Manager", "GetConnections",
  1113. vpnconnections_list, NULL,
  1114. NULL, NULL);
  1115. if (check_dbus_name(vpnconnection_name) == false)
  1116. return -EINVAL;
  1117. path = g_strdup_printf("/net/connman/vpn/connection/%s",
  1118. vpnconnection_name);
  1119. return __connmanctl_dbus_method_call(connection, VPN_SERVICE, path,
  1120. "net.connman.vpn.Connection", "GetProperties",
  1121. vpnconnections_properties, path, NULL, NULL);
  1122. }
  1123. static int cmd_vpnagent(char *args[], int num, struct connman_option *options)
  1124. {
  1125. if (!__connmanctl_is_interactive()) {
  1126. fprintf(stderr, "Error: Not supported in non-interactive "
  1127. "mode\n");
  1128. return 0;
  1129. }
  1130. if (num > 2)
  1131. return -E2BIG;
  1132. if (num < 2)
  1133. return -EINVAL;
  1134. switch(parse_boolean(args[1])) {
  1135. case 0:
  1136. __connmanctl_vpn_agent_unregister(connection);
  1137. break;
  1138. case 1:
  1139. if (__connmanctl_vpn_agent_register(connection) ==
  1140. -EINPROGRESS)
  1141. return -EINPROGRESS;
  1142. break;
  1143. default:
  1144. return -EINVAL;
  1145. break;
  1146. }
  1147. return 0;
  1148. }
  1149. static DBusMessage *session_release(DBusConnection *connection,
  1150. DBusMessage *message, void *user_data)
  1151. {
  1152. __connmanctl_save_rl();
  1153. fprintf(stdout, "Session %s released\n", session_path);
  1154. __connmanctl_redraw_rl();
  1155. g_free(session_path);
  1156. session_path = NULL;
  1157. session_connected = false;
  1158. return g_dbus_create_reply(message, DBUS_TYPE_INVALID);
  1159. }
  1160. static DBusMessage *session_update(DBusConnection *connection,
  1161. DBusMessage *message, void *user_data)
  1162. {
  1163. DBusMessageIter iter, dict;
  1164. __connmanctl_save_rl();
  1165. fprintf(stdout, "Session Update = {\n");
  1166. dbus_message_iter_init(message, &iter);
  1167. dbus_message_iter_recurse(&iter, &dict);
  1168. __connmanctl_dbus_print(&dict, "", " = ", "\n");
  1169. fprintf(stdout, "\n}\n");
  1170. dbus_message_iter_recurse(&iter, &dict);
  1171. while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
  1172. DBusMessageIter entry, variant;
  1173. char *field, *state;
  1174. dbus_message_iter_recurse(&dict, &entry);
  1175. dbus_message_iter_get_basic(&entry, &field);
  1176. if (dbus_message_iter_get_arg_type(&entry)
  1177. == DBUS_TYPE_STRING
  1178. && !strcmp(field, "State")) {
  1179. dbus_message_iter_next(&entry);
  1180. dbus_message_iter_recurse(&entry, &variant);
  1181. if (dbus_message_iter_get_arg_type(&variant)
  1182. != DBUS_TYPE_STRING)
  1183. break;
  1184. dbus_message_iter_get_basic(&variant, &state);
  1185. if (!session_connected && (!strcmp(state, "connected")
  1186. || !strcmp(state, "online"))) {
  1187. fprintf(stdout, "Session %s connected\n",
  1188. session_path);
  1189. session_connected = true;
  1190. break;
  1191. }
  1192. if (!strcmp(state, "disconnected") &&
  1193. session_connected) {
  1194. fprintf(stdout, "Session %s disconnected\n",
  1195. session_path);
  1196. session_connected = false;
  1197. }
  1198. break;
  1199. }
  1200. dbus_message_iter_next(&dict);
  1201. }
  1202. __connmanctl_redraw_rl();
  1203. return g_dbus_create_reply(message, DBUS_TYPE_INVALID);
  1204. }
  1205. static const GDBusMethodTable notification_methods[] = {
  1206. { GDBUS_METHOD("Release", NULL, NULL, session_release) },
  1207. { GDBUS_METHOD("Update", GDBUS_ARGS({"settings", "a{sv}"}),
  1208. NULL, session_update) },
  1209. { },
  1210. };
  1211. static int session_notify_add(const char *path)
  1212. {
  1213. if (session_notify_path)
  1214. return 0;
  1215. if (!g_dbus_register_interface(connection, path,
  1216. "net.connman.Notification",
  1217. notification_methods, NULL, NULL,
  1218. NULL, NULL)) {
  1219. fprintf(stderr, "Error: Failed to register VPN Agent "
  1220. "callbacks\n");
  1221. return -EIO;
  1222. }
  1223. session_notify_path = g_strdup(path);
  1224. return 0;
  1225. }
  1226. static void session_notify_remove(void)
  1227. {
  1228. if (!session_notify_path)
  1229. return;
  1230. g_dbus_unregister_interface(connection, session_notify_path,
  1231. "net.connman.Notification");
  1232. g_free(session_notify_path);
  1233. session_notify_path = NULL;
  1234. }
  1235. static int session_connect_cb(DBusMessageIter *iter, const char *error,
  1236. void *user_data)
  1237. {
  1238. if (error) {
  1239. fprintf(stderr, "Error: %s", error);
  1240. return 0;
  1241. }
  1242. return -EINPROGRESS;
  1243. }
  1244. static int session_connect(void)
  1245. {
  1246. return __connmanctl_dbus_method_call(connection, "net.connman",
  1247. session_path, "net.connman.Session", "Connect",
  1248. session_connect_cb, NULL, NULL, NULL);
  1249. }
  1250. static int session_disconnect_cb(DBusMessageIter *iter, const char *error,
  1251. void *user_data)
  1252. {
  1253. if (error)
  1254. fprintf(stderr, "Error: %s", error);
  1255. return 0;
  1256. }
  1257. static int session_disconnect(void)
  1258. {
  1259. return __connmanctl_dbus_method_call(connection, "net.connman",
  1260. session_path, "net.connman.Session", "Disconnect",
  1261. session_disconnect_cb, NULL, NULL, NULL);
  1262. }
  1263. static int session_create_cb(DBusMessageIter *iter, const char *error,
  1264. void *user_data)
  1265. {
  1266. gboolean connect = GPOINTER_TO_INT(user_data);
  1267. char *str;
  1268. if (error) {
  1269. fprintf(stderr, "Error creating session: %s", error);
  1270. session_notify_remove();
  1271. return 0;
  1272. }
  1273. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH) {
  1274. fprintf(stderr, "Error creating session: No session path\n");
  1275. return -EINVAL;
  1276. }
  1277. g_free(session_path);
  1278. dbus_message_iter_get_basic(iter, &str);
  1279. session_path = g_strdup(str);
  1280. fprintf(stdout, "Session %s created\n", session_path);
  1281. if (connect)
  1282. return session_connect();
  1283. return -EINPROGRESS;
  1284. }
  1285. static void session_create_append(DBusMessageIter *iter, void *user_data)
  1286. {
  1287. const char *notify_path = user_data;
  1288. __connmanctl_dbus_append_dict(iter, NULL, NULL);
  1289. dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
  1290. &notify_path);
  1291. }
  1292. static int session_create(gboolean connect)
  1293. {
  1294. int res;
  1295. char *notify_path;
  1296. notify_path = g_strdup_printf("/net/connman/connmanctl%d", getpid());
  1297. session_notify_add(notify_path);
  1298. res = __connmanctl_dbus_method_call(connection, "net.connman", "/",
  1299. "net.connman.Manager", "CreateSession",
  1300. session_create_cb, GINT_TO_POINTER(connect),
  1301. session_create_append, notify_path);
  1302. g_free(notify_path);
  1303. if (res < 0 && res != -EINPROGRESS)
  1304. session_notify_remove();
  1305. return res;
  1306. }
  1307. static int session_destroy_cb(DBusMessageIter *iter, const char *error,
  1308. void *user_data)
  1309. {
  1310. if (error) {
  1311. fprintf(stderr, "Error destroying session: %s", error);
  1312. return 0;
  1313. }
  1314. fprintf(stdout, "Session %s ended\n", session_path);
  1315. g_free(session_path);
  1316. session_path = NULL;
  1317. session_connected = false;
  1318. return 0;
  1319. }
  1320. static void session_destroy_append(DBusMessageIter *iter, void *user_data)
  1321. {
  1322. const char *path = user_data;
  1323. dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
  1324. }
  1325. static int session_destroy(void)
  1326. {
  1327. return __connmanctl_dbus_method_call(connection, "net.connman", "/",
  1328. "net.connman.Manager", "DestroySession",
  1329. session_destroy_cb, NULL,
  1330. session_destroy_append, session_path);
  1331. }
  1332. static int session_config_return(DBusMessageIter *iter, const char *error,
  1333. void *user_data)
  1334. {
  1335. char *property_name = user_data;
  1336. if (error)
  1337. fprintf(stderr, "Error setting session %s: %s\n",
  1338. property_name, error);
  1339. return 0;
  1340. }
  1341. static void session_config_append_array(DBusMessageIter *iter,
  1342. void *user_data)
  1343. {
  1344. struct config_append *append = user_data;
  1345. char **opts = append->opts;
  1346. int i = 1;
  1347. if (!opts)
  1348. return;
  1349. while (opts[i] && strncmp(opts[i], "--", 2) != 0) {
  1350. dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
  1351. &opts[i]);
  1352. i++;
  1353. }
  1354. append->values = i;
  1355. }
  1356. static int session_config(char *args[], int num,
  1357. struct connman_option *options)
  1358. {
  1359. int index = 0, res = 0;
  1360. struct config_append append;
  1361. char c;
  1362. while (index < num && args[index]) {
  1363. append.opts = &args[index];
  1364. append.values = 0;
  1365. c = parse_args(args[index], options);
  1366. switch (c) {
  1367. case 'b':
  1368. res = __connmanctl_dbus_session_change_array(connection,
  1369. session_path, session_config_return,
  1370. "AllowedBearers", "AllowedBearers",
  1371. session_config_append_array, &append);
  1372. break;
  1373. case 't':
  1374. if (!args[index + 1]) {
  1375. res = -EINVAL;
  1376. break;
  1377. }
  1378. res = __connmanctl_dbus_session_change(connection,
  1379. session_path, session_config_return,
  1380. "ConnectionType", "ConnectionType",
  1381. DBUS_TYPE_STRING, &args[index + 1]);
  1382. append.values = 2;
  1383. break;
  1384. default:
  1385. res = -EINVAL;
  1386. }
  1387. if (res < 0 && res != -EINPROGRESS) {
  1388. printf("Error '%s': %s\n", args[index],
  1389. strerror(-res));
  1390. return 0;
  1391. }
  1392. index += append.values;
  1393. }
  1394. return 0;
  1395. }
  1396. static int cmd_session(char *args[], int num, struct connman_option *options)
  1397. {
  1398. char *command;
  1399. if (num < 2)
  1400. return -EINVAL;
  1401. command = args[1];
  1402. switch(parse_boolean(command)) {
  1403. case 0:
  1404. if (!session_path)
  1405. return -EALREADY;
  1406. return session_destroy();
  1407. case 1:
  1408. if (session_path)
  1409. return -EALREADY;
  1410. return session_create(FALSE);
  1411. default:
  1412. if (!strcmp(command, "connect")) {
  1413. if (!session_path)
  1414. return session_create(TRUE);
  1415. return session_connect();
  1416. } else if (!strcmp(command, "disconnect")) {
  1417. if (!session_path) {
  1418. fprintf(stdout, "Session does not exist\n");
  1419. return 0;
  1420. }
  1421. return session_disconnect();
  1422. } else if (!strcmp(command, "config")) {
  1423. if (!session_path) {
  1424. fprintf(stdout, "Session does not exist\n");
  1425. return 0;
  1426. }
  1427. if (num == 2)
  1428. return -EINVAL;
  1429. return session_config(&args[2], num - 2, options);
  1430. }
  1431. }
  1432. return -EINVAL;
  1433. }
  1434. static int cmd_exit(char *args[], int num, struct connman_option *options)
  1435. {
  1436. return 1;
  1437. }
  1438. static char *lookup_service(const char *text, int state)
  1439. {
  1440. static int len = 0;
  1441. static GHashTableIter iter;
  1442. gpointer key, value;
  1443. if (state == 0) {
  1444. g_hash_table_iter_init(&iter, service_hash);
  1445. len = strlen(text);
  1446. }
  1447. while (g_hash_table_iter_next(&iter, &key, &value)) {
  1448. const char *service = key;
  1449. if (strncmp(text, service, len) == 0)
  1450. return strdup(service);
  1451. }
  1452. return NULL;
  1453. }
  1454. static char *lookup_service_arg(const char *text, int state)
  1455. {
  1456. if (__connmanctl_input_calc_level() > 1) {
  1457. __connmanctl_input_lookup_end();
  1458. return NULL;
  1459. }
  1460. return lookup_service(text, state);
  1461. }
  1462. static char *lookup_peer(const char *text, int state)
  1463. {
  1464. static GHashTableIter iter;
  1465. gpointer key, value;
  1466. static int len = 0;
  1467. if (state == 0) {
  1468. g_hash_table_iter_init(&iter, peer_hash);
  1469. len = strlen(text);
  1470. }
  1471. while (g_hash_table_iter_next(&iter, &key, &value)) {
  1472. const char *peer = key;
  1473. if (strncmp(text, peer, len) == 0)
  1474. return strdup(peer);
  1475. }
  1476. return NULL;
  1477. }
  1478. static char *lookup_peer_arg(const char *text, int state)
  1479. {
  1480. if (__connmanctl_input_calc_level() > 1) {
  1481. __connmanctl_input_lookup_end();
  1482. return NULL;
  1483. }
  1484. return lookup_peer(text, state);
  1485. }
  1486. static char *lookup_technology(const char *text, int state)
  1487. {
  1488. static int len = 0;
  1489. static GHashTableIter iter;
  1490. gpointer key, value;
  1491. if (state == 0) {
  1492. g_hash_table_iter_init(&iter, technology_hash);
  1493. len = strlen(text);
  1494. }
  1495. while (g_hash_table_iter_next(&iter, &key, &value)) {
  1496. const char *technology = key;
  1497. if (strncmp(text, technology, len) == 0)
  1498. return strdup(technology);
  1499. }
  1500. return NULL;
  1501. }
  1502. static char *lookup_technology_arg(const char *text, int state)
  1503. {
  1504. if (__connmanctl_input_calc_level() > 1) {
  1505. __connmanctl_input_lookup_end();
  1506. return NULL;
  1507. }
  1508. return lookup_technology(text, state);
  1509. }
  1510. static char *lookup_technology_offline(const char *text, int state)
  1511. {
  1512. static int len = 0;
  1513. static bool end = false;
  1514. char *str;
  1515. if (__connmanctl_input_calc_level() > 1) {
  1516. __connmanctl_input_lookup_end();
  1517. return NULL;
  1518. }
  1519. if (state == 0) {
  1520. len = strlen(text);
  1521. end = false;
  1522. }
  1523. if (end)
  1524. return NULL;
  1525. str = lookup_technology(text, state);
  1526. if (str)
  1527. return str;
  1528. end = true;
  1529. if (strncmp(text, "offline", len) == 0)
  1530. return strdup("offline");
  1531. return NULL;
  1532. }
  1533. static char *lookup_on_off(const char *text, int state)
  1534. {
  1535. char *onoff[] = { "on", "off", NULL };
  1536. static int idx = 0;
  1537. static int len = 0;
  1538. char *str;
  1539. if (!state) {
  1540. idx = 0;
  1541. len = strlen(text);
  1542. }
  1543. while (onoff[idx]) {
  1544. str = onoff[idx];
  1545. idx++;
  1546. if (!strncmp(text, str, len))
  1547. return strdup(str);
  1548. }
  1549. return NULL;
  1550. }
  1551. static char *lookup_tether(const char *text, int state)
  1552. {
  1553. int level;
  1554. level = __connmanctl_input_calc_level();
  1555. if (level < 2)
  1556. return lookup_technology(text, state);
  1557. if (level == 2)
  1558. return lookup_on_off(text, state);
  1559. __connmanctl_input_lookup_end();
  1560. return NULL;
  1561. }
  1562. static char *lookup_agent(const char *text, int state)
  1563. {
  1564. if (__connmanctl_input_calc_level() > 1) {
  1565. __connmanctl_input_lookup_end();
  1566. return NULL;
  1567. }
  1568. return lookup_on_off(text, state);
  1569. }
  1570. static struct connman_option service_options[] = {
  1571. {"properties", 'p', "[<service>] (obsolete)"},
  1572. { NULL, }
  1573. };
  1574. static struct connman_option config_options[] = {
  1575. {"nameservers", 'n', "<dns1> [<dns2>] [<dns3>]"},
  1576. {"timeservers", 't', "<ntp1> [<ntp2>] [...]"},
  1577. {"domains", 'd', "<domain1> [<domain2>] [...]"},
  1578. {"ipv6", 'v', "off|auto [enable|disable|preferred]|\n"
  1579. "\t\t\tmanual <address> <prefixlength> <gateway>"},
  1580. {"proxy", 'x', "direct|auto <URL>|manual <URL1> [<URL2>] [...]\n"
  1581. "\t\t\t[exclude <exclude1> [<exclude2>] [...]]"},
  1582. {"autoconnect", 'a', "yes|no"},
  1583. {"ipv4", 'i', "off|dhcp|manual <address> <netmask> <gateway>"},
  1584. {"remove", 'r', " Remove service"},
  1585. { NULL, }
  1586. };
  1587. static struct connman_option monitor_options[] = {
  1588. {"services", 's', "[off] Monitor only services"},
  1589. {"tech", 'c', "[off] Monitor only technologies"},
  1590. {"manager", 'm', "[off] Monitor only manager interface"},
  1591. {"vpnmanager", 'M', "[off] Monitor only VPN manager "
  1592. "interface"},
  1593. {"vpnconnection", 'C', "[off] Monitor only VPN "
  1594. "connections" },
  1595. { NULL, }
  1596. };
  1597. static struct connman_option session_options[] = {
  1598. {"bearers", 'b', "<technology1> [<technology2> [...]]"},
  1599. {"type", 't', "local|internet|any"},
  1600. { NULL, }
  1601. };
  1602. static char *lookup_options(struct connman_option *options, const char *text,
  1603. int state)
  1604. {
  1605. static int idx = 0;
  1606. static int len = 0;
  1607. const char *str;
  1608. if (state == 0) {
  1609. idx = 0;
  1610. len = strlen(text);
  1611. }
  1612. while (options[idx].name) {
  1613. str = options[idx].name;
  1614. idx++;
  1615. if (str && strncmp(text, str, len) == 0)
  1616. return strdup(str);
  1617. }
  1618. return NULL;
  1619. }
  1620. static char *lookup_monitor(const char *text, int state)
  1621. {
  1622. int level;
  1623. level = __connmanctl_input_calc_level();
  1624. if (level < 2)
  1625. return lookup_options(monitor_options, text, state);
  1626. if (level == 2)
  1627. return lookup_on_off(text, state);
  1628. __connmanctl_input_lookup_end();
  1629. return NULL;
  1630. }
  1631. static char *lookup_config(const char *text, int state)
  1632. {
  1633. if (__connmanctl_input_calc_level() < 2)
  1634. return lookup_service(text, state);
  1635. return lookup_options(config_options, text, state);
  1636. }
  1637. static char *lookup_session(const char *text, int state)
  1638. {
  1639. return lookup_options(session_options, text, state);
  1640. }
  1641. static const struct {
  1642. const char *cmd;
  1643. const char *argument;
  1644. struct connman_option *options;
  1645. int (*func) (char *args[], int num, struct connman_option *options);
  1646. const char *desc;
  1647. __connmanctl_lookup_cb cb;
  1648. } cmd_table[] = {
  1649. { "state", NULL, NULL, cmd_state,
  1650. "Shows if the system is online or offline", NULL },
  1651. { "technologies", NULL, NULL, cmd_technologies,
  1652. "Display technologies", NULL },
  1653. { "enable", "<technology>|offline", NULL, cmd_enable,
  1654. "Enables given technology or offline mode",
  1655. lookup_technology_offline },
  1656. { "disable", "<technology>|offline", NULL, cmd_disable,
  1657. "Disables given technology or offline mode",
  1658. lookup_technology_offline },
  1659. { "tether", "<technology> on|off\n"
  1660. " wifi [on|off] <ssid> <passphrase> ",
  1661. NULL, cmd_tether,
  1662. "Enable, disable tethering, set SSID and passphrase for wifi",
  1663. lookup_tether },
  1664. { "services", "[<service>]", service_options, cmd_services,
  1665. "Display services", lookup_service_arg },
  1666. { "peers", "[peer]", NULL, cmd_peers,
  1667. "Display peers", lookup_peer_arg },
  1668. { "scan", "<technology>", NULL, cmd_scan,
  1669. "Scans for new services for given technology",
  1670. lookup_technology_arg },
  1671. { "connect", "<service>", NULL, cmd_connect,
  1672. "Connect a given service", lookup_service_arg },
  1673. { "disconnect", "<service>", NULL, cmd_disconnect,
  1674. "Disconnect a given service", lookup_service_arg },
  1675. { "config", "<service>", config_options, cmd_config,
  1676. "Set service configuration options", lookup_config },
  1677. { "monitor", "[off]", monitor_options, cmd_monitor,
  1678. "Monitor signals from interfaces", lookup_monitor },
  1679. { "agent", "on|off", NULL, cmd_agent,
  1680. "Agent mode", lookup_agent },
  1681. {"vpnconnections", "[<connection>]", NULL, cmd_vpnconnections,
  1682. "Display VPN connections", NULL },
  1683. { "vpnagent", "on|off", NULL, cmd_vpnagent,
  1684. "VPN Agent mode", lookup_agent },
  1685. { "session", "on|off|connect|disconnect|config", session_options,
  1686. cmd_session, "Enable or disable a session", lookup_session },
  1687. { "help", NULL, NULL, cmd_help,
  1688. "Show help", NULL },
  1689. { "exit", NULL, NULL, cmd_exit,
  1690. "Exit", NULL },
  1691. { "quit", NULL, NULL, cmd_exit,
  1692. "Quit", NULL },
  1693. { NULL, },
  1694. };
  1695. static int cmd_help(char *args[], int num, struct connman_option *options)
  1696. {
  1697. bool interactive = __connmanctl_is_interactive();
  1698. int i, j;
  1699. if (interactive == false)
  1700. fprintf(stdout, "Usage: connmanctl [[command] [args]]\n");
  1701. for (i = 0; cmd_table[i].cmd; i++) {
  1702. const char *cmd = cmd_table[i].cmd;
  1703. const char *argument = cmd_table[i].argument;
  1704. const char *desc = cmd_table[i].desc;
  1705. printf("%-16s%-22s%s\n", cmd? cmd: "",
  1706. argument? argument: "",
  1707. desc? desc: "");
  1708. if (cmd_table[i].options) {
  1709. for (j = 0; cmd_table[i].options[j].name;
  1710. j++) {
  1711. const char *options_desc =
  1712. cmd_table[i].options[j].desc ?
  1713. cmd_table[i].options[j].desc: "";
  1714. printf(" --%-16s%s\n",
  1715. cmd_table[i].options[j].name,
  1716. options_desc);
  1717. }
  1718. }
  1719. }
  1720. if (interactive == false)
  1721. fprintf(stdout, "\nNote: arguments and output are considered "
  1722. "EXPERIMENTAL for now.\n");
  1723. return 0;
  1724. }
  1725. __connmanctl_lookup_cb __connmanctl_get_lookup_func(const char *text)
  1726. {
  1727. int i, cmdlen, textlen;
  1728. if (!text)
  1729. return NULL;
  1730. textlen = strlen(text);
  1731. for (i = 0; cmd_table[i].cmd; i++) {
  1732. cmdlen = strlen(cmd_table[i].cmd);
  1733. if (textlen > cmdlen && text[cmdlen] != ' ')
  1734. continue;
  1735. if (strncmp(cmd_table[i].cmd, text, cmdlen) == 0)
  1736. return cmd_table[i].cb;
  1737. }
  1738. return NULL;
  1739. }
  1740. int __connmanctl_commands(DBusConnection *dbus_conn, char *argv[], int argc)
  1741. {
  1742. int i, result;
  1743. connection = dbus_conn;
  1744. for (i = 0; cmd_table[i].cmd; i++) {
  1745. if (g_strcmp0(cmd_table[i].cmd, argv[0]) == 0 &&
  1746. cmd_table[i].func) {
  1747. result = cmd_table[i].func(argv, argc,
  1748. cmd_table[i].options);
  1749. if (result < 0 && result != -EINPROGRESS)
  1750. fprintf(stderr, "Error '%s': %s\n", argv[0],
  1751. strerror(-result));
  1752. return result;
  1753. }
  1754. }
  1755. fprintf(stderr, "Error '%s': Unknown command\n", argv[0]);
  1756. return -EINVAL;
  1757. }
  1758. char *__connmanctl_lookup_command(const char *text, int state)
  1759. {
  1760. static int i = 0;
  1761. static int len = 0;
  1762. if (state == 0) {
  1763. i = 0;
  1764. len = strlen(text);
  1765. }
  1766. while (cmd_table[i].cmd) {
  1767. const char *command = cmd_table[i].cmd;
  1768. i++;
  1769. if (strncmp(text, command, len) == 0)
  1770. return strdup(command);
  1771. }
  1772. return NULL;
  1773. }
  1774. static char *get_path(char *full_path)
  1775. {
  1776. char *path;
  1777. path = strrchr(full_path, '/');
  1778. if (path && *path != '\0')
  1779. path++;
  1780. else
  1781. path = full_path;
  1782. return path;
  1783. }
  1784. static void add_service_id(const char *path)
  1785. {
  1786. g_hash_table_replace(service_hash, g_strdup(path),
  1787. GINT_TO_POINTER(TRUE));
  1788. }
  1789. static void remove_service_id(const char *path)
  1790. {
  1791. g_hash_table_remove(service_hash, path);
  1792. }
  1793. static void services_added(DBusMessageIter *iter)
  1794. {
  1795. DBusMessageIter array;
  1796. char *path = NULL;
  1797. while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
  1798. dbus_message_iter_recurse(iter, &array);
  1799. if (dbus_message_iter_get_arg_type(&array) !=
  1800. DBUS_TYPE_OBJECT_PATH)
  1801. return;
  1802. dbus_message_iter_get_basic(&array, &path);
  1803. add_service_id(get_path(path));
  1804. dbus_message_iter_next(iter);
  1805. }
  1806. }
  1807. static void update_services(DBusMessageIter *iter)
  1808. {
  1809. DBusMessageIter array;
  1810. char *path;
  1811. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
  1812. return;
  1813. dbus_message_iter_recurse(iter, &array);
  1814. services_added(&array);
  1815. dbus_message_iter_next(iter);
  1816. if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
  1817. return;
  1818. dbus_message_iter_recurse(iter, &array);
  1819. while (dbus_message_iter_get_arg_type(&array) ==
  1820. DBUS_TYPE_OBJECT_PATH) {
  1821. dbus_message_iter_get_basic(&array, &path);
  1822. remove_service_id(get_path(path));
  1823. dbus_message_iter_next(&array);
  1824. }
  1825. }
  1826. static int populate_service_hash(DBusMessageIter *iter, const char *error,
  1827. void *user_data)
  1828. {
  1829. update_services(iter);
  1830. return 0;
  1831. }
  1832. static void add_peer_id(const char *path)
  1833. {
  1834. g_hash_tab

Large files files are truncated, but you can click here to view the full file