1 /*
2  * Copyright (C) 2022 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 #include "connectivity_native.h"
18 
19 #include <android/binder_manager.h>
20 #include <android-modules-utils/sdk_level.h>
21 #include <aidl/android/net/connectivity/aidl/ConnectivityNative.h>
22 
23 using aidl::android::net::connectivity::aidl::IConnectivityNative;
24 
25 
getBinder()26 static std::shared_ptr<IConnectivityNative> getBinder() {
27     ndk::SpAIBinder sBinder = ndk::SpAIBinder(reinterpret_cast<AIBinder*>(
28         AServiceManager_checkService("connectivity_native")));
29     return aidl::android::net::connectivity::aidl::IConnectivityNative::fromBinder(sBinder);
30 }
31 
getErrno(const::ndk::ScopedAStatus & status)32 static int getErrno(const ::ndk::ScopedAStatus& status) {
33     switch (status.getExceptionCode()) {
34         case EX_NONE:
35             return 0;
36         case EX_ILLEGAL_ARGUMENT:
37             return EINVAL;
38         case EX_SECURITY:
39             return EPERM;
40         case EX_SERVICE_SPECIFIC:
41             return status.getServiceSpecificError();
42         default:
43             return EPROTO;
44     }
45 }
46 
AConnectivityNative_blockPortForBind(in_port_t port)47 int AConnectivityNative_blockPortForBind(in_port_t port) {
48     if (!android::modules::sdklevel::IsAtLeastU()) return ENOSYS;
49     std::shared_ptr<IConnectivityNative> c = getBinder();
50     if (!c) {
51         return EAGAIN;
52     }
53     return getErrno(c->blockPortForBind(port));
54 }
55 
AConnectivityNative_unblockPortForBind(in_port_t port)56 int AConnectivityNative_unblockPortForBind(in_port_t port) {
57     if (!android::modules::sdklevel::IsAtLeastU()) return ENOSYS;
58     std::shared_ptr<IConnectivityNative> c = getBinder();
59     if (!c) {
60         return EAGAIN;
61     }
62     return getErrno(c->unblockPortForBind(port));
63 }
64 
AConnectivityNative_unblockAllPortsForBind()65 int AConnectivityNative_unblockAllPortsForBind() {
66     if (!android::modules::sdklevel::IsAtLeastU()) return ENOSYS;
67     std::shared_ptr<IConnectivityNative> c = getBinder();
68     if (!c) {
69         return EAGAIN;
70     }
71     return getErrno(c->unblockAllPortsForBind());
72 }
73 
AConnectivityNative_getPortsBlockedForBind(in_port_t * ports,size_t * count)74 int AConnectivityNative_getPortsBlockedForBind(in_port_t *ports, size_t *count) {
75     if (!android::modules::sdklevel::IsAtLeastU()) return ENOSYS;
76     std::shared_ptr<IConnectivityNative> c = getBinder();
77     if (!c) {
78         return EAGAIN;
79     }
80     std::vector<int32_t> actualBlockedPorts;
81     int err = getErrno(c->getPortsBlockedForBind(&actualBlockedPorts));
82     if (err) {
83         return err;
84     }
85 
86     for (int i = 0; i < *count && i < actualBlockedPorts.size(); i++) {
87         ports[i] = actualBlockedPorts[i];
88     }
89     *count = actualBlockedPorts.size();
90     return 0;
91 }
92