/* * Copyright (C) 2017 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 "common/libs/net/netlink_request.h" #include #include #include #include #include #include #include #include "android-base/logging.h" namespace cuttlefish { namespace { uint32_t kRequestSequenceNumber = 0; } // namespace uint32_t NetlinkRequest::SeqNo() const { return header_->nlmsg_seq; } void* NetlinkRequest::AppendRaw(const void* data, size_t length) { auto* output = static_cast(ReserveRaw(length)); const auto* input = static_cast(data); std::copy(input, input + length, output); return output; } void* NetlinkRequest::ReserveRaw(size_t length) { size_t original_size = request_.size(); request_.resize(original_size + RTA_ALIGN(length), '\0'); return reinterpret_cast(request_.data() + original_size); } nlattr* NetlinkRequest::AppendTag( uint16_t type, const void* data, uint16_t data_length) { nlattr* attr = Reserve(); attr->nla_type = type; attr->nla_len = RTA_LENGTH(data_length); AppendRaw(data, data_length); return attr; } NetlinkRequest::NetlinkRequest(int32_t command, int32_t flags) { request_.reserve(512); header_ = Reserve(); flags |= NLM_F_ACK | NLM_F_REQUEST; header_->nlmsg_flags = flags; header_->nlmsg_type = command; header_->nlmsg_pid = getpid(); header_->nlmsg_seq = kRequestSequenceNumber++; } NetlinkRequest::NetlinkRequest(NetlinkRequest&& other) { using std::swap; swap(lists_, other.lists_); swap(header_, other.header_); swap(request_, other.request_); } void NetlinkRequest::AddString(uint16_t type, const std::string& value) { AppendTag(type, value.c_str(), value.length() + 1); } void NetlinkRequest::AddIfInfo(int32_t if_index, bool operational) { ifinfomsg* if_info = Reserve(); if_info->ifi_family = AF_UNSPEC; if_info->ifi_index = if_index; if_info->ifi_flags = operational ? IFF_UP : 0; if_info->ifi_change = IFF_UP; } void NetlinkRequest::AddAddrInfo(int32_t if_index, int prefix_len) { ifaddrmsg* ad_info = Reserve(); ad_info->ifa_family = AF_INET; ad_info->ifa_prefixlen = prefix_len; ad_info->ifa_flags = IFA_F_PERMANENT | IFA_F_SECONDARY; ad_info->ifa_scope = 0; ad_info->ifa_index = if_index; } void NetlinkRequest::AddMacAddress(const std::array& address) { AppendTag(IFLA_ADDRESS, address.data(), 6); } void NetlinkRequest::PushList(uint16_t type) { int length = request_.size(); nlattr* list = AppendTag(type, NULL, 0); lists_.push_back(std::make_pair(list, length)); } void NetlinkRequest::PopList() { if (lists_.empty()) { LOG(ERROR) << "List pop with no lists left on stack."; return; } std::pair list = lists_.back(); lists_.pop_back(); list.first->nla_len = request_.size() - list.second; } void* NetlinkRequest::RequestData() const { // Update request length before reporting raw data. header_->nlmsg_len = request_.size(); return header_; } size_t NetlinkRequest::RequestLength() const { return request_.size(); } } // namespace cuttlefish