dhcp6_srv.h 31.7 KB
Newer Older
1
// Copyright (C) 2011-2014 Internet Systems Consortium, Inc. ("ISC")
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.

#ifndef DHCPV6_SRV_H
#define DHCPV6_SRV_H

18
#include <dhcp_ddns/ncr_msg.h>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
19
#include <dhcp/dhcp6.h>
20
#include <dhcp/duid.h>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
21
#include <dhcp/option.h>
22
#include <dhcp/option6_client_fqdn.h>
23
#include <dhcp/option6_ia.h>
24
#include <dhcp/option_definition.h>
25
#include <dhcp/pkt6.h>
26
#include <dhcpsrv/alloc_engine.h>
27
#include <dhcpsrv/d2_client_mgr.h>
28
#include <dhcpsrv/subnet.h>
Tomek Mrugalski's avatar
Tomek Mrugalski committed
29
#include <hooks/callout_handle.h>
30
#include <dhcpsrv/daemon.h>
31

32
#include <iostream>
33
#include <queue>
34

35
namespace isc {
36
namespace dhcp {
37

38 39 40 41 42 43 44 45
/// @brief This exception is thrown when DHCP server hits the error which should
/// result in discarding the message being processed.
class DHCPv6DiscardMessageError : public Exception {
public:
    DHCPv6DiscardMessageError(const char* file, size_t line, const char* what) :
        isc::Exception(file, line, what) { };
};

46 47
/// @brief DHCPv6 server service.
///
Stephen Morris's avatar
Stephen Morris committed
48
/// This class represents DHCPv6 server. It contains all
49 50 51 52 53
/// top-level methods and routines necessary for server operation.
/// In particular, it instantiates IfaceMgr, loads or generates DUID
/// that is going to be used as server-identifier, receives incoming
/// packets, processes them, manages leases assignment and generates
/// appropriate responses.
54
class Dhcpv6Srv : public Daemon {
55 56

public:
57 58 59 60 61 62
    /// @brief defines if certain option may, must or must not appear
    typedef enum {
        FORBIDDEN,
        MANDATORY,
        OPTIONAL
    } RequirementLevel;
Tomek Mrugalski's avatar
Tomek Mrugalski committed
63 64 65 66

    /// @brief Minimum length of a MAC address to be used in DUID generation.
    static const size_t MIN_MAC_LEN = 6;

67 68 69 70 71 72
    /// @brief Default constructor.
    ///
    /// Instantiates necessary services, required to run DHCPv6 server.
    /// In particular, creates IfaceMgr that will be responsible for
    /// network interaction. Will instantiate lease manager, and load
    /// old or create new DUID.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
73 74
    ///
    /// @param port port on will all sockets will listen
75
    Dhcpv6Srv(uint16_t port = DHCP6_SERVER_PORT);
76 77

    /// @brief Destructor. Used during DHCPv6 service shutdown.
78
    virtual ~Dhcpv6Srv();
79

80
    /// @brief Returns server-indentifier option.
81 82
    ///
    /// @return server-id option
83
    OptionPtr getServerID() { return serverid_; }
84 85 86 87 88

    /// @brief Main server processing loop.
    ///
    /// Main server processing loop. Receives incoming packets, verifies
    /// their correctness, generates appropriate answer (if needed) and
89
    /// transmits responses.
90 91 92 93 94
    ///
    /// @return true, if being shut down gracefully, fail if experienced
    ///         critical error.
    bool run();

95 96
    /// @brief Instructs the server to shut down.
    void shutdown();
97

98 99
    /// @brief Get UDP port on which server should listen.
    ///
100 101 102
    /// Typically, server listens on UDP port 547. Other ports are only
    /// used for testing purposes.
    ///
103 104 105 106 107 108 109 110 111 112 113
    /// This accessor must be public because sockets are reopened from the
    /// static configuration callback handler. This callback handler invokes
    /// @c ControlledDhcpv4Srv::openActiveSockets which requires port parameter
    /// which has to be retrieved from the @c ControlledDhcpv4Srv object.
    /// They are retrieved using this public function.
    ///
    /// @return UDP port on which server should listen.
    uint16_t getPort() const {
        return (port_);
    }

114 115 116 117 118 119 120 121 122 123
    /// @brief Open sockets which are marked as active in @c CfgMgr.
    ///
    /// This function reopens sockets according to the current settings in the
    /// Configuration Manager. It holds the list of the interfaces which server
    /// should listen on. This function will open sockets on these interfaces
    /// only. This function is not exception safe.
    ///
    /// @param port UDP port on which server should listen.
    static void openActiveSockets(const uint16_t port);

124 125 126 127 128 129 130 131 132
    /// @brief Starts DHCP_DDNS client IO if DDNS updates are enabled.
    ///
    /// If updates are enabled, it Instructs the D2ClientMgr singleton to
    /// enter send mode.  If D2ClientMgr encounters errors it may throw
    /// D2ClientErrors. This method does not catch exceptions.
    void startD2();

    /// @brief Implements the error handler for DHCP_DDNS IO errors
    ///
133
    /// Invoked when a NameChangeRequest send to kea-dhcp-ddns completes with
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
    /// a failed status.  These are communications errors, not data related
    /// failures.
    ///
    /// This method logs the failure and then suspends all further updates.
    /// Updating can only be restored by reconfiguration or restarting the
    /// server.  There is currently no retry logic so the first IO error that
    /// occurs will suspend updates.
    /// @todo We may wish to make this more robust or sophisticated.
    ///
    /// @param result Result code of the send operation.
    /// @param ncr NameChangeRequest which failed to send.
    virtual void d2ClientErrorHandler(const dhcp_ddns::
                                      NameChangeSender::Result result,
                                      dhcp_ddns::NameChangeRequestPtr& ncr);

149
protected:
150

151
    /// @brief Compare received server id with our server id
wlodek's avatar
wlodek committed
152
    ///
153 154
    /// Checks if the server id carried in a query from a client matches
    /// server identifier being used by the server.
wlodek's avatar
wlodek committed
155
    ///
156
    /// @param pkt DHCPv6 packet carrying server identifier to be checked.
157 158
    /// @return true if server id carried in the query matches server id
    /// used by the server; false otherwise.
159
    bool testServerID(const Pkt6Ptr& pkt);
160

161 162 163 164 165 166 167 168 169 170 171 172
    /// @brief Check if the message can be sent to unicast.
    ///
    /// This function checks if the received message conforms to the section 15
    /// of RFC3315 which says that: "A server MUST discard any Solicit, Confirm,
    /// Rebind or Information-request messages it receives with a unicast
    /// destination address.
    ///
    /// @param pkt DHCPv6 message to be checked.
    /// @return false if the message has been sent to unicast address but it is
    /// not allowed according to RFC3315, section 15; true otherwise.
    bool testUnicast(const Pkt6Ptr& pkt) const;

173 174 175 176 177 178 179 180 181 182 183 184
    /// @brief verifies if specified packet meets RFC requirements
    ///
    /// Checks if mandatory option is really there, that forbidden option
    /// is not there, and that client-id or server-id appears only once.
    ///
    /// @param pkt packet to be checked
    /// @param clientid expectation regarding client-id option
    /// @param serverid expectation regarding server-id option
    /// @throw RFCViolation if any issues are detected
    void sanityCheck(const Pkt6Ptr& pkt, RequirementLevel clientid,
                     RequirementLevel serverid);

185 186 187 188
    /// @brief Processes incoming SOLICIT and returns response.
    ///
    /// Processes received SOLICIT message and verifies that its sender
    /// should be served. In particular IA, TA and PD options are populated
189
    /// with to-be assigned addresses, temporary addresses and delegated
190 191 192 193 194 195 196 197 198
    /// prefixes, respectively. In the usual 4 message exchange, server is
    /// expected to respond with ADVERTISE message. However, if client
    /// requests rapid-commit and server supports it, REPLY will be sent
    /// instead of ADVERTISE and requested leases will be assigned
    /// immediately.
    ///
    /// @param solicit SOLICIT message received from client
    ///
    /// @return ADVERTISE, REPLY message or NULL
199
    Pkt6Ptr processSolicit(const Pkt6Ptr& solicit);
200 201 202 203 204

    /// @brief Processes incoming REQUEST and returns REPLY response.
    ///
    /// Processes incoming REQUEST message and verifies that its sender
    /// should be served. In particular IA, TA and PD options are populated
205
    /// with assigned addresses, temporary addresses and delegated
206 207 208 209 210 211
    /// prefixes, respectively. Uses LeaseMgr to allocate or update existing
    /// leases.
    ///
    /// @param request a message received from client
    ///
    /// @return REPLY message or NULL
212
    Pkt6Ptr processRequest(const Pkt6Ptr& request);
213 214 215 216

    /// @brief Stub function that will handle incoming RENEW messages.
    ///
    /// @param renew message received from client
217
    Pkt6Ptr processRenew(const Pkt6Ptr& renew);
218 219 220 221

    /// @brief Stub function that will handle incoming REBIND messages.
    ///
    /// @param rebind message received from client
222
    Pkt6Ptr processRebind(const Pkt6Ptr& rebind);
223

224
    /// @brief Processes incoming Confirm message and returns Reply.
225
    ///
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246
    /// This function processes Confirm message from the client according
    /// to section 18.2.2. of RFC3315. It discards the Confirm message if
    /// the message sent by the client contains no addresses, i.e. it has
    /// no IA_NA options or all IA_NA options contain no IAAddr options.
    ///
    /// If the Confirm message contains addresses this function will perform
    /// the following checks:
    /// - check if there is appropriate subnet configured for the client
    /// (e.g. subnet from which addresses are assigned for requests
    /// received on the particular interface).
    /// - check if all addresses sent in the Confirm message belong to the
    /// selected subnet.
    ///
    /// If any of the checks above fails, the Reply message with the status
    /// code NotOnLink is returned. Otherwise, the Reply message with the
    /// status code Success is returned.
    ///
    /// @param confirm Confirm message sent by a client.
    ///
    /// @return Reply message from the server al NULL pointer if Confirm
    /// message should be discarded by the server.
247
    Pkt6Ptr processConfirm(const Pkt6Ptr& confirm);
248 249 250 251

    /// @brief Stub function that will handle incoming RELEASE messages.
    ///
    /// @param release message received from client
252
    Pkt6Ptr processRelease(const Pkt6Ptr& release);
253 254 255 256

    /// @brief Stub function that will handle incoming DECLINE messages.
    ///
    /// @param decline message received from client
257
    Pkt6Ptr processDecline(const Pkt6Ptr& decline);
258 259 260 261

    /// @brief Stub function that will handle incoming INF-REQUEST messages.
    ///
    /// @param infRequest message received from client
262
    Pkt6Ptr processInfRequest(const Pkt6Ptr& infRequest);
263

Tomek Mrugalski's avatar
Tomek Mrugalski committed
264
    /// @brief Creates status-code option.
265 266 267 268 269 270
    ///
    /// @param code status code value (see RFC3315)
    /// @param text textual explanation (will be sent in status code option)
    /// @return status-code option
    OptionPtr createStatusCode(uint16_t code, const std::string& text);

Tomek Mrugalski's avatar
Tomek Mrugalski committed
271
    /// @brief Selects a subnet for a given client's packet.
272
    ///
Tomek Mrugalski's avatar
Tomek Mrugalski committed
273
    /// @param question client's message
274
    /// @return selected subnet (or NULL if no suitable subnet was found)
275
    isc::dhcp::Subnet6Ptr selectSubnet(const Pkt6Ptr& question);
276

Tomek Mrugalski's avatar
Tomek Mrugalski committed
277
    /// @brief Processes IA_NA option (and assigns addresses if necessary).
278 279
    ///
    /// Generates response to IA_NA. This typically includes selecting (and
280
    /// allocating a lease in case of REQUEST) an address lease and creating
281 282 283 284 285 286
    /// IAADDR option. In case of allocation failure, it may contain
    /// status code option with non-zero status, denoting cause of the
    /// allocation failure.
    ///
    /// @param subnet subnet the client is connected to
    /// @param duid client's duid
287
    /// @param query client's message (typically SOLICIT or REQUEST)
288 289 290
    /// @param answer server's response to the client's message. This
    /// message should contain Client FQDN option being sent by the server
    /// to the client (if the client sent this option to the server).
291
    /// @param ia pointer to client's IA_NA option (client's request)
292
    ///
293
    /// @return IA_NA option (server's response)
294
    OptionPtr assignIA_NA(const isc::dhcp::Subnet6Ptr& subnet,
295
                          const isc::dhcp::DuidPtr& duid,
296
                          const isc::dhcp::Pkt6Ptr& query,
297 298
                          const isc::dhcp::Pkt6Ptr& answer,
                          Option6IAPtr ia);
299

300 301 302
    /// @brief Processes IA_PD option (and assigns prefixes if necessary).
    ///
    /// Generates response to IA_PD. This typically includes selecting (and
303 304 305
    /// allocating in the case of REQUEST) a prefix lease and creating an
    /// IAPREFIX option. In case of an allocation failure, it may contain a
    /// status code option with non-zero status denoting the cause of the
306 307 308 309 310 311 312 313 314 315 316
    /// allocation failure.
    ///
    /// @param subnet subnet the client is connected to
    /// @param duid client's duid
    /// @param query client's message (typically SOLICIT or REQUEST)
    /// @param ia pointer to client's IA_PD option (client's request)
    /// @return IA_PD option (server's response)
    OptionPtr assignIA_PD(const Subnet6Ptr& subnet, const DuidPtr& duid,
                          const Pkt6Ptr& query,
                          boost::shared_ptr<Option6IA> ia);

317
    /// @brief Extends lifetime of the specific IA_NA option.
318
    ///
319 320 321 322
    /// Generates response to IA_NA in Renew or Rebind. This typically includes
    /// finding a lease that corresponds to the received address. If no such
    /// lease is found, an IA_NA response is generated with an appropriate
    /// status code.
323
    ///
324 325 326 327 328 329 330 331 332 333 334 335
    /// @todo The behavior of this function will need to be extended to support
    /// draft-ietf-dhc-dhcpv6-stateful-issues. This draft modifies the behavior
    /// described in RFC3315 with respect to Renew and Rebind processing. Key
    /// changes are (version -05):
    /// - Renewing and Rebinding client MAY request additional bindings by
    /// putting an IA for all bindings it desires but has been unable to obtain.
    /// Server MAY allocate addresses if it finds that they are appropriate for
    /// the link that client is attached to.
    /// - When receiving Rebind, if the server determines that the addresses are
    /// not appropriate for the link the client is attached to, the server MAY
    /// send the IA with address lifetimes set to 0 or discard the message.
    ///
336 337
    /// @param subnet subnet the sender belongs to
    /// @param duid client's duid
338
    /// @param query client's message (Renew or Rebind)
339 340 341
    /// @param answer server's response to the client's message. This
    /// message should contain Client FQDN option being sent by the server
    /// to the client (if the client sent this option to the server).
342 343
    /// @param ia IA_NA option which carries adress for which lease lifetime
    /// will be extended.
344
    /// @return IA_NA option (server's response)
345 346
    OptionPtr extendIA_NA(const Subnet6Ptr& subnet, const DuidPtr& duid,
                          const Pkt6Ptr& query, const Pkt6Ptr& answer,
347
                          Option6IAPtr ia);
348

349 350 351 352
    /// @brief Extends lifetime of the prefix.
    ///
    /// This function is called by the logic which processes Renew and Rebind
    /// messages to extend the lifetime of the existing prefix.
353
    ///
354 355 356 357 358
    /// The behavior of this function is different in that when there is no
    /// binding found in the lease database for the particular client the
    /// NoBinding status code is returned when processing Renew, the exception
    /// is thrown when there is no binding and the Rebind message is processed
    /// (see RFC3633, section 12.2. for details).
359 360 361 362 363 364
    ///
    /// @param subnet subnet the sender belongs to
    /// @param duid client's duid
    /// @param query client's message
    /// @param ia IA_PD option that is being renewed
    /// @return IA_PD option (server's response)
365 366 367 368 369
    /// @throw DHCPv6DiscardMessageError when the message being processed should
    /// be discarded by the server, i.e. there is no binding for the client doing
    /// Rebind.
    OptionPtr extendIA_PD(const Subnet6Ptr& subnet, const DuidPtr& duid,
                          const Pkt6Ptr& query, Option6IAPtr ia);
370

371 372 373 374 375 376 377
    /// @brief Releases specific IA_NA option
    ///
    /// Generates response to IA_NA in Release message. This covers finding and
    /// removal of a lease that corresponds to the received address. If no such
    /// lease is found, an IA_NA response is generated with an appropriate
    /// status code.
    ///
Tomek Mrugalski's avatar
Tomek Mrugalski committed
378 379 380 381
    /// As RFC 3315 requires that a single status code be sent for the whole message,
    /// this method may update the passed general_status: it is set to SUCCESS when
    /// message processing begins, but may be updated to some error code if the
    /// release process fails.
382 383
    ///
    /// @param duid client's duid
384
    /// @param query client's message
385
    /// @param general_status a global status (it may be updated in case of errors)
386
    /// @param ia IA_NA option that is being released
387
    /// @return IA_NA option (server's response)
388
    OptionPtr releaseIA_NA(const DuidPtr& duid, const Pkt6Ptr& query,
389 390 391
                           int& general_status,
                           boost::shared_ptr<Option6IA> ia);

392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407
    /// @brief Releases specific IA_PD option
    ///
    /// Generates response to IA_PD in Release message. This covers finding and
    /// removal of a lease that corresponds to the received prefix(es). If no such
    /// lease is found, an IA_PD response is generated with an appropriate
    /// status code.
    ///
    /// @param duid client's duid
    /// @param query client's message
    /// @param general_status a global status (it may be updated in case of errors)
    /// @param ia IA_PD option that is being released
    /// @return IA_PD option (server's response)
    OptionPtr releaseIA_PD(const DuidPtr& duid, const Pkt6Ptr& query,
                           int& general_status,
                           boost::shared_ptr<Option6IA> ia);

Tomek Mrugalski's avatar
Tomek Mrugalski committed
408
    /// @brief Copies required options from client message to server answer.
409 410 411 412 413 414 415
    ///
    /// Copies options that must appear in any server response (ADVERTISE, REPLY)
    /// to client's messages (SOLICIT, REQUEST, RENEW, REBIND, DECLINE, RELEASE).
    /// One notable example is client-id. Other options may be copied as required.
    ///
    /// @param question client's message (options will be copied from here)
    /// @param answer server's message (options will be copied here)
416
    void copyDefaultOptions(const Pkt6Ptr& question, Pkt6Ptr& answer);
417 418 419 420 421 422 423 424 425

    /// @brief Appends default options to server's answer.
    ///
    /// Adds required options to server's answer. In particular, server-id
    /// is added. Possibly other mandatory options will be added, depending
    /// on type (or content) of client message.
    ///
    /// @param question client's message
    /// @param answer server's message (options will be added here)
426
    void appendDefaultOptions(const Pkt6Ptr& question, Pkt6Ptr& answer);
427 428 429 430 431 432 433

    /// @brief Appends requested options to server's answer.
    ///
    /// Appends options requested by client to the server's answer.
    ///
    /// @param question client's message
    /// @param answer server's message (options will be added here)
434
    void appendRequestedOptions(const Pkt6Ptr& question, Pkt6Ptr& answer);
435

436 437 438 439 440 441 442 443
    /// @brief Appends requested vendor options to server's answer.
    ///
    /// This is mostly useful for Cable Labs options for now, but the method
    /// is easily extensible to other vendors.
    ///
    /// @param question client's message
    /// @param answer server's message (vendor options will be added here)
    void appendRequestedVendorOptions(const Pkt6Ptr& question, Pkt6Ptr& answer);
444 445 446

    /// @brief Assigns leases.
    ///
447 448
    /// It supports addresses (IA_NA) only. It does NOT support temporary
    /// addresses (IA_TA) nor prefixes (IA_PD).
Tomek Mrugalski's avatar
Tomek Mrugalski committed
449
    /// @todo: Extend this method once TA and PD becomes supported
450 451
    ///
    /// @param question client's message (with requested IA_NA)
452 453 454 455
    /// @param answer server's message (IA_NA options will be added here).
    /// This message should contain Client FQDN option being sent by the server
    /// to the client (if the client sent this option to the server).
    void assignLeases(const Pkt6Ptr& question, Pkt6Ptr& answer);
456

457 458 459 460 461 462 463
    /// @brief Processes Client FQDN Option.
    ///
    /// This function retrieves DHCPv6 Client FQDN %Option (if any) from the
    /// packet sent by a client and takes necessary actions upon this option.
    /// Received option comprises flags field which controls what DNS updates
    /// server should do. Server may override client's preference based on
    /// the current configuration. Server indicates that it has overridden
464
    /// the preference by storing DHCPv6 Client FQDN option with the
465 466 467 468 469 470 471 472 473 474
    /// appropriate flags in the response to a client. This option is also
    /// used to communicate the client's domain-name which should be sent
    /// to the DNS in the update. Again, server may act upon the received
    /// domain-name, i.e. if the provided domain-name is partial it should
    /// generate the fully qualified domain-name.
    ///
    /// All the logic required to form appropriate answer to the client is
    /// held in this function.
    ///
    /// @param question Client's message.
475 476 477 478
    /// @param answer Server's response to a client. If server generated
    /// Client FQDN option for the client, this option is stored in this
    /// object.
    void processClientFqdn(const Pkt6Ptr& question, const Pkt6Ptr& answer);
479

480 481
    /// @brief Creates a number of @c isc::dhcp_ddns::NameChangeRequest objects
    /// based on the DHCPv6 Client FQDN %Option.
482
    ///
483 484 485
    /// The @c isc::dhcp_ddns::NameChangeRequest class encapsulates the request
    /// from the DHCPv6 server to the DHCP-DDNS module to perform DNS Update.
    /// The FQDN option carries response to the client about DNS updates that
486
    /// server intents to perform for the DNS client. Based on this, the
487 488 489 490
    /// function will create zero or more @c isc::dhcp_ddns::NameChangeRequest
    /// objects and store them in the internal queue. Requests created by this
    /// function are only adding or updating DNS records. In order to generate
    /// requests for DNS records removal, use @c createRemovalNameChangeRequest.
491
    /// If ddns updates are disabled, this method returns immediately.
492
    ///
493 494
    /// @todo Add support for multiple IAADDR options in the IA_NA.
    ///
495 496
    /// @param answer A message beging sent to the Client. If it holds the
    /// Client FQDN option, this option is used to create NameChangeRequests.
497
    void createNameChangeRequests(const Pkt6Ptr& answer);
498

499 500
    /// @brief Creates a @c isc::dhcp_ddns::NameChangeRequest which requests
    /// removal of DNS entries for a particular lease.
501 502 503
    ///
    /// This function should be called upon removal of the lease from the lease
    /// database, i.e, when client sent Release or Decline message. It will
504 505 506 507 508
    /// create a single @c isc::dhcp_ddns::NameChangeRequest which removes the
    /// existing DNS records for the lease, which server is responsible for.
    /// Note that this function will not remove the entries which server hadn't
    /// added. This is the case, when client performs forward DNS update on its
    /// own.
509
    /// If ddns updates are disabled, this method returns immediately.
510
    ///
511
    /// @param lease A lease for which the the removal of corresponding DNS
512 513
    /// records will be performed.
    void createRemovalNameChangeRequest(const Lease6Ptr& lease);
514

515 516 517 518 519 520 521
    /// @brief Attempts to extend the lifetime of IAs.
    ///
    /// This function is called when a client sends Renew or Rebind message.
    /// It iterates through received IA options and attempts to extend
    /// corresponding lease lifetimes. Internally, it calls
    /// @c Dhcpv6Srv::extendIA_NA and @c Dhcpv6Srv::extendIA_PD to extend
    /// the lifetime of IA_NA and IA_PD leases accordingly.
522
    ///
523
    /// @param query client's Renew or Rebind message
524
    /// @param reply server's response
525
    void extendLeases(const Pkt6Ptr& query, Pkt6Ptr& reply);
526

527 528 529 530 531 532 533 534 535 536 537
    /// @brief Attempts to release received addresses
    ///
    /// It iterates through received IA_NA options and attempts to release
    /// received addresses. If no such leases are found, or the lease fails
    /// proper checks (e.g. belongs to someone else), a proper status
    /// code is added to reply message. Released addresses are not added
    /// to REPLY packet, just its IA_NA containers.
    /// @param release client's message asking to release
    /// @param reply server's response
    void releaseLeases(const Pkt6Ptr& release, Pkt6Ptr& reply);

538 539
    /// @brief Sets server-identifier.
    ///
540 541 542
    /// This method attempts to generate server-identifier DUID. It generates a
    /// new DUID using interface link-layer addresses (EUI-64) + timestamp (DUID
    /// type duid-llt, see RFC3315, section 9.2). If there are no suitable
543 544 545 546
    /// interfaces present, exception it thrown
    ///
    /// @throws isc::Unexpected Failed to read DUID file and no suitable
    ///         interfaces for new DUID generation are detected.
547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
    void generateServerID();

    /// @brief attempts to load DUID from a file
    ///
    /// Tries to load duid from a text file. If the load is successful,
    /// it creates server-id option and stores it in serverid_ (to be used
    /// later by getServerID()).
    ///
    /// @param file_name name of the DUID file to load
    /// @return true if load was successful, false otherwise
    bool loadServerID(const std::string& file_name);

    /// @brief attempts to write DUID to a file
    /// Tries to write duid content (stored in serverid_) to a text file.
    ///
    /// @param file_name name of the DUID file to write
    /// @return true if write was successful, false otherwise
    bool writeServerID(const std::string& file_name);

    /// @brief converts DUID to text
    /// Converts content of DUID option to a text representation, e.g.
    /// 01:ff:02:03:06:80:90:ab:cd:ef
    ///
    /// @param opt option that contains DUID
    /// @return string representation
    static std::string duidToString(const OptionPtr& opt);
573

574 575 576 577 578 579 580

    /// @brief dummy wrapper around IfaceMgr::receive6
    ///
    /// This method is useful for testing purposes, where its replacement
    /// simulates reception of a packet. For that purpose it is protected.
    virtual Pkt6Ptr receivePacket(int timeout);

581 582 583
    /// @brief dummy wrapper around IfaceMgr::send()
    ///
    /// This method is useful for testing purposes, where its replacement
Tomek Mrugalski's avatar
Tomek Mrugalski committed
584
    /// simulates transmission of a packet. For that purpose it is protected.
585 586
    virtual void sendPacket(const Pkt6Ptr& pkt);

587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604
    /// @brief Implements a callback function to parse options in the message.
    ///
    /// @param buf a A buffer holding options in on-wire format.
    /// @param option_space A name of the option space which holds definitions
    /// of to be used to parse options in the packets.
    /// @param [out] options A reference to the collection where parsed options
    /// will be stored.
    /// @param relay_msg_offset Reference to a size_t structure. If specified,
    /// offset to beginning of relay_msg option will be stored in it.
    /// @param relay_msg_len reference to a size_t structure. If specified,
    /// length of the relay_msg option will be stored in it.
    /// @return An offset to the first byte after last parsed option.
    size_t unpackOptions(const OptionBuffer& buf,
                         const std::string& option_space,
                         isc::dhcp::OptionCollection& options,
                         size_t* relay_msg_offset,
                         size_t* relay_msg_len);

605 606 607 608 609 610 611 612 613 614
    /// @brief Assigns incoming packet to zero or more classes.
    ///
    /// @note For now, the client classification is very simple. It just uses
    /// content of the vendor-class-identifier option as a class. The resulting
    /// class will be stored in packet (see @ref isc::dhcp::Pkt6::classes_ and
    /// @ref isc::dhcp::Pkt6::inClass).
    ///
    /// @param pkt packet to be classified
    void classifyPacket(const Pkt6Ptr& pkt);

615 616 617 618 619 620 621 622 623

    /// @brief this is a prefix added to the contend of vendor-class option
    ///
    /// If incoming packet has a vendor class option, its content is
    /// prepended with this prefix and then interpreted as a class.
    /// For example, a packet that sends vendor class with value of "FOO"
    /// will cause the packet to be assigned to class VENDOR_CLASS_FOO.
    static const std::string VENDOR_CLASS_PREFIX;

624
private:
625 626 627 628 629 630 631 632 633 634

    /// @brief Implements the error handler for socket open failure.
    ///
    /// This callback function is installed on the @c isc::dhcp::IfaceMgr
    /// when IPv6 sockets are being open. When socket fails to open for
    /// any reason, this function is called. It simply logs the error message.
    ///
    /// @param errmsg An error message containing a cause of the failure.
    static void ifaceMgrSocket6ErrorHandler(const std::string& errmsg);

635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
    /// @brief Generate FQDN to be sent to a client if none exists.
    ///
    /// This function is meant to be called by the functions which process
    /// client's messages. The function should be called after a function
    /// which creates FQDN option for the client. This option must exist
    /// in the answer message specified as an argument. It must also be
    /// called after functions which assign leases for a client. The
    /// IA options being a result of lease acquisition must be appended
    /// to the message specified as a parameter.
    ///
    /// If the Client FQDN option being present in the message carries empty
    /// hostname, this function will attempt to generate hostname from the
    /// IPv6 address being acquired by the client. The IPv6 address is retrieved
    /// from the IA_NA option carried in the specified message. If multiple
    /// addresses are present in the particular IA_NA option or multiple IA_NA
    /// options exist, the first address found is selected.
    ///
    /// The IPv6 address is converted to the hostname using the following
    /// pattern:
    /// @code
    ///     prefix-converted-ip-address.domain-name-suffix.
    /// @endcode
    /// where:
    /// - prefix is a configurable prefix string appended to all auto-generated
    /// hostnames.
    /// - converted-ip-address is created by replacing all colons from the IPv6
    /// address with hyphens.
    /// - domain-name-suffix is a suffix for a domain name that, together with
    /// the other parts, constitute the fully qualified domain name.
    ///
    /// When hostname is successfully generated, it is either used to update
    /// FQDN-related fields in a lease database or to update the Client FQDN
    /// option being sent back to the client. The lease database update is
    /// NOT performed if Advertise message is being processed.
    ///
    /// @param answer Message being sent to a client, which may hold IA_NA
    /// and Client FQDN options to be used to generate name for a client.
    ///
    /// @throw isc::Unexpected if specified message is NULL. This is treated
    /// as a programmatic error.
    void generateFqdn(const Pkt6Ptr& answer);

Tomek Mrugalski's avatar
Tomek Mrugalski committed
677
    /// @brief Allocation Engine.
678 679 680
    /// Pointer to the allocation engine that we are currently using
    /// It must be a pointer, because we will support changing engines
    /// during normal operation (e.g. to use different allocators)
Stephen Morris's avatar
Stephen Morris committed
681 682 683
    boost::shared_ptr<AllocEngine> alloc_engine_;

    /// Server DUID (to be sent in server-identifier option)
684
    OptionPtr serverid_;
685

686 687
    /// UDP port number on which server listens.
    uint16_t port_;
688

689 690
protected:

691 692 693 694
    /// Indicates if shutdown is in progress. Setting it to true will
    /// initiate server shutdown procedure.
    volatile bool shutdown_;

695
    /// Holds a list of @c isc::dhcp_ddns::NameChangeRequest objects, which
696
    /// are waiting for sending to kea-dhcp-ddns module.
697
    std::queue<isc::dhcp_ddns::NameChangeRequest> name_change_reqs_;
698 699 700
};

}; // namespace isc::dhcp
701
}; // namespace isc
702 703

#endif // DHCP6_SRV_H