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 #pragma once
18 
19 #include <libnl++/Socket.h>
20 
21 #include <atomic>
22 #include <mutex>
23 #include <thread>
24 
25 namespace android::nlinterceptor {
26 
27 class InterceptorRelay {
28    public:
29     /**
30      * Wrapper around the netlink socket and thread which relays messages.
31      *
32      * \param nlFamily - netlink family to use for the netlink socket.
33      * \param clientNlPid - pid of the client netlink socket.
34      * \param clientName - name of the client to be used for debugging.
35      */
36     InterceptorRelay(uint32_t nlFamily, uint32_t clientNlPid,
37                      const std::string& clientName);
38 
39     /**
40      * Stops the relay thread if running and destroys itself.
41      */
42     ~InterceptorRelay();
43 
44     /**
45      * Returns the PID of the internal Netlink socket.
46      *
47      * \return value of PID,
48      */
49     uint32_t getPid();
50 
51     /**
52      * Spawns relay thread.
53      */
54     bool start();
55 
56     /**
57      * Subscribes the internal socket to a single Netlink multicast group.
58      *
59      * \param nlGroup - Netlink group to subscribe to.
60      * \returns - true for success, false for failure.
61      */
62     bool subscribeGroup(uint32_t nlGroup);
63 
64     /**
65      * Unsubscribes the internal socket from a single Netlink multicast group.
66      *
67      * \param nlGroup - Netlink group to unsubscribe from.
68      * \returns - true for success, false for failure.
69      */
70     bool unsubscribeGroup(uint32_t nlGroup);
71 
72    private:
73     std::string mClientName;  ///< Name of client (Wificond, for example).
74     std::optional<nl::Socket> mNlSocket;
75     const uint32_t mClientNlPid = 0;  ///< pid of client NL socket.
76 
77     /**
78      * If set to true, the relay thread should be running. Setting this to false
79      * stops the relay thread.
80      */
81     std::atomic_bool mRunning = false;
82 
83     /**
84      * Reads incoming Netlink messages destined for mNlSocket. If from the
85      * kernel, the message is relayed to the client specified in the
86      * constructor. Otherwise, the message is relayed to the kernel. This will
87      * run as long as mRunning is set to true.
88      */
89     void relayMessages();
90 
91     std::thread mRelayThread;
92 };
93 
94 }  // namespace android::nlinterceptor
95