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
17337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang#ifndef WIFICOND_NET_NL80211_PACKET_H_
18337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang#define WIFICOND_NET_NL80211_PACKET_H_
19337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
20337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang#include <memory>
21337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang#include <vector>
22337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
23337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang#include <linux/genetlink.h>
24337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang#include <linux/netlink.h>
25337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
26337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang#include <android-base/macros.h>
27337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
28808c670699b218f8cc16f83e81be408ae441d44aNingyuan Wang#include "wificond/net/nl80211_attribute.h"
29337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
30337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangnamespace android {
31337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangnamespace wificond {
32337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
33337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang// NL80211Packets are used to communicate with the cfg80211 kernel subsystem
34337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang// (via the nl80211 interface).  An NL80211 packet is a type of generic netlink
35337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang// packet (i.e. it includes netlink and generic netlink headers).
36337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang// In order to simplify the design, we also allow this class to represent a
37337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang// few types of netlink control messages. In this way the API user is supposed to
38337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang// call IsValid() and GetMessageType() in the first place to avoid misuse of
39337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang// this class.
40337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wangclass NL80211Packet {
41337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang public:
42337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // This is used for creating a NL80211Packet from buffer.
43337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  explicit NL80211Packet(const std::vector<uint8_t>& data);
44337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // This is used for creating an empty NL80211Packet to be filled later.
457397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  // See comment of SetMessageType() for |type|.
467397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  // See comment of SetCommand() for |command|.
477397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  // See comment of SetMessageSequence() for |sequence|.
487397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  // See comment of SetPortId() for |pid|.
497397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  NL80211Packet(uint16_t type,
507397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang                uint8_t command,
517397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang                uint32_t sequence,
527397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang                uint32_t pid);
5321ff4c7ad0b0ec8da8392c00eedbae022d6e21e5Ningyuan Wang  // We don't copy NL80211Packet for performance reasons.
5421ff4c7ad0b0ec8da8392c00eedbae022d6e21e5Ningyuan Wang  // However we keep this copy constructor because it makes unit tests easy.
5521ff4c7ad0b0ec8da8392c00eedbae022d6e21e5Ningyuan Wang  // It prints WARNING log when this copy constructor is called.
56703601782dc0dcf952b16b8c906e623f276b6098Ningyuan Wang  NL80211Packet(const NL80211Packet& packet);
57337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  ~NL80211Packet() = default;
58337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
59337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Returns whether a packet has consistent header fields.
60337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  bool IsValid() const;
61337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
62337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Helper functions for Netlink flags.
63337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
64337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Requesting a dump of a kernel obejct.
65337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  bool IsDump() const;
66337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Multipart messages are used to send lists or trees of objects.
67337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // They are supposed to be parsed independently, and must not be reassembled.
68337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Multipart messages are terminated by NLMSG_DONE, which should be returned
69337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // by GetMessageType().
70337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  bool IsMulti() const;
71337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
72337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Getter functions.
73337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  uint8_t GetCommand() const;
74337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  uint16_t GetFlags() const;
75337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  uint16_t GetMessageType() const;
76337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  uint32_t GetMessageSequence() const;
77337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  uint32_t GetPortId() const;
7839f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang  // Caller is responsible for checking that this is a valid
7939f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang  // NLMSG_ERROR message before calling GetErrorCode().
8039f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang  // Returns an error number defined in errno.h
8139f581c0a6e2d9f6943b9b7069b6f096e0e5e858Ningyuan Wang  int GetErrorCode() const;
827397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  const std::vector<uint8_t>& GetConstData() const;
83337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
84337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Setter functions.
85337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
86337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // In the contexet of nl80211 messages,
87337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // |command| is one of |enum nl80211_commands| in nl80211.h
88337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  void SetCommand(uint8_t command);
89337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // |flags| is set of flag bits described by NLM_F_* macros in netlink.h
90e6dce59eaa5f1fcbdfb4b3fc6a60d5cd3b522b06Ningyuan Wang  void AddFlag(uint16_t flag);
91337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  void SetFlags(uint16_t flags);
92337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // In the context of nl80211 messages,
93337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // message type is a nl80211 message family id dynamiclly allocated by kernel.
94337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // If this is a control message, it could be one of the following value:
95337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // NLMSG_NOOP, NLMSG_ERROR, NLMSG_DONE, NLMSG_OVERRUN
96337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  void SetMessageType(uint16_t message_type);
977397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  // Requests should carry a sequence number incremented for each request sent.
987397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  // For reply message, the sequence number is used to allow referring to a
997397e6b7c3635e2121f6d2229557e684bc4756cfNingyuan Wang  // previous message with the same sequence number.
100337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  void SetMessageSequence(uint32_t message_sequemce);
101337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // Set nlmsg_pid in netlink header.
102337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // nlmsg_pid is the sender process port ID.
103337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // It is *not* associated with a process but a netlink socket.
104337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // We should use sockaddr_nl.nl_pid from sender socket.
105337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // This value should be 0 if message is from kernel.
106337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // See man 7 netlink for details.
107337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  void SetPortId(uint32_t pid);
108337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
109337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  void AddAttribute(const BaseNL80211Attr& attribute);
110337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  // For NLA_FLAG attribute
111337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  void AddFlagAttribute(int attribute_id);
112337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
113337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  bool HasAttribute(int id) const;
114337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  bool GetAttribute(int id, NL80211NestedAttr* attribute) const;
115337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
116337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  template <typename T>
117337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  bool GetAttributeValue(int id, T* value) const {
118337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    std::vector<uint8_t> empty_vec;
119337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    // All data in |attribute| created here will be overwritten by
120337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    // GetAttribute(). So we use an empty vector to initialize it,
121337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    // regardless of the fact that an empty buffer is not qualified
122337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    // for creating a valid attribute.
123337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    NL80211Attr<T> attribute(empty_vec);
124337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    if (!GetAttribute(id, &attribute)) {
125337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      return false;
126337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    }
127337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    *value = attribute.GetValue();
128337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    return true;
129337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  }
130337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
131337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  template <typename T>
132337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  bool GetAttribute(int id, NL80211Attr<T>* attribute) const {
133337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    uint8_t* start = nullptr;
134337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    uint8_t* end = nullptr;
135337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    if (!BaseNL80211Attr::GetAttributeImpl(
136337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang            data_.data() + NLMSG_HDRLEN + GENL_HDRLEN,
137337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang            data_.size() - NLMSG_HDRLEN - GENL_HDRLEN,
138337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang            id, &start, &end) ||
139337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang        start == nullptr ||
140337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang        end == nullptr) {
141337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      return false;
142337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    }
143337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    *attribute = NL80211Attr<T>(std::vector<uint8_t>(start, end));
144337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    if (!attribute->IsValid()) {
145337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang      return false;
146337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    }
147337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang    return true;
148337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  }
149337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
1508c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley  void DebugLog() const;
1518c8faa2a8999e5ecbe5b05605946ad66a7a202a4Christopher Wiley
15221ff4c7ad0b0ec8da8392c00eedbae022d6e21e5Ningyuan Wang private:
153337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang  std::vector<uint8_t> data_;
154337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang};
155337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
156337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}  // namespace wificond
157337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang}  // namespace android
158337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang
159337a336edb8fc48848883a4c0d7a91e63f445f6fNingyuan Wang#endif  // WIFICOND_NET_NL80211_PACKET_H_
160