1 /*
2  * Copyright (C) 2008 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 #ifndef _CLATD_CONTROLLER_H
18 #define _CLATD_CONTROLLER_H
19 
20 #include <map>
21 #include <mutex>
22 #include <string>
23 
24 #include <linux/if.h>
25 #include <netinet/in.h>
26 
27 #include <android-base/thread_annotations.h>
28 
29 #include "Fwmark.h"
30 #include "NetdConstants.h"
31 #include "bpf/BpfMap.h"
32 #include "netdbpf/bpf_shared.h"
33 #include "netdutils/DumpWriter.h"
34 
35 namespace android {
36 namespace net {
37 
38 class NetworkController;
39 
40 class ClatdController {
41   public:
ClatdController(NetworkController * controller)42     explicit ClatdController(NetworkController* controller) EXCLUDES(mutex)
43         : mNetCtrl(controller){};
~ClatdController()44     virtual ~ClatdController() EXCLUDES(mutex){};
45 
46     /* First thing init/startClatd/stopClatd/dump do is grab the mutex. */
47     void init(void) EXCLUDES(mutex);
48 
49     int startClatd(const std::string& interface, const std::string& nat64Prefix,
50                    std::string* v6Addr) EXCLUDES(mutex);
51     int stopClatd(const std::string& interface) EXCLUDES(mutex);
52 
53     void dump(netdutils::DumpWriter& dw) EXCLUDES(mutex);
54 
55     static constexpr const char LOCAL_RAW_PREROUTING[] = "clat_raw_PREROUTING";
56 
57   private:
58     struct ClatdTracker {
59         pid_t pid = -1;
60         unsigned ifIndex;
61         char iface[IFNAMSIZ];
62         unsigned v4ifIndex;
63         char v4iface[IFNAMSIZ];
64         Fwmark fwmark;
65         char fwmarkString[UINT32_STRLEN];
66         in_addr v4;
67         char v4Str[INET_ADDRSTRLEN];
68         in6_addr v6;
69         char v6Str[INET6_ADDRSTRLEN];
70         in6_addr pfx96;
71         char pfx96String[INET6_ADDRSTRLEN];
72 
73         int init(unsigned networkId, const std::string& interface, const std::string& v4interface,
74                  const std::string& nat64Prefix);
75     };
76 
77     std::mutex mutex;
78 
79     const NetworkController* mNetCtrl GUARDED_BY(mutex);
80     std::map<std::string, ClatdTracker> mClatdTrackers GUARDED_BY(mutex);
81     ClatdTracker* getClatdTracker(const std::string& interface) REQUIRES(mutex);
82 
83     void dumpEgress(netdutils::DumpWriter& dw) REQUIRES(mutex);
84     void dumpIngress(netdutils::DumpWriter& dw) REQUIRES(mutex);
85     void dumpTrackers(netdutils::DumpWriter& dw) REQUIRES(mutex);
86 
87     static in_addr_t selectIpv4Address(const in_addr ip, int16_t prefixlen);
88     static int generateIpv6Address(const char* iface, const in_addr v4, const in6_addr& nat64Prefix,
89                                    in6_addr* v6);
90     static void makeChecksumNeutral(in6_addr* v6, const in_addr v4, const in6_addr& nat64Prefix);
91 
92     enum eClatEbpfMode {
93         ClatEbpfDisabled,  //  <4.9 kernel ||  <P api shipping level -- will not work
94         ClatEbpfMaybe,     // >=4.9 kernel &&   P api shipping level -- might work
95         ClatEbpfEnabled,   // >=4.9 kernel && >=Q api shipping level -- must work
96     };
97     eClatEbpfMode mClatEbpfMode GUARDED_BY(mutex);
getEbpfMode()98     eClatEbpfMode getEbpfMode() EXCLUDES(mutex) {
99         std::lock_guard guard(mutex);
100         return mClatEbpfMode;
101     }
102 
103     bpf::BpfMap<ClatEgressKey, ClatEgressValue> mClatEgressMap GUARDED_BY(mutex);
104     bpf::BpfMap<ClatIngressKey, ClatIngressValue> mClatIngressMap GUARDED_BY(mutex);
105 
106     void maybeStartBpf(const ClatdTracker& tracker) REQUIRES(mutex);
107     void maybeStopBpf(const ClatdTracker& tracker) REQUIRES(mutex);
108     void setIptablesDropRule(bool add, const char* iface, const char* pfx96Str, const char* v6Str)
109             REQUIRES(mutex);
110 
111     // For testing.
112     friend class ClatdControllerTest;
113 
114     static bool (*isIpv4AddressFreeFunc)(in_addr_t);
115     static bool isIpv4AddressFree(in_addr_t addr);
116     static int (*iptablesRestoreFunction)(IptablesTarget target, const std::string& commands);
117 };
118 
119 }  // namespace net
120 }  // namespace android
121 
122 #endif
123