| // Copyright 2018 The ChromiumOS Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // This code is derived from the 'iw' source code. The copyright and license |
| // of that code is as follows: |
| // |
| // Copyright (c) 2007, 2008 Johannes Berg |
| // Copyright (c) 2007 Andy Lutomirski |
| // Copyright (c) 2007 Mike Kershaw |
| // Copyright (c) 2008-2009 Luis R. Rodriguez |
| // |
| // Permission to use, copy, modify, and/or distribute this software for any |
| // purpose with or without fee is hereby granted, provided that the above |
| // copyright notice and this permission notice appear in all copies. |
| // |
| // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
| // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
| // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
| // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
| // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
| // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
| // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
| |
| #ifndef NET_BASE_NETLINK_SOCKET_H_ |
| #define NET_BASE_NETLINK_SOCKET_H_ |
| |
| #include <memory> |
| #include <vector> |
| |
| #include <base/containers/span.h> |
| #include <base/functional/bind.h> |
| #include <base/logging.h> |
| #include <base/time/time.h> |
| #include <brillo/brillo_export.h> |
| #include <gtest/gtest_prod.h> // for FRIEND_TEST |
| |
| #include "net-base/socket.h" |
| |
| namespace net_base { |
| |
| // Provides an abstraction to a netlink socket. See |
| // http://www.infradead.org/~tgr/libnl/doc/core.html#core_netlink_fundamentals |
| // for documentation on how netlink sockets work (note that most of the rest of |
| // this document discusses libnl -- something not used by this code). |
| class BRILLO_EXPORT NetlinkSocket { |
| public: |
| // Creates a NetlinkSocket instance, using the SocketFactory. |
| static std::unique_ptr<NetlinkSocket> Create(); |
| |
| // Creates a NetlinkSocket instance with injecting the customized |
| // SocketFactory for testing. |
| static std::unique_ptr<NetlinkSocket> CreateWithSocketFactory( |
| std::unique_ptr<SocketFactory> socket_factory); |
| |
| NetlinkSocket(const NetlinkSocket&) = delete; |
| NetlinkSocket& operator=(const NetlinkSocket&) = delete; |
| |
| virtual ~NetlinkSocket(); |
| |
| // Returns the file descriptor used by the socket. |
| virtual int file_descriptor() const { return socket_->Get(); } |
| |
| // Get the next message sequence number for this socket. |
| // |GetSequenceNumber| won't return zero because that is the 'broadcast' |
| // sequence number. |
| virtual uint32_t GetSequenceNumber(); |
| |
| // Delegates to Socket::RecvMessage(). |
| virtual bool RecvMessage(std::vector<uint8_t>* message); |
| |
| // Sends a message, returns true if successful. |
| virtual bool SendMessage(base::span<const uint8_t> message); |
| |
| // Subscribes to netlink broadcast events. |
| virtual bool SubscribeToEvents(uint32_t group_id); |
| |
| // Delegates to select() to wait for the socket ready to read with timeout. |
| // Returns 1 if successful. |
| // Returns 0 if timeout. |
| // Returns -1 if error occurs, and errno is set. The caller should use PLOG to |
| // print errno. |
| virtual int WaitForRead(base::TimeDelta timeout) const; |
| |
| // Sets the value of |sequence_number_| for testing. |
| void set_sequence_number_for_test(uint32_t sequence_number) { |
| sequence_number_ = sequence_number; |
| } |
| |
| protected: |
| explicit NetlinkSocket(std::unique_ptr<Socket> socket); |
| |
| uint32_t sequence_number_ = 0; |
| |
| private: |
| // The netlink socket. It's always valid during the lifetime of NetlinkSocket |
| // instance. |
| std::unique_ptr<Socket> socket_; |
| }; |
| |
| } // namespace net_base |
| |
| #endif // NET_BASE_NETLINK_SOCKET_H_ |