1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <libnl++/MessageMutator.h>
18
19 namespace android::nl {
20
MessageMutator(nlmsghdr * buffer,size_t totalLen)21 MessageMutator::MessageMutator(nlmsghdr* buffer, size_t totalLen)
22 : mMutableBuffer(buffer), mTotalLen(totalLen) {
23 CHECK(totalLen >= sizeof(nlmsghdr));
24 }
25
operator ->() const26 nlmsghdr* MessageMutator::operator->() const {
27 return mMutableBuffer;
28 }
29
constBuffer() const30 Buffer<nlmsghdr> MessageMutator::constBuffer() const {
31 return {mMutableBuffer, mTotalLen};
32 }
33
operator Buffer<nlmsghdr>() const34 MessageMutator::operator Buffer<nlmsghdr>() const {
35 return constBuffer();
36 }
37
read(Buffer<nlattr> attr) const38 uint64_t MessageMutator::read(Buffer<nlattr> attr) const {
39 return attr.data<uint64_t>().copyFirst();
40 }
41
write(Buffer<nlattr> attr,uint64_t val) const42 void MessageMutator::write(Buffer<nlattr> attr, uint64_t val) const {
43 const auto attrData = attr.data<uint64_t>();
44 // TODO(b/177251183): deduplicate this code against fragment()
45 const auto offset = constBuffer().getOffset(attrData);
46 CHECK(offset.has_value()) << "Trying to write attribute that's not a member of this message";
47
48 const auto writeableBuffer = reinterpret_cast<uint8_t*>(mMutableBuffer) + *offset;
49 const auto attrSize = attrData.getRaw().len();
50
51 if (attrSize > sizeof(val)) memset(writeableBuffer, 0, attrSize);
52 memcpy(writeableBuffer, &val, std::min(sizeof(val), attrSize));
53 }
54
fragment(Buffer<nlmsghdr> buf) const55 MessageMutator MessageMutator::fragment(Buffer<nlmsghdr> buf) const {
56 const auto offset = constBuffer().getOffset(buf);
57 CHECK(offset.has_value()) << "Trying to modify a fragment outside of buffer range";
58
59 const auto writeableBuffer = reinterpret_cast<nlmsghdr*>(uintptr_t(mMutableBuffer) + *offset);
60 const auto len = buf.getRaw().len();
61 CHECK(len <= mTotalLen - *offset);
62
63 return {writeableBuffer, len};
64 }
65
begin() const66 MessageMutator::iterator MessageMutator::begin() const {
67 return {*this, constBuffer().begin()};
68 }
69
end() const70 MessageMutator::iterator MessageMutator::end() const {
71 return {*this, constBuffer().end()};
72 }
73
iterator(const MessageMutator & container,Buffer<nlmsghdr>::iterator current)74 MessageMutator::iterator::iterator(const MessageMutator& container,
75 Buffer<nlmsghdr>::iterator current)
76 : mContainer(container), mCurrent(current) {}
77
operator ++()78 MessageMutator::iterator MessageMutator::iterator::operator++() {
79 ++mCurrent;
80 return *this;
81 }
82
operator ==(const iterator & other) const83 bool MessageMutator::iterator::operator==(const iterator& other) const {
84 return other.mCurrent == mCurrent;
85 }
86
operator *() const87 const MessageMutator MessageMutator::iterator::operator*() const {
88 return mContainer.fragment(*mCurrent);
89 }
90
91 } // namespace android::nl
92