/* * 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); }