blob: fef7897f7830741e6723df4cfc88a2c3d163f758 [file] [log] [blame] [edit]
// 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_