#ifdef HAVE_SYS_SOCKET_H #include #endif #define EFL_BETA_API_SUPPORT #include #include #include static Eina_Bool monitoring = EINA_TRUE; static const char * _access_point_state_to_str(Efl_Net_Control_Access_Point_State state) { const char *strs[] = { [EFL_NET_CONTROL_ACCESS_POINT_STATE_IDLE] = "idle", [EFL_NET_CONTROL_ACCESS_POINT_STATE_ASSOCIATION] = "association", [EFL_NET_CONTROL_ACCESS_POINT_STATE_CONFIGURATION] = "configuration", [EFL_NET_CONTROL_ACCESS_POINT_STATE_LOCAL] = "local", [EFL_NET_CONTROL_ACCESS_POINT_STATE_ONLINE] = "online", [EFL_NET_CONTROL_ACCESS_POINT_STATE_DISCONNECT] = "disconnect", [EFL_NET_CONTROL_ACCESS_POINT_STATE_FAILURE] = "failure", }; if ((unsigned)state > sizeof(strs)/sizeof(strs[0])) return "???"; if (!strs[state]) return "???"; return strs[state]; } static const char * _access_point_error_to_str(Efl_Net_Control_Access_Point_Error error) { const char *strs[] = { [EFL_NET_CONTROL_ACCESS_POINT_ERROR_NONE] = "none", [EFL_NET_CONTROL_ACCESS_POINT_ERROR_OUT_OF_RANGE] = "out_of_range", [EFL_NET_CONTROL_ACCESS_POINT_ERROR_PIN_MISSING] = "pin_missing", [EFL_NET_CONTROL_ACCESS_POINT_ERROR_DHCP_FAILED] = "dhcp_failed", [EFL_NET_CONTROL_ACCESS_POINT_ERROR_CONNECT_FAILED] = "connect_failed", [EFL_NET_CONTROL_ACCESS_POINT_ERROR_LOGIN_FAILED] = "login_failed", }; if ((unsigned)error > sizeof(strs)/sizeof(strs[0])) return "???"; if (!strs[error]) return "???"; return strs[error]; } static const char * _access_point_security_to_str(Efl_Net_Control_Access_Point_Security security) { static char buf[128]; int pos = 0; #define MAP(x, s) \ if ((security & EFL_NET_CONTROL_ACCESS_POINT_SECURITY_ ## x) == EFL_NET_CONTROL_ACCESS_POINT_SECURITY_ ## x) \ snprintf(buf + pos, sizeof(buf) - pos, "%s%s", \ (pos == 0) ? "" : ", ", s) MAP(NONE, "none"); MAP(WEP, "wep"); MAP(PSK, "psk"); MAP(IEEE802_1X, "ieee802.1X"); #undef MAP return buf; } static void _str_iterator_print(const char *header, const char *footer, Eina_Iterator *it) { Eina_Bool first = EINA_TRUE; const char *str; fputs(header, stdout); EINA_ITERATOR_FOREACH(it, str) { if (first) { putc('[', stdout); first = EINA_FALSE; } else fputs(", ", stdout); printf("'%s'", str); } if (first) fputs("", stdout); else putc(']', stdout); fputs(footer, stdout); eina_iterator_free(it); } static void _access_point_print(Eo *ap) { const char *address, *netmask, *gateway, *str; Efl_Net_Control_Access_Point_Ipv4_Method ipv4_method; Efl_Net_Control_Access_Point_Ipv6_Method ipv6_method; Efl_Net_Control_Access_Point_Proxy_Method proxy_method; uint8_t prefix_length; Eina_Iterator *servers, *excludes; printf("INFO: - name=%s\n" "INFO: - state=%s\n" "INFO: - error=%s\n" "INFO: - priority=%u\n" "INFO: - technology=%s\n" "INFO: - strength=%hhu%%\n" "INFO: - roaming=%hhu\n" "INFO: - auto_connect=%hhu\n" "INFO: - remembered=%hhu\n" "INFO: - immutable=%hhu\n" "INFO: - security=%#x %s\n", efl_net_control_access_point_ssid_get(ap), _access_point_state_to_str(efl_net_control_access_point_state_get(ap)), _access_point_error_to_str(efl_net_control_access_point_error_get(ap)), efl_net_control_access_point_priority_get(ap), efl_name_get(efl_net_control_access_point_technology_get(ap)), efl_net_control_access_point_strength_get(ap), efl_net_control_access_point_roaming_get(ap), efl_net_control_access_point_auto_connect_get(ap), efl_net_control_access_point_remembered_get(ap), efl_net_control_access_point_immutable_get(ap), efl_net_control_access_point_security_get(ap), _access_point_security_to_str(efl_net_control_access_point_security_get(ap))); /* actual values */ efl_net_control_access_point_ipv4_get(ap, &ipv4_method, &address, &netmask, &gateway); if (ipv4_method == EFL_NET_CONTROL_ACCESS_POINT_IPV4_METHOD_OFF) printf("INFO: - ipv4=off\n"); else { str = "???"; switch (ipv4_method) { case EFL_NET_CONTROL_ACCESS_POINT_IPV4_METHOD_UNSET: str = ""; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV4_METHOD_OFF: str = "off"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV4_METHOD_DHCP: str = "dhcp"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV4_METHOD_MANUAL: str = "manual"; break; } printf("INFO: - ipv4=%s address=%s, netmask=%s, gateway=%s\n", str, address, netmask, gateway); } efl_net_control_access_point_ipv6_get(ap, &ipv6_method, &address, &prefix_length, &netmask, &gateway); str = "???"; switch (ipv6_method) { case EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_FIXED: str = "fixed (operator)"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_MANUAL: str = "manual"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_AUTO_PRIVACY_NONE: str = "auto (privacy=none)"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_AUTO_PRIVACY_PUBLIC: str = "auto (privacy=public)"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_AUTO_PRIVACY_TEMPORARY: str = "auto (privacy=temporary)"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_TUNNEL6TO4: str = "6-to-4"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_OFF: str = "off"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_UNSET: str = ""; break; } if ((ipv6_method == EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_OFF) || (ipv6_method == EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_UNSET)) printf("INFO: - ipv6=%s\n", str); else printf("INFO: - ipv6=%s address=%s/%hhu, netmask=%s, gateway=%s\n", str, address, prefix_length, netmask, gateway); _str_iterator_print("INFO: - name_servers=", "\n", efl_net_control_access_point_name_servers_get(ap)); _str_iterator_print("INFO: - time_servers=", "\n", efl_net_control_access_point_time_servers_get(ap)); _str_iterator_print("INFO: - domains=", "\n", efl_net_control_access_point_domains_get(ap)); efl_net_control_access_point_proxy_get(ap, &proxy_method, &address, &servers, &excludes); str = "???"; switch (proxy_method) { case EFL_NET_CONTROL_ACCESS_POINT_PROXY_METHOD_OFF: str = "off"; break; case EFL_NET_CONTROL_ACCESS_POINT_PROXY_METHOD_AUTO: str = "auto"; break; case EFL_NET_CONTROL_ACCESS_POINT_PROXY_METHOD_MANUAL: str = "manual"; break; case EFL_NET_CONTROL_ACCESS_POINT_PROXY_METHOD_UNSET: str = ""; break; } printf("INFO: - proxy=%s, address=%s", str, address ? address : ""); _str_iterator_print(", servers=", "", servers); _str_iterator_print(", excludes=", "\n", excludes); /* configured values */ efl_net_control_access_point_configuration_ipv4_get(ap, &ipv4_method, &address, &netmask, &gateway); if (ipv4_method == EFL_NET_CONTROL_ACCESS_POINT_IPV4_METHOD_UNSET) printf("INFO: - configured ipv4=\n"); else if (ipv4_method == EFL_NET_CONTROL_ACCESS_POINT_IPV4_METHOD_OFF) printf("INFO: - configured ipv4=off\n"); else { str = "???"; switch (ipv4_method) { case EFL_NET_CONTROL_ACCESS_POINT_IPV4_METHOD_UNSET: str = ""; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV4_METHOD_OFF: str = "off"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV4_METHOD_DHCP: str = "dhcp"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV4_METHOD_MANUAL: str = "manual"; break; } printf("INFO: - configured ipv4=%s address=%s, netmask=%s, gateway=%s\n", str, address, netmask, gateway); } efl_net_control_access_point_configuration_ipv6_get(ap, &ipv6_method, &address, &prefix_length, &netmask, &gateway); str = "???"; switch (ipv6_method) { case EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_FIXED: str = "fixed (operator)"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_MANUAL: str = "manual"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_AUTO_PRIVACY_NONE: str = "auto (privacy=none)"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_AUTO_PRIVACY_PUBLIC: str = "auto (privacy=public)"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_AUTO_PRIVACY_TEMPORARY: str = "auto (privacy=temporary)"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_TUNNEL6TO4: str = "6-to-4"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_OFF: str = "off"; break; case EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_UNSET: str = ""; break; } if ((ipv6_method == EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_OFF) || (ipv6_method == EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_UNSET)) printf("INFO: - configured ipv6=%s\n", str); else printf("INFO: - configured ipv6=%s address=%s/%hhu, netmask=%s, gateway=%s\n", str, address, prefix_length, netmask, gateway); _str_iterator_print("INFO: - configured name_servers=", "\n", efl_net_control_access_point_configuration_name_servers_get(ap)); _str_iterator_print("INFO: - configured time_servers=", "\n", efl_net_control_access_point_configuration_time_servers_get(ap)); _str_iterator_print("INFO: - configured domains=", "\n", efl_net_control_access_point_configuration_domains_get(ap)); efl_net_control_access_point_configuration_proxy_get(ap, &proxy_method, &address, &servers, &excludes); str = "???"; switch (proxy_method) { case EFL_NET_CONTROL_ACCESS_POINT_PROXY_METHOD_OFF: str = "off"; break; case EFL_NET_CONTROL_ACCESS_POINT_PROXY_METHOD_AUTO: str = "auto"; break; case EFL_NET_CONTROL_ACCESS_POINT_PROXY_METHOD_MANUAL: str = "manual"; break; case EFL_NET_CONTROL_ACCESS_POINT_PROXY_METHOD_UNSET: str = ""; break; } printf("INFO: - configured proxy=%s, address=%s", str, address ? address : ""); _str_iterator_print(", servers=", "", servers); _str_iterator_print(", excludes=", "\n", excludes); } static void _access_point_changed(void *data EINA_UNUSED, const Efl_Event *event) { Eo *ap = event->object; if (!monitoring) return; printf("INFO: Access Point Changed:\n"); _access_point_print(ap); } static void _ctl_access_point_add(void *data EINA_UNUSED, const Efl_Event *event) { Eo *ap = event->info; if (!monitoring) return; printf("INFO: Access Point Added:\n"); _access_point_print(ap); efl_event_callback_add(ap, EFL_NET_CONTROL_ACCESS_POINT_EVENT_CHANGED, _access_point_changed, NULL); } static void _ctl_access_point_del(void *data EINA_UNUSED, const Efl_Event *event) { Eo *ap = event->info; if (!monitoring) return; printf("INFO: Access Point Removed: %s [%s]\n", efl_net_control_access_point_ssid_get(ap), efl_name_get(efl_net_control_access_point_technology_get(ap))); } static void _access_points_list(Eina_Iterator *it) { Eo *ap; Eina_Bool first = EINA_TRUE; EINA_ITERATOR_FOREACH(it, ap) { if (first) { printf("INFO: PRIO | NAME | FLAGS | STATE | TECH\n" "INFO: -----+--------------------+-------+---------------+---------------\n"); first = EINA_FALSE; } printf("INFO: %4u | %-18.18s | %c%c%c | %-13.13s | %s\n", efl_net_control_access_point_priority_get(ap), efl_net_control_access_point_ssid_get(ap), efl_net_control_access_point_remembered_get(ap) ? 'R' : '.', efl_net_control_access_point_immutable_get(ap) ? 'I' : '.', efl_net_control_access_point_auto_connect_get(ap) ? 'A' : '.', _access_point_state_to_str(efl_net_control_access_point_state_get(ap)), efl_name_get(efl_net_control_access_point_technology_get(ap))); } if (!first) { printf("INFO: -----+--------------------+-------+---------------+---------------\n" "INFO: FLAGS: [R]emembered, [I]mmutable, [A]uto-connect\n"); } eina_iterator_free(it); } static void _ctl_access_points_changed(void *data EINA_UNUSED, const Efl_Event *event) { if (!monitoring) return; _access_points_list(efl_net_control_manager_access_points_get(event->object)); } static const char * _technology_type_str(Efl_Net_Control_Technology_Type type) { const char *strs[] = { [EFL_NET_CONTROL_TECHNOLOGY_TYPE_UNKNOWN] = "unknown", [EFL_NET_CONTROL_TECHNOLOGY_TYPE_SYSTEM] = "system", [EFL_NET_CONTROL_TECHNOLOGY_TYPE_ETHERNET] = "ethernet", [EFL_NET_CONTROL_TECHNOLOGY_TYPE_WIFI] = "wifi", [EFL_NET_CONTROL_TECHNOLOGY_TYPE_BLUETOOTH] = "bluetooth", [EFL_NET_CONTROL_TECHNOLOGY_TYPE_CELLULAR] = "cellular", [EFL_NET_CONTROL_TECHNOLOGY_TYPE_GPS] = "gps", [EFL_NET_CONTROL_TECHNOLOGY_TYPE_VPN] = "vpn", [EFL_NET_CONTROL_TECHNOLOGY_TYPE_GADGET] = "gadget", [EFL_NET_CONTROL_TECHNOLOGY_TYPE_P2P] = "p2p", }; if ((unsigned)type > sizeof(strs)/sizeof(strs[0])) return "???"; if (!strs[type]) return "???"; return strs[type]; } static void _technology_print(Eo *tech) { Eina_Bool tethering; const char *teth_id, *teth_pass; efl_net_control_technology_tethering_get(tech, &tethering, &teth_id, &teth_pass); if (!tethering) teth_id = teth_pass = ""; printf("INFO: - name=%s\n" "INFO: - powered=%hhu\n" "INFO: - connected=%hhu\n" "INFO: - tethering=%hhu (id='%s', passphrase='%s')\n" "INFO: - type=%s\n", efl_name_get(tech), efl_net_control_technology_powered_get(tech), efl_net_control_technology_connected_get(tech), tethering, teth_id, teth_pass, _technology_type_str(efl_net_control_technology_type_get(tech))); } static void _technology_changed(void *data EINA_UNUSED, const Efl_Event *event) { Eo *ap = event->object; if (!monitoring) return; printf("INFO: Technology Changed:\n"); _technology_print(ap); } static void _ctl_technology_add(void *data EINA_UNUSED, const Efl_Event *event) { Eo *tech = event->info; if (!monitoring) return; printf("INFO: Technology Added:\n"); _technology_print(tech); efl_event_callback_add(tech, EFL_NET_CONTROL_TECHNOLOGY_EVENT_CHANGED, _technology_changed, NULL); } static void _ctl_technology_del(void *data EINA_UNUSED, const Efl_Event *event) { Eo *tech = event->info; if (!monitoring) return; printf("INFO: Technology Removed: %s [%s]\n", efl_name_get(tech), _technology_type_str(efl_net_control_technology_type_get(tech))); } static void _ctl_radios_offline_changed(void *data EINA_UNUSED, const Efl_Event *event) { if (!monitoring) return; printf("INFO: radios_offline=%hhu\n", efl_net_control_manager_radios_offline_get(event->object)); } static void _ctl_state_changed(void *data EINA_UNUSED, const Efl_Event *event) { const char *str = "???"; Efl_Net_Control_State state = efl_net_control_manager_state_get(event->object); switch (state) { case EFL_NET_CONTROL_STATE_OFFLINE: str = "offline"; break; case EFL_NET_CONTROL_STATE_ONLINE: str = "online"; break; case EFL_NET_CONTROL_STATE_LOCAL: str = "local"; break; } if (!monitoring) return; printf("INFO: state=%s\n", str); } static void _ctl_agent_released(void *data EINA_UNUSED, const Efl_Event *event EINA_UNUSED) { printf("INFO: Agent released\n"); } static void _ctl_agent_error(void *data EINA_UNUSED, const Efl_Event *event) { const Efl_Net_Control_Agent_Error *e = event->info; printf("INFO: Agent Error:\n" "INFO: - Access Point: %s\n" "INFO: - Message: %s\n", efl_net_control_access_point_ssid_get(e->access_point), e->message); } static void _ctl_agent_browser_url(void *data EINA_UNUSED, const Efl_Event *event) { const Efl_Net_Control_Agent_Browser_Url *e = event->info; printf("INFO: Agent requested to open browser:\n" "INFO: - Access Point: %s\n" "INFO: - URL: %s\n", efl_net_control_access_point_ssid_get(e->access_point), e->url); } static void _ctl_agent_request_input(void *data EINA_UNUSED, const Efl_Event *event) { char buf[100]; Eo *ctl = event->object; Efl_Net_Control_Agent_Request_Input *ri = event->info; Efl_Net_Control_Agent_Request_Input_Information *info; char *name = NULL; char *username = NULL; char *passphrase = NULL; char *ssid = NULL; char *wps = NULL; Eina_Slice ssid_slice = { }; size_t len; unsigned int n; printf("INFO: Needs agent input!\n"); EINA_ACCESSOR_FOREACH(ri->informational, n, info) printf("INFO: - %s: %s\n", info->name, info->value); if (ri->fields) { printf("INFO: The following fields may be entered:\n"); if (ri->fields & EFL_NET_CONTROL_AGENT_REQUEST_INPUT_FIELD_NAME) { printf("INFO: Name="); fflush(stdout); if ((name = fgets(buf, sizeof(buf), stdin)) != NULL) { len = strlen(name); if (name[len - 1] == '\n') { name[len - 1] = '\0'; } else { free(name); name = NULL; } } } if (ri->fields & EFL_NET_CONTROL_AGENT_REQUEST_INPUT_FIELD_SSID) { printf("INFO: SSID="); fflush(stdout); if ((ssid = fgets(buf, sizeof(buf), stdin)) != NULL) { len = strlen(ssid); if (ssid[len - 1] == '\n') { ssid[len - 1] = '\0'; ssid_slice.mem = ssid; ssid_slice.len = len - 1; } else { free(ssid); ssid = NULL; } } } if (ri->fields & EFL_NET_CONTROL_AGENT_REQUEST_INPUT_FIELD_USERNAME) { printf("INFO: Username="); fflush(stdout); if ((username = fgets(buf, sizeof(buf), stdin)) != NULL) { len = strlen(username); if (username[len - 1] == '\n') { username[len - 1] = '\0'; } else { free(username); username = NULL; } } } if (ri->fields & EFL_NET_CONTROL_AGENT_REQUEST_INPUT_FIELD_PASSPHRASE) { if (ri->passphrase_type) printf("INFO: Passphrase(%s)=", ri->passphrase_type); else printf("INFO: Passphrase="); fflush(stdout); if ((passphrase = fgets(buf, sizeof(buf), stdin)) != NULL) { len = strlen(passphrase); if (passphrase[len - 1] == '\n') { passphrase[len - 1] = '\0'; } else { free(passphrase); passphrase = NULL; } } } if (ri->fields & EFL_NET_CONTROL_AGENT_REQUEST_INPUT_FIELD_WPS) { printf("INFO: WPS (use a single dot, '.', for pushbutton)="); fflush(stdout); if ((wps = fgets(buf, sizeof(buf), stdin)) != NULL) { len = strlen(wps); if (wps[len - 1] == '\n') { wps[len - 1] = '\0'; if ((len == 2) && (wps[0] == '.')) wps[0] = '\0'; /* API uses empty string for pushbutton */ } else { free(wps); wps = NULL; } } } } efl_net_control_manager_agent_reply(ctl, name, ssid ? &ssid_slice : NULL, username, passphrase, wps); free(name); free(ssid); free(username); free(passphrase); free(wps); } static void _cmd_technologies_list(Eo *ctl, size_t argc EINA_UNUSED, char **argv EINA_UNUSED) { Eina_Iterator *it = efl_net_control_manager_technologies_get(ctl); Eo *tech; Eina_Bool first = EINA_TRUE; EINA_ITERATOR_FOREACH(it, tech) { if (first) { printf("INFO: NAME | ON | CONN | TYPE\n" "INFO: --------------------+----+------+---------------\n"); first = EINA_FALSE; } printf("INFO: %-18.18s | %c | %c | %s\n", efl_name_get(tech), efl_net_control_technology_powered_get(tech) ? 'X' : ' ', efl_net_control_technology_connected_get(tech) ? 'X' : ' ', _technology_type_str(efl_net_control_technology_type_get(tech))); } if (!first) { printf("INFO: --------------------+----+------+---------------\n"); } eina_iterator_free(it); } static Eina_Bool _parse_bool(const char *header, const char *str, Eina_Bool *ret) { if (str == NULL) { fprintf(stderr, "ERROR: %s requires a boolean.\n", header); return EINA_FALSE; } if (strcmp(str, "on") == 0) { *ret = EINA_TRUE; return EINA_TRUE; } else if (strcmp(str, "off") == 0) { *ret = EINA_FALSE; return EINA_TRUE; } else { fprintf(stderr, "ERROR: %s required boolean 'on' or 'off', got '%s'\n", header, str); return EINA_FALSE; } } static const char * _fmt_bool(Eina_Bool val) { return val ? "on" : "off"; } static Eo * _technology_find(Eo *ctl, const char *name) { Eina_Iterator *it; Eo *child; if (!name) { fprintf(stderr, "ERROR: required technology name\n"); return NULL; } it = efl_net_control_manager_technologies_get(ctl); EINA_ITERATOR_FOREACH(it, child) { const char *tn = efl_name_get(child); if (strcasecmp(name, tn) == 0) { eina_iterator_free(it); return child; } } fprintf(stderr, "ERROR: did not find technology named '%s'\n", name); eina_iterator_free(it); return NULL; } static void _cmd_technology_show(Eo *ctl, size_t argc EINA_UNUSED, char **argv) { Eo *tech = _technology_find(ctl, argv[1]); if (!tech) return; printf("INFO: show technology '%s'\n", argv[1]); _technology_print(tech); } static Eina_Value _technology_scan_done(void *data, const Eina_Value v, const Eina_Future *dead EINA_UNUSED) { Eo *tech = data; if (v.type == EINA_VALUE_TYPE_ERROR) { Eina_Error err = 0; eina_value_error_get(&v, &err); printf("INFO: technology '%s' could not scan: %s\n", efl_name_get(tech), eina_error_msg_get(err)); } else { printf("INFO: technology '%s' finished scan.\n", efl_name_get(tech)); } return v; } static void _cmd_technology_scan(Eo *ctl, size_t argc EINA_UNUSED, char **argv) { Eo *tech = _technology_find(ctl, argv[1]); if (!tech) return; printf("INFO: started scan on technology '%s'\n", argv[1]); eina_future_then(efl_net_control_technology_scan(tech), _technology_scan_done, tech); } static void _cmd_technology_powered(Eo *ctl, size_t argc, char **argv) { Eo *tech = _technology_find(ctl, argv[1]); const char *name; Eina_Bool powered; if (!tech) return; name = efl_name_get(tech); if (argc <= 2) { printf("INFO: technology '%s' powered %s\n", name, _fmt_bool(efl_net_control_technology_powered_get(tech))); return; } if (!_parse_bool(argv[0], argv[2], &powered)) return; printf("INFO: technology '%s' set to powered %s\n", name, _fmt_bool(powered)); efl_net_control_technology_powered_set(tech, powered); } static void _cmd_technology_tethering(Eo *ctl, size_t argc, char **argv) { Eo *tech = _technology_find(ctl, argv[1]); const char *name; Eina_Bool enabled; const char *id = NULL, *pass = NULL; if (!tech) return; name = efl_name_get(tech); if (argc <= 2) { efl_net_control_technology_tethering_get(tech, &enabled, &id, &pass); printf("INFO: technology '%s' tethering %s, id='%s', passphrase='%s'\n", name, _fmt_bool(efl_net_control_technology_powered_get(tech)), id ? id : "", pass ? pass : ""); return; } if (!_parse_bool(argv[0], argv[2], &enabled)) return; if (argc > 3) id = argv[3]; if (argc > 4) pass = argv[4]; printf("INFO: technology '%s' set to tethering %s, id='%s', pass='%s'\n", name, _fmt_bool(enabled), id ? id : "", pass ? pass : ""); efl_net_control_technology_tethering_set(tech, enabled, id, pass); } static void _cmd_access_points_list(Eo *ctl, size_t argc EINA_UNUSED, char **argv EINA_UNUSED) { _access_points_list(efl_net_control_manager_access_points_get(ctl)); } static Eo * _access_point_find(Eo *ctl, const char *name) { Eina_Iterator *it; Eo *child; uint32_t prio = UINT32_MAX; if (!name) { fprintf(stderr, "ERROR: required access_point name\n"); return NULL; } if (name[0] == '#') prio = strtoul(name + 1, NULL, 10); it = efl_net_control_manager_access_points_get(ctl); EINA_ITERATOR_FOREACH(it, child) { if (prio == UINT32_MAX) { const char *n = efl_net_control_access_point_ssid_get(child); if (strcasecmp(name, n) == 0) { eina_iterator_free(it); return child; } } else { uint32_t p = efl_net_control_access_point_priority_get(child); if (p == prio) { eina_iterator_free(it); return child; } } } if (prio == UINT32_MAX) fprintf(stderr, "ERROR: did not find access_point named '%s'\n", name); else fprintf(stderr, "ERROR: did not find access_point at priority '%u'\n", prio); eina_iterator_free(it); return NULL; } static void _cmd_access_point_show(Eo *ctl, size_t argc EINA_UNUSED, char **argv) { Eo *ap = _access_point_find(ctl, argv[1]); if (!ap) return; printf("INFO: show access point '%s'\n", argv[1]); _access_point_print(ap); } static Eina_Value _access_point_connect(void *data, const Eina_Value v, const Eina_Future *dead EINA_UNUSED) { Eo *ap = data; if (v.type == EINA_VALUE_TYPE_ERROR) { Eina_Error err = 0; eina_value_error_get(&v, &err); printf("INFO: access point '%s' could not connect: %s\n", efl_net_control_access_point_ssid_get(ap), eina_error_msg_get(err)); } else { printf("INFO: access point '%s' finished connect.\n", efl_net_control_access_point_ssid_get(ap)); } return v; } static void _cmd_access_point_connect(Eo *ctl, size_t argc EINA_UNUSED, char **argv) { Eo *ap = _access_point_find(ctl, argv[1]); if (!ap) return; printf("INFO: connecting point '%s'\n", argv[1]); eina_future_then(efl_net_control_access_point_connect(ap), _access_point_connect, ap); } static void _cmd_access_point_disconnect(Eo *ctl, size_t argc EINA_UNUSED, char **argv) { Eo *ap = _access_point_find(ctl, argv[1]); if (!ap) return; printf("INFO: disconnect access point '%s'\n", argv[1]); efl_net_control_access_point_disconnect(ap); } static void _cmd_access_point_forget(Eo *ctl, size_t argc EINA_UNUSED, char **argv) { Eo *ap = _access_point_find(ctl, argv[1]); if (!ap) return; printf("INFO: forget access point '%s'\n", argv[1]); efl_net_control_access_point_forget(ap); } static void _cmd_access_point_reorder(Eo *ctl, size_t argc, char **argv) { Eo *ap = _access_point_find(ctl, argv[1]); uint32_t prio; if (!ap) return; if (argc < 3) { fprintf(stderr, "ERROR: missing priority\n"); return; } else if ((strcasecmp(argv[2], "UINT32_MAX") == 0) || (strcasecmp(argv[2], "UINT_MAX") == 0) || (strcasecmp(argv[2], "last") == 0)) prio = UINT32_MAX; else prio = strtoul(argv[2], NULL, 10); printf("INFO: reorder access point '%s' %u -> %u\n", argv[1], efl_net_control_access_point_priority_get(ap), prio); efl_net_control_access_point_priority_set(ap, prio); } static void _cmd_access_point_auto_connect(Eo *ctl, size_t argc EINA_UNUSED, char **argv) { Eo *ap = _access_point_find(ctl, argv[1]); const char *name; Eina_Bool auto_connect; if (!ap) return; name = efl_net_control_access_point_ssid_get(ap); if (argc <= 2) { printf("INFO: access_point '%s' auto connect %s\n", name, _fmt_bool(efl_net_control_access_point_auto_connect_get(ap))); return; } if (!_parse_bool(argv[0], argv[2], &auto_connect)) return; printf("INFO: access_point '%s' set to auto connect %s\n", name, _fmt_bool(auto_connect)); efl_net_control_access_point_auto_connect_set(ap, auto_connect); } static void _cmd_access_point_configure_name_servers(Eo *ctl, size_t argc EINA_UNUSED, char **argv) { Eo *ap = _access_point_find(ctl, argv[1]); Eina_Iterator *it; if (!ap) return; it = eina_carray_iterator_new((void **)(argv + 2)); printf("INFO: configure access point '%s' name servers\n", argv[1]); efl_net_control_access_point_configuration_name_servers_set(ap, it); } static void _cmd_access_point_configure_time_servers(Eo *ctl, size_t argc EINA_UNUSED, char **argv) { Eo *ap = _access_point_find(ctl, argv[1]); Eina_Iterator *it; if (!ap) return; it = eina_carray_iterator_new((void **)(argv + 2)); printf("INFO: configure access point '%s' time servers\n", argv[1]); efl_net_control_access_point_configuration_time_servers_set(ap, it); } static void _cmd_access_point_configure_domains(Eo *ctl, size_t argc EINA_UNUSED, char **argv) { Eo *ap = _access_point_find(ctl, argv[1]); Eina_Iterator *it; if (!ap) return; it = eina_carray_iterator_new((void **)(argv + 2)); printf("INFO: configure access point '%s' domains\n", argv[1]); efl_net_control_access_point_configuration_domains_set(ap, it); } static void _cmd_monitor_set(Eo *ctl EINA_UNUSED, size_t argc, char **argv) { if (argc == 1) { printf("INFO: monitor is %s\n", _fmt_bool(monitoring)); return; } if (!_parse_bool(argv[0], argv[1], &monitoring)) return; printf("INFO: monitor is now %s\n", _fmt_bool(monitoring)); } static void _cmd_agent_set(Eo *ctl, size_t argc, char **argv) { Eina_Bool enabled; if (argc == 1) { printf("INFO: agent is %s\n", _fmt_bool(efl_net_control_manager_agent_enabled_get(ctl))); return; } if (!_parse_bool(argv[0], argv[1], &enabled)) return; efl_net_control_manager_agent_enabled_set(ctl, enabled); printf("INFO: agent is now %s\n", _fmt_bool(enabled)); } static void _cmd_access_point_configure_ipv4(Eo *ctl, size_t argc, char **argv) { Eo *ap = _access_point_find(ctl, argv[1]); const char *name; Efl_Net_Control_Access_Point_Ipv4_Method ipv4_method; const char *address = NULL; const char *netmask = NULL; const char *gateway = NULL; if (!ap) return; if (argc <= 2) { fprintf(stderr, "ERROR: missing IPv4 configuration method: off, dhcp or manual.\n"); return; } name = efl_net_control_access_point_ssid_get(ap); if (strcmp(argv[2], "off") == 0) ipv4_method = EFL_NET_CONTROL_ACCESS_POINT_IPV4_METHOD_OFF; else if (strcmp(argv[2], "dhcp") == 0) ipv4_method = EFL_NET_CONTROL_ACCESS_POINT_IPV4_METHOD_DHCP; else if (strcmp(argv[2], "manual") == 0) ipv4_method = EFL_NET_CONTROL_ACCESS_POINT_IPV4_METHOD_MANUAL; else { fprintf(stderr, "ERROR: invalid IPv4 configuration method '%s', expected: off, dhcp or manual.\n", argv[2]); return; } if (argc > 3) address = argv[3]; if (argc > 4) netmask = argv[4]; if (argc > 5) gateway = argv[5]; printf("INFO: access point '%s' IPv4 set to %s address=%s, netmask=%s, gateway=%s\n", name, argv[2], address, netmask, gateway); efl_net_control_access_point_configuration_ipv4_set(ap, ipv4_method, address, netmask, gateway); } static void _cmd_access_point_configure_ipv6(Eo *ctl, size_t argc, char **argv) { Eo *ap = _access_point_find(ctl, argv[1]); const char *name; Efl_Net_Control_Access_Point_Ipv6_Method ipv6_method; const char *address = NULL; const char *netmask = NULL; const char *gateway = NULL; uint8_t prefix = 0; if (!ap) return; if (argc <= 2) { fprintf(stderr, "ERROR: missing IPv6 configuration method: off, manual, auto-privacy-none, auto-privacy-public or auto-privacy-temporary.\n"); return; } name = efl_net_control_access_point_ssid_get(ap); if (strcmp(argv[2], "off") == 0) ipv6_method = EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_OFF; else if (strcmp(argv[2], "manual") == 0) ipv6_method = EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_MANUAL; else if (strcmp(argv[2], "auto-privacy-none") == 0) ipv6_method = EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_AUTO_PRIVACY_NONE; else if (strcmp(argv[2], "auto-privacy-public") == 0) ipv6_method = EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_AUTO_PRIVACY_PUBLIC; else if (strcmp(argv[2], "auto-privacy-temporary") == 0) ipv6_method = EFL_NET_CONTROL_ACCESS_POINT_IPV6_METHOD_AUTO_PRIVACY_TEMPORARY; else { fprintf(stderr, "ERROR: invalid IPv6 configuration method '%s', expected: off, manual, auto-privacy-none, auto-privacy-public or auto-privacy-temporary.\n", argv[2]); return; } if (argc > 3) address = argv[3]; if (argc > 4) { char *endptr; prefix = strtoul(argv[4], &endptr, 10); if ((endptr == argv[4]) || (*endptr != '\0')) { fprintf(stderr, "ERROR: invalid IPv6 prefix length: %s\n", argv[4]); return; } } if (argc > 5) netmask = argv[5]; if (argc > 6) gateway = argv[6]; printf("INFO: access point '%s' IPv6 set to %s address=%s/%hhu, netmask=%s, gateway=%s\n", name, argv[2], address, prefix, netmask, gateway); efl_net_control_access_point_configuration_ipv6_set(ap, ipv6_method, address, prefix, netmask, gateway); } static void _cmd_access_point_configure_proxy(Eo *ctl, size_t argc, char **argv) { Eo *ap = _access_point_find(ctl, argv[1]); const char *name; Efl_Net_Control_Access_Point_Proxy_Method proxy_method; const char *url = NULL; Eina_Iterator *servers = NULL; Eina_Iterator *excludes = NULL; if (!ap) return; if (argc <= 2) { fprintf(stderr, "ERROR: missing Proxy configuration method: off, dhcp or manual.\n"); return; } name = efl_net_control_access_point_ssid_get(ap); if (strcmp(argv[2], "off") == 0) proxy_method = EFL_NET_CONTROL_ACCESS_POINT_PROXY_METHOD_OFF; else if (strcmp(argv[2], "auto") == 0) proxy_method = EFL_NET_CONTROL_ACCESS_POINT_PROXY_METHOD_AUTO; else if (strcmp(argv[2], "manual") == 0) proxy_method = EFL_NET_CONTROL_ACCESS_POINT_PROXY_METHOD_MANUAL; else { fprintf(stderr, "ERROR: invalid Proxy configuration method '%s', expected: off, dhcp or manual.\n", argv[2]); return; } if (proxy_method == EFL_NET_CONTROL_ACCESS_POINT_PROXY_METHOD_AUTO) { if (argc > 3) url = argv[3]; } else if (proxy_method == EFL_NET_CONTROL_ACCESS_POINT_PROXY_METHOD_MANUAL) { size_t i, servers_start = 3, excludes_start = 0; for (i = 3; i < argc; i++) { if (strcmp(argv[i], "--servers") == 0) { argv[i] = NULL; /* carray iterator operates on null terminated arrays */ servers_start = i + 1; } else if (strcmp(argv[i], "--excludes") == 0) { argv[i] = NULL; /* carray iterator operates on null terminated arrays */ excludes_start = i + 1; } } servers = eina_carray_iterator_new((void **)(argv + servers_start)); if (excludes_start) excludes = eina_carray_iterator_new((void **)(argv + excludes_start)); } printf("INFO: access point '%s' Proxy set to %s url=%s, servers=%p, excludes=%p\n", name, argv[2], url, servers, excludes); efl_net_control_access_point_configuration_proxy_set(ap, proxy_method, url, servers, excludes); } static void _cmd_quit(Eo *ctl, size_t argc EINA_UNUSED, char **argv EINA_UNUSED) { printf("INFO: bye!\n"); efl_loop_quit(efl_loop_get(ctl), EINA_VALUE_EMPTY); } static void _cmd_help(Eo *ctl EINA_UNUSED, size_t argc EINA_UNUSED, char **argv EINA_UNUSED) { puts("HELP:\n" "technologies-list Show all technologies.\n" "technology-show Show all detail of a given technology.\n" "technology-scan Trigger technology scan.\n" "technology-powered [on|off] Get or set technology powered state.\n" "technology-tethering [ [identifier] [passphrase]]\n" " Get or set technology tethering\n" " configuration.\n" "\n" "access-points-list Show all access points.\n" "access-point-show Show all detail of a given access point.\n" "access-point-connect Connect access point.\n" "access-point-disconnect Disconnect access point.\n" "access-point-forget Disconnect and forget access point\n" " configurations.\n" "access-point-reorder Change access point priority, 0 means\n" " first, UINT32_MAX means last.\n" "access-point-auto-connect [on|off]\n" " Get or set access point auto connect.\n" "access-point-configure-name-servers [ns2] ...\n" " Configure Name Servers to use.\n" "access-point-configure-time-servers [ts2] ...\n" " Configure Time Servers to use.\n" "access-point-configure-domains [d2] ...\n" " Configure Domains to use.\n" "access-point-configure-ipv4 [address [netmask [gateway]]]\n" " Configure IPv4.\n" "access-point-configure-ipv6 [address [prefix_length [netmask [gateway]]]]\n" " Configure IPv6.\n" "access-point-configure-proxy off\n" "access-point-configure-proxy auto [url]\n" "access-point-configure-proxy manual --servers ... --excludes ...\n" " Configure Proxy.\n" "\n" "agent [on|off] Enable the agent to answer for requests.\n" "monitor [on|off] Automatically print all changed objects.\n" "help Shows commands and their usage.\n" "quit Quit the application.\n" ""); } static char ** _cmd_split(Eina_Rw_Slice arguments, size_t *argc) { char **array = calloc(arguments.len + 1, sizeof(char *)); char *buf = arguments.mem; size_t len = arguments.len, src, dst, item = 0; char quote = 0; Eina_Bool is_escaped = EINA_FALSE; for (src = 0, dst = 0; src < len; src++) { char c = buf[src]; if (is_escaped) { is_escaped = EINA_FALSE; switch (c) { case 'n': buf[dst++] = '\n'; break; case 't': buf[dst++] = '\t'; break; case 'r': buf[dst++] = '\r'; break; case 'f': buf[dst++] = '\f'; break; case '"': buf[dst++] = '"'; break; case '\'': buf[dst++] = '\''; break; case '\\': buf[dst++] = '\\'; break; default: buf[dst++] = '\\'; buf[dst++] = c; } } else { if (c == '\\') { is_escaped = EINA_TRUE; if (!array[item]) array[item] = buf + dst; } else if ((quote == 0) && ((c == '"') || (c == '\''))) { quote = c; if (!array[item]) array[item] = buf + dst; } else { if ((quote == 0) && (isspace(c))) { buf[dst] = '\0'; dst++; if (array[item]) item++; continue; } else if (quote == c) { quote = 0; continue; } else if (dst < src) buf[dst] = buf[src]; if (!array[item]) array[item] = buf + dst; dst++; } } } if (dst < len) buf[dst] = '\0'; if (array[item]) item++; *argc = item; return array; } static void _cmd_line(void *data, const Efl_Event *event) { Eo *ctl = data; Eina_Binbuf *binbuf = efl_io_copier_binbuf_steal(event->object); Eina_Rw_Slice rw_slice = eina_binbuf_rw_slice_get(binbuf); const struct { const char *cmd; void (*cb)(Eo *ctl, size_t argc, char **argv); } *itr, map[] = { {"technologies-list", _cmd_technologies_list}, {"t-list", _cmd_technologies_list}, {"technology-show", _cmd_technology_show}, {"t-show", _cmd_technology_show}, {"technology-scan", _cmd_technology_scan}, {"t-scan", _cmd_technology_scan}, {"technology-powered", _cmd_technology_powered}, {"t-powered", _cmd_technology_powered}, {"technology-tethering", _cmd_technology_tethering}, {"t-tethering", _cmd_technology_tethering}, {"access-points-list", _cmd_access_points_list}, {"ap-list", _cmd_access_points_list}, {"access-point-show", _cmd_access_point_show}, {"ap-show", _cmd_access_point_show}, {"access-point-connect", _cmd_access_point_connect}, {"ap-connect", _cmd_access_point_connect}, {"access-point-disconnect", _cmd_access_point_disconnect}, {"ap-disconnect", _cmd_access_point_disconnect}, {"access-point-forget", _cmd_access_point_forget}, {"ap-forget", _cmd_access_point_forget}, {"access-point-reorder", _cmd_access_point_reorder}, {"ap-reorder", _cmd_access_point_reorder}, {"access-point-auto-connect", _cmd_access_point_auto_connect}, {"ap-auto-connect", _cmd_access_point_auto_connect}, {"access-point-configure-name-servers", _cmd_access_point_configure_name_servers}, {"ap-configure-name-servers", _cmd_access_point_configure_name_servers}, {"access-point-configure-time-servers", _cmd_access_point_configure_time_servers}, {"ap-configure-time-servers", _cmd_access_point_configure_time_servers}, {"access-point-configure-domains", _cmd_access_point_configure_domains}, {"ap-configure-domains", _cmd_access_point_configure_domains}, {"access-point-configure-ipv4", _cmd_access_point_configure_ipv4}, {"ap-configure-ipv4", _cmd_access_point_configure_ipv4}, {"access-point-configure-ipv6", _cmd_access_point_configure_ipv6}, {"ap-configure-ipv6", _cmd_access_point_configure_ipv6}, {"access-point-configure-proxy", _cmd_access_point_configure_proxy}, {"ap-configure-proxy", _cmd_access_point_configure_proxy}, {"agent", _cmd_agent_set}, {"monitor", _cmd_monitor_set}, {"help", _cmd_help}, {"quit", _cmd_quit}, { } }; char **argv; size_t argc; if (rw_slice.len == 0) { char *dummy[1] = { NULL }; _cmd_quit(ctl, 0, dummy); return; } if (eina_rw_slice_endswith(rw_slice, (Eina_Slice)EINA_SLICE_STR_LITERAL("\n"))) { rw_slice.len--; rw_slice.bytes[rw_slice.len] = '\0'; } argv = _cmd_split(rw_slice, &argc); if (!argv[0]) goto end; for (itr = map; itr->cb; itr++) { if (strcmp(itr->cmd, argv[0]) == 0) { itr->cb(ctl, argc, argv); break; } } if (!itr->cb) fprintf(stderr, "ERROR: command not found: '%s'\n", argv[0]); end: free(argv); eina_binbuf_free(binbuf); } EFL_CALLBACKS_ARRAY_DEFINE(ctl_events_cbs, { EFL_NET_CONTROL_MANAGER_EVENT_ACCESS_POINT_ADD, _ctl_access_point_add }, { EFL_NET_CONTROL_MANAGER_EVENT_ACCESS_POINT_DEL, _ctl_access_point_del }, { EFL_NET_CONTROL_MANAGER_EVENT_ACCESS_POINTS_CHANGED, _ctl_access_points_changed }, { EFL_NET_CONTROL_MANAGER_EVENT_TECHNOLOGY_ADD, _ctl_technology_add }, { EFL_NET_CONTROL_MANAGER_EVENT_TECHNOLOGY_DEL, _ctl_technology_del }, { EFL_NET_CONTROL_MANAGER_EVENT_RADIOS_OFFLINE_CHANGED, _ctl_radios_offline_changed }, { EFL_NET_CONTROL_MANAGER_EVENT_STATE_CHANGED, _ctl_state_changed }, { EFL_NET_CONTROL_MANAGER_EVENT_AGENT_RELEASED, _ctl_agent_released }, { EFL_NET_CONTROL_MANAGER_EVENT_AGENT_ERROR, _ctl_agent_error }, { EFL_NET_CONTROL_MANAGER_EVENT_AGENT_BROWSER_URL, _ctl_agent_browser_url }, { EFL_NET_CONTROL_MANAGER_EVENT_AGENT_REQUEST_INPUT, _ctl_agent_request_input }); static Eo *copier = NULL; EAPI_MAIN void efl_pause(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED) { } EAPI_MAIN void efl_resume(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED) { } EAPI_MAIN void efl_terminate(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED) { efl_del(copier); copier = NULL; } EAPI_MAIN void efl_main(void *data EINA_UNUSED, const Efl_Event *ev) { Eo *ctl; Eo *input; Eina_Slice line_delimiter = EINA_SLICE_STR("\n"); ctl = efl_add(EFL_NET_CONTROL_MANAGER_CLASS, ev->object, efl_event_callback_array_add(efl_added, ctl_events_cbs(), NULL)); if (!ctl) { fputs("ERROR: Could not create Efl.Net.Control object.\n", stderr); goto end; } input = efl_add(EFL_IO_STDIN_CLASS, ev->object); copier = efl_add(EFL_IO_COPIER_CLASS, ev->object, efl_io_copier_source_set(efl_added, input), efl_io_copier_line_delimiter_set(efl_added, line_delimiter), efl_io_copier_buffer_limit_set(efl_added, 8192), efl_io_copier_read_chunk_size_set(efl_added, 8192), efl_event_callback_add(efl_added, EFL_IO_COPIER_EVENT_LINE, _cmd_line, ctl)); printf("INFO: monitoring is on, disable with 'monitor off'. See 'help'.\n"); printf("INFO: type commands, if unsure try: 'help'\n"); return ; end: efl_loop_quit(efl_loop_get(ev->object), eina_value_int_init(EXIT_FAILURE)); } EFL_MAIN_EX();