patchpanel: ndproxy: assign public v6 addr to guest-facing ifs
Currently there is no public IPv6 address assigned on the
guest-facing interfaces (arc bridges and taps) when device is on
IPv6 network. This is causing Linux choosing a wrong src address
on packets directly originated from host to guest and drop the
returning traffic.
This patch generates an EUI-64 address based on virtual interface
MAC address upon receiving an RA, and add it to the interface.
BUG=chromium:1069985
TEST=unit;fuzz
TEST=manual(deploy on octopus and verify pinging penguin from host)
Change-Id: Id3ae953df6b3c84411461294bbc8dbd236cef901
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2428652
Tested-by: Taoyu Li <taoyl@chromium.org>
Reviewed-by: Garrick Evans <garrick@chromium.org>
Reviewed-by: Hugo Benichi <hugobenichi@google.com>
Commit-Queue: Taoyu Li <taoyl@chromium.org>
diff --git a/patchpanel/ndproxy.h b/patchpanel/ndproxy.h
index 4a4427b..3857169 100644
--- a/patchpanel/ndproxy.h
+++ b/patchpanel/ndproxy.h
@@ -16,6 +16,7 @@
#include <memory>
#include <set>
#include <string>
+#include <vector>
#include <base/files/scoped_file.h>
#include <base/macros.h>
@@ -47,6 +48,9 @@
const MacAddress& local_mac_addr,
uint8_t* out_frame);
+ static const nd_opt_prefix_info* GetPrefixInfoOption(const uint8_t* in_frame,
+ ssize_t frame_len);
+
// Given an extended |buffer|, find a proper frame buffer pointer so that
// pt > buffer, and start of IP header (pt + ETH_H_LEN) is 4-bytes aligned.
// In the worst case the size of usable buffer will be original size minus 3.
@@ -76,6 +80,11 @@
const base::Callback<void(const std::string&, const std::string&)>&
handler);
+ // Callback upon receiving prefix information from RA frame.
+ void RegisterOnRouterDiscoveryHandler(
+ const base::Callback<void(const std::string&, const std::string&)>&
+ handler);
+
// To proxy between upstream interface and guest OS interface (eth0-arc_eth0)
// Outbound RS, inbound RA, and bidirectional NS/NA will be proxied.
bool AddInterfacePair(const std::string& ifname_physical,
@@ -88,6 +97,11 @@
// Remove all proxy interface pair with ifindex.
bool RemoveInterface(const std::string& ifname);
+ // Utility to get a list of guest interfaces names that are currently being
+ // proxied with a specific physical interface.
+ std::vector<std::string> GetGuestInterfaces(
+ const std::string& ifname_physical);
+
private:
// Data structure to store interface mapping for a certain kind of packet to
// be proxied. For example, {1: {2}, 2: {1}} means that packet from interfaces
@@ -110,6 +124,7 @@
interface_mapping* MapForType(uint8_t type);
bool IsGuestInterface(int ifindex);
+ bool IsRouterInterface(int ifindex);
// Socket used to communicate with kernel through ioctl. No real packet data
// goes through this socket.
@@ -129,6 +144,8 @@
base::Callback<void(const std::string&, const std::string&)>
guest_discovery_handler_;
+ base::Callback<void(const std::string&, const std::string&)>
+ router_discovery_handler_;
base::WeakPtrFactory<NDProxy> weak_factory_{this};
@@ -156,6 +173,16 @@
void OnGuestIpDiscovery(const std::string& ifname,
const std::string& ip6addr);
+ // Callback from NDProxy core when receive prefix info from router
+ void OnRouterDiscovery(const std::string& ifname, const std::string& ip6addr);
+
+ void SendMessage(NDProxyMessage::NDProxyEventType type,
+ const std::string& ifname,
+ const std::string& ip6addr);
+
+ // Map from guest-facing ifname to eui address we assigned
+ std::map<std::string, std::string> guest_if_addrs_;
+
// Utilize MessageDispatcher to watch control fd
std::unique_ptr<MessageDispatcher> msg_dispatcher_;