1//
2// Copyright (C) 2015 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 SHILL_NET_NETLINK_PACKET_H_
18#define SHILL_NET_NETLINK_PACKET_H_
19
20#include <linux/genetlink.h>
21#include <linux/netlink.h>
22
23#include <memory>
24
25#include <base/macros.h>
26
27#include "shill/net/attribute_list.h"
28#include "shill/net/shill_export.h"
29
30namespace shill {
31
32class ByteString;
33
34class SHILL_EXPORT NetlinkPacket {
35 public:
36  NetlinkPacket(const unsigned char* buf, size_t len);
37  virtual ~NetlinkPacket();
38
39  // Returns whether a packet was properly retrieved in the constructor.
40  bool IsValid() const;
41
42  // Returns the entire packet length (including the nlmsghdr).  Callers
43  // can consder this to be the number of bytes consumed from |buf| in the
44  // constructor.  This value will not change as data is consumed -- use
45  // GetRemainingLength() instead for this.
46  size_t GetLength() const;
47
48  // Get the message type from the header.
49  uint16_t GetMessageType() const;
50
51  // Get the sequence number from the header.
52  uint32_t GetMessageSequence() const;
53
54  // Returns the remaining (un-consumed) payload length.
55  size_t GetRemainingLength() const;
56
57  // Returns the payload data.  It is a fatal error to call this method
58  // on an invalid packet.
59  const ByteString& GetPayload() const;
60
61  // Consume netlink attributes from the remaining payload.
62  bool ConsumeAttributes(const AttributeList::NewFromIdMethod& factory,
63                         const AttributeListRefPtr& attributes);
64
65  // Consume |len| bytes out of the payload, and place them in |data|.
66  // Any trailing alignment padding in |payload| is also consumed.  Returns
67  // true if there is enough data, otherwise returns false and does not
68  // modify |data|.
69  bool ConsumeData(size_t len, void* data);
70
71  // Copies the initial part of the payload to |header| without
72  // consuming any data.  Returns true if this operation succeeds (there
73  // is enough data in the payload), false otherwise.
74  bool GetGenlMsgHdr(genlmsghdr* header) const;
75
76  // Returns the nlmsghdr associated with the packet.  It is a fatal error
77  // to call this method on an invalid packet.
78  const nlmsghdr& GetNlMsgHeader() const;
79
80 protected:
81  // These getters are protected so that derived classes may allow
82  // the packet contents to be modified.
83  nlmsghdr* mutable_header() { return &header_; }
84  ByteString* mutable_payload() { return payload_.get(); }
85  void set_consumed_bytes(size_t consumed_bytes) {
86      consumed_bytes_ = consumed_bytes;
87  }
88
89 private:
90  friend class NetlinkPacketTest;
91
92  nlmsghdr header_;
93  std::unique_ptr<ByteString> payload_;
94  size_t consumed_bytes_;
95
96  DISALLOW_COPY_AND_ASSIGN(NetlinkPacket);
97};
98
99// Mutable Netlink packets are used in unit tests where it is convenient
100// to modify the header and payload of a packet before passing it to the
101// NetlinkMessage subclasses or NetlinkManager.
102class SHILL_EXPORT MutableNetlinkPacket : public NetlinkPacket {
103 public:
104  MutableNetlinkPacket(const unsigned char* buf, size_t len);
105  virtual ~MutableNetlinkPacket();
106
107  // Reset consumed_bytes_ as if this packet never underwent processing.
108  // This is useful for unit tests that wish to re-send a previously
109  // processed packet.
110  void ResetConsumedBytes();
111
112  // Returns mutable references to the header and payload.
113  nlmsghdr* GetMutableHeader();
114  ByteString* GetMutablePayload();
115
116  // Set the message type in the header.
117  void SetMessageType(uint16_t type);
118
119  // Set the sequence number in the header.
120  void SetMessageSequence(uint32_t sequence);
121
122 private:
123  DISALLOW_COPY_AND_ASSIGN(MutableNetlinkPacket);
124};
125
126}  // namespace shill
127
128#endif  // SHILL_NET_NETLINK_PACKET_H_
129