1*387f9dfdSAndroid Build Coastguard Worker /*
2*387f9dfdSAndroid Build Coastguard Worker * Copyright (c) 2017 Politecnico di Torino
3*387f9dfdSAndroid Build Coastguard Worker *
4*387f9dfdSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*387f9dfdSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*387f9dfdSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*387f9dfdSAndroid Build Coastguard Worker *
8*387f9dfdSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*387f9dfdSAndroid Build Coastguard Worker *
10*387f9dfdSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*387f9dfdSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*387f9dfdSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*387f9dfdSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*387f9dfdSAndroid Build Coastguard Worker * limitations under the License.
15*387f9dfdSAndroid Build Coastguard Worker */
16*387f9dfdSAndroid Build Coastguard Worker
17*387f9dfdSAndroid Build Coastguard Worker #include <linux/version.h>
18*387f9dfdSAndroid Build Coastguard Worker #include <unistd.h>
19*387f9dfdSAndroid Build Coastguard Worker #include <string>
20*387f9dfdSAndroid Build Coastguard Worker
21*387f9dfdSAndroid Build Coastguard Worker #include "BPF.h"
22*387f9dfdSAndroid Build Coastguard Worker #include "catch.hpp"
23*387f9dfdSAndroid Build Coastguard Worker
bpf_module_rw_engine_enabled()24*387f9dfdSAndroid Build Coastguard Worker TEST_CASE("test bpf table", ebpf::bpf_module_rw_engine_enabled() ? "[bpf_table]" : "[bpf_table][!mayfail]") {
25*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"(
26*387f9dfdSAndroid Build Coastguard Worker BPF_TABLE("hash", int, int, myhash, 128);
27*387f9dfdSAndroid Build Coastguard Worker )";
28*387f9dfdSAndroid Build Coastguard Worker
29*387f9dfdSAndroid Build Coastguard Worker auto bpf = std::make_unique<ebpf::BPF>();
30*387f9dfdSAndroid Build Coastguard Worker ebpf::StatusTuple res(0);
31*387f9dfdSAndroid Build Coastguard Worker std::vector<std::pair<std::string, std::string>> elements;
32*387f9dfdSAndroid Build Coastguard Worker res = bpf->init(BPF_PROGRAM);
33*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
34*387f9dfdSAndroid Build Coastguard Worker
35*387f9dfdSAndroid Build Coastguard Worker ebpf::BPFTable t = bpf->get_table("myhash");
36*387f9dfdSAndroid Build Coastguard Worker
37*387f9dfdSAndroid Build Coastguard Worker // update element
38*387f9dfdSAndroid Build Coastguard Worker std::string value;
39*387f9dfdSAndroid Build Coastguard Worker res = t.update_value("0x07", "0x42");
40*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
41*387f9dfdSAndroid Build Coastguard Worker res = t.get_value("0x7", value);
42*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
43*387f9dfdSAndroid Build Coastguard Worker REQUIRE(value == "0x42");
44*387f9dfdSAndroid Build Coastguard Worker
45*387f9dfdSAndroid Build Coastguard Worker // update another element
46*387f9dfdSAndroid Build Coastguard Worker res = t.update_value("0x11", "0x777");
47*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
48*387f9dfdSAndroid Build Coastguard Worker res = t.get_value("0x11", value);
49*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
50*387f9dfdSAndroid Build Coastguard Worker REQUIRE(value == "0x777");
51*387f9dfdSAndroid Build Coastguard Worker
52*387f9dfdSAndroid Build Coastguard Worker // remove value
53*387f9dfdSAndroid Build Coastguard Worker res = t.remove_value("0x11");
54*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
55*387f9dfdSAndroid Build Coastguard Worker res = t.get_value("0x11", value);
56*387f9dfdSAndroid Build Coastguard Worker REQUIRE(!res.ok());
57*387f9dfdSAndroid Build Coastguard Worker
58*387f9dfdSAndroid Build Coastguard Worker res = t.update_value("0x15", "0x888");
59*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
60*387f9dfdSAndroid Build Coastguard Worker res = t.get_table_offline(elements);
61*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
62*387f9dfdSAndroid Build Coastguard Worker REQUIRE(elements.size() == 2);
63*387f9dfdSAndroid Build Coastguard Worker
64*387f9dfdSAndroid Build Coastguard Worker // check that elements match what is in the table
65*387f9dfdSAndroid Build Coastguard Worker for (auto &it : elements) {
66*387f9dfdSAndroid Build Coastguard Worker if (it.first == "0x15") {
67*387f9dfdSAndroid Build Coastguard Worker REQUIRE(it.second == "0x888");
68*387f9dfdSAndroid Build Coastguard Worker } else if (it.first == "0x7") {
69*387f9dfdSAndroid Build Coastguard Worker REQUIRE(it.second == "0x42");
70*387f9dfdSAndroid Build Coastguard Worker } else {
71*387f9dfdSAndroid Build Coastguard Worker FAIL("Element " + it.first + " should not be on the table", it.first);
72*387f9dfdSAndroid Build Coastguard Worker }
73*387f9dfdSAndroid Build Coastguard Worker }
74*387f9dfdSAndroid Build Coastguard Worker
75*387f9dfdSAndroid Build Coastguard Worker res = t.clear_table_non_atomic();
76*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
77*387f9dfdSAndroid Build Coastguard Worker res = t.get_table_offline(elements);
78*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
79*387f9dfdSAndroid Build Coastguard Worker REQUIRE(elements.size() == 0);
80*387f9dfdSAndroid Build Coastguard Worker
81*387f9dfdSAndroid Build Coastguard Worker // delete bpf_module, call to key/leaf printf/scanf must fail
82*387f9dfdSAndroid Build Coastguard Worker bpf.reset();
83*387f9dfdSAndroid Build Coastguard Worker
84*387f9dfdSAndroid Build Coastguard Worker res = t.update_value("0x07", "0x42");
85*387f9dfdSAndroid Build Coastguard Worker REQUIRE(!res.ok());
86*387f9dfdSAndroid Build Coastguard Worker
87*387f9dfdSAndroid Build Coastguard Worker res = t.get_value("0x07", value);
88*387f9dfdSAndroid Build Coastguard Worker REQUIRE(!res.ok());
89*387f9dfdSAndroid Build Coastguard Worker
90*387f9dfdSAndroid Build Coastguard Worker res = t.remove_value("0x07");
91*387f9dfdSAndroid Build Coastguard Worker REQUIRE(!res.ok());
92*387f9dfdSAndroid Build Coastguard Worker }
93*387f9dfdSAndroid Build Coastguard Worker
94*387f9dfdSAndroid Build Coastguard Worker #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
bpf_module_rw_engine_enabled()95*387f9dfdSAndroid Build Coastguard Worker TEST_CASE("test bpf percpu tables", ebpf::bpf_module_rw_engine_enabled() ? "[bpf_percpu_table]" : "[bpf_percpu_table][!mayfail]") {
96*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"(
97*387f9dfdSAndroid Build Coastguard Worker BPF_PERCPU_HASH(myhash, int, u64, 128);
98*387f9dfdSAndroid Build Coastguard Worker )";
99*387f9dfdSAndroid Build Coastguard Worker
100*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF bpf;
101*387f9dfdSAndroid Build Coastguard Worker ebpf::StatusTuple res(0);
102*387f9dfdSAndroid Build Coastguard Worker res = bpf.init(BPF_PROGRAM);
103*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
104*387f9dfdSAndroid Build Coastguard Worker
105*387f9dfdSAndroid Build Coastguard Worker ebpf::BPFTable t = bpf.get_table("myhash");
106*387f9dfdSAndroid Build Coastguard Worker size_t ncpus = ebpf::BPFTable::get_possible_cpu_count();
107*387f9dfdSAndroid Build Coastguard Worker
108*387f9dfdSAndroid Build Coastguard Worker std::vector<std::string> v1(ncpus);
109*387f9dfdSAndroid Build Coastguard Worker for (size_t i = 0; i < ncpus; i++) {
110*387f9dfdSAndroid Build Coastguard Worker v1.at(i) = std::to_string(42 * i);
111*387f9dfdSAndroid Build Coastguard Worker }
112*387f9dfdSAndroid Build Coastguard Worker
113*387f9dfdSAndroid Build Coastguard Worker // update element
114*387f9dfdSAndroid Build Coastguard Worker std::vector<std::string> value;
115*387f9dfdSAndroid Build Coastguard Worker res = t.update_value("0x07", v1);
116*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
117*387f9dfdSAndroid Build Coastguard Worker res = t.get_value("0x07", value);
118*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
119*387f9dfdSAndroid Build Coastguard Worker for (size_t i = 0; i < ncpus; i++) {
120*387f9dfdSAndroid Build Coastguard Worker REQUIRE(42 * i == std::stoul(value.at(i), nullptr, 16));
121*387f9dfdSAndroid Build Coastguard Worker }
122*387f9dfdSAndroid Build Coastguard Worker }
123*387f9dfdSAndroid Build Coastguard Worker #endif
124*387f9dfdSAndroid Build Coastguard Worker
125*387f9dfdSAndroid Build Coastguard Worker TEST_CASE("test bpf hash table", "[bpf_hash_table]") {
126*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"(
127*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(myhash, int, int, 128);
128*387f9dfdSAndroid Build Coastguard Worker )";
129*387f9dfdSAndroid Build Coastguard Worker
130*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF bpf;
131*387f9dfdSAndroid Build Coastguard Worker ebpf::StatusTuple res(0);
132*387f9dfdSAndroid Build Coastguard Worker res = bpf.init(BPF_PROGRAM);
133*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
134*387f9dfdSAndroid Build Coastguard Worker
135*387f9dfdSAndroid Build Coastguard Worker auto t = bpf.get_hash_table<int, int>("myhash");
136*387f9dfdSAndroid Build Coastguard Worker
137*387f9dfdSAndroid Build Coastguard Worker int key, value;
138*387f9dfdSAndroid Build Coastguard Worker
139*387f9dfdSAndroid Build Coastguard Worker // updaate element
140*387f9dfdSAndroid Build Coastguard Worker key = 0x08;
141*387f9dfdSAndroid Build Coastguard Worker value = 0x43;
142*387f9dfdSAndroid Build Coastguard Worker res = t.update_value(key, value);
143*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
144*387f9dfdSAndroid Build Coastguard Worker REQUIRE(t[key] == value);
145*387f9dfdSAndroid Build Coastguard Worker
146*387f9dfdSAndroid Build Coastguard Worker // update another element
147*387f9dfdSAndroid Build Coastguard Worker key = 0x12;
148*387f9dfdSAndroid Build Coastguard Worker value = 0x778;
149*387f9dfdSAndroid Build Coastguard Worker res = t.update_value(key, value);
150*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
151*387f9dfdSAndroid Build Coastguard Worker key = 0x31;
152*387f9dfdSAndroid Build Coastguard Worker value = 0x123;
153*387f9dfdSAndroid Build Coastguard Worker res = t.update_value(key, value);
154*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
155*387f9dfdSAndroid Build Coastguard Worker key = 0x12;
156*387f9dfdSAndroid Build Coastguard Worker value = 0;
157*387f9dfdSAndroid Build Coastguard Worker res = t.get_value(key, value);
158*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
159*387f9dfdSAndroid Build Coastguard Worker REQUIRE(value == 0x778);
160*387f9dfdSAndroid Build Coastguard Worker
161*387f9dfdSAndroid Build Coastguard Worker // remove value and dump table
162*387f9dfdSAndroid Build Coastguard Worker key = 0x12;
163*387f9dfdSAndroid Build Coastguard Worker res = t.remove_value(key);
164*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
165*387f9dfdSAndroid Build Coastguard Worker auto values = t.get_table_offline();
166*387f9dfdSAndroid Build Coastguard Worker REQUIRE(values.size() == 2);
167*387f9dfdSAndroid Build Coastguard Worker
168*387f9dfdSAndroid Build Coastguard Worker // clear table
169*387f9dfdSAndroid Build Coastguard Worker res = t.clear_table_non_atomic();
170*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
171*387f9dfdSAndroid Build Coastguard Worker values = t.get_table_offline();
172*387f9dfdSAndroid Build Coastguard Worker REQUIRE(values.size() == 0);
173*387f9dfdSAndroid Build Coastguard Worker }
174*387f9dfdSAndroid Build Coastguard Worker
175*387f9dfdSAndroid Build Coastguard Worker TEST_CASE("test bpf stack table", "[bpf_stack_table]") {
176*387f9dfdSAndroid Build Coastguard Worker #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)
177*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"(
178*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(id, int, int, 1);
179*387f9dfdSAndroid Build Coastguard Worker BPF_STACK_TRACE(stack_traces, 8);
180*387f9dfdSAndroid Build Coastguard Worker
181*387f9dfdSAndroid Build Coastguard Worker int on_sys_getuid(void *ctx) {
182*387f9dfdSAndroid Build Coastguard Worker int stack_id = stack_traces.get_stackid(ctx, BPF_F_REUSE_STACKID);
183*387f9dfdSAndroid Build Coastguard Worker int zero = 0, *val;
184*387f9dfdSAndroid Build Coastguard Worker val = id.lookup_or_try_init(&zero, &stack_id);
185*387f9dfdSAndroid Build Coastguard Worker if (val) {
186*387f9dfdSAndroid Build Coastguard Worker (*val) = stack_id;
187*387f9dfdSAndroid Build Coastguard Worker }
188*387f9dfdSAndroid Build Coastguard Worker
189*387f9dfdSAndroid Build Coastguard Worker return 0;
190*387f9dfdSAndroid Build Coastguard Worker }
191*387f9dfdSAndroid Build Coastguard Worker )";
192*387f9dfdSAndroid Build Coastguard Worker
193*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF bpf;
194*387f9dfdSAndroid Build Coastguard Worker ebpf::StatusTuple res(0);
195*387f9dfdSAndroid Build Coastguard Worker res = bpf.init(BPF_PROGRAM);
196*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
197*387f9dfdSAndroid Build Coastguard Worker std::string getuid_fnname = bpf.get_syscall_fnname("getuid");
198*387f9dfdSAndroid Build Coastguard Worker res = bpf.attach_kprobe(getuid_fnname, "on_sys_getuid");
199*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
200*387f9dfdSAndroid Build Coastguard Worker REQUIRE(getuid() >= 0);
201*387f9dfdSAndroid Build Coastguard Worker res = bpf.detach_kprobe(getuid_fnname);
202*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
203*387f9dfdSAndroid Build Coastguard Worker
204*387f9dfdSAndroid Build Coastguard Worker auto id = bpf.get_hash_table<int, int>("id");
205*387f9dfdSAndroid Build Coastguard Worker auto stack_traces = bpf.get_stack_table("stack_traces");
206*387f9dfdSAndroid Build Coastguard Worker
207*387f9dfdSAndroid Build Coastguard Worker int stack_id = id[0];
208*387f9dfdSAndroid Build Coastguard Worker REQUIRE(stack_id >= 0);
209*387f9dfdSAndroid Build Coastguard Worker
210*387f9dfdSAndroid Build Coastguard Worker auto addrs = stack_traces.get_stack_addr(stack_id);
211*387f9dfdSAndroid Build Coastguard Worker auto symbols = stack_traces.get_stack_symbol(stack_id, -1);
212*387f9dfdSAndroid Build Coastguard Worker REQUIRE(addrs.size() > 0);
213*387f9dfdSAndroid Build Coastguard Worker REQUIRE(addrs.size() == symbols.size());
214*387f9dfdSAndroid Build Coastguard Worker bool found = false;
215*387f9dfdSAndroid Build Coastguard Worker for (const auto &symbol : symbols)
216*387f9dfdSAndroid Build Coastguard Worker if (symbol.find("sys_getuid") != std::string::npos) {
217*387f9dfdSAndroid Build Coastguard Worker found = true;
218*387f9dfdSAndroid Build Coastguard Worker break;
219*387f9dfdSAndroid Build Coastguard Worker }
220*387f9dfdSAndroid Build Coastguard Worker REQUIRE(found);
221*387f9dfdSAndroid Build Coastguard Worker
222*387f9dfdSAndroid Build Coastguard Worker stack_traces.clear_table_non_atomic();
223*387f9dfdSAndroid Build Coastguard Worker addrs = stack_traces.get_stack_addr(stack_id);
224*387f9dfdSAndroid Build Coastguard Worker REQUIRE(addrs.size() == 0);
225*387f9dfdSAndroid Build Coastguard Worker #endif
226*387f9dfdSAndroid Build Coastguard Worker }
227*387f9dfdSAndroid Build Coastguard Worker
228*387f9dfdSAndroid Build Coastguard Worker TEST_CASE("test bpf stack_id table", "[bpf_stack_table]") {
229*387f9dfdSAndroid Build Coastguard Worker #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0)
230*387f9dfdSAndroid Build Coastguard Worker const std::string BPF_PROGRAM = R"(
231*387f9dfdSAndroid Build Coastguard Worker BPF_HASH(id, int, int, 1);
232*387f9dfdSAndroid Build Coastguard Worker BPF_STACK_TRACE_BUILDID(stack_traces, 8);
233*387f9dfdSAndroid Build Coastguard Worker
234*387f9dfdSAndroid Build Coastguard Worker int on_sys_getuid(void *ctx) {
235*387f9dfdSAndroid Build Coastguard Worker int stack_id = stack_traces.get_stackid(ctx, BPF_F_USER_STACK);
236*387f9dfdSAndroid Build Coastguard Worker int zero = 0, *val;
237*387f9dfdSAndroid Build Coastguard Worker val = id.lookup_or_try_init(&zero, &stack_id);
238*387f9dfdSAndroid Build Coastguard Worker if (val) {
239*387f9dfdSAndroid Build Coastguard Worker (*val) = stack_id;
240*387f9dfdSAndroid Build Coastguard Worker }
241*387f9dfdSAndroid Build Coastguard Worker
242*387f9dfdSAndroid Build Coastguard Worker return 0;
243*387f9dfdSAndroid Build Coastguard Worker }
244*387f9dfdSAndroid Build Coastguard Worker )";
245*387f9dfdSAndroid Build Coastguard Worker
246*387f9dfdSAndroid Build Coastguard Worker ebpf::BPF bpf;
247*387f9dfdSAndroid Build Coastguard Worker ebpf::StatusTuple res(0);
248*387f9dfdSAndroid Build Coastguard Worker res = bpf.init(BPF_PROGRAM);
249*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
250*387f9dfdSAndroid Build Coastguard Worker std::string getuid_fnname = bpf.get_syscall_fnname("getuid");
251*387f9dfdSAndroid Build Coastguard Worker res = bpf.attach_kprobe(getuid_fnname, "on_sys_getuid");
252*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
253*387f9dfdSAndroid Build Coastguard Worker REQUIRE(getuid() >= 0);
254*387f9dfdSAndroid Build Coastguard Worker res = bpf.detach_kprobe(getuid_fnname);
255*387f9dfdSAndroid Build Coastguard Worker REQUIRE(res.ok());
256*387f9dfdSAndroid Build Coastguard Worker
257*387f9dfdSAndroid Build Coastguard Worker auto id = bpf.get_hash_table<int, int>("id");
258*387f9dfdSAndroid Build Coastguard Worker auto stack_traces = bpf.get_stackbuildid_table("stack_traces");
259*387f9dfdSAndroid Build Coastguard Worker
260*387f9dfdSAndroid Build Coastguard Worker /* libc locations on different distributions are added below*/
261*387f9dfdSAndroid Build Coastguard Worker bpf.add_module("/lib/x86_64-linux-gnu/libc.so.6"); //Location of libc in ubuntu
262*387f9dfdSAndroid Build Coastguard Worker bpf.add_module("/lib64/libc.so.6"); //Location of libc fedora machine
263*387f9dfdSAndroid Build Coastguard Worker
264*387f9dfdSAndroid Build Coastguard Worker int stack_id = id[0];
265*387f9dfdSAndroid Build Coastguard Worker REQUIRE(stack_id >= 0);
266*387f9dfdSAndroid Build Coastguard Worker
267*387f9dfdSAndroid Build Coastguard Worker auto addrs = stack_traces.get_stack_addr(stack_id);
268*387f9dfdSAndroid Build Coastguard Worker auto symbols = stack_traces.get_stack_symbol(stack_id);
269*387f9dfdSAndroid Build Coastguard Worker REQUIRE(addrs.size() > 0);
270*387f9dfdSAndroid Build Coastguard Worker REQUIRE(addrs.size() == symbols.size());
271*387f9dfdSAndroid Build Coastguard Worker bool found = false;
272*387f9dfdSAndroid Build Coastguard Worker for (const auto &symbol : symbols) {
273*387f9dfdSAndroid Build Coastguard Worker if (symbol.find("getuid") != std::string::npos) {
274*387f9dfdSAndroid Build Coastguard Worker found = true;
275*387f9dfdSAndroid Build Coastguard Worker break;
276*387f9dfdSAndroid Build Coastguard Worker }
277*387f9dfdSAndroid Build Coastguard Worker }
278*387f9dfdSAndroid Build Coastguard Worker REQUIRE(found);
279*387f9dfdSAndroid Build Coastguard Worker
280*387f9dfdSAndroid Build Coastguard Worker stack_traces.clear_table_non_atomic();
281*387f9dfdSAndroid Build Coastguard Worker addrs = stack_traces.get_stack_addr(stack_id);
282*387f9dfdSAndroid Build Coastguard Worker REQUIRE(addrs.size()==0);
283*387f9dfdSAndroid Build Coastguard Worker #endif
284*387f9dfdSAndroid Build Coastguard Worker }
285