Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4b8f50c1 authored by Tomasz Wasilczyk's avatar Tomasz Wasilczyk
Browse files

Implement message kinds for flag printing

Bug: 162032964
Test: adb shell canhalctrl up test virtual vcan1
Change-Id: Ib71c928862b0d098cc698c09f2efdd72bf03d8b0
parent 3ab105b1
Loading
Loading
Loading
Loading
+3 −4
Original line number Diff line number Diff line
@@ -49,8 +49,8 @@ Socket::Socket(int protocol, unsigned pid, uint32_t groups) : mProtocol(protocol

bool Socket::send(const Buffer<nlmsghdr>& msg, const sockaddr_nl& sa) {
    if constexpr (kSuperVerbose) {
        LOG(VERBOSE) << (mFailed ? "(not) " : "") << "sending Netlink message ("  //
                     << msg->nlmsg_pid << " -> " << sa.nl_pid << "): " << toString(msg, mProtocol);
        LOG(VERBOSE) << (mFailed ? "(not) " : "") << "sending to " << sa.nl_pid << ": "
                     << toString(msg, mProtocol);
    }
    if (mFailed) return false;

@@ -97,8 +97,7 @@ std::pair<std::optional<Buffer<nlmsghdr>>, sockaddr_nl> Socket::receiveFrom(size

    Buffer<nlmsghdr> msg(reinterpret_cast<nlmsghdr*>(mReceiveBuffer.data()), bytesReceived);
    if constexpr (kSuperVerbose) {
        LOG(VERBOSE) << "received (" << sa.nl_pid << " -> " << msg->nlmsg_pid << "):"  //
                     << toString(msg, mProtocol);
        LOG(VERBOSE) << "received from " << sa.nl_pid << ": " << toString(msg, mProtocol);
    }
    return {msg, sa};
}
+1 −1
Original line number Diff line number Diff line
@@ -32,6 +32,6 @@ namespace android::nl {
 * \param printPayload True will stringify message data, false will only stringify the header(s).
 * \return Stringified message.
 */
std::string toString(const Buffer<nlmsghdr> hdr, int protocol, bool printPayload = false);
std::string toString(const Buffer<nlmsghdr> hdr, int protocol, bool printPayload = true);

}  // namespace android::nl
+33 −15
Original line number Diff line number Diff line
@@ -28,10 +28,10 @@

namespace android::nl {

static void flagsToStream(std::stringstream& ss, __u16 nlmsg_flags) {
static void flagsToStream(std::stringstream& ss, __u16 nlmsg_flags, protocols::MessageGenre genre) {
    bool first = true;
    auto printFlag = [&ss, &first, &nlmsg_flags](__u16 flag, const std::string& name) {
        if (!(nlmsg_flags & flag)) return;
        if ((nlmsg_flags & flag) != flag) return;
        nlmsg_flags &= ~flag;

        if (first) {
@@ -42,6 +42,7 @@ static void flagsToStream(std::stringstream& ss, __u16 nlmsg_flags) {

        ss << name;
    };

    printFlag(NLM_F_REQUEST, "REQUEST");
    printFlag(NLM_F_MULTI, "MULTI");
    printFlag(NLM_F_ACK, "ACK");
@@ -49,11 +50,29 @@ static void flagsToStream(std::stringstream& ss, __u16 nlmsg_flags) {
    printFlag(NLM_F_DUMP_INTR, "DUMP_INTR");
    printFlag(NLM_F_DUMP_FILTERED, "DUMP_FILTERED");

    // TODO(twasilczyk): print flags depending on request type
    printFlag(NLM_F_ROOT, "ROOT-REPLACE");
    printFlag(NLM_F_MATCH, "MATCH-EXCL");
    printFlag(NLM_F_ATOMIC, "ATOMIC-CREATE");
    switch (genre) {
        case protocols::MessageGenre::UNKNOWN:
            break;
        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:
            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:
            printFlag(NLM_F_NONREC, "NONREC");
            break;
        case protocols::MessageGenre::ACK:
            printFlag(NLM_F_CAPPED, "CAPPED");
            printFlag(NLM_F_ACK_TLVS, "ACK_TLVS");
            break;
    }

    if (nlmsg_flags != 0) {
        if (!first) ss << '|';
@@ -128,27 +147,26 @@ std::string toString(const Buffer<nlmsghdr> hdr, int protocol, bool printPayload
    }
    protocols::NetlinkProtocol& protocolDescr = *protocolMaybe;

    auto msgDescMaybe = protocolDescr.getMessageDescriptor(hdr->nlmsg_type);
    const auto msgTypeName = msgDescMaybe.has_value()
                                     ? msgDescMaybe->get().getMessageName(hdr->nlmsg_type)
                                     : std::to_string(hdr->nlmsg_type);
    const auto msgDescMaybe = protocolDescr.getMessageDescriptor(hdr->nlmsg_type);
    const auto msgDetails =
            protocols::MessageDescriptor::getMessageDetails(msgDescMaybe, hdr->nlmsg_type);

    ss << "nlmsg{" << protocolDescr.getName() << " ";

    ss << "hdr={";
    ss << "type=" << msgTypeName;
    ss << "type=" << msgDetails.name;
    if (hdr->nlmsg_flags != 0) {
        ss << ", flags=";
        flagsToStream(ss, hdr->nlmsg_flags);
        flagsToStream(ss, hdr->nlmsg_flags, msgDetails.genre);
    }
    if (hdr->nlmsg_seq != 0) ss << ", seq=" << hdr->nlmsg_seq;
    if (hdr->nlmsg_pid != 0) ss << ", pid=" << hdr->nlmsg_pid;
    ss << ", len=" << hdr->nlmsg_len;

    ss << ", crc=" << std::hex << std::setw(4) << crc16(hdr.data<uint8_t>()) << std::dec;
    ss << "} ";
    ss << '}';

    if (!printPayload) return ss.str();
    ss << ' ';

    if (!msgDescMaybe.has_value()) {
        toStream(ss, hdr.data<uint8_t>());
+15 −7
Original line number Diff line number Diff line
@@ -32,11 +32,12 @@ const AttributeDefinition AttributeMap::operator[](nlattrtype_t nla_type) const
    return find(nla_type)->second;
}

MessageDescriptor::MessageDescriptor(const std::string& name, const MessageTypeMap&& messageTypes,
MessageDescriptor::MessageDescriptor(const std::string& name,
                                     const MessageDetailsMap&& messageDetails,
                                     const AttributeMap&& attrTypes, size_t contentsSize)
    : mName(name),
      mContentsSize(contentsSize),
      mMessageTypes(messageTypes),
      mMessageDetails(messageDetails),
      mAttributeMap(attrTypes) {}

MessageDescriptor::~MessageDescriptor() {}
@@ -45,18 +46,25 @@ size_t MessageDescriptor::getContentsSize() const {
    return mContentsSize;
}

const MessageDescriptor::MessageTypeMap& MessageDescriptor::getMessageTypeMap() const {
    return mMessageTypes;
const MessageDescriptor::MessageDetailsMap& MessageDescriptor::getMessageDetailsMap() const {
    return mMessageDetails;
}

const AttributeMap& MessageDescriptor::getAttributeMap() const {
    return mAttributeMap;
}

const std::string MessageDescriptor::getMessageName(nlmsgtype_t msgtype) const {
    const auto it = mMessageTypes.find(msgtype);
    if (it == mMessageTypes.end()) return "?";
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};
    return it->second;
}

MessageDescriptor::MessageDetails MessageDescriptor::getMessageDetails(
        const std::optional<std::reference_wrapper<const MessageDescriptor>>& msgDescMaybe,
        nlmsgtype_t msgtype) {
    if (msgDescMaybe.has_value()) return msgDescMaybe->get().getMessageDetails(msgtype);
    return {std::to_string(msgtype), protocols::MessageGenre::UNKNOWN};
}

}  // namespace android::nl::protocols
+34 −11
Original line number Diff line number Diff line
@@ -67,31 +67,54 @@ struct AttributeDefinition {
    std::variant<AttributeMap, ToStream> ops = AttributeMap{};
};

/**
 * General message type's kind.
 *
 * For example, RTM_NEWLINK is a NEW kind. For details, please see "Flags values"
 * section in linux/netlink.h.
 */
enum class MessageGenre {
    UNKNOWN,
    GET,
    NEW,
    DELETE,
    ACK,
};

/**
 * Message family descriptor.
 *
 * Describes the structure of all message types with the same header and attributes.
 */
class MessageDescriptor {
  protected:
    typedef std::map<nlmsgtype_t, std::string> MessageTypeMap;

    MessageDescriptor(const std::string& name, const MessageTypeMap&& messageTypes,
                      const AttributeMap&& attrTypes, size_t contentsSize);
  public:
    struct MessageDetails {
        std::string name;
        MessageGenre genre;
    };
    typedef std::map<nlmsgtype_t, MessageDetails> MessageDetailsMap;

  public:
    virtual ~MessageDescriptor();

    size_t getContentsSize() const;
    const MessageTypeMap& getMessageTypeMap() const;
    const MessageDetailsMap& getMessageDetailsMap() const;
    const AttributeMap& getAttributeMap() const;
    const std::string getMessageName(nlmsgtype_t msgtype) const;
    MessageDetails getMessageDetails(nlmsgtype_t msgtype) const;
    virtual void dataToStream(std::stringstream& ss, const Buffer<nlmsghdr> hdr) const = 0;

    static MessageDetails getMessageDetails(
            const std::optional<std::reference_wrapper<const MessageDescriptor>>& msgDescMaybe,
            nlmsgtype_t msgtype);

  protected:
    MessageDescriptor(const std::string& name, const MessageDetailsMap&& messageDetails,
                      const AttributeMap&& attrTypes, size_t contentsSize);

  private:
    const std::string mName;
    const size_t mContentsSize;
    const MessageTypeMap mMessageTypes;
    const MessageDetailsMap mMessageDetails;
    const AttributeMap mAttributeMap;
};

@@ -103,11 +126,11 @@ class MessageDescriptor {
template <typename T>
class MessageDefinition : public MessageDescriptor {
  public:
    MessageDefinition(
    MessageDefinition(  //
            const std::string& name,
            const std::initializer_list<MessageDescriptor::MessageTypeMap::value_type> messageTypes,
            const std::initializer_list<MessageDescriptor::MessageDetailsMap::value_type> msgDet,
            const std::initializer_list<AttributeMap::value_type> attrTypes = {})
        : MessageDescriptor(name, messageTypes, attrTypes, sizeof(T)) {}
        : MessageDescriptor(name, msgDet, attrTypes, sizeof(T)) {}

    void dataToStream(std::stringstream& ss, const Buffer<nlmsghdr> hdr) const override {
        const auto& [ok, msg] = hdr.data<T>().getFirst();
Loading