Skip to content

Commit 871e63d

Browse files
author
Erik Kline
committed
Add multinetwork debugging tools, dnschk and httpurl
Bug: 19537384 Bug: 27199751 Bug: 28719525 Change-Id: Ie983ec12ac6c550fa76c89cd44343220688a99b4
1 parent 2787958 commit 871e63d

File tree

6 files changed

+604
-0
lines changed

6 files changed

+604
-0
lines changed

multinetwork/Android.mk

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
LOCAL_PATH := $(call my-dir)
2+
3+
# Sample util binaries.
4+
include $(CLEAR_VARS)
5+
LOCAL_MODULE := dnschk
6+
7+
LOCAL_C_INCLUDES += frameworks/native/include external/libcxx/include
8+
LOCAL_CPPFLAGS += -std=c++11
9+
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
10+
LOCAL_MODULE_TAGS := debug
11+
LOCAL_SHARED_LIBRARIES := libandroid libbase libc++
12+
LOCAL_SRC_FILES := dnschk.cpp common.cpp
13+
include $(BUILD_EXECUTABLE)
14+
15+
include $(CLEAR_VARS)
16+
LOCAL_MODULE := httpurl
17+
18+
LOCAL_C_INCLUDES += frameworks/native/include external/libcxx/include
19+
LOCAL_CPPFLAGS += -std=c++11
20+
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
21+
LOCAL_MODULE_TAGS := debug
22+
LOCAL_SHARED_LIBRARIES := libandroid libbase libc++
23+
LOCAL_SRC_FILES := httpurl.cpp common.cpp
24+
include $(BUILD_EXECUTABLE)

multinetwork/common.cpp

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
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+
}

multinetwork/common.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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+
#ifndef SYSTEM_EXTRAS_MULTINETWORK_COMMON_H_
19+
#define SYSTEM_EXTRAS_MULTINETWORK_COMMON_H_
20+
21+
#include <sys/cdefs.h>
22+
#include <sys/socket.h>
23+
#include <unistd.h>
24+
#include <string>
25+
#include <android/multinetwork.h>
26+
27+
enum class ApiMode {
28+
EXPLICIT,
29+
PROCESS,
30+
};
31+
32+
33+
struct Arguments {
34+
Arguments() : nethandle(NETWORK_UNSPECIFIED),
35+
api_mode(ApiMode::EXPLICIT),
36+
family(AF_UNSPEC),
37+
arg1(nullptr) {}
38+
~Arguments();
39+
40+
bool parseArguments(int argc, const char* argv[]);
41+
42+
net_handle_t nethandle;
43+
ApiMode api_mode;
44+
sa_family_t family;
45+
const char* arg1;
46+
};
47+
48+
49+
void printUsage(const char *progname);
50+
51+
// If port is non-zero returns strings of the form "192.0.2.1:port" or
52+
// "[2001:db8::1]:port", else it returns the bare IP string literal.
53+
std::string inetSockaddrToString(const sockaddr* sa);
54+
55+
56+
struct FdAutoCloser {
57+
FdAutoCloser() : fd(-1) {}
58+
/* not explicit */ FdAutoCloser(int fd) : fd(fd) {}
59+
~FdAutoCloser() {
60+
if (fd > -1) {
61+
close(fd);
62+
}
63+
fd = -1;
64+
}
65+
66+
int fd;
67+
};
68+
69+
#endif // SYSTEM_EXTRAS_MULTINETWORK_COMMON_H_

multinetwork/dnschk.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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 <arpa/inet.h>
19+
#include <errno.h>
20+
#include <netdb.h>
21+
#include <netinet/in.h>
22+
#include <string.h>
23+
#include <sys/socket.h>
24+
25+
#include <iostream>
26+
#include <string>
27+
28+
#include <android/multinetwork.h>
29+
#include "common.h"
30+
31+
32+
int main(int argc, const char* argv[]) {
33+
int rval = -1;
34+
35+
struct Arguments args;
36+
if (!args.parseArguments(argc, argv)) { return rval; }
37+
38+
const struct addrinfo hints = {
39+
.ai_family = args.family,
40+
.ai_socktype = SOCK_DGRAM,
41+
};
42+
struct addrinfo *result = nullptr;
43+
44+
std::cout << "# " << args.arg1
45+
<< " (via nethandle " << args.nethandle << "):"
46+
<< std::endl;
47+
48+
switch (args.api_mode) {
49+
case ApiMode::EXPLICIT:
50+
rval = android_getaddrinfofornetwork(args.nethandle,
51+
args.arg1, nullptr, &hints, &result);
52+
break;
53+
case ApiMode::PROCESS:
54+
if (args.nethandle != NETWORK_UNSPECIFIED) {
55+
rval = android_setprocnetwork(args.nethandle);
56+
if (rval != 0) {
57+
std::cerr << "android_setprocnetwork returned " << rval
58+
<< std::endl;
59+
return rval;
60+
}
61+
}
62+
rval = getaddrinfo(args.arg1, nullptr, &hints, &result);
63+
break;
64+
default:
65+
// Unreachable.
66+
std::cerr << "Unknown api mode." << std::endl;
67+
return -1;
68+
}
69+
70+
if (rval != 0) {
71+
std::cerr << "DNS resolution failure; gaierror=" << rval
72+
<< " [" << gai_strerror(rval) << "]"
73+
<< std::endl;
74+
return rval;
75+
}
76+
77+
for (struct addrinfo* rp = result; rp != nullptr; rp = rp->ai_next) {
78+
std::cout << inetSockaddrToString(rp->ai_addr) << std::endl;
79+
}
80+
81+
freeaddrinfo(result);
82+
return 0;
83+
}

0 commit comments

Comments
 (0)