blob: ea7ae28beb1ed77bb0812377aeb13a9471626630 [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>
14
Jason Jeremy Imana7273a32020-08-04 11:25:31 +090015#include "patchpanel/firewall.h"
Garrick Evans3388a032020-03-24 11:25:55 +090016#include "patchpanel/mac_address_generator.h"
17#include "patchpanel/minijailed_process_runner.h"
Hugo Benichi8d622b52020-08-13 15:24:12 +090018#include "patchpanel/routing_service.h"
Garrick Evans3388a032020-03-24 11:25:55 +090019#include "patchpanel/subnet.h"
Garrick Evansf0ab7132019-06-18 14:50:42 +090020
Garrick Evans3388a032020-03-24 11:25:55 +090021namespace patchpanel {
Garrick Evansf0ab7132019-06-18 14:50:42 +090022
Hugo Benichid82d8832020-08-14 10:05:03 +090023// Simple enum of bitmasks used for specifying a set of IP family values.
24enum IpFamily {
25 NONE = 0,
26 IPv4 = 1 << 0,
27 IPv6 = 1 << 1,
Taoyu Lia0727dc2020-09-24 19:54:59 +090028 Dual = IPv4 | IPv6, // (1 << 0) | (1 << 1);
Hugo Benichid82d8832020-08-14 10:05:03 +090029};
30
Taoyu Li90c13912019-11-26 17:56:54 +090031// cros lint will yell to force using int16/int64 instead of long here, however
32// note that unsigned long IS the correct signature for ioctl in Linux kernel -
33// it's 32 bits on 32-bit platform and 64 bits on 64-bit one.
34using ioctl_req_t = unsigned long;
35typedef int (*ioctl_t)(int, ioctl_req_t, ...);
Garrick Evansc7ae82c2019-09-04 16:25:10 +090036
Garrick Evans54861622019-07-19 09:05:09 +090037// Returns for given interface name the host name of a ARC veth pair.
Garrick Evans2f581a02020-05-11 10:43:35 +090038std::string ArcVethHostName(const std::string& ifname);
Garrick Evans54861622019-07-19 09:05:09 +090039
Garrick Evans8a067562020-05-11 12:47:30 +090040// Returns the ARC bridge interface name for the given interface.
41std::string ArcBridgeName(const std::string& ifname);
42
Garrick Evansf0ab7132019-06-18 14:50:42 +090043// ARC networking data path configuration utility.
Garrick Evans54861622019-07-19 09:05:09 +090044// IPV4 addresses are always specified in singular dotted-form (a.b.c.d)
45// (not in CIDR representation
Garrick Evansf0ab7132019-06-18 14:50:42 +090046class Datapath {
47 public:
Jason Jeremy Imana7273a32020-08-04 11:25:31 +090048 // |process_runner| and |firewall| must not be null; it is not owned.
49 Datapath(MinijailedProcessRunner* process_runner, Firewall* firewall);
Garrick Evansc7ae82c2019-09-04 16:25:10 +090050 // Provided for testing only.
Jason Jeremy Imana7273a32020-08-04 11:25:31 +090051 Datapath(MinijailedProcessRunner* process_runner,
52 Firewall* firewall,
53 ioctl_t ioctl_hook);
Garrick Evansf0ab7132019-06-18 14:50:42 +090054 virtual ~Datapath() = default;
55
Hugo Benichi33860d72020-07-09 16:34:01 +090056 // Attaches the name |netns_name| to a network namespace identified by
57 // |netns_pid|. If |netns_name| had already been created, it will be deleted
58 // first.
59 virtual bool NetnsAttachName(const std::string& netns_name, pid_t netns_pid);
60
61 // Deletes the name |netns_name| of a network namespace.
62 virtual bool NetnsDeleteName(const std::string& netns_name);
63
Garrick Evans8a949dc2019-07-18 16:17:53 +090064 virtual bool AddBridge(const std::string& ifname,
Garrick Evans7a1a9ee2020-01-28 11:03:57 +090065 uint32_t ipv4_addr,
66 uint32_t ipv4_prefix_len);
Garrick Evans8a949dc2019-07-18 16:17:53 +090067 virtual void RemoveBridge(const std::string& ifname);
68
Garrick Evans621ed262019-11-13 12:28:43 +090069 virtual bool AddToBridge(const std::string& br_ifname,
70 const std::string& ifname);
71
Garrick Evansc7ae82c2019-09-04 16:25:10 +090072 // Adds a new TAP device.
73 // |name| may be empty, in which case a default device name will be used;
74 // it may be a template (e.g. vmtap%d), in which case the kernel will
75 // generate the name; or it may be fully defined. In all cases, upon success,
76 // the function returns the actual name of the interface.
Garrick Evans621ed262019-11-13 12:28:43 +090077 // |mac_addr| and |ipv4_addr| should be null if this interface will be later
78 // bridged.
Garrick Evans4f9f5572019-11-26 10:25:16 +090079 // If |user| is empty, no owner will be set
Garrick Evansc7ae82c2019-09-04 16:25:10 +090080 virtual std::string AddTAP(const std::string& name,
Garrick Evans621ed262019-11-13 12:28:43 +090081 const MacAddress* mac_addr,
82 const SubnetAddress* ipv4_addr,
Garrick Evans4f9f5572019-11-26 10:25:16 +090083 const std::string& user);
Garrick Evansc7ae82c2019-09-04 16:25:10 +090084
85 // |ifname| must be the actual name of the interface.
86 virtual void RemoveTAP(const std::string& ifname);
87
88 // The following are iptables methods.
89 // When specified, |ipv4_addr| is always singlar dotted-form (a.b.c.d)
90 // IPv4 address (not a CIDR representation).
91
Hugo Benichi76675592020-04-08 14:29:57 +090092 // Creates a virtual interface pair split across the current namespace and the
93 // namespace corresponding to |pid|, and set up the remote interface
94 // |peer_ifname| according // to the given parameters.
95 virtual bool ConnectVethPair(pid_t pid,
Hugo Benichi33860d72020-07-09 16:34:01 +090096 const std::string& netns_name,
Hugo Benichi76675592020-04-08 14:29:57 +090097 const std::string& veth_ifname,
98 const std::string& peer_ifname,
99 const MacAddress& remote_mac_addr,
100 uint32_t remote_ipv4_addr,
101 uint32_t remote_ipv4_prefix_len,
102 bool remote_multicast_flag);
103
Garrick Evans2470caa2020-03-04 14:15:41 +0900104 // Creates a virtual interface pair.
Hugo Benichi9ab5a052020-07-28 11:29:01 +0900105 virtual bool AddVirtualInterfacePair(const std::string& netns_name,
Hugo Benichi33860d72020-07-09 16:34:01 +0900106 const std::string& veth_ifname,
Garrick Evans2470caa2020-03-04 14:15:41 +0900107 const std::string& peer_ifname);
108
109 // Sets the link status.
110 virtual bool ToggleInterface(const std::string& ifname, bool up);
111
112 // Sets the configuration of an interface.
113 virtual bool ConfigureInterface(const std::string& ifname,
114 const MacAddress& mac_addr,
115 uint32_t ipv4_addr,
116 uint32_t ipv4_prefix_len,
117 bool up,
118 bool enable_multicast);
119
Garrick Evans54861622019-07-19 09:05:09 +0900120 virtual void RemoveInterface(const std::string& ifname);
121
Hugo Benichi321f23b2020-09-25 15:42:05 +0900122 // Create (or delete) an OUTPUT DROP rule for any locally originated traffic
123 // whose src IPv4 matches |src_ip| and would exit |oif|. This is mainly used
124 // for dropping Chrome webRTC traffic incorrectly bound on ARC and other
125 // guests virtual interfaces (chromium:898210).
126 virtual bool AddSourceIPv4DropRule(const std::string& oif,
127 const std::string& src_ip);
128 virtual bool RemoveSourceIPv4DropRule(const std::string& oif,
129 const std::string& src_ip);
130
Hugo Benichi8d622b52020-08-13 15:24:12 +0900131 // Sets up IPv4 SNAT, IP forwarding, and traffic marking for the given
132 // virtual device |int_ifname| associated to |source|. if |ext_ifname| is
133 // empty, the device is implicitly routed through the highest priority
134 // network.
135 virtual void StartRoutingDevice(const std::string& ext_ifname,
136 const std::string& int_ifname,
137 uint32_t int_ipv4_addr,
138 TrafficSource source);
139
140 // Removes IPv4 iptables, IP forwarding, and traffic marking for the given
141 // virtual device |int_ifname|.
142 virtual void StopRoutingDevice(const std::string& ext_ifname,
143 const std::string& int_ifname,
144 uint32_t int_ipv4_addr,
145 TrafficSource source);
146
Hugo Benichi76be34a2020-08-26 22:35:54 +0900147 // Starts or stops marking conntrack entries routed to |ext_ifname| with its
148 // associated fwmark routing tag. Once a conntrack entry is marked with the
149 // fwmark routing tag of a external device, the connection will be pinned
150 // to that deviced if conntrack fwmark restore is set for the source.
151 virtual void StartConnectionPinning(const std::string& ext_ifname);
152 virtual void StopConnectionPinning(const std::string& ext_ifname);
153
Garrick Evansf0ab7132019-06-18 14:50:42 +0900154 // Create (or delete) pre-routing rules allowing direct ingress on |ifname|
155 // to guest desintation |ipv4_addr|.
156 virtual bool AddInboundIPv4DNAT(const std::string& ifname,
157 const std::string& ipv4_addr);
158 virtual void RemoveInboundIPv4DNAT(const std::string& ifname,
159 const std::string& ipv4_addr);
160
161 // Create (or delete) a forwarding rule for |ifname|.
162 virtual bool AddOutboundIPv4(const std::string& ifname);
163 virtual void RemoveOutboundIPv4(const std::string& ifname);
164
Garrick Evansd291af62020-05-25 10:39:06 +0900165 // Creates (or deletes) the forwarding and postrouting rules for SNAT
166 // fwmarked IPv4 traffic.
167 virtual bool AddSNATMarkRules();
168 virtual void RemoveSNATMarkRules();
169
Garrick Evansff6e37f2020-05-25 10:54:47 +0900170 virtual bool AddInterfaceSNAT(const std::string& ifname);
171 virtual void RemoveInterfaceSNAT(const std::string& ifname);
172
Hugo Benichie8758b52020-04-03 14:49:01 +0900173 // Create (or delete) a mangle PREROUTING rule for marking IPv4 traffic
174 // outgoing of |ifname| with the SNAT fwmark value 0x1.
175 // TODO(hugobenichi) Refer to RoutingService to obtain the fwmark value and
176 // add a fwmark mask in the generated rule.
177 virtual bool AddOutboundIPv4SNATMark(const std::string& ifname);
178 virtual void RemoveOutboundIPv4SNATMark(const std::string& ifname);
179
Garrick Evansd291af62020-05-25 10:39:06 +0900180 // Create (or delete) a forward rule for established connections.
181 virtual bool AddForwardEstablishedRule();
182 virtual void RemoveForwardEstablishedRule();
183
Taoyu Li90c13912019-11-26 17:56:54 +0900184 // Methods supporting IPv6 configuration for ARC.
Garrick Evans664a82f2019-12-17 12:18:05 +0900185 virtual bool MaskInterfaceFlags(const std::string& ifname,
186 uint16_t on,
187 uint16_t off = 0);
Garrick Evans260ff302019-07-25 11:22:50 +0900188
Hugo Benichid82d8832020-08-14 10:05:03 +0900189 // Starts or stops accepting IP traffic forwarded between |iif| and |oif|
190 // by adding or removing ACCEPT rules in the filter FORWARD chain of iptables
191 // and/or ip6tables. If |iif| is empty, only specifies |oif| as the output
192 // interface. If |iif| is empty, only specifies |iif| as the input interface.
193 // |oif| and |iif| cannot be both empty.
194 virtual bool StartIpForwarding(IpFamily family,
195 const std::string& iif,
196 const std::string& oif);
197 virtual bool StopIpForwarding(IpFamily family,
198 const std::string& iif,
199 const std::string& oif);
200
201 // Convenience functions for enabling or disabling IPv6 forwarding in both
202 // directions between a pair of interfaces
Taoyu Li90c13912019-11-26 17:56:54 +0900203 virtual bool AddIPv6Forwarding(const std::string& ifname1,
204 const std::string& ifname2);
205 virtual void RemoveIPv6Forwarding(const std::string& ifname1,
206 const std::string& ifname2);
207
Garrick Evans260ff302019-07-25 11:22:50 +0900208 virtual bool AddIPv6HostRoute(const std::string& ifname,
209 const std::string& ipv6_addr,
210 int ipv6_prefix_len);
211 virtual void RemoveIPv6HostRoute(const std::string& ifname,
212 const std::string& ipv6_addr,
213 int ipv6_prefix_len);
214
Taoyu Lia0727dc2020-09-24 19:54:59 +0900215 virtual bool AddIPv6Address(const std::string& ifname,
216 const std::string& ipv6_addr);
217 virtual void RemoveIPv6Address(const std::string& ifname,
218 const std::string& ipv6_addr);
Garrick Evans260ff302019-07-25 11:22:50 +0900219
Hugo Benichie8758b52020-04-03 14:49:01 +0900220 // Adds (or deletes) a route to direct to |gateway_addr| the traffic destined
221 // to the subnet defined by |addr| and |netmask|.
Garrick Evans3d97a392020-02-21 15:24:37 +0900222 virtual bool AddIPv4Route(uint32_t gateway_addr,
223 uint32_t addr,
224 uint32_t netmask);
Hugo Benichie8758b52020-04-03 14:49:01 +0900225 virtual bool DeleteIPv4Route(uint32_t gateway_addr,
226 uint32_t addr,
227 uint32_t netmask);
228 // Adds (or deletes) a route to direct to |ifname| the traffic destined to the
229 // subnet defined by |addr| and |netmask|.
230 virtual bool AddIPv4Route(const std::string& ifname,
231 uint32_t addr,
232 uint32_t netmask);
233 virtual bool DeleteIPv4Route(const std::string& ifname,
234 uint32_t addr,
235 uint32_t netmask);
Garrick Evans3d97a392020-02-21 15:24:37 +0900236
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900237 // Adds (or deletes) an iptables rule for ADB port forwarding.
238 virtual bool AddAdbPortForwardRule(const std::string& ifname);
239 virtual void DeleteAdbPortForwardRule(const std::string& ifname);
240
241 // Adds (or deletes) an iptables rule for ADB port access.
242 virtual bool AddAdbPortAccessRule(const std::string& ifname);
243 virtual void DeleteAdbPortAccessRule(const std::string& ifname);
244
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900245 // Set or override the interface name to index mapping for |ifname|.
246 // Only used for testing.
247 void SetIfnameIndex(const std::string& ifname, int ifindex);
248
Garrick Evans260ff302019-07-25 11:22:50 +0900249 MinijailedProcessRunner& runner() const;
250
Garrick Evansf0ab7132019-06-18 14:50:42 +0900251 private:
Hugo Benichi76be34a2020-08-26 22:35:54 +0900252 bool ModifyConnmarkSetPostrouting(IpFamily family,
253 const std::string& op,
254 const std::string& oif);
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900255 bool ModifyConnmarkRestore(IpFamily family,
256 const std::string& chain,
257 const std::string& op,
258 const std::string& iif);
259 bool ModifyFwmarkRoutingTag(const std::string& op,
260 const std::string& ext_ifname,
261 const std::string& int_ifname);
Hugo Benichi9be19b12020-08-14 15:33:40 +0900262 bool ModifyFwmarkSourceTag(const std::string& op,
263 const std::string& iif,
264 TrafficSource source);
265 bool ModifyFwmarkPrerouting(IpFamily family,
266 const std::string& op,
267 const std::string& iif,
268 Fwmark mark,
269 Fwmark mask,
270 bool log_failures = true);
Hugo Benichid82d8832020-08-14 10:05:03 +0900271 bool ModifyIpForwarding(IpFamily family,
272 const std::string& op,
273 const std::string& iif,
274 const std::string& oif,
275 bool log_failures = true);
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900276 bool ModifyRtentry(ioctl_req_t op, struct rtentry* route);
277 int FindIfIndex(const std::string& ifname);
Hugo Benichid82d8832020-08-14 10:05:03 +0900278
Garrick Evansf0ab7132019-06-18 14:50:42 +0900279 MinijailedProcessRunner* process_runner_;
Jason Jeremy Imana7273a32020-08-04 11:25:31 +0900280 Firewall* firewall_;
Garrick Evansc7ae82c2019-09-04 16:25:10 +0900281 ioctl_t ioctl_;
Garrick Evansf0ab7132019-06-18 14:50:42 +0900282
Hugo Benichiaf9d8a72020-08-26 13:28:13 +0900283 // A map used for remembering the interface index of an interface. This
284 // information is necessary when cleaning up iptables fwmark rules that
285 // directly references the interface index. When removing these rules on
286 // an RTM_DELLINK event, the interface index cannot be retrieved anymore.
287 // A new entry is only added when a new physical device appears, and entries
288 // are not removed.
289 // TODO(b/161507671) Rely on RoutingService to obtain this information once
290 // shill/routing_table.cc has been migrated to patchpanel.
291 std::map<std::string, int> if_nametoindex_;
Hugo Benichie8758b52020-04-03 14:49:01 +0900292
Garrick Evansf0ab7132019-06-18 14:50:42 +0900293 DISALLOW_COPY_AND_ASSIGN(Datapath);
294};
295
Garrick Evans3388a032020-03-24 11:25:55 +0900296} // namespace patchpanel
Garrick Evansf0ab7132019-06-18 14:50:42 +0900297
Garrick Evans3388a032020-03-24 11:25:55 +0900298#endif // PATCHPANEL_DATAPATH_H_