blob: 36b1d89000fc3a2011970b43021179d8afd4d228 [file] [log] [blame]
Taoyu Liaa6238b2019-09-06 17:38:52 +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
5#ifndef ARC_NETWORK_NDPROXY_H_
6#define ARC_NETWORK_NDPROXY_H_
7
8#include <stdint.h>
9
10#include <netinet/icmp6.h>
11#include <netinet/ip.h>
12#include <netinet/ip6.h>
13
14#include <map>
15#include <set>
16#include <string>
17
18#include <base/files/scoped_file.h>
19#include <base/macros.h>
20
21namespace arc_networkd {
22
23// Forward ICMPv6 RS/RA/NS/NA mssages between network interfaces according to
24// RFC 4389. Support asymmetric proxy that RS will be proxied one-way from
25// guest interface to physical interface ('Outbound') and RA the other way back
26// ('Inbound'), as well as symmetric proxy among guest interfaces that only
27// NS/NA will be proxied. Sample Usage:
28// arc_networkd::NDProxy nd_proxy;
29// nd_proxy.AddRouterInterfacePair("eth0", "arc_eth0");
30// nd_proxy.Start();
31class NDProxy {
32 public:
33 NDProxy() = default;
34 ~NDProxy() = default;
35
36 static const ssize_t kTranslateErrorNotICMPv6Frame;
37 static const ssize_t kTranslateErrorNotNDFrame;
38 static const ssize_t kTranslateErrorInsufficientLength;
39
40 // To proxy between upstream interface and guest OS interface (eth0-arc_eth0)
41 // Outbound RS, inbound RA, and bidirectional NS/NA will be proxied.
42 bool AddRouterInterfacePair(const std::string& ifname_physical,
43 const std::string& ifname_guest);
44
45 // To proxy between two different guest OS interface (arc_eth0-vmtap0)
46 // Only NS/NA will be proxied (bidirectionally).
47 bool AddPeeringInterfacePair(const std::string& ifname1,
48 const std::string& ifname2);
49
50 // Remove all proxy interface pair with ifindex.
51 bool RemoveInterface(const std::string& ifname);
52
53 // Start proxying. This is a blocking call.
54 void Start();
55
56 static uint16_t Icmpv6Checksum(const ip6_hdr* ip6, const icmp6_hdr* icmp6);
57 static void ReplaceMacInIcmpOption(uint8_t* frame,
58 ssize_t frame_len,
59 size_t nd_hdr_len,
60 uint8_t opt_type,
61 const uint8_t* target_mac);
62 static ssize_t TranslateNDFrame(const uint8_t* in_frame,
63 ssize_t frame_len,
64 const uint8_t* local_mac_addr,
65 uint8_t* out_frame);
66
67 private:
68 // Data structure to store interface mapping for a certain kind of packet to
69 // be proxied. For example, {1: {2}, 2: {1}} means that packet from interfaces
70 // 1 and 2 will be proxied to each other.
71 using interface_mapping = std::map<int, std::set<int>>;
72
73 interface_mapping* MapForType(uint8_t type);
74 bool AddInterfacePairInternal(const std::string& ifname1,
75 const std::string& ifname2,
76 bool proxy_rs_ra);
77
78 void ProxyNDFrame(int target_if, ssize_t frame_len);
79
80 base::ScopedFD fd_;
81 uint8_t in_frame_buffer_[IP_MAXPACKET];
82 uint8_t out_frame_buffer_[IP_MAXPACKET];
83
84 interface_mapping if_map_rs_;
85 interface_mapping if_map_ra_;
86 interface_mapping if_map_ns_na_;
87
88 DISALLOW_COPY_AND_ASSIGN(NDProxy);
89};
90
91} // namespace arc_networkd
92
93#endif // ARC_NETWORK_NDPROXY_H_