Kea 1.5.0
pkt.cc
Go to the documentation of this file.
1// Copyright (C) 2014-2018 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8#include <utility>
9#include <dhcp/pkt.h>
10#include <dhcp/iface_mgr.h>
11#include <dhcp/hwaddr.h>
12#include <vector>
13
14namespace isc {
15namespace dhcp {
16
17Pkt::Pkt(uint32_t transid, const isc::asiolink::IOAddress& local_addr,
18 const isc::asiolink::IOAddress& remote_addr, uint16_t local_port,
19 uint16_t remote_port)
20 :transid_(transid),
21 iface_(""),
22 ifindex_(-1),
23 local_addr_(local_addr),
24 remote_addr_(remote_addr),
25 local_port_(local_port),
26 remote_port_(remote_port),
27 buffer_out_(0),
28 copy_retrieved_options_(false)
29{
30}
31
32Pkt::Pkt(const uint8_t* buf, uint32_t len, const isc::asiolink::IOAddress& local_addr,
33 const isc::asiolink::IOAddress& remote_addr, uint16_t local_port,
34 uint16_t remote_port)
35 :transid_(0),
36 iface_(""),
37 ifindex_(-1),
38 local_addr_(local_addr),
39 remote_addr_(remote_addr),
40 local_port_(local_port),
41 remote_port_(remote_port),
42 buffer_out_(0),
43 copy_retrieved_options_(false)
44{
45
46 if (len != 0) {
47 if (buf == NULL) {
48 isc_throw(InvalidParameter, "data buffer passed to Pkt is NULL");
49 }
50 data_.resize(len);
51 memcpy(&data_[0], buf, len);
52 }
53}
54
55void
57 options_.insert(std::pair<int, OptionPtr>(opt->getType(), opt));
58}
59
61Pkt::getNonCopiedOption(const uint16_t type) const {
62 OptionCollection::const_iterator x = options_.find(type);
63 if (x != options_.end()) {
64 return (x->second);
65 }
66 return (OptionPtr());
67}
68
70Pkt::getOption(const uint16_t type) {
71 OptionCollection::iterator x = options_.find(type);
72 if (x != options_.end()) {
74 OptionPtr option_copy = x->second->clone();
75 x->second = option_copy;
76 }
77 return (x->second);
78 }
79 return (OptionPtr()); // NULL
80}
81
82bool
83Pkt::delOption(uint16_t type) {
84
85 isc::dhcp::OptionCollection::iterator x = options_.find(type);
86 if (x!=options_.end()) {
87 options_.erase(x);
88 return (true); // delete successful
89 } else {
90 return (false); // can't find option to be deleted
91 }
92}
93
94bool
95Pkt::inClass(const std::string& client_class) {
96 return (classes_.contains(client_class));
97}
98
99void
100Pkt::addClass(const std::string& client_class, bool required) {
101 ClientClasses& classes = !required ? classes_ : required_classes_;
102 if (!classes.contains(client_class)) {
103 classes.insert(client_class);
104 }
105}
106
107void
109 timestamp_ = boost::posix_time::microsec_clock::universal_time();
110}
111
113 if (!data_.empty()) {
114 buffer_out_.writeData(&data_[0], data_.size());
115 }
116}
117
118void
119Pkt::setRemoteHWAddr(const uint8_t htype, const uint8_t hlen,
120 const std::vector<uint8_t>& hw_addr) {
121 setHWAddrMember(htype, hlen, hw_addr, remote_hwaddr_);
122}
123
124void
126 if (!hw_addr) {
127 isc_throw(BadValue, "Setting remote HW address to NULL is"
128 << " forbidden.");
129 }
130 remote_hwaddr_ = hw_addr;
131}
132
133void
134Pkt::setHWAddrMember(const uint8_t htype, const uint8_t,
135 const std::vector<uint8_t>& hw_addr,
136 HWAddrPtr& storage) {
137
138 storage.reset(new HWAddr(hw_addr, htype));
139}
140
142Pkt::getMAC(uint32_t hw_addr_src) {
143 HWAddrPtr mac;
144
146
147 // Method 1: from raw sockets.
148 if (hw_addr_src & HWAddr::HWADDR_SOURCE_RAW) {
149 mac = getRemoteHWAddr();
150 if (mac) {
151 mac->source_ = HWAddr::HWADDR_SOURCE_RAW;
152 return (mac);
153 } else if (hw_addr_src == HWAddr::HWADDR_SOURCE_RAW) {
154 // If we're interested only in RAW sockets as source of that info,
155 // there's no point in trying other options.
156 return (HWAddrPtr());
157 }
158 }
159
160 // Method 2: From client link-layer address option inserted by a relay
163 if (mac) {
164 return (mac);
165 } else if (hw_addr_src == HWAddr::HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION) {
166 // If we're interested only in RFC6939 link layer address as source
167 // of that info, there's no point in trying other options.
168 return (HWAddrPtr());
169 }
170 }
171
172 // Method 3: Extracted from DUID-LLT or DUID-LL
173 if(hw_addr_src & HWAddr::HWADDR_SOURCE_DUID) {
174 mac = getMACFromDUID();
175 if (mac) {
176 return (mac);
177 } else if (hw_addr_src == HWAddr::HWADDR_SOURCE_DUID) {
178 // If the only source allowed is DUID then we can skip the other
179 // methods.
180 return (HWAddrPtr());
181 }
182 }
183
184 // Method 4: Extracted from source IPv6 link-local address
185 if (hw_addr_src & HWAddr::HWADDR_SOURCE_IPV6_LINK_LOCAL) {
187 if (mac) {
188 return (mac);
189 } else if (hw_addr_src == HWAddr::HWADDR_SOURCE_IPV6_LINK_LOCAL) {
190 // If we're interested only in link-local addr as source of that
191 // info, there's no point in trying other options.
192 return (HWAddrPtr());
193 }
194 }
195
196 // Method 5: From remote-id option inserted by a relay
197 if(hw_addr_src & HWAddr::HWADDR_SOURCE_REMOTE_ID) {
199 if (mac) {
200 return (mac);
201 } else if (hw_addr_src == HWAddr::HWADDR_SOURCE_REMOTE_ID) {
202 // If the only source allowed is remote-id option then we can skip
203 // the other methods.
204 return (HWAddrPtr());
205 }
206 }
207
208 // Method 6: From subscriber-id option inserted by a relay
209
210 // Method 7: From docsis options
211 if (hw_addr_src & HWAddr::HWADDR_SOURCE_DOCSIS_CMTS) {
212 mac = getMACFromDocsisCMTS();
213 if (mac) {
214 return (mac);
215 } else if (hw_addr_src == HWAddr::HWADDR_SOURCE_DOCSIS_CMTS) {
216 // If we're interested only in CMTS options as a source of that
217 // info, there's no point in trying other options.
218 return (HWAddrPtr());
219 }
220 }
221
222 // Method 8: From docsis options
223 if (hw_addr_src & HWAddr::HWADDR_SOURCE_DOCSIS_MODEM) {
224 mac = getMACFromDocsisModem();
225 if (mac) {
226 return (mac);
227 } else if (hw_addr_src == HWAddr::HWADDR_SOURCE_DOCSIS_MODEM) {
228 // If we're interested only in CMTS options as a source of that
229 // info, there's no point in trying other options.
230 return (HWAddrPtr());
231 }
232 }
233
234 // Ok, none of the methods were suitable. Return NULL.
235 return (HWAddrPtr());
236}
237
240 HWAddrPtr mac;
241
242 if (addr.isV6LinkLocal()) {
243 std::vector<uint8_t> bin = addr.toBytes();
244
245 // Double check that it's of appropriate size
246 if ((bin.size() == isc::asiolink::V6ADDRESS_LEN) &&
247 // Check that it's link-local (starts with fe80).
248 (bin[0] == 0xfe) && (bin[1] == 0x80) &&
249 // Check that u bit is set and g is clear.
250 // See Section 2.5.1 of RFC2373 for details.
251 ((bin[8] & 3) == 2) &&
252 // And that the IID is of EUI-64 type.
253 (bin[11] == 0xff) && (bin[12] == 0xfe)) {
254
255 // Remove 8 most significant bytes
256 bin.erase(bin.begin(), bin.begin() + 8);
257
258 // Ok, we're down to EUI-64 only now: XX:XX:XX:ff:fe:XX:XX:XX
259 bin.erase(bin.begin() + 3, bin.begin() + 5);
260
261 // MAC-48 to EUI-64 involves inverting u bit (see explanation
262 // in Section 2.5.1 of RFC2373). We need to revert that.
263 bin[0] = bin[0] ^ 2;
264
265 // Let's get the interface this packet was received on.
266 // We need it to get hardware type
268 uint16_t hwtype = 0; // not specified
269 if (iface) {
270 hwtype = iface->getHWType();
271 }
272
273 mac.reset(new HWAddr(bin, hwtype));
275 }
276 }
277
278 return (mac);
279}
280
281};
282};
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown if a parameter given to a method or function is considered invalid...
Container for storing client class names.
Definition: classify.h:43
bool contains(const ClientClass &x) const
returns if class x belongs to the defined classes
Definition: classify.h:94
void insert(const ClientClass &class_name)
Insert an element.
Definition: classify.h:62
static IfaceMgr & instance()
IfaceMgr is a singleton class.
Definition: iface_mgr.cc:53
IfacePtr getIface(int ifindex)
Returns interface specified interface index.
Definition: iface_mgr.cc:752
bool delOption(uint16_t type)
Attempts to delete first suboption of requested type.
Definition: pkt.cc:83
virtual HWAddrPtr getMACFromDocsisModem()=0
Attempts to extract MAC/Hardware address from DOCSIS options inserted by the modem itself.
virtual HWAddrPtr getMACFromDocsisCMTS()=0
Attempts to extract MAC/Hardware address from DOCSIS options inserted by the CMTS (the relay agent)
ClientClasses required_classes_
Classes which are required to be evaluated.
Definition: pkt.h:596
void repack()
Copies content of input buffer to output buffer.
Definition: pkt.cc:112
virtual HWAddrPtr getMACFromRemoteIdRelayOption()=0
Attempts to obtain MAC address from remote-id relay option.
OptionBuffer data_
Unparsed data (in received packets).
Definition: pkt.h:312
HWAddrPtr getRemoteHWAddr() const
Returns the remote HW address obtained from raw sockets.
Definition: pkt.h:551
virtual HWAddrPtr getMACFromSrcLinkLocalAddr()=0
Attempts to obtain MAC address from source link-local IPv6 address.
ClientClasses classes_
Classes this packet belongs to.
Definition: pkt.h:588
virtual size_t len()=0
Returns packet size in binary format.
HWAddrPtr remote_hwaddr_
Definition: pkt.h:768
isc::dhcp::OptionCollection options_
Collection of options present in this message.
Definition: pkt.h:606
isc::util::OutputBuffer buffer_out_
Output buffer (used during message transmission)
Definition: pkt.h:756
virtual HWAddrPtr getMACFromDUID()=0
Attempts to obtain MAC address from DUID-LL or DUID-LLT.
Pkt(uint32_t transid, const isc::asiolink::IOAddress &local_addr, const isc::asiolink::IOAddress &remote_addr, uint16_t local_port, uint16_t remote_port)
Constructor.
Definition: pkt.cc:17
OptionPtr getOption(const uint16_t type)
Returns the first option of specified type.
Definition: pkt.cc:70
void setRemoteHWAddr(const HWAddrPtr &hw_addr)
Sets remote hardware address.
Definition: pkt.cc:125
bool inClass(const isc::dhcp::ClientClass &client_class)
Checks whether a client belongs to a given class.
Definition: pkt.cc:95
virtual HWAddrPtr getMACFromIPv6RelayOpt()=0
Attempts to obtain MAC address from relay option client-linklayer-addr.
boost::posix_time::ptime timestamp_
packet timestamp
Definition: pkt.h:765
HWAddrPtr getMAC(uint32_t hw_addr_src)
Returns MAC address.
Definition: pkt.cc:142
void updateTimestamp()
Update packet timestamp.
Definition: pkt.cc:108
bool copy_retrieved_options_
Indicates if a copy of the retrieved option should be returned when Pkt::getOption is called.
Definition: pkt.h:762
std::string iface_
Name of the network interface the packet was received/to be sent over.
Definition: pkt.h:721
void addClass(const isc::dhcp::ClientClass &client_class, bool required=false)
Adds packet to a specified class.
Definition: pkt.cc:100
OptionPtr getNonCopiedOption(const uint16_t type) const
Returns the first option of specified type without copying.
Definition: pkt.cc:61
HWAddrPtr getMACFromIPv6(const isc::asiolink::IOAddress &addr)
Attempts to convert IPv6 address into MAC.
Definition: pkt.cc:239
virtual void addOption(const OptionPtr &opt)
Adds an option to this packet.
Definition: pkt.cc:56
void writeData(const void *data, size_t len)
Copy an arbitrary length of data into the buffer.
Definition: buffer.h:547
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
static const uint32_t HWADDR_SOURCE_RAW
Obtained first hand from raw socket (100% reliable).
Definition: hwaddr.h:44
static const uint32_t HWADDR_SOURCE_REMOTE_ID
A relay can insert remote-id.
Definition: hwaddr.h:63
static const uint32_t HWADDR_SOURCE_CLIENT_ADDR_RELAY_OPTION
Get it from RFC6939 option.
Definition: hwaddr.h:59
static const uint32_t HWADDR_SOURCE_IPV6_LINK_LOCAL
Extracted from IPv6 link-local address.
Definition: hwaddr.h:53
static const uint32_t HWADDR_SOURCE_DOCSIS_MODEM
A cable modem (acting as DHCP client) that supports DOCSIS standard can insert DOCSIS options that co...
Definition: hwaddr.h:79
static const uint32_t HWADDR_SOURCE_DUID
Extracted from DUID-LL or DUID-LLT (not 100% reliable as the client can send fake DUID).
Definition: hwaddr.h:48
static const uint32_t HWADDR_SOURCE_DOCSIS_CMTS
A CMTS (acting as DHCP relay agent) that supports DOCSIS standard can insert DOCSIS options that cont...
Definition: hwaddr.h:73
boost::shared_ptr< Iface > IfacePtr
Definition: iface_mgr.h:457
boost::shared_ptr< HWAddr > HWAddrPtr
Shared pointer to a hardware address structure.
Definition: hwaddr.h:154
boost::shared_ptr< Option > OptionPtr
Definition: option.h:38
Defines the logger used by the top-level component of kea-dhcp-ddns.
Hardware type that represents information from DHCPv4 packet.
Definition: hwaddr.h:20