blob: 11dd26d31c4d170d11730020c6fbc9dfc508ebff [file] [log] [blame]
Thierry Strudel582b9e52017-05-23 16:11:15 -07001/*
2 * Copyright (c) 2017, The Linux Foundation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29#ifndef DBG
30 #define DBG true
31#endif /* DBG */
32#define LOG_TAG "IPAHALService"
33
34/* HIDL Includes */
35#include <hwbinder/IPCThreadState.h>
36#include <hwbinder/ProcessState.h>
37
38/* Kernel Includes */
39#include <linux/netfilter/nfnetlink_compat.h>
40
41/* External Includes */
42#include <cutils/log.h>
43#include <string>
Niranjan Pendharkare549f662017-08-08 17:02:57 -070044#include <sys/socket.h>
Thierry Strudel582b9e52017-05-23 16:11:15 -070045#include <sys/types.h>
46#include <vector>
47
48/* Internal Includes */
49#include "HAL.h"
50#include "LocalLogBuffer.h"
51#include "PrefixParser.h"
52
53/* Namespace pollution avoidance */
54using ::android::hardware::Void;
55using ::android::status_t;
56
57using RET = ::IOffloadManager::RET;
58using Prefix = ::IOffloadManager::Prefix;
59
60using ::std::map;
61using ::std::vector;
62
63
64/* ------------------------------ PUBLIC ------------------------------------ */
65HAL* HAL::makeIPAHAL(int version, IOffloadManager* mgr) {
66 if (DBG)
67 ALOGI("makeIPAHAL(%d, %s)", version,
68 (mgr != nullptr) ? "provided" : "null");
69 if (nullptr == mgr) return NULL;
70 else if (version != 1) return NULL;
71 HAL* ret = new HAL(mgr);
72 if (nullptr == ret) return NULL;
73 configureRpcThreadpool(1, false);
Niranjan Pendharkar89596502017-06-26 22:19:52 -070074 ret->registerAsSystemService();
Thierry Strudel582b9e52017-05-23 16:11:15 -070075 return ret;
76} /* makeIPAHAL */
77
78
79/* ------------------------------ PRIVATE ----------------------------------- */
Niranjan Pendharkar3493aca2017-08-15 21:54:41 -070080HAL::HAL(IOffloadManager* mgr) : mLogs("HAL Function Calls", 100) {
Thierry Strudel582b9e52017-05-23 16:11:15 -070081 mIPA = mgr;
82 mCb.clear();
83 mCbIpa = nullptr;
84 mCbCt = nullptr;
85} /* HAL */
86
Niranjan Pendharkar89596502017-06-26 22:19:52 -070087void HAL::registerAsSystemService() {
Thierry Strudel582b9e52017-05-23 16:11:15 -070088 status_t ret = 0;
89
Niranjan Pendharkar89596502017-06-26 22:19:52 -070090 ret = IOffloadControl::registerAsService();
Thierry Strudel582b9e52017-05-23 16:11:15 -070091 if (ret != 0) ALOGE("Failed to register IOffloadControl (%d)", ret);
92 else if (DBG) {
Niranjan Pendharkar89596502017-06-26 22:19:52 -070093 ALOGI("Successfully registered IOffloadControl");
Thierry Strudel582b9e52017-05-23 16:11:15 -070094 }
95
Niranjan Pendharkar89596502017-06-26 22:19:52 -070096 IOffloadConfig::registerAsService();
Thierry Strudel582b9e52017-05-23 16:11:15 -070097 if (ret != 0) ALOGE("Failed to register IOffloadConfig (%d)", ret);
98 else if (DBG) {
Niranjan Pendharkar89596502017-06-26 22:19:52 -070099 ALOGI("Successfully registered IOffloadConfig");
Thierry Strudel582b9e52017-05-23 16:11:15 -0700100 }
101} /* registerAsSystemService */
102
103void HAL::doLogcatDump() {
104 ALOGD("mHandles");
105 ALOGD("========");
106 /* @TODO This will segfault if they aren't initialized and I don't currently
107 * care to check for initialization in a function that isn't used anyways
108 * ALOGD("fd1->%d", mHandle1->data[0]);
109 * ALOGD("fd2->%d", mHandle2->data[0]);
110 */
111 ALOGD("========");
112} /* doLogcatDump */
113
114HAL::BoolResult HAL::makeInputCheckFailure(string customErr) {
115 BoolResult ret;
116 ret.success = false;
117 ret.errMsg = "Failed Input Checks: " + customErr;
118 return ret;
119} /* makeInputCheckFailure */
120
121HAL::BoolResult HAL::ipaResultToBoolResult(RET in) {
122 BoolResult ret;
123 ret.success = (in >= RET::SUCCESS);
124 switch (in) {
125 case RET::FAIL_TOO_MANY_PREFIXES:
126 ret.errMsg = "Too Many Prefixes Provided";
127 break;
128 case RET::FAIL_UNSUPPORTED:
129 ret.errMsg = "Unsupported by Hardware";
130 break;
131 case RET::FAIL_INPUT_CHECK:
132 ret.errMsg = "Failed Input Checks";
133 break;
134 case RET::FAIL_HARDWARE:
135 ret.errMsg = "Hardware did not accept";
136 break;
137 case RET::FAIL_TRY_AGAIN:
138 ret.errMsg = "Try Again";
139 break;
140 case RET::SUCCESS:
141 ret.errMsg = "Successful";
142 break;
143 case RET::SUCCESS_DUPLICATE_CONFIG:
144 ret.errMsg = "Successful: Was a duplicate configuration";
145 break;
146 case RET::SUCCESS_NO_OP:
147 ret.errMsg = "Successful: No action needed";
148 break;
149 case RET::SUCCESS_OPTIMIZED:
150 ret.errMsg = "Successful: Performed optimized version of action";
151 break;
152 default:
153 ret.errMsg = "Unknown Error";
154 break;
155 }
156 return ret;
157} /* ipaResultToBoolResult */
158
159/* This will likely always result in doubling the number of loops the execution
160 * goes through. Obviously that is suboptimal. But if we first translate
161 * away from all HIDL specific code, then we can avoid sprinkling HIDL
162 * dependencies everywhere.
163 */
164vector<string> HAL::convertHidlStrToStdStr(hidl_vec<hidl_string> in) {
165 vector<string> ret;
166 for (size_t i = 0; i < in.size(); i++) {
167 string add = in[i];
168 ret.push_back(add);
169 }
170 return ret;
171} /* convertHidlStrToStdStr */
172
173void HAL::registerEventListeners() {
174 registerIpaCb();
175 registerCtCb();
176} /* registerEventListeners */
177
178void HAL::registerIpaCb() {
179 if (isInitialized() && mCbIpa == nullptr) {
180 LocalLogBuffer::FunctionLog fl("registerEventListener");
181 mCbIpa = new IpaEventRelay(mCb);
182 mIPA->registerEventListener(mCbIpa);
183 mLogs.addLog(fl);
184 } else {
185 ALOGE("Failed to registerIpaCb (isInitialized()=%s, (mCbIpa == nullptr)=%s)",
186 isInitialized() ? "true" : "false",
187 (mCbIpa == nullptr) ? "true" : "false");
188 }
189} /* registerIpaCb */
190
191void HAL::registerCtCb() {
192 if (isInitialized() && mCbCt == nullptr) {
193 LocalLogBuffer::FunctionLog fl("registerCtTimeoutUpdater");
194 mCbCt = new CtUpdateAmbassador(mCb);
195 mIPA->registerCtTimeoutUpdater(mCbCt);
196 mLogs.addLog(fl);
197 } else {
198 ALOGE("Failed to registerCtCb (isInitialized()=%s, (mCbCt == nullptr)=%s)",
199 isInitialized() ? "true" : "false",
200 (mCbCt == nullptr) ? "true" : "false");
201 }
202} /* registerCtCb */
203
204void HAL::unregisterEventListeners() {
205 unregisterIpaCb();
206 unregisterCtCb();
207} /* unregisterEventListeners */
208
209void HAL::unregisterIpaCb() {
210 if (mCbIpa != nullptr) {
211 LocalLogBuffer::FunctionLog fl("unregisterEventListener");
212 mIPA->unregisterEventListener(mCbIpa);
213 mCbIpa = nullptr;
214 mLogs.addLog(fl);
215 } else {
216 ALOGE("Failed to unregisterIpaCb");
217 }
218} /* unregisterIpaCb */
219
220void HAL::unregisterCtCb() {
221 if (mCbCt != nullptr) {
222 LocalLogBuffer::FunctionLog fl("unregisterCtTimeoutUpdater");
223 mIPA->unregisterCtTimeoutUpdater(mCbCt);
224 mCbCt = nullptr;
225 mLogs.addLog(fl);
226 } else {
227 ALOGE("Failed to unregisterCtCb");
228 }
229} /* unregisterCtCb */
230
231void HAL::clearHandles() {
232 ALOGI("clearHandles()");
233 /* @TODO handle this more gracefully... also remove the log
234 *
235 * Things that would be nice, but I can't do:
236 * [1] Destroy the object (it's on the stack)
237 * [2] Call freeHandle (it's private)
238 *
239 * Things I can do but are hacks:
240 * [1] Look at code and notice that setTo immediately calls freeHandle
241 */
242 mHandle1.setTo(nullptr, true);
243 mHandle2.setTo(nullptr, true);
244} /* clearHandles */
245
246bool HAL::isInitialized() {
247 return mCb.get() != nullptr;
248} /* isInitialized */
249
250
251/* -------------------------- IOffloadConfig -------------------------------- */
252Return<void> HAL::setHandles(
253 const hidl_handle &fd1,
254 const hidl_handle &fd2,
255 setHandles_cb hidl_cb
256) {
257 LocalLogBuffer::FunctionLog fl(__func__);
258
259 if (fd1->numFds != 1) {
260 BoolResult res = makeInputCheckFailure("Must provide exactly one FD per handle (fd1)");
261 hidl_cb(res.success, res.errMsg);
262 fl.setResult(res.success, res.errMsg);
263
264 mLogs.addLog(fl);
265 return Void();
266 }
267
268 if (fd2->numFds != 1) {
269 BoolResult res = makeInputCheckFailure("Must provide exactly one FD per handle (fd2)");
270 hidl_cb(res.success, res.errMsg);
271 fl.setResult(res.success, res.errMsg);
272
273 mLogs.addLog(fl);
274 return Void();
275 }
276
277 /* The = operator calls freeHandle internally. Therefore, if we were using
278 * these handles previously, they're now gone... forever. But hopefully the
279 * new ones kick in very quickly.
280 *
281 * After freeing anything previously held, it will dup the FD so we have our
282 * own copy.
283 */
284 mHandle1 = fd1;
285 mHandle2 = fd2;
286
287 /* Log the DUPed FD instead of the actual input FD so that we can lookup
288 * this value in ls -l /proc/<pid>/<fd>
289 */
290 fl.addArg("fd1", mHandle1->data[0]);
291 fl.addArg("fd2", mHandle2->data[0]);
292
293 /* Try to provide each handle to IPACM. Destroy our DUPed hidl_handles if
294 * IPACM does not like either input. This keeps us from leaking FDs or
295 * providing half solutions.
296 *
297 * @TODO unfortunately, this does not cover duplicate configs where IPACM
298 * thinks it is still holding on to a handle that we would have freed above.
299 * It also probably means that IPACM would not know about the first FD being
300 * freed if it rejects the second FD.
301 */
302 RET ipaReturn = mIPA->provideFd(mHandle1->data[0], UDP_SUBSCRIPTIONS);
303 if (ipaReturn == RET::SUCCESS) {
304 ipaReturn = mIPA->provideFd(mHandle2->data[0], TCP_SUBSCRIPTIONS);
305 }
306
307 if (ipaReturn != RET::SUCCESS) {
308 ALOGE("IPACM failed to accept the FDs (%d %d)", mHandle1->data[0],
309 mHandle2->data[0]);
310 clearHandles();
311 } else {
312 /* @TODO remove logs after stabilization */
313 ALOGI("IPACM was provided two FDs (%d, %d)", mHandle1->data[0],
314 mHandle2->data[0]);
315 }
316
317 BoolResult res = ipaResultToBoolResult(ipaReturn);
318 hidl_cb(res.success, res.errMsg);
319
320 fl.setResult(res.success, res.errMsg);
321 mLogs.addLog(fl);
322 return Void();
323} /* setHandles */
324
325
326/* -------------------------- IOffloadControl ------------------------------- */
327Return<void> HAL::initOffload
328(
329 const ::android::sp<ITetheringOffloadCallback>& cb,
330 initOffload_cb hidl_cb
331) {
332 LocalLogBuffer::FunctionLog fl(__func__);
333
334 if (isInitialized()) {
335 BoolResult res = makeInputCheckFailure("Already initialized");
336 hidl_cb(res.success, res.errMsg);
337 fl.setResult(res.success, res.errMsg);
338 mLogs.addLog(fl);
339 } else {
340 /* Should storing the CB be a function? */
341 mCb = cb;
342 registerEventListeners();
343 BoolResult res = ipaResultToBoolResult(RET::SUCCESS);
344 hidl_cb(res.success, res.errMsg);
345 fl.setResult(res.success, res.errMsg);
346 mLogs.addLog(fl);
347 }
348
349 return Void();
350} /* initOffload */
351
352Return<void> HAL::stopOffload
353(
354 stopOffload_cb hidl_cb
355) {
356 LocalLogBuffer::FunctionLog fl(__func__);
357
358 if (!isInitialized()) {
359 BoolResult res = makeInputCheckFailure("Was never initialized");
360 hidl_cb(res.success, res.errMsg);
361 fl.setResult(res.success, res.errMsg);
362 mLogs.addLog(fl);
363 } else {
364 /* Should removing the CB be a function? */
365 mCb.clear();
366 unregisterEventListeners();
367
368 RET ipaReturn = mIPA->stopAllOffload();
369 if (ipaReturn != RET::SUCCESS) {
370 /* Ignore IPAs return value here and provide why stopAllOffload
371 * failed. However, if IPA failed to clearAllFds, then we can't
372 * clear our map because they may still be in use.
373 */
374 RET ret = mIPA->clearAllFds();
375 if (ret == RET::SUCCESS) {
376 clearHandles();
377 }
378 } else {
379 ipaReturn = mIPA->clearAllFds();
380 /* If IPA fails, they may still be using these for some reason. */
381 if (ipaReturn == RET::SUCCESS) {
382 clearHandles();
383 } else {
384 ALOGE("IPACM failed to return success for clearAllFds so they will not be released...");
385 }
386 }
387
388 BoolResult res = ipaResultToBoolResult(ipaReturn);
389 hidl_cb(res.success, res.errMsg);
390
391 fl.setResult(res.success, res.errMsg);
392 mLogs.addLog(fl);
393 }
394
395 return Void();
396} /* stopOffload */
397
398Return<void> HAL::setLocalPrefixes
399(
400 const hidl_vec<hidl_string>& prefixes,
401 setLocalPrefixes_cb hidl_cb
402) {
Niranjan Pendharkare549f662017-08-08 17:02:57 -0700403 BoolResult res;
404 PrefixParser parser;
405 vector<string> prefixesStr = convertHidlStrToStdStr(prefixes);
406
Thierry Strudel582b9e52017-05-23 16:11:15 -0700407 LocalLogBuffer::FunctionLog fl(__func__);
Niranjan Pendharkare549f662017-08-08 17:02:57 -0700408 fl.addArg("prefixes", prefixesStr);
Thierry Strudel582b9e52017-05-23 16:11:15 -0700409
Niranjan Pendharkare549f662017-08-08 17:02:57 -0700410 if (!isInitialized()) {
411 BoolResult res = makeInputCheckFailure("Not initialized");
412 } else if(prefixesStr.size() < 1) {
413 res = ipaResultToBoolResult(RET::FAIL_INPUT_CHECK);
414 } else if (!parser.add(prefixesStr)) {
415 res = makeInputCheckFailure(parser.getLastErrAsStr());
416 } else {
417 res = ipaResultToBoolResult(RET::SUCCESS);
418 }
419
Thierry Strudel582b9e52017-05-23 16:11:15 -0700420 hidl_cb(res.success, res.errMsg);
Thierry Strudel582b9e52017-05-23 16:11:15 -0700421 fl.setResult(res.success, res.errMsg);
Niranjan Pendharkare549f662017-08-08 17:02:57 -0700422 mLogs.addLog(fl);
Thierry Strudel582b9e52017-05-23 16:11:15 -0700423 return Void();
424} /* setLocalPrefixes */
425
426Return<void> HAL::getForwardedStats
427(
428 const hidl_string& upstream,
429 getForwardedStats_cb hidl_cb
430) {
431 LocalLogBuffer::FunctionLog fl(__func__);
432 fl.addArg("upstream", upstream);
433
434 OffloadStatistics ret;
435 RET ipaReturn = mIPA->getStats(upstream.c_str(), true, ret);
436 if (ipaReturn == RET::SUCCESS) {
437 hidl_cb(ret.getTotalRxBytes(), ret.getTotalTxBytes());
438 fl.setResult(ret.getTotalRxBytes(), ret.getTotalTxBytes());
439 } else {
440 /* @TODO Ensure the output is zeroed, but this is probably not enough to
441 * tell Framework that an error has occurred. If, for example, they had
442 * not yet polled for statistics previously, they may incorrectly assume
443 * that simply no statistics have transpired on hardware path.
444 *
445 * Maybe ITetheringOffloadCallback:onEvent(OFFLOAD_STOPPED_ERROR) is
446 * enough to handle this case, time will tell.
447 */
448 hidl_cb(0, 0);
449 fl.setResult(0, 0);
450 }
451
452 mLogs.addLog(fl);
453 return Void();
454} /* getForwardedStats */
455
456Return<void> HAL::setDataLimit
457(
458 const hidl_string& upstream,
459 uint64_t limit,
460 setDataLimit_cb hidl_cb
461) {
462 LocalLogBuffer::FunctionLog fl(__func__);
463 fl.addArg("upstream", upstream);
464 fl.addArg("limit", limit);
465
Thierry Strudelf7f77062017-09-15 10:46:48 -0700466 if (!isInitialized()) {
467 BoolResult res = makeInputCheckFailure("Not initialized (setDataLimit)");
468 hidl_cb(res.success, res.errMsg);
469 fl.setResult(res.success, res.errMsg);
470 } else {
471 RET ipaReturn = mIPA->setQuota(upstream.c_str(), limit);
472 BoolResult res = ipaResultToBoolResult(ipaReturn);
473 hidl_cb(res.success, res.errMsg);
474 fl.setResult(res.success, res.errMsg);
475 }
Thierry Strudel582b9e52017-05-23 16:11:15 -0700476
Thierry Strudel582b9e52017-05-23 16:11:15 -0700477 mLogs.addLog(fl);
478 return Void();
479} /* setDataLimit */
480
481Return<void> HAL::setUpstreamParameters
482(
483 const hidl_string& iface,
484 const hidl_string& v4Addr,
485 const hidl_string& v4Gw,
486 const hidl_vec<hidl_string>& v6Gws,
487 setUpstreamParameters_cb hidl_cb
488) {
489 vector<string> v6GwStrs = convertHidlStrToStdStr(v6Gws);
490
491 LocalLogBuffer::FunctionLog fl(__func__);
492 fl.addArg("iface", iface);
493 fl.addArg("v4Addr", v4Addr);
494 fl.addArg("v4Gw", v4Gw);
495 fl.addArg("v6Gws", v6GwStrs);
496
497 PrefixParser v4AddrParser;
498 PrefixParser v4GwParser;
499 PrefixParser v6GwParser;
500
501 /* @TODO maybe we should enforce that these addresses and gateways are fully
502 * qualified here. But then, how do we allow them to be empty/null as well
503 * while still preserving a sane API on PrefixParser?
504 */
Niranjan Pendharkare549f662017-08-08 17:02:57 -0700505 if (!isInitialized()) {
506 BoolResult res = makeInputCheckFailure("Not initialized (setUpstreamParameters)");
507 hidl_cb(res.success, res.errMsg);
508 fl.setResult(res.success, res.errMsg);
Niranjan Pendharkar541f8062017-10-14 19:40:34 -0700509 } else if (!v4AddrParser.addV4(v4Addr) && !v4Addr.empty()) {
Thierry Strudel582b9e52017-05-23 16:11:15 -0700510 BoolResult res = makeInputCheckFailure(v4AddrParser.getLastErrAsStr());
511 hidl_cb(res.success, res.errMsg);
512 fl.setResult(res.success, res.errMsg);
513 } else if (!v4GwParser.addV4(v4Gw) && !v4Gw.empty()) {
514 BoolResult res = makeInputCheckFailure(v4GwParser.getLastErrAsStr());
515 hidl_cb(res.success, res.errMsg);
516 fl.setResult(res.success, res.errMsg);
517 } else if (v6GwStrs.size() >= 1 && !v6GwParser.addV6(v6GwStrs)) {
518 BoolResult res = makeInputCheckFailure(v6GwParser.getLastErrAsStr());
519 hidl_cb(res.success, res.errMsg);
520 fl.setResult(res.success, res.errMsg);
Niranjan Pendharkar541f8062017-10-14 19:40:34 -0700521 } else if (iface.size()>= 1) {
Thierry Strudel582b9e52017-05-23 16:11:15 -0700522 RET ipaReturn = mIPA->setUpstream(
523 iface.c_str(),
524 v4GwParser.getFirstPrefix(),
525 v6GwParser.getFirstPrefix());
526 BoolResult res = ipaResultToBoolResult(ipaReturn);
527 hidl_cb(res.success, res.errMsg);
528 fl.setResult(res.success, res.errMsg);
Niranjan Pendharkar541f8062017-10-14 19:40:34 -0700529 } else {
530 /* send NULL iface string when upstream down */
531 RET ipaReturn = mIPA->setUpstream(
532 NULL,
533 v4GwParser.getFirstPrefix(),
534 v6GwParser.getFirstPrefix());
535 BoolResult res = ipaResultToBoolResult(ipaReturn);
536 hidl_cb(res.success, res.errMsg);
537 fl.setResult(res.success, res.errMsg);
Thierry Strudel582b9e52017-05-23 16:11:15 -0700538 }
539
540 mLogs.addLog(fl);
541 return Void();
542} /* setUpstreamParameters */
543
544Return<void> HAL::addDownstream
545(
546 const hidl_string& iface,
547 const hidl_string& prefix,
548 addDownstream_cb hidl_cb
549) {
550 LocalLogBuffer::FunctionLog fl(__func__);
551 fl.addArg("iface", iface);
552 fl.addArg("prefix", prefix);
553
554 PrefixParser prefixParser;
555
Niranjan Pendharkare549f662017-08-08 17:02:57 -0700556 if (!isInitialized()) {
557 BoolResult res = makeInputCheckFailure("Not initialized (setUpstreamParameters)");
558 hidl_cb(res.success, res.errMsg);
559 fl.setResult(res.success, res.errMsg);
560 }
561 else if (!prefixParser.add(prefix)) {
Thierry Strudel582b9e52017-05-23 16:11:15 -0700562 BoolResult res = makeInputCheckFailure(prefixParser.getLastErrAsStr());
563 hidl_cb(res.success, res.errMsg);
564 fl.setResult(res.success, res.errMsg);
565 } else {
566 RET ipaReturn = mIPA->addDownstream(
567 iface.c_str(),
568 prefixParser.getFirstPrefix());
569 BoolResult res = ipaResultToBoolResult(ipaReturn);
570 hidl_cb(res.success, res.errMsg);
571 fl.setResult(res.success, res.errMsg);
572 }
573
574 mLogs.addLog(fl);
575 return Void();
576} /* addDownstream */
577
578Return<void> HAL::removeDownstream
579(
580 const hidl_string& iface,
581 const hidl_string& prefix,
582 removeDownstream_cb hidl_cb
583) {
584 LocalLogBuffer::FunctionLog fl(__func__);
585 fl.addArg("iface", iface);
586 fl.addArg("prefix", prefix);
587
588 PrefixParser prefixParser;
589
Niranjan Pendharkare549f662017-08-08 17:02:57 -0700590 if (!isInitialized()) {
591 BoolResult res = makeInputCheckFailure("Not initialized (setUpstreamParameters)");
592 hidl_cb(res.success, res.errMsg);
593 fl.setResult(res.success, res.errMsg);
594 }
595 else if (!prefixParser.add(prefix)) {
Thierry Strudel582b9e52017-05-23 16:11:15 -0700596 BoolResult res = makeInputCheckFailure(prefixParser.getLastErrAsStr());
597 hidl_cb(res.success, res.errMsg);
598 fl.setResult(res.success, res.errMsg);
599 } else {
600 RET ipaReturn = mIPA->removeDownstream(
601 iface.c_str(),
602 prefixParser.getFirstPrefix());
603 BoolResult res = ipaResultToBoolResult(ipaReturn);
604 hidl_cb(res.success, res.errMsg);
605 fl.setResult(res.success, res.errMsg);
606 }
607
608 mLogs.addLog(fl);
609 return Void();
610} /* removeDownstream */
Niranjan Pendharkar3493aca2017-08-15 21:54:41 -0700611
612Return<void> HAL::debug
613(
Steven Moreland8a33ca22018-01-17 18:52:25 -0800614 const hidl_handle& handle,
Niranjan Pendharkar3493aca2017-08-15 21:54:41 -0700615 const hidl_vec<hidl_string>& /* options */
616) {
Steven Moreland8a33ca22018-01-17 18:52:25 -0800617 if (handle != nullptr && handle->numFds >= 1) {
618 mLogs.toFd(handle->data[0]);
619 }
Niranjan Pendharkar3493aca2017-08-15 21:54:41 -0700620 return Void();
621} /* debug */