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