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>
GetAttributeValue(int id,T * value)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>
GetAttribute(int id,NL80211Attr<T> * attribute)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