Home | History | Annotate | Download | only in net
      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   ~NL80211Packet() = default;
     58 
     59   // Returns whether a packet has consistent header fields.
     60   bool IsValid() const;
     61 
     62   // Helper functions for Netlink flags.
     63 
     64   // Requesting a dump of a kernel obejct.
     65   bool IsDump() const;
     66   // Multipart messages are used to send lists or trees of objects.
     67   // They are supposed to be parsed independently, and must not be reassembled.
     68   // Multipart messages are terminated by NLMSG_DONE, which should be returned
     69   // by GetMessageType().
     70   bool IsMulti() const;
     71 
     72   // Getter functions.
     73   uint8_t GetCommand() const;
     74   uint16_t GetFlags() const;
     75   uint16_t GetMessageType() const;
     76   uint32_t GetMessageSequence() const;
     77   uint32_t GetPortId() const;
     78   // Caller is responsible for checking that this is a valid
     79   // NLMSG_ERROR message before calling GetErrorCode().
     80   // Returns an error number defined in errno.h
     81   int GetErrorCode() const;
     82   const std::vector<uint8_t>& GetConstData() const;
     83 
     84   // Setter functions.
     85 
     86   // In the contexet of nl80211 messages,
     87   // |command| is one of |enum nl80211_commands| in nl80211.h
     88   void SetCommand(uint8_t command);
     89   // |flags| is set of flag bits described by NLM_F_* macros in netlink.h
     90   void AddFlag(uint16_t flag);
     91   void SetFlags(uint16_t flags);
     92   // In the context of nl80211 messages,
     93   // message type is a nl80211 message family id dynamiclly allocated by kernel.
     94   // If this is a control message, it could be one of the following value:
     95   // NLMSG_NOOP, NLMSG_ERROR, NLMSG_DONE, NLMSG_OVERRUN
     96   void SetMessageType(uint16_t message_type);
     97   // Requests should carry a sequence number incremented for each request sent.
     98   // For reply message, the sequence number is used to allow referring to a
     99   // previous message with the same sequence number.
    100   void SetMessageSequence(uint32_t message_sequemce);
    101   // Set nlmsg_pid in netlink header.
    102   // nlmsg_pid is the sender process port ID.
    103   // It is *not* associated with a process but a netlink socket.
    104   // We should use sockaddr_nl.nl_pid from sender socket.
    105   // This value should be 0 if message is from kernel.
    106   // See man 7 netlink for details.
    107   void SetPortId(uint32_t pid);
    108 
    109   void AddAttribute(const BaseNL80211Attr& attribute);
    110   // For NLA_FLAG attribute
    111   void AddFlagAttribute(int attribute_id);
    112 
    113   bool HasAttribute(int id) const;
    114   bool GetAttribute(int id, NL80211NestedAttr* attribute) const;
    115 
    116   template <typename T>
    117   bool GetAttributeValue(int id, T* value) const {
    118     std::vector<uint8_t> empty_vec;
    119     // All data in |attribute| created here will be overwritten by
    120     // GetAttribute(). So we use an empty vector to initialize it,
    121     // regardless of the fact that an empty buffer is not qualified
    122     // for creating a valid attribute.
    123     NL80211Attr<T> attribute(empty_vec);
    124     if (!GetAttribute(id, &attribute)) {
    125       return false;
    126     }
    127     *value = attribute.GetValue();
    128     return true;
    129   }
    130 
    131   template <typename T>
    132   bool GetAttribute(int id, NL80211Attr<T>* attribute) const {
    133     uint8_t* start = nullptr;
    134     uint8_t* end = nullptr;
    135     if (!BaseNL80211Attr::GetAttributeImpl(
    136             data_.data() + NLMSG_HDRLEN + GENL_HDRLEN,
    137             data_.size() - NLMSG_HDRLEN - GENL_HDRLEN,
    138             id, &start, &end) ||
    139         start == nullptr ||
    140         end == nullptr) {
    141       return false;
    142     }
    143     *attribute = NL80211Attr<T>(std::vector<uint8_t>(start, end));
    144     if (!attribute->IsValid()) {
    145       return false;
    146     }
    147     return true;
    148   }
    149 
    150   void DebugLog() const;
    151 
    152  private:
    153   std::vector<uint8_t> data_;
    154 };
    155 
    156 }  // namespace wificond
    157 }  // namespace android
    158 
    159 #endif  // WIFICOND_NET_NL80211_PACKET_H_
    160