• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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