int tool_cmd_peek(int argc, char* argv[]) { int ret = 0; int c; int timeout = DEFAULT_TIMEOUT_IN_SECONDS * 1000; DBusConnection* connection = NULL; DBusMessage *message = NULL; DBusMessage *reply = NULL; DBusError error; uint32_t address = 0; uint16_t count = 32; bool simple_data_format = false; dbus_error_init(&error); while (1) { static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"timeout", required_argument, 0, 't'}, {"count", required_argument, 0, 'c'}, {"data", no_argument, 0, 'd'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long(argc, argv, "ht:c:d", long_options, &option_index); if (c == -1) { break; } switch (c) { case 'h': print_arg_list_help(peek_option_list, argv[0], peek_cmd_syntax); ret = ERRORCODE_HELP; goto bail; case 't': timeout = strtol(optarg, NULL, 0); break; case 'c': count = strtol(optarg, NULL, 0); break; case 'd': simple_data_format = true; break; } } if (optind < argc) { address = strtol(argv[optind], NULL, 0); optind++; } else { fprintf(stderr, "%s: error: Missing required address parameter\n", argv[0]); ret = ERRORCODE_BADARG; goto bail; } if (optind < argc) { fprintf(stderr, "%s: error: Unexpected extra argument: \"%s\"\n", argv[0], argv[optind]); ret = ERRORCODE_BADARG; goto bail; } if (gInterfaceName[0] == 0) { fprintf( stderr, "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n", argv[0] ); ret = ERRORCODE_BADARG; goto bail; } connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); require_string(connection != NULL, bail, error.message); { char path[DBUS_MAXIMUM_NAME_LENGTH+1]; char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1]; bool did_succeed; uint8_t *data_ptr = NULL; int data_len = 0; uint16_t i; ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName); if (ret != 0) { print_error_diagnosis(ret); goto bail; } snprintf(path, sizeof(path), "%s/%s", WPANTUND_DBUS_PATH, gInterfaceName); message = dbus_message_new_method_call( interface_dbus_name, path, WPANTUND_DBUS_APIv1_INTERFACE, WPANTUND_IF_CMD_PEEK ); fprintf(stdout, "Peeking at address 0x%x (%d) for %d bytes\n", address, address, count); dbus_message_append_args( message, DBUS_TYPE_UINT32, &address, DBUS_TYPE_UINT16, &count, DBUS_TYPE_INVALID ); reply = dbus_connection_send_with_reply_and_block( connection, message, timeout, &error ); if (!reply) { fprintf(stderr, "%s: error: %s\n", argv[0], error.message); ret = ERRORCODE_TIMEOUT; goto bail; } did_succeed = dbus_message_get_args(reply, &error, DBUS_TYPE_INT32, &ret, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data_ptr, &data_len, DBUS_TYPE_INVALID ); if (!did_succeed) { did_succeed = dbus_message_get_args(reply, NULL, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID ); } if (!did_succeed || ret != 0) { fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret)); print_error_diagnosis(ret); goto bail; } if (simple_data_format) { for (i = 0; i < data_len; i++) { fprintf(stdout, "%02X ", *data_ptr++); if (i % 32 == 31) { fprintf(stdout, "\n"); } } fprintf(stdout, "\n"); } else { dump_data(data_ptr, data_len); } } bail: if (connection) { dbus_connection_unref(connection); } if (message) { dbus_message_unref(message); } if (reply) { dbus_message_unref(reply); } dbus_error_free(&error); return ret; }
int tool_cmd_scan(int argc, char *argv[]) { int ret = 0; int c; int timeout = DEFAULT_TIMEOUT_IN_SECONDS * 1000; DBusConnection* connection = NULL; DBusMessage *message = NULL; DBusMessage *reply = NULL; DBusPendingCall *pending = NULL; DBusError error; int32_t scan_period = 0; uint32_t channel_mask = 0; dbus_error_init(&error); while (1) { static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"timeout", required_argument, 0, 't'}, {"channel", required_argument, 0, 'c'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long(argc, argv, "hc:t:", long_options, &option_index); if (c == -1) break; switch (c) { case 'h': print_arg_list_help(scan_option_list, argv[0], scan_cmd_syntax); ret = ERRORCODE_HELP; goto bail; case 't': timeout = strtol(optarg, NULL, 0); break; case 'c': channel_mask = strtomask_uint32(optarg); break; } } if (optind < argc) { if (scan_period == 0) { scan_period = strtol(argv[optind], NULL, 0); optind++; } } if (optind < argc) { fprintf(stderr, "%s: error: Unexpected extra argument: \"%s\"\n", argv[0], argv[optind]); ret = ERRORCODE_BADARG; goto bail; } if (gInterfaceName[0] == 0) { fprintf(stderr, "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n", argv[0]); ret = ERRORCODE_BADARG; goto bail; } connection = dbus_bus_get(DBUS_BUS_STARTER, &error); if (!connection) { dbus_error_free(&error); dbus_error_init(&error); connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); } require_string(connection != NULL, bail, error.message); dbus_bus_add_match(connection, gDBusObjectManagerMatchString, &error); require_string(error.name == NULL, bail, error.message); dbus_connection_add_filter(connection, &dbus_beacon_handler, NULL, NULL); { char path[DBUS_MAXIMUM_NAME_LENGTH+1]; char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1]; DBusMessageIter iter; ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName); if (ret != 0) { goto bail; } snprintf( path, sizeof(path), "%s/%s", WPANTUND_DBUS_PATH, gInterfaceName ); message = dbus_message_new_method_call( interface_dbus_name, path, WPANTUND_DBUS_APIv1_INTERFACE, WPANTUND_IF_CMD_NET_SCAN_START ); dbus_message_append_args( message, DBUS_TYPE_UINT32, &channel_mask, DBUS_TYPE_INVALID ); print_scan_header(); gScannedNetworkCount = 0; if(!dbus_connection_send_with_reply( connection, message, &pending, timeout )) { fprintf(stderr, "%s: error: IPC failure\n", argv[0]); ret = ERRORCODE_UNKNOWN; goto bail; } while ((dbus_connection_get_dispatch_status(connection) == DBUS_DISPATCH_DATA_REMAINS) || dbus_connection_has_messages_to_send(connection) || !dbus_pending_call_get_completed(pending) ) { dbus_connection_read_write_dispatch(connection, 5000 /*ms*/); } reply = dbus_pending_call_steal_reply(pending); require(reply!=NULL, bail); dbus_message_iter_init(reply, &iter); if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INT32) { fprintf(stderr, "%s: error: Server returned a bad response ('%c')\n", argv[0], dbus_message_iter_get_arg_type(&iter)); ret = ERRORCODE_UNKNOWN; goto bail; } // Get return code dbus_message_iter_get_basic(&iter, &ret); if (ret) { fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret)); print_error_diagnosis(ret); goto bail; } } bail: if (reply) { dbus_message_unref(reply); } if (pending != NULL) { dbus_pending_call_unref(pending); } if (message) { dbus_message_unref(message); } if (connection) { dbus_bus_remove_match(connection, gDBusObjectManagerMatchString, NULL); dbus_connection_remove_filter(connection,&dbus_beacon_handler,NULL); dbus_connection_unref(connection); } dbus_error_free(&error); return ret; }
int tool_cmd_leave(int argc, char* argv[]) { int ret = 0; int c; int timeout = 10 * 1000; DBusConnection* connection = NULL; DBusMessage *message = NULL; DBusMessage *reply = NULL; DBusError error; dbus_error_init(&error); while (1) { static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"timeout", required_argument, 0, 't'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long(argc, argv, "ht:", long_options, &option_index); if (c == -1) break; switch (c) { case 'h': print_arg_list_help(leave_option_list, argv[0], leave_cmd_syntax); ret = ERRORCODE_HELP; goto bail; case 't': timeout = strtol(optarg, NULL, 0); break; } } if (optind < argc) { fprintf(stderr, "%s: error: Unexpected extra argument: \"%s\"\n", argv[0], argv[optind]); ret = ERRORCODE_BADARG; goto bail; } if (gInterfaceName[0] == 0) { fprintf(stderr, "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n", argv[0]); ret = ERRORCODE_BADARG; goto bail; } connection = dbus_bus_get(DBUS_BUS_STARTER, &error); if (!connection) { dbus_error_free(&error); dbus_error_init(&error); connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); } require_string(connection != NULL, bail, error.message); { DBusMessageIter iter; DBusMessageIter list_iter; char path[DBUS_MAXIMUM_NAME_LENGTH+1]; char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1]; ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName); if (ret != 0) { goto bail; } snprintf(path, sizeof(path), "%s/%s", WPANTUND_DBUS_PATH, gInterfaceName); message = dbus_message_new_method_call( interface_dbus_name, path, WPANTUND_DBUS_APIv1_INTERFACE, WPANTUND_IF_CMD_LEAVE ); fprintf(stderr, "Leaving current WPAN. . .\n"); reply = dbus_connection_send_with_reply_and_block( connection, message, timeout, &error ); if (!reply) { fprintf(stderr, "%s: error: %s\n", argv[0], error.message); ret = ERRORCODE_TIMEOUT; goto bail; } dbus_message_get_args(reply, &error, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID ); if (ret) { fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret)); print_error_diagnosis(ret); } } bail: if (connection) dbus_connection_unref(connection); if (message) dbus_message_unref(message); if (reply) dbus_message_unref(reply); dbus_error_free(&error); return ret; }
int tool_cmd_joiner(int argc, char* argv[]) { int ret = 0; int c; int timeout = DEFAULT_TIMEOUT_IN_SECONDS * 1000; DBusConnection* connection = NULL; DBusMessage *message = NULL; DBusMessage *reply = NULL; DBusMessageIter iter; DBusMessageIter dict_iter; DBusError error; const char *empty_string = ""; const char *psk = NULL; const char *provisioning_url = NULL; const char *vendor_name = NULL; const char *vendor_model = NULL; const char *vendor_sw_version = NULL; const char *vendor_data = NULL; const char *property_joiner_state = kWPANTUNDProperty_ThreadJoinerState; dbus_bool_t action = false; dbus_error_init(&error); if (argc == 1) { fprintf(stderr, "%s: error: Missing command.\n", argv[0]); print_arg_list_help(joiner_option_list, argv[0], joiner_cmd_syntax); goto bail; } while (1) { static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"timeout", required_argument, 0, 't'}, {"start", no_argument, 0, 'e'}, {"stop", no_argument, 0, 'd'}, {"attach", no_argument, 0, 'a'}, {"state", no_argument, 0, 's'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long(argc, argv, "hst:eda", long_options, &option_index); if (c == -1) { break; } switch (c) { case 'h': print_arg_list_help(joiner_option_list, argv[0], joiner_cmd_syntax); ret = ERRORCODE_HELP; goto bail; case 't': //timeout timeout = strtol(optarg, NULL, 0); break; case 's': // state if (optind < argc) { fprintf(stderr, "%s: error: Unexpected extra argument: \"%s\"\n", argv[0], argv[optind]); ret = ERRORCODE_BADARG; goto bail; } connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); ret = create_new_wpan_dbus_message(&message, WPANTUND_IF_CMD_PROP_GET); require_action(ret == 0, bail, print_error_diagnosis(ret)); dbus_message_append_args( message, DBUS_TYPE_STRING, &property_joiner_state, DBUS_TYPE_INVALID ); reply = dbus_connection_send_with_reply_and_block( connection, message, timeout, &error ); if (!reply) { fprintf(stderr, "%s: error: %s\n", argv[0], error.message); ret = ERRORCODE_TIMEOUT; goto bail; } dbus_message_iter_init(reply, &iter); // Get return code dbus_message_iter_get_basic(&iter, &ret); if (ret) { const char* error_cstr = NULL; // Try to see if there is an error explanation we can extract dbus_message_iter_next(&iter); if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_STRING) { dbus_message_iter_get_basic(&iter, &error_cstr); } if(!error_cstr || error_cstr[0] == 0) { error_cstr = (ret<0)?strerror(-ret):"Get failed"; } fprintf(stderr, "%s: %s (%d)\n", property_joiner_state, error_cstr, ret); goto bail; } // Move to the property dbus_message_iter_next(&iter); uint8_t state; dbus_message_iter_get_basic(&iter, &state); fprintf(stdout, "%d (%s)\n", state, joiner_state_int2str(state)); goto bail; case 'a': // joiner attaches to commissioned thread network connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); ret = create_new_wpan_dbus_message(&message, WPANTUND_IF_CMD_JOINER_ATTACH); require_action(ret == 0, bail, print_error_diagnosis(ret)); reply = dbus_connection_send_with_reply_and_block( connection, message, timeout, &error ); if (!reply) { fprintf(stderr, "%s: error: %s\n", argv[0], error.message); ret = ERRORCODE_TIMEOUT; goto bail; } dbus_message_get_args(reply, &error, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID ); if (!ret) { fprintf(stderr, "Successfully Attached!\n"); } else { fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret)); print_error_diagnosis(ret); } goto bail; case 'e': // start commissioning if (optind < argc) { psk = argv[optind]; optind++; } if (!psk) { fprintf(stderr, "%s: error: Missing PSK value.\n", argv[0]); ret = ERRORCODE_BADARG; goto bail; } ret = check_psk_format(psk); if (ret != 0) { fprintf(stderr, "%s: error: Invalid PSKd %d\n", argv[0], ret); goto bail; } if (optind < argc) { size_t len; provisioning_url = argv[optind++]; len = strnlen(provisioning_url, (COMMR_PROVIISIONING_URL_MAX_LENGTH + 1)); if (len > COMMR_PROVIISIONING_URL_MAX_LENGTH) { fprintf(stderr, "%s: error: Provisioning URL is too long, must be maximum %d characters\n", argv[0], COMMR_PROVIISIONING_URL_MAX_LENGTH); ret = ERRORCODE_BADARG; goto bail; } } if (optind < argc) { vendor_name = argv[optind++]; } if (optind < argc) { vendor_model = argv[optind++]; } if (optind < argc) { vendor_sw_version = argv[optind++]; } if (optind < argc) { vendor_data = argv[optind++]; } if (optind < argc) { fprintf(stderr, "%s: error: Unexpected extra argument: \"%s\"\n", argv[0], argv[optind]); ret = ERRORCODE_BADARG; goto bail; } connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); require_string(connection != NULL, bail, error.message); ret = create_new_wpan_dbus_message(&message, WPANTUND_IF_CMD_JOINER_START); require_action(ret == 0, bail, print_error_diagnosis(ret)); dbus_message_iter_init_append(message, &iter); // Open a container as "Array of Dictionary entries from String to Variants" (dbus type "a{sv}") dbus_message_iter_open_container( &iter, DBUS_TYPE_ARRAY, DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict_iter ); // Append dictionary entries append_dbus_dict_entry_basic( &dict_iter, kWPANTUNDValueMapKey_Joiner_PSKd, DBUS_TYPE_STRING, &psk ); if (provisioning_url) { append_dbus_dict_entry_basic( &dict_iter, kWPANTUNDValueMapKey_Joiner_ProvisioningUrl, DBUS_TYPE_STRING, &provisioning_url ); } if (vendor_name) { append_dbus_dict_entry_basic( &dict_iter, kWPANTUNDValueMapKey_Joiner_VendorName, DBUS_TYPE_STRING, &vendor_name ); } if (vendor_model) { append_dbus_dict_entry_basic( &dict_iter, kWPANTUNDValueMapKey_Joiner_VendorModel, DBUS_TYPE_STRING, &vendor_model ); } if (vendor_sw_version) { append_dbus_dict_entry_basic( &dict_iter, kWPANTUNDValueMapKey_Joiner_VendorSwVersion, DBUS_TYPE_STRING, &vendor_sw_version ); } if (vendor_data) { append_dbus_dict_entry_basic( &dict_iter, kWPANTUNDValueMapKey_Joiner_VendorData, DBUS_TYPE_STRING, &vendor_data ); } dbus_message_iter_close_container(&iter, &dict_iter); // Send DBus message and parse the DBus reply reply = dbus_connection_send_with_reply_and_block(connection, message, timeout, &error); if (!reply) { fprintf(stderr, "%s: error: %s\n", argv[0], error.message); ret = ERRORCODE_TIMEOUT; goto bail; } dbus_message_get_args(reply, &error, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); if (ret) { fprintf(stderr, "Failed to start Joiner Commissioning - error %d. %s\n", ret, wpantund_status_to_cstr(ret)); print_error_diagnosis(ret); goto bail; } fprintf(stdout, "Started joiner commissioning, PSKd:\"%s\"", psk); if (provisioning_url) { fprintf(stdout, ", ProvisioningURL:\"%s\"", provisioning_url); } if (vendor_name) { fprintf(stdout, ", VendorName:\"%s\"", vendor_name); } if (vendor_model) { fprintf(stdout, ", VendorModel:\"%s\"", vendor_model); } if (vendor_sw_version) { fprintf(stdout, ", VendorSwVersion:\"%s\"", vendor_sw_version); } if (vendor_data) { fprintf(stdout, ", VendorData:\"%s\"", vendor_data); } fprintf(stdout, "\n", psk); goto bail; case 'd': // stop commissioning if (optind < argc) { fprintf(stderr, "%s: error: Unexpected extra argument: \"%s\"\n", argv[0], argv[optind]); ret = ERRORCODE_BADARG; goto bail; } connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); require_string(connection != NULL, bail, error.message); ret = create_new_wpan_dbus_message(&message, WPANTUND_IF_CMD_JOINER_STOP); require_action(ret == 0, bail, print_error_diagnosis(ret)); reply = dbus_connection_send_with_reply_and_block(connection, message, timeout, &error); if (!reply) { fprintf(stderr, "%s: error: %s\n", argv[0], error.message); ret = ERRORCODE_TIMEOUT; goto bail; } dbus_message_get_args(reply, &error, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID); if (ret) { fprintf(stderr, "Failed to stop joiner commissioning - error %d. %s\n", ret, wpantund_status_to_cstr(ret)); print_error_diagnosis(ret); goto bail; } fprintf(stdout, "Stopped joiner commissioning\n"); goto bail; } } bail: if (connection) { dbus_connection_unref(connection); } if (message) { dbus_message_unref(message); } if (reply) { dbus_message_unref(reply); } dbus_error_free(&error); return ret; }
int tool_cmd_begin_net_wake(int argc, char *argv[]) { int ret = 0; int c; int timeout = DEFAULT_TIMEOUT_IN_SECONDS * 1000; DBusConnection* connection = NULL; DBusMessage *message = NULL; DBusMessage *reply = NULL; DBusError error; bool has_net_wake_data = false; uint8_t net_wake_data = 0; uint32_t net_wake_flags = -1; dbus_error_init(&error); while (1) { static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"timeout", required_argument, 0, 't'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long(argc, argv, "ht:", long_options, &option_index); if (c == -1) break; switch (c) { case 'h': print_arg_list_help(begin_net_wake_option_list, argv[0], begin_net_wake_cmd_syntax); ret = ERRORCODE_HELP; goto bail; case 't': timeout = strtol(optarg, NULL, 0); break; } } if (optind < argc) { if (!has_net_wake_data) { net_wake_data = strtol(argv[optind], NULL, 0); has_net_wake_data = true; optind++; } } if (optind < argc) { fprintf(stderr, "%s: error: Unexpected extra argument: \"%s\"\n", argv[0], argv[optind]); ret = ERRORCODE_BADARG; goto bail; } if (gInterfaceName[0] == 0) { fprintf(stderr, "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n", argv[0]); ret = ERRORCODE_BADARG; goto bail; } connection = dbus_bus_get(DBUS_BUS_STARTER, &error); if (!connection) { dbus_error_free(&error); dbus_error_init(&error); connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); } require_string(connection != NULL, bail, error.message); { DBusMessageIter iter; DBusMessageIter list_iter; char path[DBUS_MAXIMUM_NAME_LENGTH+1]; char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1]; ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName); if (ret != 0) { goto bail; } snprintf(path, sizeof(path), "%s/%s", WPAN_TUNNEL_DBUS_PATH, gInterfaceName); message = dbus_message_new_method_call( interface_dbus_name, path, WPAN_TUNNEL_DBUS_INTERFACE, WPAN_IFACE_CMD_BEGIN_NET_WAKE ); dbus_message_append_args( message, DBUS_TYPE_BYTE, &net_wake_data, DBUS_TYPE_UINT32, &net_wake_flags, DBUS_TYPE_INVALID ); fprintf(stderr, "Begin Net Wake, data = 0x%02X\n", net_wake_data); reply = dbus_connection_send_with_reply_and_block( connection, message, timeout, &error ); if (!reply) { fprintf(stderr, "%s: error: %s\n", argv[0], error.message); ret = ERRORCODE_TIMEOUT; goto bail; } dbus_message_get_args(reply, &error, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID ); if (ret) { fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, (ret<0)?strerror(-ret):""); print_error_diagnosis(ret); } } bail: if (connection) dbus_connection_unref(connection); if (message) dbus_message_unref(message); if (reply) dbus_message_unref(reply); dbus_error_free(&error); return ret; }
int tool_cmd_form(int argc, char* argv[]) { int ret = 0; int c; int timeout = DEFAULT_TIMEOUT_IN_SECONDS * 1000; DBusConnection* connection = NULL; DBusMessage *message = NULL; DBusMessage *reply = NULL; DBusError error; const char* network_name = NULL; const char* ula_prefix = NULL; uint16_t node_type = WPAN_IFACE_ROLE_ROUTER; // Default to router for form uint32_t channel_mask = 0; dbus_error_init(&error); while (1) { static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"timeout", required_argument, 0, 't'}, {"channel", required_argument, 0, 'c'}, {"ula-prefix", required_argument, 0, 'u'}, {"mesh-local-prefix", required_argument, 0, 'M'}, {"legacy-prefix", required_argument, 0, 'L'}, {"type", required_argument, 0, 'T'}, {0, 0, 0, 0} }; int option_index = 0; c = getopt_long(argc, argv, "hc:t:T:u:", long_options, &option_index); if (c == -1) break; switch (c) { case 'h': print_arg_list_help(form_option_list, argv[0], form_cmd_syntax); ret = ERRORCODE_HELP; goto bail; case 't': timeout = strtol(optarg, NULL, 0); break; case 'c': channel_mask = (1 << strtol(optarg, NULL, 0)); break; case 'M': fprintf(stderr, "%s: error: Setting the mesh local address at the command line isn't yet implemented. Set it as a property instead.\n", argv[0]); ret = ERRORCODE_BADARG; goto bail; break; case 'L': case 'u': ula_prefix = optarg; break; case 'T': node_type = node_type_str2int(optarg); break; } } if (optind < argc) { if (!network_name) { network_name = argv[optind]; optind++; } } if (optind < argc) { fprintf(stderr, "%s: error: Unexpected extra argument: \"%s\"\n", argv[0], argv[optind]); ret = ERRORCODE_BADARG; goto bail; } if (!network_name) { fprintf(stderr, "%s: error: Missing network name.\n", argv[0]); ret = ERRORCODE_BADARG; goto bail; } if (gInterfaceName[0] == 0) { fprintf(stderr, "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n", argv[0]); ret = ERRORCODE_BADARG; goto bail; } connection = dbus_bus_get(DBUS_BUS_STARTER, &error); if (!connection) { dbus_error_free(&error); dbus_error_init(&error); connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error); } require_string(connection != NULL, bail, error.message); { DBusMessageIter iter; DBusMessageIter list_iter; char path[DBUS_MAXIMUM_NAME_LENGTH+1]; char interface_dbus_name[DBUS_MAXIMUM_NAME_LENGTH+1]; ret = lookup_dbus_name_from_interface(interface_dbus_name, gInterfaceName); if (ret != 0) { goto bail; } snprintf(path, sizeof(path), "%s/%s", WPAN_TUNNEL_DBUS_PATH, gInterfaceName); message = dbus_message_new_method_call( interface_dbus_name, path, WPAN_TUNNEL_DBUS_INTERFACE, WPAN_IFACE_CMD_FORM ); dbus_message_append_args( message, DBUS_TYPE_STRING, &network_name, DBUS_TYPE_INT16, &node_type, DBUS_TYPE_UINT32, &channel_mask, DBUS_TYPE_INVALID ); if(ula_prefix) { uint8_t ula_bytes[16] = {}; // So the ULA prefix could either be // specified like an IPv6 address, or // specified as a bunch of hex numbers. // We use the presence of a colon (':') // to differentiate. if(strstr(ula_prefix,":")) { // Address-style int bits = inet_pton(AF_INET6,ula_prefix,ula_bytes); if(bits<0) { fprintf(stderr, "Bad ULA \"%s\", errno=%d (%s)\n", ula_prefix, errno, strerror(errno)); goto bail; } else if(!bits) { fprintf(stderr, "Bad ULA \"%s\"\n", ula_prefix); goto bail; } } else { // DATA-style int length = parse_string_into_data(ula_bytes, 8, ula_prefix); if(length<=0) { fprintf(stderr, "Bad ULA \"%s\"\n", ula_prefix); goto bail; } } fprintf(stderr, "Using ULA prefix \"%s\"\n", ula_prefix); uint8_t *addr = ula_bytes; dbus_message_append_args( message, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &addr, 8, DBUS_TYPE_INVALID ); } fprintf(stderr, "Forming WPAN \"%s\" as node type %d\n", network_name, node_type); reply = dbus_connection_send_with_reply_and_block( connection, message, timeout, &error ); if (!reply) { fprintf(stderr, "%s: error: %s\n", argv[0], error.message); ret = ERRORCODE_TIMEOUT; goto bail; } dbus_message_get_args(reply, &error, DBUS_TYPE_INT32, &ret, DBUS_TYPE_INVALID ); if (!ret) { fprintf(stderr, "Successfully formed!\n"); } else { fprintf(stderr, "%s failed with error %d. %s\n", argv[0], ret, wpantund_status_to_cstr(ret)); print_error_diagnosis(ret); } } bail: if (connection) dbus_connection_unref(connection); if (message) dbus_message_unref(message); if (reply) dbus_message_unref(reply); dbus_error_free(&error); return ret; }
int tool_cmd_pcap(int argc, char *argv[]) { static const int set = 1; int ret = 0; int timeout = 10 * 1000; int fd_out = -1; int fd_pair[2] = { -1, -1 }; bool force_ctty = false; bool stdout_was_closed = false; DBusError error; dbus_error_init(&error); while (1) { static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"timeout", required_argument, 0, 't'}, {0, 0, 0, 0} }; int option_index = 0; int c; c = getopt_long(argc, argv, "fht:", long_options, &option_index); if (c == -1) { break; } switch (c) { case 'h': print_arg_list_help(pcap_option_list, argv[0], pcap_cmd_syntax); ret = ERRORCODE_HELP; goto bail; case 'f': force_ctty = true; break; case 't': timeout = strtol(optarg, NULL, 0); break; } } // We use a socket pair for the socket we hand to wpantund, // so that the termination of this process will stop packet // capture. if (socketpair(PF_UNIX, SOCK_DGRAM, 0, fd_pair) < 0) { perror("socketpair"); ret = ERRORCODE_UNKNOWN; goto bail; } if (optind < argc) { // Capture packets to a file path fd_out = open(argv[optind], O_WRONLY|O_CREAT|O_TRUNC, 0666); optind++; } else { // Capture packets to stdout if (!force_ctty && is_descriptor_ctty(STDOUT_FILENO)) { fprintf(stderr, "%s: error: Cowardly refusing write binary data to controlling tty, use -f to override\n", argv[0]); ret = ERRORCODE_REFUSED; goto bail; } // Update fd_out, close the original stdout. fd_out = dup(STDOUT_FILENO); close(STDOUT_FILENO); stdout_was_closed = true; } if (optind < argc) { fprintf( stderr, "%s: error: Unexpected extra argument: \"%s\"\n", argv[0], argv[optind] ); ret = ERRORCODE_BADARG; goto bail; } if (fd_out < 0) { fprintf( stderr, "%s: error: Unable to open file for pcap: \"%s\"\n", argv[0], strerror(errno) ); ret = ERRORCODE_BADARG; goto bail; } if (gInterfaceName[0] == 0) { fprintf( stderr, "%s: error: No WPAN interface set (use the `cd` command, or the `-I` argument for `wpanctl`).\n", argv[0] ); ret = ERRORCODE_BADARG; goto bail; } // Have wpantund start writing PCAP data to one end of our socket pair. ret = do_pcap_to_fd(fd_pair[1], timeout, &error); if (ret) { if (error.message != NULL) { fprintf(stderr, "%s: error: %s\n", argv[0], error.message); } goto bail; } // Close this side of the socket pair so that we can // detect if wpantund closed the socket. close(fd_pair[1]); #ifdef SO_NOSIGPIPE // Turn off sigpipe so we can gracefully exit. setsockopt(fd_pair[0], SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)); setsockopt(fd_out, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)); #endif fprintf(stderr, "%s: Capture started\n", argv[0]); // Data pump while (true) { char buffer[2048]; ssize_t buffer_len; // Read in from datagram socket buffer_len = read(fd_pair[0], buffer, sizeof(buffer)); if (buffer_len <= 0) { break; } // Write out the buffer to our file descriptor buffer_len = write(fd_out, buffer, buffer_len); if (buffer_len <= 0) { break; } } fprintf(stderr, "%s: Capture terminated\n", argv[0]); bail: if (ret) { fprintf(stderr, "pcap: failed with error %d. %s\n", ret, wpantund_status_to_cstr(ret)); print_error_diagnosis(ret); } // Clean up. close(fd_out); close(fd_pair[0]); close(fd_pair[1]); dbus_error_free(&error); if (stdout_was_closed) { exit (ret); } return ret; }