Merge changes I56edff81,I6839a899
* changes: Print error names instead of numbers Implement NL80211 protocol printer
This commit is contained in:
commit
58a92454ba
18 changed files with 1390 additions and 57 deletions
|
@ -25,6 +25,7 @@ cc_library_static {
|
|||
"protocols/generic/Generic.cpp",
|
||||
"protocols/generic/GenericMessageBase.cpp",
|
||||
"protocols/generic/Unknown.cpp",
|
||||
"protocols/generic/families/Nl80211.cpp",
|
||||
"protocols/route/Link.cpp",
|
||||
"protocols/route/Route.cpp",
|
||||
"protocols/route/structs.cpp",
|
||||
|
|
|
@ -51,24 +51,24 @@ static void flagsToStream(std::stringstream& ss, __u16 nlmsg_flags, protocols::M
|
|||
printFlag(NLM_F_DUMP_FILTERED, "DUMP_FILTERED");
|
||||
|
||||
switch (genre) {
|
||||
case protocols::MessageGenre::UNKNOWN:
|
||||
case protocols::MessageGenre::Unknown:
|
||||
break;
|
||||
case protocols::MessageGenre::GET:
|
||||
case protocols::MessageGenre::Get:
|
||||
printFlag(NLM_F_DUMP, "DUMP"); // ROOT | MATCH
|
||||
printFlag(NLM_F_ROOT, "ROOT");
|
||||
printFlag(NLM_F_MATCH, "MATCH");
|
||||
printFlag(NLM_F_ATOMIC, "ATOMIC");
|
||||
break;
|
||||
case protocols::MessageGenre::NEW:
|
||||
case protocols::MessageGenre::New:
|
||||
printFlag(NLM_F_REPLACE, "REPLACE");
|
||||
printFlag(NLM_F_EXCL, "EXCL");
|
||||
printFlag(NLM_F_CREATE, "CREATE");
|
||||
printFlag(NLM_F_APPEND, "APPEND");
|
||||
break;
|
||||
case protocols::MessageGenre::DELETE:
|
||||
case protocols::MessageGenre::Delete:
|
||||
printFlag(NLM_F_NONREC, "NONREC");
|
||||
break;
|
||||
case protocols::MessageGenre::ACK:
|
||||
case protocols::MessageGenre::Ack:
|
||||
printFlag(NLM_F_CAPPED, "CAPPED");
|
||||
printFlag(NLM_F_ACK_TLVS, "ACK_TLVS");
|
||||
break;
|
||||
|
@ -99,11 +99,25 @@ static void toStream(std::stringstream& ss, const Buffer<uint8_t> data) {
|
|||
static void toStream(std::stringstream& ss, const Buffer<nlattr> attr,
|
||||
const protocols::AttributeMap& attrMap) {
|
||||
using DataType = protocols::AttributeDefinition::DataType;
|
||||
using Flags = protocols::AttributeDefinition::Flags;
|
||||
const auto attrtype = attrMap[attr->nla_type];
|
||||
|
||||
ss << attrtype.name << ": ";
|
||||
ss << attrtype.name;
|
||||
|
||||
if (attrtype.dataType == DataType::Flag && attr.data<uint8_t>().getRaw().len() == 0) return;
|
||||
ss << ": ";
|
||||
|
||||
if (attrtype.flags == Flags::Verbose) {
|
||||
const auto raw = attr.data<uint8_t>();
|
||||
ss << "{len=" << raw.getRaw().len();
|
||||
ss << ", crc=" << std::hex << std::setw(4) << crc16(raw) << std::dec;
|
||||
ss << "}";
|
||||
return;
|
||||
}
|
||||
|
||||
switch (attrtype.dataType) {
|
||||
case DataType::Raw:
|
||||
case DataType::Flag:
|
||||
toStream(ss, attr.data<uint8_t>());
|
||||
break;
|
||||
case DataType::Nested: {
|
||||
|
@ -117,13 +131,19 @@ static void toStream(std::stringstream& ss, const Buffer<nlattr> attr,
|
|||
ss << '}';
|
||||
break;
|
||||
}
|
||||
case DataType::StringNul:
|
||||
case DataType::String: {
|
||||
const auto str = attr.data<char>().getRaw();
|
||||
ss << '"' << printableOnly({str.ptr(), str.len()}) << '"';
|
||||
auto len = str.len();
|
||||
if (attrtype.dataType == DataType::StringNul && len > 0 && str.ptr()[len - 1] == '\0') {
|
||||
len--;
|
||||
}
|
||||
|
||||
ss << '"' << printableOnly({str.ptr(), len}) << '"';
|
||||
break;
|
||||
}
|
||||
case DataType::Uint:
|
||||
ss << attr.data<uint32_t>().copyFirst();
|
||||
ss << attr.data<uint64_t>().copyFirst();
|
||||
break;
|
||||
case DataType::Struct: {
|
||||
const auto structToStream =
|
||||
|
@ -147,10 +167,12 @@ std::string toString(const Buffer<nlmsghdr> hdr, int protocol, bool printPayload
|
|||
}
|
||||
protocols::NetlinkProtocol& protocolDescr = *protocolMaybe;
|
||||
|
||||
const auto msgDescMaybe = protocolDescr.getMessageDescriptor(hdr->nlmsg_type);
|
||||
auto msgDescMaybe = protocolDescr.getMessageDescriptor(hdr->nlmsg_type);
|
||||
const auto msgDetails =
|
||||
protocols::MessageDescriptor::getMessageDetails(msgDescMaybe, hdr->nlmsg_type);
|
||||
|
||||
if (msgDescMaybe.has_value()) msgDescMaybe->get().track(hdr);
|
||||
|
||||
ss << "nlmsg{" << protocolDescr.getName() << " ";
|
||||
|
||||
ss << "hdr={";
|
||||
|
|
|
@ -56,15 +56,17 @@ const AttributeMap& MessageDescriptor::getAttributeMap() const {
|
|||
|
||||
MessageDescriptor::MessageDetails MessageDescriptor::getMessageDetails(nlmsgtype_t msgtype) const {
|
||||
const auto it = mMessageDetails.find(msgtype);
|
||||
if (it == mMessageDetails.end()) return {std::to_string(msgtype), MessageGenre::UNKNOWN};
|
||||
if (it == mMessageDetails.end()) return {std::to_string(msgtype), MessageGenre::Unknown};
|
||||
return it->second;
|
||||
}
|
||||
|
||||
MessageDescriptor::MessageDetails MessageDescriptor::getMessageDetails(
|
||||
const std::optional<std::reference_wrapper<const MessageDescriptor>>& msgDescMaybe,
|
||||
const std::optional<std::reference_wrapper<MessageDescriptor>>& msgDescMaybe,
|
||||
nlmsgtype_t msgtype) {
|
||||
if (msgDescMaybe.has_value()) return msgDescMaybe->get().getMessageDetails(msgtype);
|
||||
return {std::to_string(msgtype), protocols::MessageGenre::UNKNOWN};
|
||||
return {std::to_string(msgtype), protocols::MessageGenre::Unknown};
|
||||
}
|
||||
|
||||
void MessageDescriptor::track(const Buffer<nlmsghdr> /* hdr */) {}
|
||||
|
||||
} // namespace android::nl::protocols
|
||||
|
|
|
@ -54,17 +54,64 @@ class AttributeMap : private std::map<std::optional<nlattrtype_t>, AttributeDefi
|
|||
*/
|
||||
struct AttributeDefinition {
|
||||
enum class DataType : uint8_t {
|
||||
/**
|
||||
* Binary blob (or attribute of unknown type).
|
||||
*/
|
||||
Raw,
|
||||
|
||||
/**
|
||||
* Nested attribute (with or without NLA_F_NESTED).
|
||||
*/
|
||||
Nested,
|
||||
|
||||
/**
|
||||
* Non-null terminated string.
|
||||
*
|
||||
* The length of the string is determined by the size of an attribute.
|
||||
*/
|
||||
String,
|
||||
|
||||
/**
|
||||
* Null terminated string.
|
||||
*/
|
||||
StringNul,
|
||||
|
||||
/**
|
||||
* Unsigned integer of size 8, 16, 32 or 64 bits.
|
||||
*/
|
||||
Uint,
|
||||
|
||||
/**
|
||||
* Structure which printer is defined in ops ToStream variant.
|
||||
*/
|
||||
Struct,
|
||||
|
||||
/**
|
||||
* Flag attribute.
|
||||
*
|
||||
* The attribute doesn't have any contents. The flag is set when the attribute is present,
|
||||
* it's not when it's absent from attribute list.
|
||||
*/
|
||||
Flag,
|
||||
};
|
||||
enum class Flags : uint8_t {
|
||||
Verbose = (1 << 0),
|
||||
};
|
||||
using ToStream = std::function<void(std::stringstream& ss, const Buffer<nlattr> attr)>;
|
||||
|
||||
std::string name;
|
||||
DataType dataType = DataType::Raw;
|
||||
std::variant<AttributeMap, ToStream> ops = AttributeMap{};
|
||||
|
||||
/**
|
||||
* Attribute flags.
|
||||
*
|
||||
* It's not really a bitmask flag set (since you are not supposed to compare enum class by
|
||||
* bitmask), but std::set<Flags> bumps compile time from 16s to 3m. Let's leave it as-is for
|
||||
* now and revisit if we get some flags that can be used in pairs. When it happens, review all
|
||||
* uses of the flags field to include the "&" operator and not "==".
|
||||
*/
|
||||
Flags flags = {};
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -74,11 +121,11 @@ struct AttributeDefinition {
|
|||
* section in linux/netlink.h.
|
||||
*/
|
||||
enum class MessageGenre {
|
||||
UNKNOWN,
|
||||
GET,
|
||||
NEW,
|
||||
DELETE,
|
||||
ACK,
|
||||
Unknown,
|
||||
Get,
|
||||
New,
|
||||
Delete,
|
||||
Ack,
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -103,8 +150,15 @@ class MessageDescriptor {
|
|||
MessageDetails getMessageDetails(nlmsgtype_t msgtype) const;
|
||||
virtual void dataToStream(std::stringstream& ss, const Buffer<nlmsghdr> hdr) const = 0;
|
||||
|
||||
/**
|
||||
* Message tracking for stateful protocols (such as NETLINK_GENERIC).
|
||||
*
|
||||
* \param hdr Message to track
|
||||
*/
|
||||
virtual void track(const Buffer<nlmsghdr> hdr);
|
||||
|
||||
static MessageDetails getMessageDetails(
|
||||
const std::optional<std::reference_wrapper<const MessageDescriptor>>& msgDescMaybe,
|
||||
const std::optional<std::reference_wrapper<MessageDescriptor>>& msgDescMaybe,
|
||||
nlmsgtype_t msgtype);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -32,7 +32,7 @@ const std::string& NetlinkProtocol::getName() const {
|
|||
return mName;
|
||||
}
|
||||
|
||||
const std::optional<std::reference_wrapper<const MessageDescriptor>>
|
||||
const std::optional<std::reference_wrapper<MessageDescriptor>>
|
||||
NetlinkProtocol::getMessageDescriptor(nlmsgtype_t nlmsg_type) {
|
||||
if (mMessageDescrs.count(nlmsg_type) == 0) return std::nullopt;
|
||||
return *mMessageDescrs.find(nlmsg_type)->second;
|
||||
|
@ -41,7 +41,7 @@ NetlinkProtocol::getMessageDescriptor(nlmsgtype_t nlmsg_type) {
|
|||
NetlinkProtocol::MessageDescriptorMap NetlinkProtocol::toMap(
|
||||
const NetlinkProtocol::MessageDescriptorList& descrs, int protocol) {
|
||||
MessageDescriptorMap map;
|
||||
for (const auto& descr : descrs) {
|
||||
for (auto& descr : descrs) {
|
||||
for (const auto& [mtype, mdet] : descr->getMessageDetailsMap()) {
|
||||
map.emplace(mtype, descr);
|
||||
}
|
||||
|
|
|
@ -40,17 +40,17 @@ class NetlinkProtocol {
|
|||
|
||||
const std::string& getName() const;
|
||||
|
||||
virtual const std::optional<std::reference_wrapper<const MessageDescriptor>>
|
||||
getMessageDescriptor(nlmsgtype_t nlmsg_type);
|
||||
virtual const std::optional<std::reference_wrapper<MessageDescriptor>> getMessageDescriptor(
|
||||
nlmsgtype_t nlmsg_type);
|
||||
|
||||
protected:
|
||||
typedef std::vector<std::shared_ptr<const MessageDescriptor>> MessageDescriptorList;
|
||||
typedef std::vector<std::shared_ptr<MessageDescriptor>> MessageDescriptorList;
|
||||
|
||||
NetlinkProtocol(int protocol, const std::string& name,
|
||||
const MessageDescriptorList&& messageDescrs);
|
||||
|
||||
private:
|
||||
typedef std::map<nlmsgtype_t, std::shared_ptr<const MessageDescriptor>> MessageDescriptorMap;
|
||||
typedef std::map<nlmsgtype_t, std::shared_ptr<MessageDescriptor>> MessageDescriptorMap;
|
||||
|
||||
const int mProtocol;
|
||||
const std::string mName;
|
||||
|
|
|
@ -20,9 +20,9 @@ namespace android::nl::protocols::base {
|
|||
|
||||
// clang-format off
|
||||
Empty::Empty() : MessageDefinition<char>("nlmsg", {
|
||||
{NLMSG_NOOP, {"NOOP", MessageGenre::UNKNOWN}},
|
||||
{NLMSG_DONE, {"DONE", MessageGenre::UNKNOWN}},
|
||||
{NLMSG_OVERRUN, {"OVERRUN", MessageGenre::UNKNOWN}},
|
||||
{NLMSG_NOOP, {"NOOP", MessageGenre::Unknown}},
|
||||
{NLMSG_DONE, {"DONE", MessageGenre::Unknown}},
|
||||
{NLMSG_OVERRUN, {"OVERRUN", MessageGenre::Unknown}},
|
||||
}) {}
|
||||
// clang-format on
|
||||
|
||||
|
|
|
@ -20,13 +20,15 @@
|
|||
|
||||
#include <libnl++/printer.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace android::nl::protocols::base {
|
||||
|
||||
using DataType = AttributeDefinition::DataType;
|
||||
|
||||
// clang-format off
|
||||
Error::Error(int protocol) : MessageDefinition<nlmsgerr>("nlmsg", {
|
||||
{NLMSG_ERROR, {"ERROR", MessageGenre::ACK}},
|
||||
{NLMSG_ERROR, {"ERROR", MessageGenre::Ack}},
|
||||
}, {
|
||||
{NLMSGERR_ATTR_MSG, {"MSG", DataType::String}},
|
||||
{NLMSGERR_ATTR_OFFS, {"OFFS", DataType::Uint}},
|
||||
|
@ -34,9 +36,156 @@ Error::Error(int protocol) : MessageDefinition<nlmsgerr>("nlmsg", {
|
|||
}), mProtocol(protocol) {}
|
||||
// clang-format on
|
||||
|
||||
std::map<int, std::string> errnoNames{
|
||||
{EPERM, "EPERM"}, // Operation not permitted
|
||||
{ENOENT, "ENOENT"}, // No such file or directory
|
||||
{ESRCH, "ESRCH"}, // No such process
|
||||
{EINTR, "EINTR"}, // Interrupted system call
|
||||
{EIO, "EIO"}, // I/O error
|
||||
{ENXIO, "ENXIO"}, // No such device or address
|
||||
{E2BIG, "E2BIG"}, // Argument list too long
|
||||
{ENOEXEC, "ENOEXEC"}, // Exec format error
|
||||
{EBADF, "EBADF"}, // Bad file number
|
||||
{ECHILD, "ECHILD"}, // No child processes
|
||||
{EAGAIN, "EAGAIN"}, // Try again
|
||||
{ENOMEM, "ENOMEM"}, // Out of memory
|
||||
{EACCES, "EACCES"}, // Permission denied
|
||||
{EFAULT, "EFAULT"}, // Bad address
|
||||
{ENOTBLK, "ENOTBLK"}, // Block device required
|
||||
{EBUSY, "EBUSY"}, // Device or resource busy
|
||||
{EEXIST, "EEXIST"}, // File exists
|
||||
{EXDEV, "EXDEV"}, // Cross-device link
|
||||
{ENODEV, "ENODEV"}, // No such device
|
||||
{ENOTDIR, "ENOTDIR"}, // Not a directory
|
||||
{EISDIR, "EISDIR"}, // Is a directory
|
||||
{EINVAL, "EINVAL"}, // Invalid argument
|
||||
{ENFILE, "ENFILE"}, // File table overflow
|
||||
{EMFILE, "EMFILE"}, // Too many open files
|
||||
{ENOTTY, "ENOTTY"}, // Not a typewriter
|
||||
{ETXTBSY, "ETXTBSY"}, // Text file busy
|
||||
{EFBIG, "EFBIG"}, // File too large
|
||||
{ENOSPC, "ENOSPC"}, // No space left on device
|
||||
{ESPIPE, "ESPIPE"}, // Illegal seek
|
||||
{EROFS, "EROFS"}, // Read-only file system
|
||||
{EMLINK, "EMLINK"}, // Too many links
|
||||
{EPIPE, "EPIPE"}, // Broken pipe
|
||||
{EDOM, "EDOM"}, // Math argument out of domain of func
|
||||
{ERANGE, "ERANGE"}, // Math result not representable
|
||||
{EDEADLK, "EDEADLK"}, // Resource deadlock would occur
|
||||
{ENAMETOOLONG, "ENAMETOOLONG"}, // File name too long
|
||||
{ENOLCK, "ENOLCK"}, // No record locks available
|
||||
{ENOSYS, "ENOSYS"}, // Invalid system call number
|
||||
{ENOTEMPTY, "ENOTEMPTY"}, // Directory not empty
|
||||
{ELOOP, "ELOOP"}, // Too many symbolic links encountered
|
||||
{ENOMSG, "ENOMSG"}, // No message of desired type
|
||||
{EIDRM, "EIDRM"}, // Identifier removed
|
||||
{ECHRNG, "ECHRNG"}, // Channel number out of range
|
||||
{EL2NSYNC, "EL2NSYNC"}, // Level 2 not synchronized
|
||||
{EL3HLT, "EL3HLT"}, // Level 3 halted
|
||||
{EL3RST, "EL3RST"}, // Level 3 reset
|
||||
{ELNRNG, "ELNRNG"}, // Link number out of range
|
||||
{EUNATCH, "EUNATCH"}, // Protocol driver not attached
|
||||
{ENOCSI, "ENOCSI"}, // No CSI structure available
|
||||
{EL2HLT, "EL2HLT"}, // Level 2 halted
|
||||
{EBADE, "EBADE"}, // Invalid exchange
|
||||
{EBADR, "EBADR"}, // Invalid request descriptor
|
||||
{EXFULL, "EXFULL"}, // Exchange full
|
||||
{ENOANO, "ENOANO"}, // No anode
|
||||
{EBADRQC, "EBADRQC"}, // Invalid request code
|
||||
{EBADSLT, "EBADSLT"}, // Invalid slot
|
||||
{EBFONT, "EBFONT"}, // Bad font file format
|
||||
{ENOSTR, "ENOSTR"}, // Device not a stream
|
||||
{ENODATA, "ENODATA"}, // No data available
|
||||
{ETIME, "ETIME"}, // Timer expired
|
||||
{ENOSR, "ENOSR"}, // Out of streams resources
|
||||
{ENONET, "ENONET"}, // Machine is not on the network
|
||||
{ENOPKG, "ENOPKG"}, // Package not installed
|
||||
{EREMOTE, "EREMOTE"}, // Object is remote
|
||||
{ENOLINK, "ENOLINK"}, // Link has been severed
|
||||
{EADV, "EADV"}, // Advertise error
|
||||
{ESRMNT, "ESRMNT"}, // Srmount error
|
||||
{ECOMM, "ECOMM"}, // Communication error on send
|
||||
{EPROTO, "EPROTO"}, // Protocol error
|
||||
{EMULTIHOP, "EMULTIHOP"}, // Multihop attempted
|
||||
{EDOTDOT, "EDOTDOT"}, // RFS specific error
|
||||
{EBADMSG, "EBADMSG"}, // Not a data message
|
||||
{EOVERFLOW, "EOVERFLOW"}, // Value too large for defined data type
|
||||
{ENOTUNIQ, "ENOTUNIQ"}, // Name not unique on network
|
||||
{EBADFD, "EBADFD"}, // File descriptor in bad state
|
||||
{EREMCHG, "EREMCHG"}, // Remote address changed
|
||||
{ELIBACC, "ELIBACC"}, // Can not access a needed shared library
|
||||
{ELIBBAD, "ELIBBAD"}, // Accessing a corrupted shared library
|
||||
{ELIBSCN, "ELIBSCN"}, // .lib section in a.out corrupted
|
||||
{ELIBMAX, "ELIBMAX"}, // Attempting to link in too many shared libraries
|
||||
{ELIBEXEC, "ELIBEXEC"}, // Cannot exec a shared library directly
|
||||
{EILSEQ, "EILSEQ"}, // Illegal byte sequence
|
||||
{ERESTART, "ERESTART"}, // Interrupted system call should be restarted
|
||||
{ESTRPIPE, "ESTRPIPE"}, // Streams pipe error
|
||||
{EUSERS, "EUSERS"}, // Too many users
|
||||
{ENOTSOCK, "ENOTSOCK"}, // Socket operation on non-socket
|
||||
{EDESTADDRREQ, "EDESTADDRREQ"}, // Destination address required
|
||||
{EMSGSIZE, "EMSGSIZE"}, // Message too long
|
||||
{EPROTOTYPE, "EPROTOTYPE"}, // Protocol wrong type for socket
|
||||
{ENOPROTOOPT, "ENOPROTOOPT"}, // Protocol not available
|
||||
{EPROTONOSUPPORT, "EPROTONOSUPPORT"}, // Protocol not supported
|
||||
{ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT"}, // Socket type not supported
|
||||
{EOPNOTSUPP, "EOPNOTSUPP"}, // Operation not supported on transport endpoint
|
||||
{EPFNOSUPPORT, "EPFNOSUPPORT"}, // Protocol family not supported
|
||||
{EAFNOSUPPORT, "EAFNOSUPPORT"}, // Address family not supported by protocol
|
||||
{EADDRINUSE, "EADDRINUSE"}, // Address already in use
|
||||
{EADDRNOTAVAIL, "EADDRNOTAVAIL"}, // Cannot assign requested address
|
||||
{ENETDOWN, "ENETDOWN"}, // Network is down
|
||||
{ENETUNREACH, "ENETUNREACH"}, // Network is unreachable
|
||||
{ENETRESET, "ENETRESET"}, // Network dropped connection because of reset
|
||||
{ECONNABORTED, "ECONNABORTED"}, // Software caused connection abort
|
||||
{ECONNRESET, "ECONNRESET"}, // Connection reset by peer
|
||||
{ENOBUFS, "ENOBUFS"}, // No buffer space available
|
||||
{EISCONN, "EISCONN"}, // Transport endpoint is already connected
|
||||
{ENOTCONN, "ENOTCONN"}, // Transport endpoint is not connected
|
||||
{ESHUTDOWN, "ESHUTDOWN"}, // Cannot send after transport endpoint shutdown
|
||||
{ETOOMANYREFS, "ETOOMANYREFS"}, // Too many references: cannot splice
|
||||
{ETIMEDOUT, "ETIMEDOUT"}, // Connection timed out
|
||||
{ECONNREFUSED, "ECONNREFUSED"}, // Connection refused
|
||||
{EHOSTDOWN, "EHOSTDOWN"}, // Host is down
|
||||
{EHOSTUNREACH, "EHOSTUNREACH"}, // No route to host
|
||||
{EALREADY, "EALREADY"}, // Operation already in progress
|
||||
{EINPROGRESS, "EINPROGRESS"}, // Operation now in progress
|
||||
{ESTALE, "ESTALE"}, // Stale file handle
|
||||
{EUCLEAN, "EUCLEAN"}, // Structure needs cleaning
|
||||
{ENOTNAM, "ENOTNAM"}, // Not a XENIX named type file
|
||||
{ENAVAIL, "ENAVAIL"}, // No XENIX semaphores available
|
||||
{EISNAM, "EISNAM"}, // Is a named type file
|
||||
{EREMOTEIO, "EREMOTEIO"}, // Remote I/O error
|
||||
{EDQUOT, "EDQUOT"}, // Quota exceeded
|
||||
{ENOMEDIUM, "ENOMEDIUM"}, // No medium found
|
||||
{EMEDIUMTYPE, "EMEDIUMTYPE"}, // Wrong medium type
|
||||
{ECANCELED, "ECANCELED"}, // Operation Canceled
|
||||
{ENOKEY, "ENOKEY"}, // Required key not available
|
||||
{EKEYEXPIRED, "EKEYEXPIRED"}, // Key has expired
|
||||
{EKEYREVOKED, "EKEYREVOKED"}, // Key has been revoked
|
||||
{EKEYREJECTED, "EKEYREJECTED"}, // Key was rejected by service
|
||||
{EOWNERDEAD, "EOWNERDEAD"}, // Owner died
|
||||
{ENOTRECOVERABLE, "ENOTRECOVERABLE"}, // State not recoverable
|
||||
{ERFKILL, "ERFKILL"}, // Operation not possible due to RF-kill
|
||||
{EHWPOISON, "EHWPOISON"}, // Memory page has hardware error
|
||||
|
||||
// Duplicates: EWOULDBLOCK (Operation would block), EDEADLOCK
|
||||
};
|
||||
|
||||
void Error::toStream(std::stringstream& ss, const nlmsgerr& data) const {
|
||||
ss << "nlmsgerr{error=" << data.error
|
||||
<< ", msg=" << toString({&data.msg, sizeof(data.msg)}, mProtocol, false) << "}";
|
||||
ss << "nlmsgerr{";
|
||||
if (data.error == 0) {
|
||||
ss << "ACK";
|
||||
} else {
|
||||
ss << "error=";
|
||||
const auto nameIt = errnoNames.find(-data.error);
|
||||
if (nameIt == errnoNames.end()) {
|
||||
ss << data.error;
|
||||
} else {
|
||||
ss << nameIt->second;
|
||||
}
|
||||
}
|
||||
ss << ", msg=" << toString({&data.msg, sizeof(data.msg)}, mProtocol, false) << "}";
|
||||
}
|
||||
|
||||
} // namespace android::nl::protocols::base
|
||||
|
|
|
@ -16,12 +16,19 @@
|
|||
|
||||
#include "Ctrl.h"
|
||||
|
||||
#include "families/Nl80211.h"
|
||||
|
||||
#include <libnl++/Message.h>
|
||||
|
||||
namespace android::nl::protocols::generic {
|
||||
|
||||
using DataType = AttributeDefinition::DataType;
|
||||
using Flags = AttributeDefinition::Flags;
|
||||
|
||||
// clang-format off
|
||||
Ctrl::Ctrl() : GenericMessageBase(GENL_ID_CTRL, "ID_CTRL", {
|
||||
Ctrl::Ctrl(Generic::FamilyRegister& familyRegister)
|
||||
: GenericMessageBase(GENL_ID_CTRL, "ID_CTRL",
|
||||
{
|
||||
{CTRL_CMD_NEWFAMILY, "NEWFAMILY"},
|
||||
{CTRL_CMD_DELFAMILY, "DELFAMILY"},
|
||||
{CTRL_CMD_GETFAMILY, "GETFAMILY"},
|
||||
|
@ -33,7 +40,7 @@ Ctrl::Ctrl() : GenericMessageBase(GENL_ID_CTRL, "ID_CTRL", {
|
|||
{CTRL_CMD_GETMCAST_GRP, "GETMCAST_GRP"},
|
||||
}, {
|
||||
{CTRL_ATTR_FAMILY_ID, {"FAMILY_ID", DataType::Uint}},
|
||||
{CTRL_ATTR_FAMILY_NAME, {"FAMILY_NAME", DataType::String}},
|
||||
{CTRL_ATTR_FAMILY_NAME, {"FAMILY_NAME", DataType::StringNul}},
|
||||
{CTRL_ATTR_VERSION, {"VERSION", DataType::Uint}},
|
||||
{CTRL_ATTR_HDRSIZE, {"HDRSIZE", DataType::Uint}},
|
||||
{CTRL_ATTR_MAXATTR, {"MAXATTR", DataType::Uint}},
|
||||
|
@ -42,14 +49,31 @@ Ctrl::Ctrl() : GenericMessageBase(GENL_ID_CTRL, "ID_CTRL", {
|
|||
{CTRL_ATTR_OP_ID, {"ID", DataType::Uint}},
|
||||
{CTRL_ATTR_OP_FLAGS, {"FLAGS", DataType::Uint}},
|
||||
}}},
|
||||
}}},
|
||||
}, Flags::Verbose}},
|
||||
{CTRL_ATTR_MCAST_GROUPS, {"MCAST_GROUPS", DataType::Nested, AttributeMap{
|
||||
{std::nullopt, {"GRP", DataType::Nested, AttributeMap{
|
||||
{CTRL_ATTR_MCAST_GRP_NAME, {"NAME", DataType::String}},
|
||||
{CTRL_ATTR_MCAST_GRP_NAME, {"NAME", DataType::StringNul}},
|
||||
{CTRL_ATTR_MCAST_GRP_ID, {"ID", DataType::Uint}},
|
||||
}}},
|
||||
}}},
|
||||
}) {}
|
||||
}), mFamilyRegister(familyRegister) {}
|
||||
// clang-format on
|
||||
|
||||
void Ctrl::track(const Buffer<nlmsghdr> hdr) {
|
||||
const auto msgMaybe = Message<genlmsghdr>::parse(hdr, {GENL_ID_CTRL});
|
||||
if (!msgMaybe.has_value()) return;
|
||||
const auto msg = *msgMaybe;
|
||||
|
||||
if (msg->cmd != CTRL_CMD_NEWFAMILY) return;
|
||||
const auto familyId = msg.attributes.get<uint16_t>(CTRL_ATTR_FAMILY_ID);
|
||||
const auto familyName = msg.attributes.get<std::string>(CTRL_ATTR_FAMILY_NAME);
|
||||
|
||||
/* For now, we support just a single family. But if you add more, please define proper
|
||||
* abstraction and not hardcode every name and class here.
|
||||
*/
|
||||
if (familyName == "nl80211") {
|
||||
mFamilyRegister[familyId] = std::make_shared<families::Nl80211>(familyId);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace android::nl::protocols::generic
|
||||
|
|
|
@ -16,13 +16,19 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "Generic.h"
|
||||
#include "GenericMessageBase.h"
|
||||
|
||||
namespace android::nl::protocols::generic {
|
||||
|
||||
class Ctrl : public GenericMessageBase {
|
||||
public:
|
||||
Ctrl();
|
||||
Ctrl(Generic::FamilyRegister& familyRegister);
|
||||
|
||||
void track(const Buffer<nlmsghdr> hdr) override;
|
||||
|
||||
private:
|
||||
Generic::FamilyRegister& mFamilyRegister;
|
||||
};
|
||||
|
||||
} // namespace android::nl::protocols::generic
|
||||
|
|
|
@ -21,11 +21,12 @@
|
|||
|
||||
namespace android::nl::protocols::generic {
|
||||
|
||||
Generic::Generic() : NetlinkProtocol(NETLINK_GENERIC, "GENERIC", {std::make_shared<Ctrl>()}) {}
|
||||
Generic::Generic()
|
||||
: NetlinkProtocol(NETLINK_GENERIC, "GENERIC", {std::make_shared<Ctrl>(mFamilyRegister)}) {}
|
||||
|
||||
const std::optional<std::reference_wrapper<const MessageDescriptor>> Generic::getMessageDescriptor(
|
||||
const std::optional<std::reference_wrapper<MessageDescriptor>> Generic::getMessageDescriptor(
|
||||
nlmsgtype_t nlmsg_type) {
|
||||
const auto desc = NetlinkProtocol::getMessageDescriptor(nlmsg_type);
|
||||
auto desc = NetlinkProtocol::getMessageDescriptor(nlmsg_type);
|
||||
if (desc.has_value()) return desc;
|
||||
|
||||
auto it = mFamilyRegister.find(nlmsg_type);
|
||||
|
|
|
@ -25,13 +25,15 @@ namespace android::nl::protocols::generic {
|
|||
*/
|
||||
class Generic : public NetlinkProtocol {
|
||||
public:
|
||||
typedef std::map<nlmsgtype_t, std::shared_ptr<MessageDescriptor>> FamilyRegister;
|
||||
|
||||
Generic();
|
||||
|
||||
const std::optional<std::reference_wrapper<const MessageDescriptor>> getMessageDescriptor(
|
||||
const std::optional<std::reference_wrapper<MessageDescriptor>> getMessageDescriptor(
|
||||
nlmsgtype_t nlmsg_type);
|
||||
|
||||
private:
|
||||
std::map<nlmsgtype_t, std::shared_ptr<const MessageDescriptor>> mFamilyRegister;
|
||||
FamilyRegister mFamilyRegister;
|
||||
};
|
||||
|
||||
} // namespace android::nl::protocols::generic
|
||||
|
|
|
@ -22,16 +22,27 @@ GenericMessageBase::GenericMessageBase(
|
|||
nlmsgtype_t msgtype, const std::string&& msgname,
|
||||
const std::initializer_list<GenericCommandNameMap::value_type> commandNames,
|
||||
const std::initializer_list<AttributeMap::value_type> attrTypes)
|
||||
: MessageDefinition<genlmsghdr>(msgname, {{msgtype, {msgname, MessageGenre::UNKNOWN}}},
|
||||
: MessageDefinition<genlmsghdr>(msgname, {{msgtype, {msgname, MessageGenre::Unknown}}},
|
||||
attrTypes),
|
||||
mCommandNames(commandNames) {}
|
||||
|
||||
void GenericMessageBase::toStream(std::stringstream& ss, const genlmsghdr& data) const {
|
||||
const auto commandNameIt = mCommandNames.find(data.cmd);
|
||||
const auto commandName = (commandNameIt == mCommandNames.end())
|
||||
? std::nullopt
|
||||
: std::optional<std::string>(commandNameIt->second);
|
||||
|
||||
if (commandName.has_value() && data.version == 1 && data.reserved == 0) {
|
||||
// short version
|
||||
ss << *commandName;
|
||||
return;
|
||||
}
|
||||
|
||||
ss << "genlmsghdr{";
|
||||
if (mCommandNames.count(data.cmd) == 0) {
|
||||
if (commandName.has_value()) {
|
||||
ss << "cmd=" << unsigned(data.cmd);
|
||||
} else {
|
||||
ss << "cmd=" << mCommandNames.find(data.cmd)->second;
|
||||
ss << "cmd=" << *commandName;
|
||||
}
|
||||
ss << ", version=" << unsigned(data.version);
|
||||
if (data.reserved != 0) ss << ", reserved=" << data.reserved;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../GenericMessageBase.h"
|
||||
|
||||
namespace android::nl::protocols::generic::families {
|
||||
|
||||
class Nl80211 : public GenericMessageBase {
|
||||
public:
|
||||
Nl80211(nlmsgtype_t familyId);
|
||||
};
|
||||
|
||||
} // namespace android::nl::protocols::generic::families
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "Link.h"
|
||||
|
||||
#include "../structs.h"
|
||||
#include "structs.h"
|
||||
|
||||
#include <net/if.h>
|
||||
|
@ -26,9 +27,9 @@ using DataType = AttributeDefinition::DataType;
|
|||
|
||||
// clang-format off
|
||||
Link::Link() : MessageDefinition<ifinfomsg>("link", {
|
||||
{RTM_NEWLINK, {"NEWLINK", MessageGenre::NEW}},
|
||||
{RTM_DELLINK, {"DELLINK", MessageGenre::DELETE}},
|
||||
{RTM_GETLINK, {"GETLINK", MessageGenre::GET}},
|
||||
{RTM_NEWLINK, {"NEWLINK", MessageGenre::New}},
|
||||
{RTM_DELLINK, {"DELLINK", MessageGenre::Delete}},
|
||||
{RTM_GETLINK, {"GETLINK", MessageGenre::Get}},
|
||||
}, {
|
||||
{IFLA_ADDRESS, {"ADDRESS"}},
|
||||
{IFLA_BROADCAST, {"BROADCAST"}},
|
||||
|
|
|
@ -30,16 +30,6 @@ void mapToStream(std::stringstream& ss, const Buffer<nlattr> attr);
|
|||
// ifla_cacheinfo
|
||||
void ifla_cacheinfoToStream(std::stringstream& ss, const Buffer<nlattr> attr);
|
||||
|
||||
template <typename T>
|
||||
void arrayToStream(std::stringstream& ss, const Buffer<nlattr> attr) {
|
||||
ss << '{';
|
||||
for (const auto it : attr.data<T>().getRaw()) {
|
||||
ss << it << ',';
|
||||
}
|
||||
ss.seekp(-1, std::ios_base::cur);
|
||||
ss << '}';
|
||||
}
|
||||
|
||||
// rtnl_link_stats or rtnl_link_stats64
|
||||
template <typename T>
|
||||
void statsToStream(std::stringstream& ss, const Buffer<nlattr> attr) {
|
||||
|
|
33
automotive/can/1.0/default/libnl++/protocols/structs.h
Normal file
33
automotive/can/1.0/default/libnl++/protocols/structs.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright (C) 2020 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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace android::nl::protocols {
|
||||
|
||||
template <typename T>
|
||||
void arrayToStream(std::stringstream& ss, const Buffer<nlattr> attr) {
|
||||
ss << '{';
|
||||
for (const auto it : attr.data<T>().getRaw()) {
|
||||
ss << it << ',';
|
||||
}
|
||||
ss.seekp(-1, std::ios_base::cur);
|
||||
ss << '}';
|
||||
}
|
||||
|
||||
} // namespace android::nl::protocols
|
Loading…
Reference in a new issue