diff options
Diffstat (limited to 'multinetwork/common.cpp')
-rw-r--r-- | multinetwork/common.cpp | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/multinetwork/common.cpp b/multinetwork/common.cpp new file mode 100644 index 00000000..7a5e7be4 --- /dev/null +++ b/multinetwork/common.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "common.h" + +#include <android/api-level.h> +#include <arpa/inet.h> +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <iostream> + + +namespace { + +bool strEqual(const char *a, const char *b) { + return strcmp(a, b) == 0; +} + +// Allow specifying network handles in decimal and hexadecimal. +bool parseNetworkHandle(const char *arg, net_handle_t *nethandle) { + if (arg == nullptr || !isdigit(arg[0]) || nethandle == nullptr) { + return false; + } + + net_handle_t nh; + char *end = nullptr; + + nh = strtoull(arg, &end, 0); + if (end != nullptr && *end == '\0') { + *nethandle = nh; + return true; + } + return false; +} + +} // namespace + + +void printUsage(const char *progname) { + std::cerr << "Usage: " << progname + << " [--nethandle <nethandle>]" + << " [--mode explicit|process]" + << " [--family unspec|ipv4|ipv6]" + << " <argument>" + << std::endl; + std::cerr << std::endl; + std::cerr << "Learn nethandle values from 'dumpsys connectivity --short' " + << "or 'dumpsys connectivity --diag'" + << std::endl; +} + +Arguments::~Arguments() {} + +bool Arguments::parseArguments(int argc, const char* argv[]) { + if (argc < 1 || argv == nullptr) { return false; } + + for (int i = 1; i < argc; i++) { + if (strEqual(argv[i], "--nethandle")) { + i++; + if (argc == i) break; + if (!parseNetworkHandle(argv[i], &nethandle)) { + std::cerr << "Failed to parse nethandle: '" << argv[i] << "'" + << std::endl; + break; + } + } else if (strEqual(argv[i], "--family")) { + i++; + if (argc == i) break; + if (strEqual(argv[i], "unspec")) { + family = AF_UNSPEC; + } else if (strEqual(argv[i], "ipv4")) { + family = AF_INET; + } else if (strEqual(argv[i], "ipv6")) { + family = AF_INET6; + } else { + break; + } + } else if (strEqual(argv[i], "--mode")) { + i++; + if (argc == i) break; + if (strEqual(argv[i], "explicit")) { + api_mode = ApiMode::EXPLICIT; + } else if (strEqual(argv[i], "process")) { + api_mode = ApiMode::PROCESS; + } else { + break; + } + } else if (arg1 == nullptr) { + arg1 = argv[i]; + } else { + arg1 = nullptr; + break; + } + } + + if (arg1 != nullptr) { + return true; + } + + printUsage(argv[0]); + return false; +} + + +std::string inetSockaddrToString(const sockaddr* sa) { + const bool is_ipv6 = (sa->sa_family == AF_INET6); + char host[INET6_ADDRSTRLEN]; + char port[sizeof("65535")]; + getnameinfo(sa, is_ipv6 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in), + host, sizeof(host), + port, sizeof(port), + NI_NUMERICHOST | NI_NUMERICSERV); + + if (port[0] == '0' || port[0] == '\0') { + return std::string(host); + } + return (is_ipv6 ? "[" : "") + std::string(host) + (is_ipv6 ? "]:" : ":") + std::string(port); +} |