Home | History | Annotate | Download | only in multinetwork
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 
     18 #include "common.h"
     19 
     20 #include <android/api-level.h>
     21 #include <arpa/inet.h>
     22 #include <assert.h>
     23 #include <ctype.h>
     24 #include <errno.h>
     25 #include <stdlib.h>
     26 #include <string.h>
     27 #include <iostream>
     28 
     29 
     30 namespace {
     31 
     32 bool strEqual(const char *a, const char *b) {
     33     return strcmp(a, b) == 0;
     34 }
     35 
     36 // Allow specifying network handles in decimal and hexadecimal.
     37 bool parseNetworkHandle(const char *arg, net_handle_t *nethandle) {
     38     if (arg == nullptr || !isdigit(arg[0]) || nethandle == nullptr) {
     39         return false;
     40     }
     41 
     42     net_handle_t nh;
     43     char *end = nullptr;
     44 
     45     nh = strtoull(arg, &end, 0);
     46     if (end != nullptr && *end == '\0') {
     47         *nethandle = nh;
     48         return true;
     49     }
     50     return false;
     51 }
     52 
     53 }  // namespace
     54 
     55 
     56 void printUsage(const char *progname) {
     57     std::cerr << "Usage: " << progname
     58               << " [--nethandle <nethandle>]"
     59               << " [--mode explicit|process]"
     60               << " [--family unspec|ipv4|ipv6]"
     61               << " <argument>"
     62               << std::endl;
     63     std::cerr << std::endl;
     64     std::cerr << "Learn nethandle values from 'dumpsys connectivity --short' "
     65               << "or 'dumpsys connectivity --diag'"
     66               << std::endl;
     67 }
     68 
     69 Arguments::~Arguments() {}
     70 
     71 bool Arguments::parseArguments(int argc, const char* argv[]) {
     72     if (argc < 1 || argv == nullptr) { return false; }
     73 
     74     for (int i = 1; i < argc; i++) {
     75         if (strEqual(argv[i], "--nethandle")) {
     76             i++;
     77             if (argc == i) break;
     78             if (!parseNetworkHandle(argv[i], &nethandle)) {
     79                 std::cerr << "Failed to parse nethandle: '" << argv[i] << "'"
     80                           << std::endl;
     81                 break;
     82             }
     83         } else if (strEqual(argv[i], "--family")) {
     84             i++;
     85             if (argc == i) break;
     86             if (strEqual(argv[i], "unspec")) {
     87                 family = AF_UNSPEC;
     88             } else if (strEqual(argv[i], "ipv4")) {
     89                 family = AF_INET;
     90             } else if (strEqual(argv[i], "ipv6")) {
     91                 family = AF_INET6;
     92             } else {
     93                 break;
     94             }
     95         } else if (strEqual(argv[i], "--mode")) {
     96             i++;
     97             if (argc == i) break;
     98             if (strEqual(argv[i], "explicit")) {
     99                 api_mode = ApiMode::EXPLICIT;
    100             } else if (strEqual(argv[i], "process")) {
    101                 api_mode = ApiMode::PROCESS;
    102             } else {
    103                 break;
    104             }
    105         } else if (arg1 == nullptr) {
    106             arg1 = argv[i];
    107         } else {
    108             arg1 = nullptr;
    109             break;
    110         }
    111     }
    112 
    113     if (arg1 != nullptr) {
    114         return true;
    115     }
    116 
    117     printUsage(argv[0]);
    118     return false;
    119 }
    120 
    121 
    122 std::string inetSockaddrToString(const sockaddr* sa) {
    123     const bool is_ipv6 = (sa->sa_family == AF_INET6);
    124     char host[INET6_ADDRSTRLEN];
    125     char port[sizeof("65535")];
    126     getnameinfo(sa, is_ipv6 ? sizeof(sockaddr_in6) : sizeof(sockaddr_in),
    127                 host, sizeof(host),
    128                 port, sizeof(port),
    129                 NI_NUMERICHOST | NI_NUMERICSERV);
    130 
    131     if (port[0] == '0' || port[0] == '\0') {
    132         return std::string(host);
    133     }
    134     return (is_ipv6 ? "[" : "") + std::string(host) + (is_ipv6 ? "]:" : ":") + std::string(port);
    135 }
    136