1 /*
2 * Copyright (C) 2021 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 "NetlinkInterceptor.h"
18
19 #include <android-base/logging.h>
20 #include <libnl++/Socket.h>
21
22 namespace android::nlinterceptor {
23
createSocket(int32_t nlFamilyAidl,int32_t clientNlPidAidl,const std::string & clientName,AidlInterceptedSocket * interceptedSocket)24 ndk::ScopedAStatus NetlinkInterceptor::createSocket(
25 int32_t nlFamilyAidl, int32_t clientNlPidAidl,
26 const std::string& clientName, AidlInterceptedSocket* interceptedSocket) {
27 auto nlFamily = static_cast<uint32_t>(nlFamilyAidl);
28 auto clientNlPid = static_cast<uint32_t>(clientNlPidAidl);
29 uint32_t interceptorNlPid = 0;
30
31 std::unique_ptr<InterceptorRelay> interceptor =
32 std::make_unique<InterceptorRelay>(nlFamily, clientNlPid, clientName);
33
34 interceptorNlPid = interceptor->getPid();
35
36 if (interceptorNlPid == 0) {
37 LOG(ERROR) << "Failed to create a Netlink socket for " << clientName
38 << ", " << nlFamily << ":" << clientNlPid;
39 return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
40 }
41
42 if (mClientMap.find({nlFamily, interceptorNlPid}) != mClientMap.end()) {
43 LOG(ERROR) << "A socket with pid " << interceptorNlPid
44 << " already exists!";
45 return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
46 }
47
48 if (!interceptor->start()) {
49 LOG(ERROR) << "Failed to start interceptor thread!";
50 return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
51 }
52
53 if (!mClientMap
54 .emplace(InterceptedSocket(nlFamily, interceptorNlPid),
55 std::move(interceptor))
56 .second) {
57 // If this happens, it is very bad.
58 LOG(FATAL) << "Failed to insert interceptor instance with pid "
59 << interceptorNlPid << " into map!";
60 return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
61 }
62
63 interceptedSocket->nlFamily = nlFamily;
64 interceptedSocket->portId = interceptorNlPid;
65
66 return ndk::ScopedAStatus::ok();
67 }
68
closeSocket(const AidlInterceptedSocket & interceptedSocket)69 ndk::ScopedAStatus NetlinkInterceptor::closeSocket(
70 const AidlInterceptedSocket& interceptedSocket) {
71 InterceptedSocket sock(interceptedSocket);
72
73 auto interceptorIt = mClientMap.find(sock);
74 if (interceptorIt == mClientMap.end()) {
75 LOG(ERROR) << "closeSocket Failed! No such socket " << sock;
76 return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
77 }
78 mClientMap.erase(interceptorIt);
79
80 return ndk::ScopedAStatus::ok();
81 }
82
subscribeGroup(const AidlInterceptedSocket & interceptedSocket,int32_t nlGroupAidl)83 ndk::ScopedAStatus NetlinkInterceptor::subscribeGroup(
84 const AidlInterceptedSocket& interceptedSocket, int32_t nlGroupAidl) {
85 InterceptedSocket sock(interceptedSocket);
86 auto nlGroup = static_cast<uint32_t>(nlGroupAidl);
87
88 auto interceptorIt = mClientMap.find(sock);
89 if (interceptorIt == mClientMap.end()) {
90 LOG(ERROR) << "subscribeGroup failed! No such socket " << sock;
91 return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
92 }
93
94 auto& interceptor = interceptorIt->second;
95 if (!interceptor->subscribeGroup(nlGroup)) {
96 LOG(ERROR) << "Failed to subscribe " << sock << " to " << nlGroup;
97 return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
98 }
99
100 return ndk::ScopedAStatus::ok();
101 }
102
unsubscribeGroup(const AidlInterceptedSocket & interceptedSocket,int32_t nlGroupAidl)103 ndk::ScopedAStatus NetlinkInterceptor::unsubscribeGroup(
104 const AidlInterceptedSocket& interceptedSocket, int32_t nlGroupAidl) {
105 InterceptedSocket sock(interceptedSocket);
106 auto nlGroup = static_cast<uint32_t>(nlGroupAidl);
107
108 auto interceptorIt = mClientMap.find(sock);
109 if (interceptorIt == mClientMap.end()) {
110 LOG(ERROR) << "unsubscribeGroup failed! No such socket " << sock;
111 return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
112 }
113
114 auto& interceptor = interceptorIt->second;
115 if (!interceptor->unsubscribeGroup(nlGroup)) {
116 LOG(ERROR) << "Failed to unsubscribe " << sock << " from " << nlGroup;
117 return ndk::ScopedAStatus(AStatus_fromStatus(::android::UNKNOWN_ERROR));
118 }
119 return ndk::ScopedAStatus::ok();
120 }
121 } // namespace android::nlinterceptor
122