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   // 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>
    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>
    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