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

Commit a7287af8 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implement MessageMutator and FamilyTracker"

parents 1fd4b9d0 71412f40
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ cc_library_static {
        "protocols/common/Empty.cpp",
        "protocols/common/Error.cpp",
        "protocols/generic/Ctrl.cpp",
        "protocols/generic/FamilyTracker.cpp",
        "protocols/generic/Generic.cpp",
        "protocols/generic/GenericMessageBase.cpp",
        "protocols/generic/Unknown.cpp",
@@ -34,6 +35,7 @@ cc_library_static {
        "protocols/all.cpp",
        "Attributes.cpp",
        "MessageFactory.cpp",
        "MessageMutator.cpp",
        "Socket.cpp",
        "common.cpp",
        "printer.cpp",
+50 −0
Original line number Diff line number Diff line
/*
 * 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.
 */

#include <libnl++/MessageMutator.h>

namespace android::nl {

MessageMutator::MessageMutator(nlmsghdr* buffer, size_t totalLen)
    : mConstBuffer(buffer, totalLen), mMutableBuffer(buffer) {
    CHECK(totalLen >= sizeof(nlmsghdr));
}

nlmsghdr* MessageMutator::operator->() const {
    return mMutableBuffer;
}

MessageMutator::operator Buffer<nlmsghdr>() const {
    return mConstBuffer;
}

uint64_t MessageMutator::read(Buffer<nlattr> attr) const {
    return attr.data<uint64_t>().copyFirst();
}

void MessageMutator::write(Buffer<nlattr> attr, uint64_t val) const {
    const auto attrData = attr.data<uint64_t>();
    const auto offset = mConstBuffer.getOffset(attrData);
    CHECK(offset.has_value()) << "Trying to write attribute that's not a member of this message";

    const auto writeableBuffer = reinterpret_cast<uint8_t*>(mMutableBuffer) + *offset;
    const auto attrSize = attrData.getRaw().len();

    if (attrSize > sizeof(val)) memset(writeableBuffer, 0, attrSize);
    memcpy(writeableBuffer, &val, std::min(sizeof(val), attrSize));
}

}  // namespace android::nl
+19 −4
Original line number Diff line number Diff line
@@ -93,14 +93,29 @@ class Attributes : private Buffer<nlattr> {
     */
    template <typename T>
    T get(nlattrtype_t attrtype) const {
        const auto& ind = index();
        const auto it = ind.find(attrtype);
        if (it == ind.end()) {
        const auto buffer = getBuffer(attrtype);
        if (!buffer.has_value()) {
            LOG(WARNING) << "Netlink attribute is missing: " << attrtype;
            return T{};
        }

        return parse<T>(it->second);
        return parse<T>(*buffer);
    }

    /**
     * Fetches underlying buffer of a given attribute.
     *
     * This is a low-level access method unlikely to be useful in most cases. Please consider
     * using #get instead.
     *
     * \param attrtype Attribute to fetch
     * \return Attribute buffer.
     */
    std::optional<Buffer<nlattr>> getBuffer(nlattrtype_t attrtype) const {
        const auto& ind = index();
        const auto it = ind.find(attrtype);
        if (it == ind.end()) return std::nullopt;
        return it->second;
    }

    /**
+12 −0
Original line number Diff line number Diff line
@@ -91,6 +91,18 @@ class Buffer {
        return {impl::data<const T, const D>(mData, offset), dataEnd()};
    }

    template <typename B>
    std::optional<uintptr_t> getOffset(Buffer<B> inner) const {
        const auto selfStart = uintptr_t(mData);
        const auto selfEnd = uintptr_t(mBufferEnd);
        const auto innerStart = uintptr_t(inner.mData);
        const auto innerEnd = uintptr_t(inner.mBufferEnd);

        if (innerStart < selfStart || innerEnd > selfEnd) return std::nullopt;

        return innerStart - selfStart;
    }

    class iterator {
      public:
        iterator() : mCurrent(nullptr, size_t(0)) {
+61 −0
Original line number Diff line number Diff line
/*
 * 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 <libnl++/Message.h>

namespace android::nl {

/**
 * In-place message mutator.
 *
 * Useful for making small changes (such as adjusting const-sized attributes or struct fields)
 * efficiently and in-place. However, if you need to rebuild the message (e.g. to modify variable
 * sized attributes or add/remove them), you need to use MessageFactory instead.
 */
class MessageMutator {
  public:
    /**
     * Construct message mutator object from editable buffer.
     */
    MessageMutator(nlmsghdr* buffer, size_t totalLen);

    nlmsghdr* operator->() const;
    operator Buffer<nlmsghdr>() const;

    /**
     * Read current attribute value.
     *
     * \param Read-only attribute buffer.
     * \returns Attribute value.
     */
    uint64_t read(Buffer<nlattr> attr) const;

    /**
     * Write new attribute value.
     *
     * \param Read-only attribute buffer.
     * \param val New value to set.
     */
    void write(Buffer<nlattr> attr, uint64_t val) const;

  private:
    const Buffer<nlmsghdr> mConstBuffer;
    nlmsghdr* mMutableBuffer;
};

}  // namespace android::nl
Loading