1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef WIFICOND_NET_NL80211_PACKET_H_ 18 #define WIFICOND_NET_NL80211_PACKET_H_ 19 20 #include <memory> 21 #include <vector> 22 23 #include <linux/genetlink.h> 24 #include <linux/netlink.h> 25 26 #include <android-base/macros.h> 27 28 #include "wificond/net/nl80211_attribute.h" 29 30 namespace android { 31 namespace wificond { 32 33 // NL80211Packets are used to communicate with the cfg80211 kernel subsystem 34 // (via the nl80211 interface). An NL80211 packet is a type of generic netlink 35 // packet (i.e. it includes netlink and generic netlink headers). 36 // In order to simplify the design, we also allow this class to represent a 37 // few types of netlink control messages. In this way the API user is supposed to 38 // call IsValid() and GetMessageType() in the first place to avoid misuse of 39 // this class. 40 class NL80211Packet { 41 public: 42 // This is used for creating a NL80211Packet from buffer. 43 explicit NL80211Packet(const std::vector<uint8_t>& data); 44 // This is used for creating an empty NL80211Packet to be filled later. 45 // See comment of SetMessageType() for |type|. 46 // See comment of SetCommand() for |command|. 47 // See comment of SetMessageSequence() for |sequence|. 48 // See comment of SetPortId() for |pid|. 49 NL80211Packet(uint16_t type, 50 uint8_t command, 51 uint32_t sequence, 52 uint32_t pid); 53 // We don't copy NL80211Packet for performance reasons. 54 // However we keep this copy constructor because it makes unit tests easy. 55 // It prints WARNING log when this copy constructor is called. 56 NL80211Packet(const NL80211Packet& packet); 57 // Explicitly specify the move constructor. Otherwise, copy constructor will 58 // be called on if we move a NL80211Packet object. 59 NL80211Packet(NL80211Packet&& packet) = default; 60 ~NL80211Packet() = default; 61 62 // Returns whether a packet has consistent header fields. 63 bool IsValid() const; 64 65 // Helper functions for Netlink flags. 66 67 // Requesting a dump of a kernel obejct. 68 bool IsDump() const; 69 // Multipart messages are used to send lists or trees of objects. 70 // They are supposed to be parsed independently, and must not be reassembled. 71 // Multipart messages are terminated by NLMSG_DONE, which should be returned 72 // by GetMessageType(). 73 bool IsMulti() const; 74 75 // Getter functions. 76 uint8_t GetCommand() const; 77 uint16_t GetFlags() const; 78 uint16_t GetMessageType() const; 79 uint32_t GetMessageSequence() const; 80 uint32_t GetPortId() const; 81 // Caller is responsible for checking that this is a valid 82 // NLMSG_ERROR message before calling GetErrorCode(). 83 // Returns an error number defined in errno.h 84 int GetErrorCode() const; 85 const std::vector<uint8_t>& GetConstData() const; 86 87 // Setter functions. 88 89 // In the contexet of nl80211 messages, 90 // |command| is one of |enum nl80211_commands| in nl80211.h 91 void SetCommand(uint8_t command); 92 // |flags| is set of flag bits described by NLM_F_* macros in netlink.h 93 void AddFlag(uint16_t flag); 94 void SetFlags(uint16_t flags); 95 // In the context of nl80211 messages, 96 // message type is a nl80211 message family id dynamiclly allocated by kernel. 97 // If this is a control message, it could be one of the following value: 98 // NLMSG_NOOP, NLMSG_ERROR, NLMSG_DONE, NLMSG_OVERRUN 99 void SetMessageType(uint16_t message_type); 100 // Requests should carry a sequence number incremented for each request sent. 101 // For reply message, the sequence number is used to allow referring to a 102 // previous message with the same sequence number. 103 void SetMessageSequence(uint32_t message_sequemce); 104 // Set nlmsg_pid in netlink header. 105 // nlmsg_pid is the sender process port ID. 106 // It is *not* associated with a process but a netlink socket. 107 // We should use sockaddr_nl.nl_pid from sender socket. 108 // This value should be 0 if message is from kernel. 109 // See man 7 netlink for details. 110 void SetPortId(uint32_t pid); 111 112 void AddAttribute(const BaseNL80211Attr& attribute); 113 // For NLA_FLAG attribute 114 void AddFlagAttribute(int attribute_id); 115 116 bool HasAttribute(int id) const; 117 bool GetAttribute(int id, NL80211NestedAttr* attribute) const; 118 // Get all attributes to |*attribute| as a vector. 119 // In case of failure, attributes up until the first invalid attribute 120 // actually will be present in |attributes|. 121 bool GetAllAttributes( 122 std::vector<BaseNL80211Attr>* attributes) const; 123 124 template <typename T> GetAttributeValue(int id,T * value)125 bool GetAttributeValue(int id, T* value) const { 126 std::vector<uint8_t> empty_vec; 127 // All data in |attribute| created here will be overwritten by 128 // GetAttribute(). So we use an empty vector to initialize it, 129 // regardless of the fact that an empty buffer is not qualified 130 // for creating a valid attribute. 131 NL80211Attr<T> attribute(empty_vec); 132 if (!GetAttribute(id, &attribute)) { 133 return false; 134 } 135 *value = attribute.GetValue(); 136 return true; 137 } 138 139 template <typename T> GetAttribute(int id,NL80211Attr<T> * attribute)140 bool GetAttribute(int id, NL80211Attr<T>* attribute) const { 141 uint8_t* start = nullptr; 142 uint8_t* end = nullptr; 143 if (!BaseNL80211Attr::GetAttributeImpl( 144 data_.data() + NLMSG_HDRLEN + GENL_HDRLEN, 145 data_.size() - NLMSG_HDRLEN - GENL_HDRLEN, 146 id, &start, &end) || 147 start == nullptr || 148 end == nullptr) { 149 return false; 150 } 151 *attribute = NL80211Attr<T>(std::vector<uint8_t>(start, end)); 152 if (!attribute->IsValid()) { 153 return false; 154 } 155 return true; 156 } 157 158 void DebugLog() const; 159 160 private: 161 std::vector<uint8_t> data_; 162 }; 163 164 } // namespace wificond 165 } // namespace android 166 167 #endif // WIFICOND_NET_NL80211_PACKET_H_ 168