nl80211_packet.cpp revision 703601782dc0dcf952b16b8c906e623f276b6098
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
26703601782dc0dcf952b16b8c906e623f276b6098Ningyuan Wangint NL80211Packet::copy_counter_ = 0;
27703601782dc0dcf952b16b8c906e623f276b6098Ningyuan Wanglong NL80211Packet::packet_bytes_copied_ = 0;
28703601782dc0dcf952b16b8c906e623f276b6098Ningyuan Wang
29337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan WangNL80211Packet::NL80211Packet(const vector<uint8_t>& data)
30337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    : data_(data) {
31337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  data_ = data;
32337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
33337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
34703601782dc0dcf952b16b8c906e623f276b6098Ningyuan WangNL80211Packet::NL80211Packet(const NL80211Packet& packet) {
35703601782dc0dcf952b16b8c906e623f276b6098Ningyuan Wang  data_ = packet.data_;
36703601782dc0dcf952b16b8c906e623f276b6098Ningyuan Wang  copy_counter_++;
37703601782dc0dcf952b16b8c906e623f276b6098Ningyuan Wang  packet_bytes_copied_+= packet.data_.size();
38703601782dc0dcf952b16b8c906e623f276b6098Ningyuan Wang  LOG(DEBUG) << "Packet copy operations: " << copy_counter_;
39703601782dc0dcf952b16b8c906e623f276b6098Ningyuan Wang  LOG(DEBUG) << "Packet bytes copied: " << packet_bytes_copied_;
40703601782dc0dcf952b16b8c906e623f276b6098Ningyuan Wang}
41703601782dc0dcf952b16b8c906e623f276b6098Ningyuan Wang
427397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan WangNL80211Packet::NL80211Packet(uint16_t type,
437397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang                             uint8_t command,
447397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang                             uint32_t sequence,
457397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang                             uint32_t pid) {
46337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Initialize the netlink header and generic netlink header.
47337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // NLMSG_HDRLEN and GENL_HDRLEN already include the padding size.
48337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  data_.resize(NLMSG_HDRLEN + GENL_HDRLEN, 0);
49337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Initialize length field.
50337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data());
51337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nl_header->nlmsg_len = data_.size();
52337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Add NLM_F_REQUEST flag.
53337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nl_header->nlmsg_flags = nl_header->nlmsg_flags | NLM_F_REQUEST;
547397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  nl_header->nlmsg_type = type;
557397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  nl_header->nlmsg_seq = sequence;
567397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  nl_header->nlmsg_pid = pid;
57337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
58337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  genlmsghdr* genl_header =
59337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      reinterpret_cast<genlmsghdr*>(data_.data() + NLMSG_HDRLEN);
60337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  genl_header->version = 1;
617397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  genl_header->cmd = command;
62337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // genl_header->reserved is aready 0.
63337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
64337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
65337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangbool NL80211Packet::IsValid() const {
66337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Verify the size of packet.
67337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  if (data_.size() < NLMSG_HDRLEN) {
68337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    LOG(ERROR) << "Cannot retrieve netlink header.";
69337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    return false;
70337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  }
71337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
7239f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang  const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(data_.data());
7339f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang
74337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // If type < NLMSG_MIN_TYPE, this should be a reserved control message,
75337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // which doesn't carry a generic netlink header.
76337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  if (GetMessageType() >= NLMSG_MIN_TYPE) {
7739f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang    if (data_.size() < NLMSG_HDRLEN + GENL_HDRLEN ||
7839f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang        nl_header->nlmsg_len < NLMSG_HDRLEN + GENL_HDRLEN) {
79337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      LOG(ERROR) << "Cannot retrieve generic netlink header.";
80337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      return false;
81337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    }
82337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  }
8339f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang  // If it is an ERROR message, it should be long enough to carry an extra error
8439f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang  // code field.
8539f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang  // Kernel uses int for this field.
8639f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang  if (GetMessageType() == NLMSG_ERROR) {
8739f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang    if (data_.size() < NLMSG_HDRLEN + sizeof(int) ||
8839f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang        nl_header->nlmsg_len < NLMSG_HDRLEN + sizeof(int)) {
8939f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang     LOG(ERROR) << "Broken error message.";
9039f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang     return false;
9139f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang    }
9239f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang  }
9339f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang
94337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Verify the netlink header.
95337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  if (data_.size() < nl_header->nlmsg_len ||
96337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      nl_header->nlmsg_len < sizeof(nlmsghdr)) {
97337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    LOG(ERROR) << "Discarding incomplete / invalid message.";
98337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    return false;
99337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  }
100337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return true;
101337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
102337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
103337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangbool NL80211Packet::IsDump() const {
104337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return GetFlags() & NLM_F_DUMP;
105337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
106337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
107337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangbool NL80211Packet::IsMulti() const {
108337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return GetFlags() & NLM_F_MULTI;
109337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
110337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
111337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wanguint8_t NL80211Packet::GetCommand() const {
112337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  const genlmsghdr* genl_header = reinterpret_cast<const genlmsghdr*>(
113337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      data_.data() + NLMSG_HDRLEN);
114337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return genl_header->cmd;
115337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
116337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
117337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wanguint16_t NL80211Packet::GetFlags() const {
118337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(data_.data());
119337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return nl_header->nlmsg_flags;
120337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
121337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
122337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wanguint16_t NL80211Packet::GetMessageType() const {
123337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(data_.data());
124337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return nl_header->nlmsg_type;
125337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
126337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
127337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wanguint32_t NL80211Packet::GetMessageSequence() const {
128337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(data_.data());
129337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return nl_header->nlmsg_seq;
130337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
131337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
132337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wanguint32_t NL80211Packet::GetPortId() const {
133337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(data_.data());
134337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return nl_header->nlmsg_pid;
135337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
136337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
13739f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wangint NL80211Packet::GetErrorCode() const {
138c2ec52ae9f449880901d50a45eae070aefba2f36Ningyuan Wang  return -*reinterpret_cast<const int*>(data_.data() + NLMSG_HDRLEN);
13939f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang}
14039f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang
1417397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wangconst vector<uint8_t>& NL80211Packet::GetConstData() const {
1427397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  return data_;
1437397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang}
1447397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang
145337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::SetCommand(uint8_t command) {
146337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  genlmsghdr* genl_header = reinterpret_cast<genlmsghdr*>(
147337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      data_.data() + NLMSG_HDRLEN);
148337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  genl_header->cmd = command;
149337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
150337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
151e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06Ningyuan Wangvoid NL80211Packet::AddFlag(uint16_t flag) {
152e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06Ningyuan Wang  nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data());
153e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06Ningyuan Wang  nl_header->nlmsg_flags |= flag;
154e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06Ningyuan Wang}
155e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06Ningyuan Wang
156337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::SetFlags(uint16_t flags) {
157337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data());
158337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nl_header->nlmsg_flags = flags;
159337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
160337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
161337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::SetMessageType(uint16_t message_type) {
162337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data());
163337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nl_header->nlmsg_type = message_type;
164337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
165337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
166337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::SetMessageSequence(uint32_t message_sequence) {
167337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data());
168337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nl_header->nlmsg_seq = message_sequence;
169337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
170337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
171337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::SetPortId(uint32_t pid) {
172337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data());
173337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nl_header->nlmsg_pid = pid;
174337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
175337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
176337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::AddAttribute(const BaseNL80211Attr& attribute) {
177337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  const vector<uint8_t>& append_data = attribute.GetConstData();
178337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Append the data of |attribute| to |this|.
179337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  data_.insert(data_.end(), append_data.begin(), append_data.end());
180337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data());
181337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // We don't need to worry about padding for a nl80211 packet.
182337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Because as long as all sub attributes have padding, the payload is aligned.
183337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nl_header->nlmsg_len += append_data.size();
184337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
185337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
186337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::AddFlagAttribute(int attribute_id) {
187337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // We only need to append a header for flag attribute.
188337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Make space for the new attribute.
189337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  data_.resize(data_.size() + NLA_HDRLEN, 0);
190337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nlattr* flag_header =
191337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      reinterpret_cast<nlattr*>(data_.data() + data_.size() - NLA_HDRLEN);
192337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  flag_header->nla_type = attribute_id;
193337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  flag_header->nla_len = NLA_HDRLEN;
194337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data());
195337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nl_header->nlmsg_len += NLA_HDRLEN;
196337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
197337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
198337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangbool NL80211Packet::HasAttribute(int id) const {
199337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return BaseNL80211Attr::GetAttributeImpl(
200337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      data_.data() + NLMSG_HDRLEN + GENL_HDRLEN,
201337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      data_.size() - NLMSG_HDRLEN - GENL_HDRLEN,
202337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      id, nullptr, nullptr);
203337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
204337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
205337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangbool NL80211Packet::GetAttribute(int id,
206337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    NL80211NestedAttr* attribute) const {
207337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  uint8_t* start = nullptr;
208337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  uint8_t* end = nullptr;
209337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  if (!BaseNL80211Attr::GetAttributeImpl(
210337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang          data_.data() + NLMSG_HDRLEN + GENL_HDRLEN,
211337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang          data_.size() - NLMSG_HDRLEN - GENL_HDRLEN,
212337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang          id, &start, &end) ||
213337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      start == nullptr ||
214337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      end == nullptr) {
215337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    return false;
216337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  }
217337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  *attribute = NL80211NestedAttr(vector<uint8_t>(start, end));
218337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  if (!attribute->IsValid()) {
219337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    return false;
220337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  }
221337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return true;
222337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
223337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
2248c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wileyvoid NL80211Packet::DebugLog() const {
2258c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley  const uint8_t* ptr = data_.data() + NLMSG_HDRLEN + GENL_HDRLEN;
2268c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley  const uint8_t* end_ptr = data_.data() + data_.size();
2278c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley  while (ptr + NLA_HDRLEN <= end_ptr) {
2288c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley    const nlattr* header = reinterpret_cast<const nlattr*>(ptr);
2298c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley    if (ptr + NLA_ALIGN(header->nla_len) > end_ptr) {
2308c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley      LOG(ERROR) << "broken nl80211 atrribute.";
2318c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley      continue;
2328c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley    }
2338c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley    LOG(INFO) << "Have attribute with nla_type=" << header->nla_type
2348c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley              << " and nla_len=" << header->nla_len;
2358c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley    ptr += NLA_ALIGN(header->nla_len);
2368c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley  }
2378c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley}
2388c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley
239337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}  // namespace wificond
240337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}  // namespace android
241