You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
6.1 KiB
168 lines
6.1 KiB
/*
|
|
* Copyright (C) 2016 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef WIFICOND_NET_NL80211_PACKET_H_
|
|
#define WIFICOND_NET_NL80211_PACKET_H_
|
|
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include <linux/genetlink.h>
|
|
#include <linux/netlink.h>
|
|
|
|
#include <android-base/macros.h>
|
|
|
|
#include "wificond/net/nl80211_attribute.h"
|
|
|
|
namespace android {
|
|
namespace wificond {
|
|
|
|
// NL80211Packets are used to communicate with the cfg80211 kernel subsystem
|
|
// (via the nl80211 interface). An NL80211 packet is a type of generic netlink
|
|
// packet (i.e. it includes netlink and generic netlink headers).
|
|
// In order to simplify the design, we also allow this class to represent a
|
|
// few types of netlink control messages. In this way the API user is supposed to
|
|
// call IsValid() and GetMessageType() in the first place to avoid misuse of
|
|
// this class.
|
|
class NL80211Packet {
|
|
public:
|
|
// This is used for creating a NL80211Packet from buffer.
|
|
explicit NL80211Packet(const std::vector<uint8_t>& data);
|
|
// This is used for creating an empty NL80211Packet to be filled later.
|
|
// See comment of SetMessageType() for |type|.
|
|
// See comment of SetCommand() for |command|.
|
|
// See comment of SetMessageSequence() for |sequence|.
|
|
// See comment of SetPortId() for |pid|.
|
|
NL80211Packet(uint16_t type,
|
|
uint8_t command,
|
|
uint32_t sequence,
|
|
uint32_t pid);
|
|
// We don't copy NL80211Packet for performance reasons.
|
|
// However we keep this copy constructor because it makes unit tests easy.
|
|
// It prints WARNING log when this copy constructor is called.
|
|
NL80211Packet(const NL80211Packet& packet);
|
|
// Explicitly specify the move constructor. Otherwise, copy constructor will
|
|
// be called on if we move a NL80211Packet object.
|
|
NL80211Packet(NL80211Packet&& packet) = default;
|
|
~NL80211Packet() = default;
|
|
|
|
// Returns whether a packet has consistent header fields.
|
|
bool IsValid() const;
|
|
|
|
// Helper functions for Netlink flags.
|
|
|
|
// Requesting a dump of a kernel obejct.
|
|
bool IsDump() const;
|
|
// Multipart messages are used to send lists or trees of objects.
|
|
// They are supposed to be parsed independently, and must not be reassembled.
|
|
// Multipart messages are terminated by NLMSG_DONE, which should be returned
|
|
// by GetMessageType().
|
|
bool IsMulti() const;
|
|
|
|
// Getter functions.
|
|
uint8_t GetCommand() const;
|
|
uint16_t GetFlags() const;
|
|
uint16_t GetMessageType() const;
|
|
uint32_t GetMessageSequence() const;
|
|
uint32_t GetPortId() const;
|
|
// Caller is responsible for checking that this is a valid
|
|
// NLMSG_ERROR message before calling GetErrorCode().
|
|
// Returns an error number defined in errno.h
|
|
int GetErrorCode() const;
|
|
const std::vector<uint8_t>& GetConstData() const;
|
|
|
|
// Setter functions.
|
|
|
|
// In the contexet of nl80211 messages,
|
|
// |command| is one of |enum nl80211_commands| in nl80211.h
|
|
void SetCommand(uint8_t command);
|
|
// |flags| is set of flag bits described by NLM_F_* macros in netlink.h
|
|
void AddFlag(uint16_t flag);
|
|
void SetFlags(uint16_t flags);
|
|
// In the context of nl80211 messages,
|
|
// message type is a nl80211 message family id dynamiclly allocated by kernel.
|
|
// If this is a control message, it could be one of the following value:
|
|
// NLMSG_NOOP, NLMSG_ERROR, NLMSG_DONE, NLMSG_OVERRUN
|
|
void SetMessageType(uint16_t message_type);
|
|
// Requests should carry a sequence number incremented for each request sent.
|
|
// For reply message, the sequence number is used to allow referring to a
|
|
// previous message with the same sequence number.
|
|
void SetMessageSequence(uint32_t message_sequemce);
|
|
// Set nlmsg_pid in netlink header.
|
|
// nlmsg_pid is the sender process port ID.
|
|
// It is *not* associated with a process but a netlink socket.
|
|
// We should use sockaddr_nl.nl_pid from sender socket.
|
|
// This value should be 0 if message is from kernel.
|
|
// See man 7 netlink for details.
|
|
void SetPortId(uint32_t pid);
|
|
|
|
void AddAttribute(const BaseNL80211Attr& attribute);
|
|
// For NLA_FLAG attribute
|
|
void AddFlagAttribute(int attribute_id);
|
|
|
|
bool HasAttribute(int id) const;
|
|
bool GetAttribute(int id, NL80211NestedAttr* attribute) const;
|
|
// Get all attributes to |*attribute| as a vector.
|
|
// In case of failure, attributes up until the first invalid attribute
|
|
// actually will be present in |attributes|.
|
|
bool GetAllAttributes(
|
|
std::vector<BaseNL80211Attr>* attributes) const;
|
|
|
|
template <typename T>
|
|
bool GetAttributeValue(int id, T* value) const {
|
|
std::vector<uint8_t> empty_vec;
|
|
// All data in |attribute| created here will be overwritten by
|
|
// GetAttribute(). So we use an empty vector to initialize it,
|
|
// regardless of the fact that an empty buffer is not qualified
|
|
// for creating a valid attribute.
|
|
NL80211Attr<T> attribute(empty_vec);
|
|
if (!GetAttribute(id, &attribute)) {
|
|
return false;
|
|
}
|
|
*value = attribute.GetValue();
|
|
return true;
|
|
}
|
|
|
|
template <typename T>
|
|
bool GetAttribute(int id, NL80211Attr<T>* attribute) const {
|
|
uint8_t* start = nullptr;
|
|
uint8_t* end = nullptr;
|
|
if (!BaseNL80211Attr::GetAttributeImpl(
|
|
data_.data() + NLMSG_HDRLEN + GENL_HDRLEN,
|
|
data_.size() - NLMSG_HDRLEN - GENL_HDRLEN,
|
|
id, &start, &end) ||
|
|
start == nullptr ||
|
|
end == nullptr) {
|
|
return false;
|
|
}
|
|
*attribute = NL80211Attr<T>(std::vector<uint8_t>(start, end));
|
|
if (!attribute->IsValid()) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void DebugLog() const;
|
|
|
|
private:
|
|
std::vector<uint8_t> data_;
|
|
};
|
|
|
|
} // namespace wificond
|
|
} // namespace android
|
|
|
|
#endif // WIFICOND_NET_NL80211_PACKET_H_
|