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
31703601782dc0dcf952b16b8c906e623f276b6098Ningyuan WangNL80211Packet::NL80211Packet(const NL80211Packet& packet) {
32703601782dc0dcf952b16b8c906e623f276b6098Ningyuan Wang  data_ = packet.data_;
3321ff4c7ad0b0ec8da8392c00eedbae022d6e21e5Ningyuan Wang  LOG(WARNING) << "Copy constructor is only used for unit tests";
34703601782dc0dcf952b16b8c906e623f276b6098Ningyuan Wang}
35703601782dc0dcf952b16b8c906e623f276b6098Ningyuan Wang
367397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan WangNL80211Packet::NL80211Packet(uint16_t type,
377397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang                             uint8_t command,
387397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang                             uint32_t sequence,
397397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang                             uint32_t pid) {
40337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Initialize the netlink header and generic netlink header.
41337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // NLMSG_HDRLEN and GENL_HDRLEN already include the padding size.
42337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  data_.resize(NLMSG_HDRLEN + GENL_HDRLEN, 0);
43337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Initialize length field.
44337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data());
45337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nl_header->nlmsg_len = data_.size();
46337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Add NLM_F_REQUEST flag.
47337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nl_header->nlmsg_flags = nl_header->nlmsg_flags | NLM_F_REQUEST;
487397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  nl_header->nlmsg_type = type;
497397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  nl_header->nlmsg_seq = sequence;
507397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  nl_header->nlmsg_pid = pid;
51337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
52337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  genlmsghdr* genl_header =
53337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      reinterpret_cast<genlmsghdr*>(data_.data() + NLMSG_HDRLEN);
54337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  genl_header->version = 1;
557397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  genl_header->cmd = command;
56337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // genl_header->reserved is aready 0.
57337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
58337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
59337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangbool NL80211Packet::IsValid() const {
60337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Verify the size of packet.
61337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  if (data_.size() < NLMSG_HDRLEN) {
62337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    LOG(ERROR) << "Cannot retrieve netlink header.";
63337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    return false;
64337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  }
65337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
6639f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang  const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(data_.data());
6739f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang
68337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // If type < NLMSG_MIN_TYPE, this should be a reserved control message,
69337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // which doesn't carry a generic netlink header.
70337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  if (GetMessageType() >= NLMSG_MIN_TYPE) {
7139f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang    if (data_.size() < NLMSG_HDRLEN + GENL_HDRLEN ||
7239f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang        nl_header->nlmsg_len < NLMSG_HDRLEN + GENL_HDRLEN) {
73337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      LOG(ERROR) << "Cannot retrieve generic netlink header.";
74337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      return false;
75337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    }
76337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  }
7739f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang  // If it is an ERROR message, it should be long enough to carry an extra error
7839f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang  // code field.
7939f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang  // Kernel uses int for this field.
8039f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang  if (GetMessageType() == NLMSG_ERROR) {
8139f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang    if (data_.size() < NLMSG_HDRLEN + sizeof(int) ||
8239f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang        nl_header->nlmsg_len < NLMSG_HDRLEN + sizeof(int)) {
8339f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang     LOG(ERROR) << "Broken error message.";
8439f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang     return false;
8539f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang    }
8639f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang  }
8739f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang
88337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Verify the netlink header.
89337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  if (data_.size() < nl_header->nlmsg_len ||
90337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      nl_header->nlmsg_len < sizeof(nlmsghdr)) {
91337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    LOG(ERROR) << "Discarding incomplete / invalid message.";
92337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    return false;
93337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  }
94337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return true;
95337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
96337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
97337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangbool NL80211Packet::IsDump() const {
98337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return GetFlags() & NLM_F_DUMP;
99337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
100337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
101337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangbool NL80211Packet::IsMulti() const {
102337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return GetFlags() & NLM_F_MULTI;
103337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
104337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
105337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wanguint8_t NL80211Packet::GetCommand() const {
106337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  const genlmsghdr* genl_header = reinterpret_cast<const genlmsghdr*>(
107337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      data_.data() + NLMSG_HDRLEN);
108337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return genl_header->cmd;
109337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
110337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
111337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wanguint16_t NL80211Packet::GetFlags() const {
112337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(data_.data());
113337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return nl_header->nlmsg_flags;
114337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
115337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
116337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wanguint16_t NL80211Packet::GetMessageType() const {
117337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(data_.data());
118337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return nl_header->nlmsg_type;
119337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
120337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
121337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wanguint32_t NL80211Packet::GetMessageSequence() const {
122337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(data_.data());
123337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return nl_header->nlmsg_seq;
124337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
125337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
126337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wanguint32_t NL80211Packet::GetPortId() const {
127337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  const nlmsghdr* nl_header = reinterpret_cast<const nlmsghdr*>(data_.data());
128337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return nl_header->nlmsg_pid;
129337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
130337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
13139f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wangint NL80211Packet::GetErrorCode() const {
132c2ec52ae9f449880901d50a45eae070aefba2f36Ningyuan Wang  return -*reinterpret_cast<const int*>(data_.data() + NLMSG_HDRLEN);
13339f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang}
13439f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang
1357397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wangconst vector<uint8_t>& NL80211Packet::GetConstData() const {
1367397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  return data_;
1377397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang}
1387397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang
139337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::SetCommand(uint8_t command) {
140337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  genlmsghdr* genl_header = reinterpret_cast<genlmsghdr*>(
141337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      data_.data() + NLMSG_HDRLEN);
142337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  genl_header->cmd = command;
143337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
144337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
145e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06Ningyuan Wangvoid NL80211Packet::AddFlag(uint16_t flag) {
146e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06Ningyuan Wang  nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data());
147e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06Ningyuan Wang  nl_header->nlmsg_flags |= flag;
148e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06Ningyuan Wang}
149e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06Ningyuan Wang
150337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::SetFlags(uint16_t flags) {
151337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data());
152337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nl_header->nlmsg_flags = flags;
153337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
154337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
155337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::SetMessageType(uint16_t message_type) {
156337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data());
157337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nl_header->nlmsg_type = message_type;
158337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
159337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
160337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::SetMessageSequence(uint32_t message_sequence) {
161337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data());
162337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nl_header->nlmsg_seq = message_sequence;
163337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
164337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
165337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::SetPortId(uint32_t pid) {
166337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data());
167337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nl_header->nlmsg_pid = pid;
168337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
169337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
170337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::AddAttribute(const BaseNL80211Attr& attribute) {
171337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  const vector<uint8_t>& append_data = attribute.GetConstData();
172337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Append the data of |attribute| to |this|.
173337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  data_.insert(data_.end(), append_data.begin(), append_data.end());
174337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data());
175337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // We don't need to worry about padding for a nl80211 packet.
176337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Because as long as all sub attributes have padding, the payload is aligned.
177337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nl_header->nlmsg_len += append_data.size();
178337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
179337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
180337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangvoid NL80211Packet::AddFlagAttribute(int attribute_id) {
181337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // We only need to append a header for flag attribute.
182337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Make space for the new attribute.
183337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  data_.resize(data_.size() + NLA_HDRLEN, 0);
184337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nlattr* flag_header =
185337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      reinterpret_cast<nlattr*>(data_.data() + data_.size() - NLA_HDRLEN);
186337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  flag_header->nla_type = attribute_id;
187337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  flag_header->nla_len = NLA_HDRLEN;
188337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nlmsghdr* nl_header = reinterpret_cast<nlmsghdr*>(data_.data());
189337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  nl_header->nlmsg_len += NLA_HDRLEN;
190337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
191337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
192337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangbool NL80211Packet::HasAttribute(int id) const {
193337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return BaseNL80211Attr::GetAttributeImpl(
194337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      data_.data() + NLMSG_HDRLEN + GENL_HDRLEN,
195337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      data_.size() - NLMSG_HDRLEN - GENL_HDRLEN,
196337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      id, nullptr, nullptr);
197337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
198337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
199337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangbool NL80211Packet::GetAttribute(int id,
200337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    NL80211NestedAttr* attribute) const {
201337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  uint8_t* start = nullptr;
202337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  uint8_t* end = nullptr;
203337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  if (!BaseNL80211Attr::GetAttributeImpl(
204337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang          data_.data() + NLMSG_HDRLEN + GENL_HDRLEN,
205337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang          data_.size() - NLMSG_HDRLEN - GENL_HDRLEN,
206337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang          id, &start, &end) ||
207337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      start == nullptr ||
208337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      end == nullptr) {
209337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    return false;
210337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  }
211337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  *attribute = NL80211NestedAttr(vector<uint8_t>(start, end));
212337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  if (!attribute->IsValid()) {
213337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    return false;
214337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  }
215337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  return true;
216337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}
217337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
2188c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wileyvoid NL80211Packet::DebugLog() const {
2198c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley  const uint8_t* ptr = data_.data() + NLMSG_HDRLEN + GENL_HDRLEN;
2208c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley  const uint8_t* end_ptr = data_.data() + data_.size();
2218c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley  while (ptr + NLA_HDRLEN <= end_ptr) {
2228c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley    const nlattr* header = reinterpret_cast<const nlattr*>(ptr);
2238c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley    if (ptr + NLA_ALIGN(header->nla_len) > end_ptr) {
2248c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley      LOG(ERROR) << "broken nl80211 atrribute.";
22517acda64ab273929b2d07b3a57501724242af875Ningyuan Wang      return;
2268c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley    }
2278c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley    LOG(INFO) << "Have attribute with nla_type=" << header->nla_type
2288c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley              << " and nla_len=" << header->nla_len;
2296fc05a9b0f0f0c86a4cfb281802d8a66ed1f9948Ningyuan Wang    if (header->nla_len == 0) {
2306fc05a9b0f0f0c86a4cfb281802d8a66ed1f9948Ningyuan Wang      LOG(ERROR) << "0 is a bad nla_len";
2316fc05a9b0f0f0c86a4cfb281802d8a66ed1f9948Ningyuan Wang      return;
2326fc05a9b0f0f0c86a4cfb281802d8a66ed1f9948Ningyuan Wang    }
2338c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley    ptr += NLA_ALIGN(header->nla_len);
2348c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley  }
2358c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley}
2368c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley
237337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}  // namespace wificond
238337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}  // namespace android
239