blob: a4df2f223eeac06a1a86bbcee0025815e3c65e24 [file] [log] [blame]
Jason Jeremy Iman16f91722020-01-14 09:53:28 +09001// Copyright 2020 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_BROADCAST_FORWARDER_H_
6#define PATCHPANEL_BROADCAST_FORWARDER_H_
Jason Jeremy Iman16f91722020-01-14 09:53:28 +09007
8#include <sys/socket.h>
9
10#include <shill/net/rtnl_listener.h>
Garrick Evans3388a032020-03-24 11:25:55 +090011#include "patchpanel/shill_client.h"
Jason Jeremy Iman16f91722020-01-14 09:53:28 +090012
13#include <map>
14#include <memory>
15#include <string>
16
17#include <base/files/file_descriptor_watcher_posix.h>
18#include <base/macros.h>
19
Garrick Evans3388a032020-03-24 11:25:55 +090020#include "patchpanel/net_util.h"
Jason Jeremy Iman16f91722020-01-14 09:53:28 +090021
Garrick Evans3388a032020-03-24 11:25:55 +090022namespace patchpanel {
Jason Jeremy Iman16f91722020-01-14 09:53:28 +090023
24constexpr uint32_t kBcastAddr = Ipv4Addr(255, 255, 255, 255);
25
26// Listens to broadcast messages sent by applications and forwards them between
27// network interfaces of host and guest.
28// BroadcastForwarder assumes that guest addresses, including broadcast and
29// netmask, are constant.
30class BroadcastForwarder {
31 public:
32 explicit BroadcastForwarder(const std::string& dev_ifname);
33 virtual ~BroadcastForwarder() = default;
34
35 bool AddGuest(const std::string& br_ifname);
36 void RemoveGuest(const std::string& br_ifname);
37
38 protected:
39 // Socket is used to keep track of an fd and its watcher.
40 // It also stores addresses corresponding to the interface it is bound to.
41 struct Socket {
42 Socket(base::ScopedFD fd,
43 const base::Callback<void(int)>& callback,
44 uint32_t addr,
45 uint32_t broadaddr,
46 uint32_t netmask = 0);
47 base::ScopedFD fd;
48 std::unique_ptr<base::FileDescriptorWatcher::Controller> watcher;
49 uint32_t addr;
50 uint32_t broadaddr;
51 uint32_t netmask;
52 };
53
54 // Bind will create a broadcast socket and return its fd.
55 // This is used for sending broadcasts.
56 static base::ScopedFD Bind(const std::string& ifname, uint16_t port);
57
58 // BindRaw will create a broadcast socket that listens to all IP packets.
59 // It filters the packets to only broadcast packets that is sent by
60 // applications.
61 // This is used to listen on broadcasts.
62 static base::ScopedFD BindRaw(const std::string& ifname);
63
64 // SendToNetwork sends |data| using a socket bound to |src_port| and
65 // |dev_ifname_| using a temporary socket.
66 bool SendToNetwork(uint16_t src_port,
67 const void* data,
68 ssize_t len,
69 const struct sockaddr_in& dst);
70
71 // SendToGuests will forward the broadcast packet to all Chrome OS guests'
72 // (ARC++, Crostini, etc) internal fd.
73 bool SendToGuests(const void* ip_pkt,
74 ssize_t len,
75 const struct sockaddr_in& dst);
76
77 // Callback from RTNetlink listener, invoked when the lan interface IPv4
78 // address is changed.
79 void AddrMsgHandler(const shill::RTNLMessage& msg);
80
81 // Listens for RTMGRP_IPV4_IFADDR messages and invokes AddrMsgHandler.
82 std::unique_ptr<shill::RTNLListener> addr_listener_;
83
84 const std::string dev_ifname_;
85 std::unique_ptr<Socket> dev_socket_;
86
87 // Mapping from guest bridge interface name to its sockets.
88 std::map<std::string, std::unique_ptr<Socket>> br_sockets_;
89
90 private:
91 void OnFileCanReadWithoutBlocking(int fd);
92
93 base::WeakPtrFactory<BroadcastForwarder> weak_factory_{this};
94 DISALLOW_COPY_AND_ASSIGN(BroadcastForwarder);
95};
96
Garrick Evans3388a032020-03-24 11:25:55 +090097} // namespace patchpanel
Jason Jeremy Iman16f91722020-01-14 09:53:28 +090098
Garrick Evans3388a032020-03-24 11:25:55 +090099#endif // PATCHPANEL_BROADCAST_FORWARDER_H_