blob: 779ce3e3542cb6dae832f87d5fb6dea6c6d59af3 [file] [log] [blame]
Garrick Evansf0ab7132019-06-18 14:50:42 +09001// Copyright 2019 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Garrick Evans3388a032020-03-24 11:25:55 +09005#ifndef PATCHPANEL_DATAPATH_H_
6#define PATCHPANEL_DATAPATH_H_
Garrick Evansf0ab7132019-06-18 14:50:42 +09007
Hugo Benichie8758b52020-04-03 14:49:01 +09008#include <net/route.h>
Hugo Benichi33860d72020-07-09 16:34:01 +09009#include <sys/types.h>
Hugo Benichie8758b52020-04-03 14:49:01 +090010
Garrick Evansf0ab7132019-06-18 14:50:42 +090011#include <string>
12
13#include <base/macros.h>
Hugo Benichi82ed5cf2020-09-08 21:30:22 +090014#include <gtest/gtest_prod.h> // for FRIEND_TEST
Garrick Evansf0ab7132019-06-18 14:50:42 +090015
Jason Jeremy Imana7273a32020-08-04 11:25:31 +090016#include "patchpanel/firewall.h"
Garrick Evans3388a032020-03-24 11:25:55 +090017#include "patchpanel/mac_address_generator.h"
18#include "patchpanel/minijailed_process_runner.h"
Hugo Benichi8d622b52020-08-13 15:24:12 +090019#include "patchpanel/routing_service.h"
Garrick Evans3388a032020-03-24 11:25:55 +090020#include "patchpanel/subnet.h"
Garrick Evansf0ab7132019-06-18 14:50:42 +090021
Garrick Evans3388a032020-03-24 11:25:55 +090022namespace patchpanel {
Garrick Evansf0ab7132019-06-18 14:50:42 +090023
Hugo Benichid82d8832020-08-14 10:05:03 +090024// Simple enum of bitmasks used for specifying a set of IP family values.
25enum IpFamily {
26 NONE = 0,
27 IPv4 = 1 << 0,
28 IPv6 = 1 << 1,
Taoyu Lia0727dc2020-09-24 19:54:59 +090029 Dual = IPv4 | IPv6, // (1 << 0) | (1 << 1);
Hugo Benichid82d8832020-08-14 10:05:03 +090030};
31
Taoyu Li90c13912019-11-26 17:56:54 +090032// cros lint will yell to force using int16/int64 instead of long here, however
33// note that unsigned long IS the correct signature for ioctl in Linux kernel -
34// it's 32 bits on 32-bit platform and 64 bits on 64-bit one.
35using ioctl_req_t = unsigned long;
36typedef int (*ioctl_t)(int, ioctl_req_t, ...);
Garrick Evansc7ae82c2019-09-04 16:25:10 +090037
Garrick Evans54861622019-07-19 09:05:09 +090038// Returns for given interface name the host name of a ARC veth pair.
Garrick Evans2f581a02020-05-11 10:43:35 +090039std::string ArcVethHostName(const std::string& ifname);
Garrick Evans54861622019-07-19 09:05:09 +090040
Garrick Evans8a067562020-05-11 12:47:30 +090041// Returns the ARC bridge interface name for the given interface.
42std::string ArcBridgeName(const std::string& ifname);
43
Garrick Evansf0ab7132019-06-18 14:50:42 +090044// ARC networking data path configuration utility.
Garrick Evans54861622019-07-19 09:05:09 +090045// IPV4 addresses are always specified in singular dotted-form (a.b.c.d)
46// (not in CIDR representation
Garrick Evansf0ab7132019-06-18 14:50:42 +090047class Datapath {
48 public:
Jason Jeremy Imana7273a32020-08-04 11:25:31 +090049 // |process_runner| and |firewall| must not be null; it is not owned.
50 Datapath(MinijailedProcessRunner* process_runner, Firewall* firewall);
Garrick Evansc7ae82c2019-09-04 16:25:10 +090051 // Provided for testing only.
Jason Jeremy Imana7273a32020-08-04 11:25:31 +090052 Datapath(MinijailedProcessRunner* process_runner,
53 Firewall* firewall,
54 ioctl_t ioctl_hook);
Qijiang Fan6bc59e12020-11-11 02:51:06 +090055 Datapath(const Datapath&) = delete;
56 Datapath& operator=(const Datapath&) = delete;
57
Garrick Evansf0ab7132019-06-18 14:50:42 +090058 virtual ~Datapath() = default;
59
Hugo Benichibf811c62020-09-07 17:30:45 +090060 // Start and stop the Datapath, creating or destroying the initial iptables
61 // setup needed for forwarding traffic from VMs and containers and for
62 // fwmark based routing.
63 virtual void Start();
64 virtual void Stop();
65
Hugo Benichi33860d72020-07-09 16:34:01 +090066 // Attaches the name |netns_name| to a network namespace identified by
67 // |netns_pid|. If |netns_name| had already been created, it will be deleted
68 // first.
69 virtual bool NetnsAttachName(const std::string& netns_name, pid_t netns_pid);
70
71 // Deletes the name |netns_name| of a network namespace.
72 virtual bool NetnsDeleteName(const std::string& netns_name);
73
Garrick Evans8a949dc2019-07-18 16:17:53 +090074 virtual bool AddBridge(const std::string& ifname,
Garrick Evans7a1a9ee2020-01-28 11:03:57 +090075 uint32_t ipv4_addr,
76 uint32_t ipv4_prefix_len);
Garrick Evans8a949dc2019-07-18 16:17:53 +090077 virtual void RemoveBridge(const std::string& ifname);
78
Garrick Evans621ed262019-11-13 12:28:43 +090079 virtual bool AddToBridge(const std::string& br_ifname,
80 const std::string& ifname);
81
Garrick Evansc7ae82c2019-09-04 16:25:10 +090082 // Adds a new TAP device.
83 // |name| may be empty, in which case a default device name will be used;
84 // it may be a template (e.g. vmtap%d), in which case the kernel will
85 // generate the name; or it may be fully defined. In all cases, upon success,
86 // the function returns the actual name of the interface.
Garrick Evans621ed262019-11-13 12:28:43 +090087 // |mac_addr| and |ipv4_addr| should be null if this interface will be later
88 // bridged.
Garrick Evans4f9f5572019-11-26 10:25:16 +090089 // If |user| is empty, no owner will be set
Garrick Evansc7ae82c2019-09-04 16:25:10 +090090 virtual std::string AddTAP(const std::string& name,
Garrick Evans621ed262019-11-13 12:28:43 +090091 const MacAddress* mac_addr,
92 const SubnetAddress* ipv4_addr,
Garrick Evans4f9f5572019-11-26 10:25:16 +090093 const std::string& user);
Garrick Evansc7ae82c2019-09-04 16:25:10 +090094
95 // |ifname| must be the actual name of the interface.
96 virtual void RemoveTAP(const std::string& ifname);
97
98 // The following are iptables methods.
99 // When specified, |ipv4_addr| is always singlar dotted-form (a.b.c.d)
100 // IPv4 address (not a CIDR representation).
101
Hugo Benichi76675592020-04-08 14:29:57 +0900102 // Creates a virtual interface pair split across the current namespace and the
103 // namespace corresponding to |pid|, and set up the remote interface
104 // |peer_ifname| according // to the given parameters.
105 virtual bool ConnectVethPair(pid_t pid,
Hugo Benichi33860d72020-07-09 16:34:01 +0900106 const std::string& netns_name,
Hugo Benichi76675592020-04-08 14:29:57 +0900107 const std::string& veth_ifname,
108 const std::string& peer_ifname,
109 const MacAddress& remote_mac_addr,
110 uint32_t remote_ipv4_addr,
111 uint32_t remote_ipv4_prefix_len,
112 bool remote_multicast_flag);
113
Garrick Evans54861622019-07-19 09:05:09 +0900114 virtual void RemoveInterface(const std::string& ifname);
115
Hugo Benichi321f23b2020-09-25 15:42:05 +0900116 // Create (or delete) an OUTPUT DROP rule for any locally originated traffic
117 // whose src IPv4 matches |src_ip| and would exit |oif|. This is mainly used
118 // for dropping Chrome webRTC traffic incorrectly bound on ARC and other
119 // guests virtual interfaces (chromium:898210).
120 virtual bool AddSourceIPv4DropRule(const std::string& oif,
121 const std::string& src_ip);
122 virtual bool RemoveSourceIPv4DropRule(const std::string& oif,
123 const std::string& src_ip);
124
Hugo Benichi7c342672020-09-08 09:18:14 +0900125 // Creates a virtual ethernet interface pair shared with the client namespace
126 // of |pid| and sets up routing outside and inside the client namespace for
127 // connecting the client namespace to the network.
128 bool StartRoutingNamespace(pid_t pid,
129 const std::string& netns_name,
130 const std::string& host_ifname,
131 const std::string& peer_ifname,
132 uint32_t subnet_ipv4_addr,
133 uint32_t subnet_prefixlen,
134 uint32_t host_ipv4_addr,
135 uint32_t peer_ipv4_addr,
136 const MacAddress& peer_mac_addr);
137 // Destroys the virtual ethernet interface, routing, and network namespace
138 // name set for |netns_name| by StartRoutingNamespace. The default route set
139 // inside the |netns_name| by patchpanel is not destroyed and it is assumed
140 // the client will teardown the namespace.
141 void StopRoutingNamespace(const std::string& netns_name,
142 const std::string& host_ifname,
143 uint32_t subnet_ipv4_addr,
144 uint32_t subnet_prefixlen,
145 uint32_t host_ipv4_addr);
146
Hugo Benichi8d622b52020-08-13 15:24:12 +0900147 // Sets up IPv4 SNAT, IP forwarding, and traffic marking for the given
148 // virtual device |int_ifname| associated to |source|. if |ext_ifname| is
149 // empty, the device is implicitly routed through the highest priority
150 // network.
151 virtual void StartRoutingDevice(const std::string& ext_ifname,
152 const std::string& int_ifname,
153 uint32_t int_ipv4_addr,
154 TrafficSource source);
155
156 // Removes IPv4 iptables, IP forwarding, and traffic marking for the given
157 // virtual device |int_ifname|.
158 virtual void StopRoutingDevice(const std::string& ext_ifname,
159 const std::string& int_ifname,
160 uint32_t int_ipv4_addr,
161 TrafficSource source);
162
Hugo Benichi76be34a2020-08-26 22:35:54 +0900163 // Starts or stops marking conntrack entries routed to |ext_ifname| with its
164 // associated fwmark routing tag. Once a conntrack entry is marked with the
165 // fwmark routing tag of a external device, the connection will be pinned
166 // to that deviced if conntrack fwmark restore is set for the source.
167 virtual void StartConnectionPinning(const std::string& ext_ifname);
168 virtual void StopConnectionPinning(const std::string& ext_ifname);
169
Taoyu Li90c13912019-11-26 17:56:54 +0900170 // Methods supporting IPv6 configuration for ARC.
Garrick Evans664a82f2019-12-17 12:18:05 +0900171 virtual bool MaskInterfaceFlags(const std::string& ifname,
172 uint16_t on,
173 uint16_t off = 0);
Garrick Evans260ff302019-07-25 11:22:50 +0900174
Hugo Benichid82d8832020-08-14 10:05:03 +0900175 // Convenience functions for enabling or disabling IPv6 forwarding in both
176 // directions between a pair of interfaces
Taoyu Li90c13912019-11-26 17:56:54 +0900177 virtual bool AddIPv6Forwarding(const std::string& ifname1,
178 const std::string& ifname2);
179 virtual void RemoveIPv6Forwarding(const std::string& ifname1,
180 const std::string& ifname2);
181
Garrick Evans260ff302019-07-25 11:22:50 +0900182 virtual bool AddIPv6HostRoute(const std::string& ifname,
183 const std::string& ipv6_addr,
184 int ipv6_prefix_len);
185 virtual void RemoveIPv6HostRoute(const std::string& ifname,
186 const std::string& ipv6_addr,
187 int ipv6_prefix_len);
188
Taoyu Lia0727dc2020-09-24 19:54:59 +0900189 virtual bool AddIPv6Address(const std::string& ifname,
190 const std::string& ipv6_addr);
191 virtual void RemoveIPv6Address(const std::string& ifname,
192 const std::string& ipv6_addr);
Garrick Evans260ff302019-07-25 11:22:50 +0900193
Hugo Benichie8758b52020-04-03 14:49:01 +0900194 // Adds (or deletes) a route to direct to |gateway_addr| the traffic destined
195 // to the subnet defined by |addr| and |netmask|.
Garrick Evans3d97a392020-02-21 15:24:37 +0900196 virtual bool AddIPv4Route(uint32_t gateway_addr,
197 uint32_t addr,
198 uint32_t netmask);
Hugo Benichie8758b52020-04-03 14:49:01 +0900199 virtual bool DeleteIPv4Route(uint32_t gateway_addr,
200 uint32_t addr,
201 uint32_t netmask);
202 // Adds (or deletes) a route to direct to |ifname| the traffic destined to the
203 // subnet defined by |addr| and |netmask|.
204 virtual bool AddIPv4Route(const std::string& ifname,
205 uint32_t addr,
206 uint32_t netmask);
207 virtual bool DeleteIPv4Route(const std::string& ifname,
208 uint32_t addr,
209 uint32_t netmask);
Garrick Evans3d97a392020-02-21 15:24:37 +0900210
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900211 // Adds (or deletes) an iptables rule for ADB port forwarding.
212 virtual bool AddAdbPortForwardRule(const std::string& ifname);
213 virtual void DeleteAdbPortForwardRule(const std::string& ifname);
214
215 // Adds (or deletes) an iptables rule for ADB port access.
216 virtual bool AddAdbPortAccessRule(const std::string& ifname);
217 virtual void DeleteAdbPortAccessRule(const std::string& ifname);
218
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900219 // Set or override the interface name to index mapping for |ifname|.
220 // Only used for testing.
221 void SetIfnameIndex(const std::string& ifname, int ifindex);
222
Garrick Evans260ff302019-07-25 11:22:50 +0900223 MinijailedProcessRunner& runner() const;
224
Garrick Evansf0ab7132019-06-18 14:50:42 +0900225 private:
Hugo Benichi82ed5cf2020-09-08 21:30:22 +0900226 // Creates a virtual interface pair.
227 bool AddVirtualInterfacePair(const std::string& netns_name,
228 const std::string& veth_ifname,
229 const std::string& peer_ifname);
230 // Sets the configuration of an interface.
231 bool ConfigureInterface(const std::string& ifname,
232 const MacAddress& mac_addr,
233 uint32_t ipv4_addr,
234 uint32_t ipv4_prefix_len,
235 bool up,
236 bool enable_multicast);
237 // Sets the link status.
238 bool ToggleInterface(const std::string& ifname, bool up);
239 // Starts or stops accepting IP traffic forwarded between |iif| and |oif|
240 // by adding or removing ACCEPT rules in the filter FORWARD chain of iptables
241 // and/or ip6tables. If |iif| is empty, only specifies |oif| as the output
242 // interface. If |iif| is empty, only specifies |iif| as the input interface.
243 // |oif| and |iif| cannot be both empty.
244 bool StartIpForwarding(IpFamily family,
245 const std::string& iif,
246 const std::string& oif);
247 bool StopIpForwarding(IpFamily family,
248 const std::string& iif,
249 const std::string& oif);
250 // Create (or delete) pre-routing rules allowing direct ingress on |ifname|
251 // to guest destination |ipv4_addr|.
252 bool AddInboundIPv4DNAT(const std::string& ifname,
253 const std::string& ipv4_addr);
254 void RemoveInboundIPv4DNAT(const std::string& ifname,
255 const std::string& ipv4_addr);
256 // Create (or delete) a forwarding rule for |ifname|.
Hugo Benichi82ed5cf2020-09-08 21:30:22 +0900257 // Creates (or deletes) the forwarding and postrouting rules for SNAT
258 // fwmarked IPv4 traffic.
259 bool AddSNATMarkRules();
260 void RemoveSNATMarkRules();
Hugo Benichi82ed5cf2020-09-08 21:30:22 +0900261 // Create (or delete) a mangle PREROUTING rule for marking IPv4 traffic
262 // outgoing of |ifname| with the SNAT fwmark value 0x1.
263 // TODO(hugobenichi) Refer to RoutingService to obtain the fwmark value and
264 // add a fwmark mask in the generated rule.
265 bool AddOutboundIPv4SNATMark(const std::string& ifname);
266 void RemoveOutboundIPv4SNATMark(const std::string& ifname);
Hugo Benichi82ed5cf2020-09-08 21:30:22 +0900267
Hugo Benichi76be34a2020-08-26 22:35:54 +0900268 bool ModifyConnmarkSetPostrouting(IpFamily family,
269 const std::string& op,
270 const std::string& oif);
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900271 bool ModifyConnmarkRestore(IpFamily family,
272 const std::string& chain,
273 const std::string& op,
274 const std::string& iif);
275 bool ModifyFwmarkRoutingTag(const std::string& op,
276 const std::string& ext_ifname,
277 const std::string& int_ifname);
Hugo Benichi9be19b12020-08-14 15:33:40 +0900278 bool ModifyFwmarkSourceTag(const std::string& op,
279 const std::string& iif,
280 TrafficSource source);
281 bool ModifyFwmarkPrerouting(IpFamily family,
282 const std::string& op,
283 const std::string& iif,
284 Fwmark mark,
285 Fwmark mask,
286 bool log_failures = true);
Hugo Benichid82d8832020-08-14 10:05:03 +0900287 bool ModifyIpForwarding(IpFamily family,
288 const std::string& op,
289 const std::string& iif,
290 const std::string& oif,
291 bool log_failures = true);
Hugo Benichi3ef370b2020-11-16 19:07:17 +0900292 bool ModifyFwmarkVpnJumpRule(const std::string& chain,
293 const std::string& op,
294 const std::string& iif,
295 Fwmark mark,
296 Fwmark mask);
297 bool ModifyChain(IpFamily family,
298 const std::string& table,
299 const std::string& op,
300 const std::string& chain);
301 bool ModifyIptables(IpFamily family,
302 const std::string& table,
303 const std::vector<std::string>& argv);
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900304 bool ModifyRtentry(ioctl_req_t op, struct rtentry* route);
305 int FindIfIndex(const std::string& ifname);
Hugo Benichid82d8832020-08-14 10:05:03 +0900306
Garrick Evansf0ab7132019-06-18 14:50:42 +0900307 MinijailedProcessRunner* process_runner_;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900308 Firewall* firewall_;
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900309 ioctl_t ioctl_;
Garrick Evansf0ab7132019-06-18 14:50:42 +0900310
Hugo Benichi82ed5cf2020-09-08 21:30:22 +0900311 FRIEND_TEST(DatapathTest, AddInboundIPv4DNAT);
Hugo Benichi82ed5cf2020-09-08 21:30:22 +0900312 FRIEND_TEST(DatapathTest, AddOutboundIPv4SNATMark);
313 FRIEND_TEST(DatapathTest, AddSNATMarkRules);
314 FRIEND_TEST(DatapathTest, AddVirtualInterfacePair);
315 FRIEND_TEST(DatapathTest, ConfigureInterface);
Hugo Benichi82ed5cf2020-09-08 21:30:22 +0900316 FRIEND_TEST(DatapathTest, RemoveInboundIPv4DNAT);
Hugo Benichi82ed5cf2020-09-08 21:30:22 +0900317 FRIEND_TEST(DatapathTest, RemoveOutboundIPv4SNATMark);
318 FRIEND_TEST(DatapathTest, RemoveSNATMarkRules);
319 FRIEND_TEST(DatapathTest, StartStopIpForwarding);
320 FRIEND_TEST(DatapathTest, ToggleInterface);
321
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900322 // A map used for remembering the interface index of an interface. This
323 // information is necessary when cleaning up iptables fwmark rules that
324 // directly references the interface index. When removing these rules on
325 // an RTM_DELLINK event, the interface index cannot be retrieved anymore.
326 // A new entry is only added when a new physical device appears, and entries
327 // are not removed.
328 // TODO(b/161507671) Rely on RoutingService to obtain this information once
329 // shill/routing_table.cc has been migrated to patchpanel.
330 std::map<std::string, int> if_nametoindex_;
Garrick Evansf0ab7132019-06-18 14:50:42 +0900331};
332
Garrick Evans3388a032020-03-24 11:25:55 +0900333} // namespace patchpanel
Garrick Evansf0ab7132019-06-18 14:50:42 +0900334
Garrick Evans3388a032020-03-24 11:25:55 +0900335#endif // PATCHPANEL_DATAPATH_H_