• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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