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