nl80211_packet.cpp revision e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06
1337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang/* 2337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang * Copyright (C) 2016 The Android Open Source Project 3337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang * 4337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang * Licensed under the Apache License, Version 2.0 (the "License"); 5337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang * you may not use this file except in compliance with the License. 6337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang * You may obtain a copy of the License at 7337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang * 8337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang * http://www.apache.org/licenses/LICENSE-2.0 9337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang * 10337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang * Unless required by applicable law or agreed to in writing, software 11337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang * distributed under the License is distributed on an "AS IS" BASIS, 12337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang * See the License for the specific language governing permissions and 14337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang * limitations under the License. 15337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang */ 16337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 17808c670699b218f8cc16f83e81be408ae441d44aNingyuan Wang#include "wificond/net/nl80211_packet.h" 18337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 19337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang#include <android-base/logging.h> 20337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 21337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangusing std::vector; 22337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 23337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangnamespace android { 24337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangnamespace wificond { 25337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 26337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan WangNL80211Packet::NL80211Packet(const vector<uint8_t>& data) 27337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang : data_(data) { 28337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang data_ = data; 29337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 30337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 317397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan WangNL80211Packet::NL80211Packet(uint16_t type, 327397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang uint8_t command, 337397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang uint32_t sequence, 347397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang uint32_t pid) { 35337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang // Initialize the netlink header and generic netlink header. 36337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang // NLMSG_HDRLEN and GENL_HDRLEN already include the padding size. 37337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang data_.resize(NLMSG_HDRLEN + GENL_HDRLEN, 0); 38337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang // Initialize length field. 39337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data()); 40337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nl_header->nlmsg_len = data_.size(); 41337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang // Add NLM_F_REQUEST flag. 42337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nl_header->nlmsg_flags = nl_header->nlmsg_flags | NLM_F_REQUEST; 437397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang nl_header->nlmsg_type = type; 447397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang nl_header->nlmsg_seq = sequence; 457397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang nl_header->nlmsg_pid = pid; 46337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 47337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang genlmsghdr* genl_header = 48337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang reinterpret_cast<genlmsghdr*>(data_.data() + NLMSG_HDRLEN); 49337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang genl_header->version = 1; 507397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang genl_header->cmd = command; 51337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang // genl_header->reserved is aready 0. 52337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 53337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 54337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangbool NL80211Packet::IsValid() const { 55337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang // Verify the size of packet. 56337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang if (data_.size() < NLMSG_HDRLEN) { 57337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang LOG(ERROR) << "Cannot retrieve netlink header."; 58337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang return false; 59337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang } 60337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 61337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang // If type < NLMSG_MIN_TYPE, this should be a reserved control message, 62337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang // which doesn't carry a generic netlink header. 63337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang if (GetMessageType() >= NLMSG_MIN_TYPE) { 64337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang if (data_.size() < NLMSG_HDRLEN + GENL_HDRLEN) { 65337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang LOG(ERROR) << "Cannot retrieve generic netlink header."; 66337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang return false; 67337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang } 68337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang } 69337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(data_.data()); 70337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang // Verify the netlink header. 71337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang if (data_.size() < nl_header->nlmsg_len || 72337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nl_header->nlmsg_len < sizeof(nlmsghdr)) { 73337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang LOG(ERROR) << "Discarding incomplete / invalid message."; 74337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang return false; 75337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang } 76337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang return true; 77337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 78337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 79337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangbool NL80211Packet::IsDump() const { 80337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang return GetFlags() & NLM_F_DUMP; 81337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 82337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 83337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangbool NL80211Packet::IsMulti() const { 84337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang return GetFlags() & NLM_F_MULTI; 85337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 86337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 87337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wanguint8_t NL80211Packet::GetCommand() const { 88337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang const genlmsghdr* genl_header = reinterpret_cast<const genlmsghdr*>( 89337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang data_.data() + NLMSG_HDRLEN); 90337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang return genl_header->cmd; 91337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 92337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 93337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wanguint16_t NL80211Packet::GetFlags() const { 94337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(data_.data()); 95337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang return nl_header->nlmsg_flags; 96337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 97337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 98337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wanguint16_t NL80211Packet::GetMessageType() const { 99337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(data_.data()); 100337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang return nl_header->nlmsg_type; 101337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 102337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 103337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wanguint32_t NL80211Packet::GetMessageSequence() const { 104337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(data_.data()); 105337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang return nl_header->nlmsg_seq; 106337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 107337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 108337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wanguint32_t NL80211Packet::GetPortId() const { 109337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(data_.data()); 110337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang return nl_header->nlmsg_pid; 111337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 112337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 1137397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wangconst vector<uint8_t>& NL80211Packet::GetConstData() const { 1147397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang return data_; 1157397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang} 1167397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang 117337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::SetCommand(uint8_t command) { 118337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang genlmsghdr* genl_header = reinterpret_cast<genlmsghdr*>( 119337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang data_.data() + NLMSG_HDRLEN); 120337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang genl_header->cmd = command; 121337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 122337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 123e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06Ningyuan Wangvoid NL80211Packet::AddFlag(uint16_t flag) { 124e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06Ningyuan Wang nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data()); 125e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06Ningyuan Wang nl_header->nlmsg_flags |= flag; 126e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06Ningyuan Wang} 127e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06Ningyuan Wang 128337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::SetFlags(uint16_t flags) { 129337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data()); 130337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nl_header->nlmsg_flags = flags; 131337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 132337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 133337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::SetMessageType(uint16_t message_type) { 134337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data()); 135337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nl_header->nlmsg_type = message_type; 136337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 137337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 138337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::SetMessageSequence(uint32_t message_sequence) { 139337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data()); 140337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nl_header->nlmsg_seq = message_sequence; 141337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 142337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 143337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::SetPortId(uint32_t pid) { 144337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data()); 145337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nl_header->nlmsg_pid = pid; 146337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 147337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 148337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::AddAttribute(const BaseNL80211Attr& attribute) { 149337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang const vector<uint8_t>& append_data = attribute.GetConstData(); 150337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang // Append the data of |attribute| to |this|. 151337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang data_.insert(data_.end(), append_data.begin(), append_data.end()); 152337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data()); 153337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang // We don't need to worry about padding for a nl80211 packet. 154337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang // Because as long as all sub attributes have padding, the payload is aligned. 155337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nl_header->nlmsg_len += append_data.size(); 156337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 157337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 158337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::AddFlagAttribute(int attribute_id) { 159337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang // We only need to append a header for flag attribute. 160337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang // Make space for the new attribute. 161337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang data_.resize(data_.size() + NLA_HDRLEN, 0); 162337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nlattr* flag_header = 163337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang reinterpret_cast<nlattr*>(data_.data() + data_.size() - NLA_HDRLEN); 164337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang flag_header->nla_type = attribute_id; 165337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang flag_header->nla_len = NLA_HDRLEN; 166337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data()); 167337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang nl_header->nlmsg_len += NLA_HDRLEN; 168337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 169337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 170337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangbool NL80211Packet::HasAttribute(int id) const { 171337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang return BaseNL80211Attr::GetAttributeImpl( 172337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang data_.data() + NLMSG_HDRLEN + GENL_HDRLEN, 173337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang data_.size() - NLMSG_HDRLEN - GENL_HDRLEN, 174337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang id, nullptr, nullptr); 175337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 176337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 177337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangbool NL80211Packet::GetAttribute(int id, 178337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang NL80211NestedAttr* attribute) const { 179337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang uint8_t* start = nullptr; 180337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang uint8_t* end = nullptr; 181337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang if (!BaseNL80211Attr::GetAttributeImpl( 182337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang data_.data() + NLMSG_HDRLEN + GENL_HDRLEN, 183337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang data_.size() - NLMSG_HDRLEN - GENL_HDRLEN, 184337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang id, &start, &end) || 185337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang start == nullptr || 186337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang end == nullptr) { 187337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang return false; 188337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang } 189337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang *attribute = NL80211NestedAttr(vector<uint8_t>(start, end)); 190337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang if (!attribute->IsValid()) { 191337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang return false; 192337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang } 193337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang return true; 194337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} 195337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang 196337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} // namespace wificond 197337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang} // namespace android 198