dhcp4_srv.h 32.9 KB
 Francis Dupont committed Jan 22, 2015 1 // Copyright (C) 2011-2015 Internet Systems Consortium, Inc. ("ISC")  Tomek Mrugalski committed Nov 27, 2011 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 DHCPV4_SRV_H #define DHCPV4_SRV_H  Tomek Mrugalski committed Dec 05, 2011 18 #include  Tomek Mrugalski committed Nov 27, 2011 19 20 #include #include  Thomas Markwalder committed Feb 19, 2014 21 #include  Marcin Siodelski committed Aug 28, 2013 22 #include  Marcin Siodelski committed Sep 09, 2013 23 #include  Marcin Siodelski committed Sep 02, 2013 24 #include  Thomas Markwalder committed Feb 13, 2014 25 #include  Tomek Mrugalski committed Dec 31, 2012 26 27 #include #include  28 #include  Tomek Mrugalski committed Jul 15, 2013 29 #include  Tomek Mrugalski committed May 21, 2014 30 #include  Stephen Morris committed Nov 16, 2012 31 32 33  #include  Tomek Mrugalski committed Nov 27, 2011 34 #include  Marcin Siodelski committed Sep 03, 2013 35 #include  Tomek Mrugalski committed Nov 27, 2011 36   Francis Dupont committed Jun 23, 2015 37 38 39 40 // Undefine the macro OPTIONAL which is defined in some operating // systems but conflicts with a member of the RequirementLevel enum in // the server class.  Francis Dupont committed May 18, 2015 41 42 43 44 #ifdef OPTIONAL #undef OPTIONAL #endif  Tomek Mrugalski committed Nov 27, 2011 45 46 namespace isc { namespace dhcp {  Tomek Mrugalski committed Dec 31, 2012 47   Marcin Siodelski committed Mar 10, 2015 48 49 50 51 52 /// @brief DHCPv4 message exchange. /// /// This class represents the DHCPv4 message exchange. The message exchange /// consists of the single client message, server response to this message /// and the mechanisms to generate the server's response. The server creates  Marcin Siodelski committed Mar 12, 2015 53 /// the instance of the @c Dhcpv4Exchange for each inbound message that it  Marcin Siodelski committed Mar 10, 2015 54 55 /// accepts for processing. ///  Marcin Siodelski committed Mar 12, 2015 56 /// The use of the @c Dhcpv4Exchange object as a central repository of  Marcin Siodelski committed Mar 10, 2015 57 58 59 60 61 62 63 64 65 66 /// information about the message exchange simplifies the API of the /// @c Dhcpv4Srv class. /// /// Another benefit of using this class is that different methods of the /// @c Dhcpv4Srv may share information. For example, the constructor of this /// class selects the subnet and multiple methods of @c Dhcpv4Srv use this /// subnet, without the need to select it again. /// /// @todo This is the initial version of this class. In the future a lot of /// code from the @c Dhcpv4Srv class will be migrated here.  Marcin Siodelski committed Mar 12, 2015 67 class Dhcpv4Exchange {  Marcin Siodelski committed Mar 10, 2015 68 69 70 71 72 73 74 75 76 77 78 79 public: /// @brief Constructor. /// /// The constructor selects the subnet for the query and checks for the /// static host reservations for the client which has sent the message. /// The information about the reservations is stored in the /// @c AllocEngine::ClientContext4 object, which can be obtained by /// calling the @c getContext. /// /// @param alloc_engine Pointer to the instance of the Allocation Engine /// used by the server. /// @param query Pointer to the client message.  Marcin Siodelski committed Mar 12, 2015 80 81 82  /// @param subnet Pointer to the subnet to which the client belongs. Dhcpv4Exchange(const AllocEnginePtr& alloc_engine, const Pkt4Ptr& query, const Subnet4Ptr& subnet);  Marcin Siodelski committed Mar 10, 2015 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113  /// @brief Initializes the instance of the response message. /// /// The type of the response depends on the type of the query message. /// For the DHCPDISCOVER the DHCPOFFER is created. For the DHCPREQUEST /// and DHCPINFORM the DHCPACK is created. For the DHCPRELEASE the /// response is not initialized. void initResponse(); /// @brief Returns the pointer to the query from the client. Pkt4Ptr getQuery() const { return (query_); } /// @brief Returns the pointer to the server's response. /// /// The returned pointer is NULL if the query type is DHCPRELEASE or DHCPDECLINE. Pkt4Ptr getResponse() const { return (resp_); } /// @brief Removes the response message by resetting the pointer to NULL. void deleteResponse() { resp_.reset(); } /// @brief Returns the copy of the context for the Allocation engine. AllocEngine::ClientContext4Ptr getContext() const { return (context_); }  Francis Dupont committed Nov 25, 2015 114  /// @brief Returns the configured option list (non-const version)  115 116 117 118  CfgOptionList& getCfgOptionList() { return (cfg_option_list_); }  Francis Dupont committed Nov 25, 2015 119  /// @brief Returns the configured option list (const version)  120 121 122 123  const CfgOptionList& getCfgOptionList() const { return (cfg_option_list_); }  Marcin Siodelski committed Mar 10, 2015 124 private:  Marcin Siodelski committed Mar 12, 2015 125 126 127 128 129 130 131 132 133 134 135 136  /// @brief Copies default parameters from client's to server's message /// /// Some fields are copied from client's message into server's response, /// e.g. client HW address, number of hops, transaction-id etc. /// /// @warning This message is called internally by @c initResponse and /// thus it doesn't check if the resp_ value has been initialized. The /// calling method is responsible for making sure that @c resp_ is /// not NULL. void copyDefaultFields();  Francis Dupont committed Oct 13, 2015 137 138 139 140 141 142 143 144 145 146 147  /// @brief Copies default options from client's to server's message /// /// Some options are copied from client's message into server's response, /// e.g. Relay Agent Info option, Subnet Selection option etc. /// /// @warning This message is called internally by @c initResponse and /// thus it doesn't check if the resp_ value has been initialized. The /// calling method is responsible for making sure that @c resp_ is /// not NULL. void copyDefaultOptions();  Marcin Siodelski committed Mar 10, 2015 148 149 150 151 152 153 154 155  /// @brief Pointer to the allocation engine used by the server. AllocEnginePtr alloc_engine_; /// @brief Pointer to the DHCPv4 message sent by the client. Pkt4Ptr query_; /// @brief Pointer to the DHCPv4 message to be sent to the client. Pkt4Ptr resp_; /// @brief Context for use with allocation engine. AllocEngine::ClientContext4Ptr context_;  Francis Dupont committed Nov 25, 2015 156 157 158  /// @brief Configured option list. /// @note The configured option list is an *ordered* list of /// @c CfgOption objects used to append options to the response.  159  CfgOptionList cfg_option_list_;  Marcin Siodelski committed Mar 10, 2015 160 161 };  Marcin Siodelski committed Mar 12, 2015 162 163 /// @brief Type representing the pointer to the @c Dhcpv4Exchange. typedef boost::shared_ptr Dhcpv4ExchangePtr;  Marcin Siodelski committed Mar 10, 2015 164 165   Tomek Mrugalski committed Nov 27, 2011 166 167 168 169 170 171 172 173 /// @brief DHCPv4 server service. /// /// This singleton class represents DHCPv4 server. It contains all /// 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.  Tomek Mrugalski committed Jun 08, 2012 174 175 /// /// This class does not support any controlling mechanisms directly.  Stephen Morris committed Dec 10, 2012 176 /// See the derived \ref ControlledDhcpv4Srv class for support for  Tomek Mrugalski committed Jun 08, 2012 177 /// command and configuration updates over msgq.  Tomek Mrugalski committed May 21, 2014 178 class Dhcpv4Srv : public Daemon {  Tomek Mrugalski committed Nov 27, 2011 179   Marcin Siodelski committed May 22, 2013 180 public:  Tomek Mrugalski committed Dec 31, 2012 181 182 183 184 185 186 187 188  /// @brief defines if certain option may, must or must not appear typedef enum { FORBIDDEN, MANDATORY, OPTIONAL } RequirementLevel;  Tomek Mrugalski committed Nov 27, 2011 189 190  /// @brief Default constructor. ///  Stephen Morris committed Sep 12, 2012 191  /// Instantiates necessary services, required to run DHCPv4 server.  Tomek Mrugalski committed Nov 27, 2011 192 193  /// In particular, creates IfaceMgr that will be responsible for /// network interaction. Will instantiate lease manager, and load  Tomek Mrugalski committed Dec 12, 2011 194 195  /// old or create new DUID. It is possible to specify alternate /// port on which DHCPv4 server will listen on. That is mostly useful  Marcin Siodelski committed Apr 29, 2013 196 197  /// for testing purposes. The Last two arguments of the constructor /// should be left at default values for normal server operation.  Marcin Siodelski committed Apr 30, 2013 198 199 200  /// They should be set to 'false' when creating an instance of this /// class for unit testing because features they enable require /// root privileges.  Tomek Mrugalski committed Dec 12, 2011 201 202  /// /// @param port specifies port number to listen on  Marcin Siodelski committed Apr 04, 2013 203  /// @param use_bcast configure sockets to support broadcast messages.  Marcin Siodelski committed Apr 30, 2013 204 205  /// @param direct_response_desired specifies if it is desired to /// use direct V4 traffic.  Tomek Mrugalski committed Dec 31, 2012 206  Dhcpv4Srv(uint16_t port = DHCP4_SERVER_PORT,  Marcin Siodelski committed Apr 29, 2013 207 208  const bool use_bcast = true, const bool direct_response_desired = true);  Tomek Mrugalski committed Nov 27, 2011 209   Stephen Morris committed Sep 12, 2012 210  /// @brief Destructor. Used during DHCPv4 service shutdown.  Mukund Sivaraman committed Jul 24, 2013 211  virtual ~Dhcpv4Srv();  Tomek Mrugalski committed Nov 27, 2011 212   Francis Dupont committed May 22, 2015 213  /// @brief returns Kea version on stdout and exit.  Francis Dupont committed Jun 11, 2015 214  /// redeclaration/redefinition. @ref Daemon::getVersion()  Francis Dupont committed May 22, 2015 215 216  static std::string getVersion(bool extended);  Tomek Mrugalski committed Nov 27, 2011 217 218 219 220  /// @brief Main server processing loop. /// /// Main server processing loop. Receives incoming packets, verifies /// their correctness, generates appropriate answer (if needed) and  Francis Dupont committed Jan 22, 2015 221  /// transmits responses.  Tomek Mrugalski committed Nov 27, 2011 222 223 224 225 226  /// /// @return true, if being shut down gracefully, fail if experienced /// critical error. bool run();  Tomek Mrugalski committed Jun 08, 2012 227  /// @brief Instructs the server to shut down.  Tomek Mrugalski committed May 30, 2012 228 229  void shutdown();  Marcin Siodelski committed Jul 11, 2013 230 231 232 233 234 235 236  /// /// @name Public accessors returning values required to (re)open sockets. /// //@{ /// /// @brief Get UDP port on which server should listen. ///  Marcin Siodelski committed Jul 19, 2013 237 238 239  /// Typically, server listens on UDP port number 67. Other ports are used /// for testing purposes only. ///  Marcin Siodelski committed Jul 11, 2013 240 241 242 243 244 245 246 247 248 249 250 251 252 253  /// @return UDP port on which server should listen. uint16_t getPort() const { return (port_); } /// @brief Return bool value indicating that broadcast flags should be set /// on sockets. /// /// @return A bool value indicating that broadcast should be used (if true). bool useBroadcast() const { return (use_bcast_); } //@}  Thomas Markwalder committed Feb 13, 2014 254 255  /// @brief Starts DHCP_DDNS client IO if DDNS updates are enabled. ///  Thomas Markwalder committed Aug 13, 2015 256  /// If updates are enabled, it instructs the D2ClientMgr singleton to  Thomas Markwalder committed Feb 13, 2014 257  /// enter send mode. If D2ClientMgr encounters errors it may throw  Thomas Markwalder committed Aug 13, 2015 258  /// D2ClientError. This method does not catch exceptions.  Thomas Markwalder committed Feb 13, 2014 259 260  void startD2();  Thomas Markwalder committed Aug 12, 2015 261 262 263 264  /// @brief Stops DHCP_DDNS client IO if DDNS updates are enabled. /// /// If updates are enabled, it instructs the D2ClientMgr singleton to /// leave send mode. If D2ClientMgr encounters errors it may throw  Thomas Markwalder committed Aug 13, 2015 265  /// D2ClientError. This method does not catch exceptions.  Thomas Markwalder committed Aug 12, 2015 266 267  void stopD2();  Thomas Markwalder committed Feb 13, 2014 268 269  /// @brief Implements the error handler for DHCP_DDNS IO errors ///  Marcin Siodelski committed Jul 02, 2014 270  /// Invoked when a NameChangeRequest send to kea-dhcp-ddns completes with  Thomas Markwalder committed Feb 13, 2014 271 272 273 274 275 276 277 278 279 280 281 282 283 284  /// 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);  Tomek Mrugalski committed Nov 27, 2011 285 protected:  Tomek Mrugalski committed Dec 31, 2012 286   Marcin Siodelski committed Feb 06, 2014 287 288 289 290 291 292 293  /// @name Functions filtering and sanity-checking received messages. /// /// @todo These functions are supposed to be moved to a new class which /// will manage different rules for accepting and rejecting messages. /// Perhaps ticket #3116 is a good opportunity to do it. /// //@{  Marcin Siodelski committed Feb 03, 2014 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316  /// @brief Checks whether received message should be processed or discarded. /// /// This function checks whether received message should be processed or /// discarded. It should be called on the beginning of message processing /// (just after the message has been decoded). This message calls a number /// of other functions which check whether message should be processed, /// using different criteria. /// /// This function should be extended when new criteria for accepting /// received message have to be implemented. This function is meant to /// aggregate all early filtering checks on the received message. By having /// a single function like this, we are avoiding bloat of the server's main /// loop. /// /// @warning This function should remain exception safe. /// /// @param query Received message. /// /// @return true if the message should be further processed, or false if /// the message should be discarded. bool accept(const Pkt4Ptr& query) const; /// @brief Check if a message sent by directly connected client should be  Francis Dupont committed Jan 22, 2015 317  /// accepted or discarded.  Marcin Siodelski committed Feb 03, 2014 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334  /// /// This function checks if the received message is from directly connected /// client. If it is, it checks that it should be processed or discarded. /// /// Note that this function doesn't validate all addresses being carried in /// the message. The primary purpose of this function is to filter out /// direct messages in the local network for which there is no suitable /// subnet configured. For example, this function accepts unicast messages /// because unicasts may be used by clients located in remote networks to /// to renew existing leases. If their notion of address is wrong, the /// server will have to sent a NAK, instead of dropping the message. /// Detailed validation of such messages is performed at later stage of /// processing. /// /// This function accepts the following messages: /// - all valid relayed messages, /// - all unicast messages,  Marcin Siodelski committed Jul 15, 2014 335 336 337  /// - all broadcast messages except DHCPINFORM received on the interface /// for which the suitable subnet exists (is configured). /// - all DHCPINFORM messages with source address or ciaddr set.  Marcin Siodelski committed Feb 03, 2014 338  ///  Marcin Siodelski committed Feb 06, 2014 339  /// @param query Message sent by a client.  Marcin Siodelski committed Feb 03, 2014 340 341 342  /// /// @return true if message is accepted for further processing, false /// otherwise.  Marcin Siodelski committed Feb 06, 2014 343 344 345 346 347  bool acceptDirectRequest(const Pkt4Ptr& query) const; /// @brief Check if received message type is valid for the server to /// process. ///  Francis Dupont committed Jan 22, 2015 348 349 350  /// This function checks that the received message type belongs to /// the range of types recognized by the server and that the /// message of this type should be processed by the server.  Marcin Siodelski committed Feb 06, 2014 351 352 353 354 355 356 357 358 359 360 361 362 363  /// /// The messages types accepted for processing are: /// - Discover /// - Request /// - Release /// - Decline /// - Inform /// /// @param query Message sent by a client. /// /// @return true if message is accepted for further processing, false /// otherwise. bool acceptMessageType(const Pkt4Ptr& query) const;  Marcin Siodelski committed Feb 03, 2014 364   Marcin Siodelski committed Jan 13, 2014 365 366 367 368 369 370 371 372 373 374 375 376 377 378  /// @brief Verifies if the server id belongs to our server. /// /// This function checks if the server identifier carried in the specified /// DHCPv4 message belongs to this server. If the server identifier option /// is absent or the value carried by this option is equal to one of the /// server identifiers used by the server, the true is returned. If the /// server identifier option is present, but it doesn't match any server /// identifier used by this server, the false value is returned. /// /// @param pkt DHCPv4 message which server identifier is to be checked. /// /// @return true, if the server identifier is absent or matches one of the /// server identifiers that the server is using; false otherwise. bool acceptServerId(const Pkt4Ptr& pkt) const;  Marcin Siodelski committed Feb 06, 2014 379  //@}  Marcin Siodelski committed Jan 13, 2014 380   Marcin Siodelski committed Mar 10, 2015 381  /// @brief Verifies if specified packet meets RFC requirements  Tomek Mrugalski committed Dec 31, 2012 382 383 384 385  /// /// Checks if mandatory option is really there, that forbidden option /// is not there, and that client-id or server-id appears only once. ///  Marcin Siodelski committed Mar 12, 2015 386  /// @param query Pointer to the client's message.  Tomek Mrugalski committed Dec 31, 2012 387 388  /// @param serverid expectation regarding server-id option /// @throw RFCViolation if any issues are detected  Marcin Siodelski committed Mar 12, 2015 389  static void sanityCheck(const Pkt4Ptr& query, RequirementLevel serverid);  Tomek Mrugalski committed Dec 31, 2012 390   Tomek Mrugalski committed Nov 27, 2011 391 392 393 394 395 396  /// @brief Processes incoming DISCOVER and returns response. /// /// Processes received DISCOVER message and verifies that its sender /// should be served. In particular, a lease is selected and sent /// as an offer to a client if it should be served. ///  Tomek Mrugalski committed Feb 03, 2012 397  /// @param discover DISCOVER message received from client  Tomek Mrugalski committed Nov 27, 2011 398 399  /// /// @return OFFER message or NULL  Tomek Mrugalski committed Feb 03, 2012 400  Pkt4Ptr processDiscover(Pkt4Ptr& discover);  Tomek Mrugalski committed Nov 27, 2011 401 402 403 404 405  /// @brief Processes incoming REQUEST and returns REPLY response. /// /// Processes incoming REQUEST message and verifies that its sender /// should be served. In particular, verifies that requested lease  Tomek Mrugalski committed Dec 12, 2011 406  /// is valid, not expired, not reserved, not used by other client and  Tomek Mrugalski committed Nov 27, 2011 407 408  /// that requesting client is allowed to use it. ///  Stephen Morris committed Sep 12, 2012 409  /// Returns ACK message, NAK message, or NULL  Tomek Mrugalski committed Nov 27, 2011 410 411 412  /// /// @param request a message received from client ///  Stephen Morris committed Sep 12, 2012 413  /// @return ACK or NAK message  Tomek Mrugalski committed Feb 03, 2012 414  Pkt4Ptr processRequest(Pkt4Ptr& request);  Tomek Mrugalski committed Nov 27, 2011 415   Marcin Siodelski committed May 12, 2015 416  /// @brief Processes incoming DHCPRELEASE messages.  Tomek Mrugalski committed Nov 27, 2011 417 418 419 420 421  /// /// In DHCPv4, server does not respond to RELEASE messages, therefore /// this function does not return anything. /// /// @param release message received from client  Tomek Mrugalski committed Feb 03, 2012 422  void processRelease(Pkt4Ptr& release);  Tomek Mrugalski committed Nov 27, 2011 423   Tomek Mrugalski committed Sep 16, 2015 424 425 426  /// @brief Process incoming DHCPDECLINE messages. /// /// This method processes incoming DHCPDECLINE. In particular, it extracts  Shawn Routhier committed Sep 16, 2015 427  /// Requested IP Address option, checks that the address really belongs to  Francis Dupont committed Dec 11, 2015 428  /// the client and if it does, calls @ref declineLease().  Tomek Mrugalski committed Nov 27, 2011 429 430  /// /// @param decline message received from client  Tomek Mrugalski committed Feb 03, 2012 431  void processDecline(Pkt4Ptr& decline);  Tomek Mrugalski committed Nov 27, 2011 432   Marcin Siodelski committed May 12, 2015 433  /// @brief Processes incoming DHCPINFORM messages.  Tomek Mrugalski committed Nov 27, 2011 434  ///  Tomek Mrugalski committed Feb 03, 2012 435  /// @param inform message received from client  Marcin Siodelski committed May 12, 2015 436 437  /// /// @return DHCPACK to be sent to the client.  Tomek Mrugalski committed Feb 03, 2012 438  Pkt4Ptr processInform(Pkt4Ptr& inform);  Tomek Mrugalski committed Nov 27, 2011 439   440 441 442 443 444 445 446 447  /// @brief Build the configured option list /// /// @note The configured option list is an *ordered* list of /// @c CfgOption objects used to append options to the response. /// /// @param ex The exchange where the configured option list is cached void buildCfgOptionList(Dhcpv4Exchange& ex);  Tomek Mrugalski committed Dec 23, 2011 448 449 450  /// @brief Appends options requested by client. /// /// This method assigns options that were requested by client  Tomek Mrugalski committed Dec 29, 2011 451  /// (sent in PRL) or are enforced by server.  Tomek Mrugalski committed Dec 23, 2011 452  ///  Marcin Siodelski committed Mar 10, 2015 453 454  /// @param ex The exchange holding both the client's message and the /// server's response.  Marcin Siodelski committed Mar 12, 2015 455  void appendRequestedOptions(Dhcpv4Exchange& ex);  Tomek Mrugalski committed Dec 23, 2011 456   Marcin Siodelski committed Oct 22, 2013 457 458 459 460 461 462 463 464  /// @brief Appends requested vendor options as requested by client. /// /// This method is similar to \ref appendRequestedOptions(), but uses /// vendor options. The major difference is that vendor-options use /// its own option spaces (there may be more than one distinct set of vendor /// options, each with unique vendor-id). Vendor options are requested /// using separate options within their respective vendor-option spaces. ///  Marcin Siodelski committed Mar 10, 2015 465 466  /// @param ex The exchange holding both the client's message and the /// server's response.  Marcin Siodelski committed Mar 12, 2015 467  void appendRequestedVendorOptions(Dhcpv4Exchange& ex);  Marcin Siodelski committed Oct 22, 2013 468   Tomek Mrugalski committed Dec 23, 2011 469 470  /// @brief Assigns a lease and appends corresponding options ///  Francis Dupont committed Jan 22, 2015 471  /// This method chooses the most appropriate lease for requesting  Tomek Mrugalski committed Dec 23, 2011 472 473 474  /// client and assigning it. Options corresponding to the lease /// are added to specific message. ///  Marcin Siodelski committed Mar 10, 2015 475 476 477 478 479 480 481 482  /// This method may reset the pointer to the response in the @c ex object /// to indicate that the response should not be sent to the client. /// The caller must check if the response is is null after calling /// this method. /// /// The response type in the @c ex object may be set to DHCPACK or DHCPNAK. /// /// @param ex DHCPv4 exchange holding the client's message to be checked.  Marcin Siodelski committed Mar 12, 2015 483  void assignLease(Dhcpv4Exchange& ex);  Tomek Mrugalski committed Dec 31, 2012 484   Marcin Siodelski committed Jan 22, 2013 485 486 487  /// @brief Append basic options if they are not present. /// /// This function adds the following basic options if they  Marcin Siodelski committed Mar 10, 2015 488  /// are not yet added to the response message:  Marcin Siodelski committed Jan 22, 2013 489 490 491 492 493  /// - Subnet Mask, /// - Router, /// - Name Server, /// - Domain Name. ///  Marcin Siodelski committed Mar 10, 2015 494  /// @param ex DHCPv4 exchange holding the client's message to be checked.  Marcin Siodelski committed Mar 12, 2015 495  void appendBasicOptions(Dhcpv4Exchange& ex);  Marcin Siodelski committed Jan 22, 2013 496   Marcin Siodelski committed Aug 28, 2013 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528  /// @brief Processes Client FQDN and Hostname Options sent by a client. /// /// Client may send Client FQDN or Hostname option to communicate its name /// to the server. Server may use this name to perform DNS update for the /// lease being assigned to a client. If server takes responsibility for /// updating DNS for a client it may communicate it by sending the Client /// FQDN or Hostname %Option back to the client. Server select a different /// name than requested by a client to update DNS. In such case, the server /// stores this different name in its response. /// /// Client should not send both Client FQDN and Hostname options. However, /// if client sends both options, server should prefer Client FQDN option /// and ignore the Hostname option. If Client FQDN option is not present, /// the Hostname option is processed. /// /// The Client FQDN %Option is processed by this function as described in /// RFC4702. /// /// In response to a Hostname %Option sent by a client, the server may send /// Hostname option with the same or different hostname. If different /// hostname is sent, it is an indication to the client that server has /// overridden the client's preferred name and will rather use this /// different name to update DNS. However, since Hostname option doesn't /// carry an information whether DNS update will be carried by the server /// or not, the client is responsible for checking whether DNS update /// has been performed. /// /// After successful processing options stored in the first parameter, /// this function may add Client FQDN or Hostname option to the response /// message. In some cases, server may cease to add any options to the /// response, i.e. when server doesn't support DNS updates. ///  Marcin Siodelski committed Nov 20, 2013 529 530 531  /// This function does not throw. It simply logs the debug message if the /// processing of the FQDN or Hostname failed. ///  Marcin Siodelski committed Mar 10, 2015 532 533  /// @param ex The exchange holding both the client's message and the /// server's response.  Marcin Siodelski committed Mar 12, 2015 534  void processClientName(Dhcpv4Exchange& ex);  Marcin Siodelski committed Aug 28, 2013 535   Tomek Mrugalski committed Feb 18, 2014 536 537 538 539 540 541 542 543  /// @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;  Marcin Siodelski committed Aug 28, 2013 544 545 546 private: /// @brief Process Client FQDN %Option sent by a client. ///  Marcin Siodelski committed Nov 19, 2013 547 548 549 550 551 552  /// This function is called by the @c Dhcpv4Srv::processClientName when /// the client has sent the FQDN option in its message to the server. /// It comprises the actual logic to parse the FQDN option and prepare /// the FQDN option to be sent back to the client in the server's /// response. ///  Marcin Siodelski committed Mar 10, 2015 553 554  /// @param ex The exchange holding both the client's message and the /// server's response.  Marcin Siodelski committed Mar 12, 2015 555  void processClientFqdnOption(Dhcpv4Exchange& ex);  Marcin Siodelski committed Aug 28, 2013 556 557 558  /// @brief Process Hostname %Option sent by a client. ///  Francis Dupont committed Jan 22, 2015 559  /// This function is called by the @c Dhcpv4Srv::processClientName when  Marcin Siodelski committed Nov 20, 2013 560 561 562 563 564  /// the client has sent the Hostname option in its message to the server. /// It comprises the actual logic to parse the Hostname option and /// prepare the Hostname option to be sent back to the client in the /// server's response. ///  Marcin Siodelski committed Mar 10, 2015 565 566  /// @param ex The exchange holding both the client's message and the /// server's response.  Marcin Siodelski committed Mar 12, 2015 567  void processHostnameOption(Dhcpv4Exchange& ex);  Marcin Siodelski committed Aug 28, 2013 568   Tomek Mrugalski committed Sep 08, 2015 569 570 571 572 573 574 575  /// @brief Marks lease as declined. /// /// This method moves a lease to declined state with all the steps involved: /// - trigger DNS removal (if necessary) /// - disassociate the client information /// - update lease in the database (switch to DECLINED state) /// - increase necessary statistics  Tomek Mrugalski committed Oct 06, 2015 576  /// - call lease4_decline hook  Tomek Mrugalski committed Sep 08, 2015 577 578  /// /// @param lease lease to be declined  Tomek Mrugalski committed Oct 06, 2015 579  /// @param decline client's message  Francis Dupont committed Dec 11, 2015 580  void declineLease(const Lease4Ptr& lease, const Pkt4Ptr& decline);  Tomek Mrugalski committed Sep 08, 2015 581   Marcin Siodelski committed Aug 28, 2013 582 protected:  Marcin Siodelski committed Sep 03, 2013 583 584 585 586  /// @brief Creates NameChangeRequests which correspond to the lease /// which has been acquired. ///  Francis Dupont committed Jan 22, 2015 587  /// If this function is called when an existing lease is renewed, it  Marcin Siodelski committed Sep 03, 2013 588 589 590 591 592 593 594 595 596 597 598 599 600  /// may generate NameChangeRequest to remove existing DNS entries which /// correspond to the old lease instance. This function may cease to /// generate NameChangeRequests if the notion of the client's FQDN hasn't /// changed between an old and new lease. /// /// @param lease A pointer to the new lease which has been acquired. /// @param old_lease A pointer to the instance of the old lease which has /// been replaced by the new lease passed in the first argument. The NULL /// value indicates that the new lease has been allocated, rather than /// lease being renewed. void createNameChangeRequests(const Lease4Ptr& lease, const Lease4Ptr& old_lease);  Tomek Mrugalski committed Dec 31, 2012 601 602 603 604 605  /// @brief Attempts to renew received addresses /// /// Attempts to renew existing lease. This typically includes finding a lease that /// corresponds to the received address. If no such lease is found, a status code /// response is generated.  Tomek Mrugalski committed Dec 23, 2011 606  ///  Tomek Mrugalski committed Dec 31, 2012 607 608 609  /// @param renew client's message asking for renew /// @param reply server's response (ACK or NAK) void renewLease(const Pkt4Ptr& renew, Pkt4Ptr& reply);  Tomek Mrugalski committed Dec 23, 2011 610   Marcin Siodelski committed Jan 03, 2014 611 612  /// @brief Adds server identifier option to the server's response. ///  Francis Dupont committed Jan 22, 2015 613  /// This method adds a server identifier to the DHCPv4 message. It expects  Marcin Siodelski committed Jan 03, 2014 614 615 616 617 618 619 620 621 622 623 624  /// that the local (source) address is set for this message. If address is /// not set, it will throw an exception. This method also expects that the /// server identifier option is not present in the specified message. /// Otherwise, it will throw an exception on attempt to add a duplicate /// server identifier option. /// /// @note This method doesn't throw exceptions by itself but the underlying /// classes being used my throw. The reason for this method to not sanity /// check the specified message is that it is meant to be called internally /// by the @c Dhcpv4Srv class. ///  Marcin Siodelski committed Jan 09, 2014 625 626 627  /// @note This method is static because it is not dependent on the class /// state. ///  Marcin Siodelski committed Mar 10, 2015 628 629  /// @param ex The exchange holding both the client's message and the /// server's response.  Marcin Siodelski committed Mar 12, 2015 630  static void appendServerID(Dhcpv4Exchange& ex);  Marcin Siodelski committed Jan 03, 2014 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647  /// @brief Set IP/UDP and interface parameters for the DHCPv4 response. /// /// This method sets the following parameters for the DHCPv4 message being /// sent to a client: /// - client unicast or a broadcast address, /// - client or relay port, /// - server address, /// - server port, /// - name and index of the interface which is to be used to send the /// message. /// /// Internally it calls the @c Dhcpv4Srv::adjustRemoteAddr to figure /// out the destination address (client unicast address or broadcast /// address). /// /// The destination port is always DHCPv4 client (68) or relay (67) port,  Marcin Siodelski committed Jan 08, 2014 648  /// depending if the response will be sent directly to a client.  Marcin Siodelski committed Jan 03, 2014 649 650 651 652 653 654 655 656 657 658  /// /// The source port is always set to DHCPv4 server port (67). /// /// The interface selected for the response is always the same as the /// one through which the query has been received. /// /// The source address for the response is the IPv4 address assigned to /// the interface being used to send the response. This function uses /// @c IfaceMgr to get the socket bound to the IPv4 address on the /// particular interface.  Marcin Siodelski committed Jan 09, 2014 659 660 661  /// /// @note This method is static because it is not dependent on the class /// state.  Marcin Siodelski committed Mar 10, 2015 662 663 664  /// /// @param ex The exchange holding both the client's message and the /// server's response.  Marcin Siodelski committed Mar 12, 2015 665  static void adjustIfaceData(Dhcpv4Exchange& ex);  Marcin Siodelski committed Jan 03, 2014 666   Marcin Siodelski committed May 21, 2013 667 668 669 670 671 672 673 674 675 676 677 678 679  /// @brief Sets remote addresses for outgoing packet. /// /// This method sets the local and remote addresses on outgoing packet. /// The addresses being set depend on the following conditions: /// - has incoming packet been relayed, /// - is direct response to a client without address supported, /// - type of the outgoing packet, /// - broadcast flag set in the incoming packet. /// /// @warning This method does not check whether provided packet pointers /// are valid. Make sure that pointers are correct before calling this /// function. ///  Marcin Siodelski committed Jan 09, 2014 680 681 682  /// @note This method is static because it is not dependent on the class /// state. ///  Marcin Siodelski committed Mar 10, 2015 683 684  /// @param ex The exchange holding both the client's message and the /// server's response.  Marcin Siodelski committed Mar 12, 2015 685  static void adjustRemoteAddr(Dhcpv4Exchange& ex);  Marcin Siodelski committed May 21, 2013 686   Tomek Mrugalski committed Jan 14, 2013 687 688 689 690 691 692 693  /// @brief converts server-id to text /// Converts content of server-id option to a text representation, e.g. /// "192.0.2.1" /// /// @param opt option that contains server-id /// @return string representation static std::string srvidToString(const OptionPtr& opt);  Tomek Mrugalski committed Nov 27, 2011 694   Tomek Mrugalski committed Dec 31, 2012 695 696  /// @brief Selects a subnet for a given client's packet. ///  Marcin Siodelski committed Mar 12, 2015 697  /// @param query client's message  Tomek Mrugalski committed Dec 31, 2012 698  /// @return selected subnet (or NULL if no suitable subnet was found)  Marcin Siodelski committed Mar 13, 2015 699  isc::dhcp::Subnet4Ptr selectSubnet(const Pkt4Ptr& query) const;  Tomek Mrugalski committed Dec 31, 2012 700   Tomek Mrugalski committed Nov 27, 2011 701 702  /// indicates if shutdown is in progress. Setting it to true will /// initiate server shutdown procedure.  Tomek Mrugalski committed Dec 12, 2011 703  volatile bool shutdown_;  Tomek Mrugalski committed Dec 31, 2012 704   Tomek Mrugalski committed Jul 15, 2013 705 706 707 708 709 710 711 712 713 714 715 716  /// @brief dummy wrapper around IfaceMgr::receive4 /// /// This method is useful for testing purposes, where its replacement /// simulates reception of a packet. For that purpose it is protected. virtual Pkt4Ptr receivePacket(int timeout); /// @brief dummy wrapper around IfaceMgr::send() /// /// This method is useful for testing purposes, where its replacement /// simulates transmission of a packet. For that purpose it is protected. virtual void sendPacket(const Pkt4Ptr& pkt);  Marcin Siodelski committed Oct 04, 2013 717 718 719 720 721 722 723 724 725 726 727 728  /// @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. /// @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);  Tomek Mrugalski committed Dec 31, 2013 729 730  /// @brief Assigns incoming packet to zero or more classes. ///  Shawn Routhier committed Nov 20, 2015 731  /// @note This is done in two phases: first the content of the  Francis Dupont committed Nov 20, 2015 732  /// vendor-class-identifier option is used as a class, by  Francis Dupont committed Dec 11, 2015 733  /// calling @ref classifyByVendor(). Second classification match  Shawn Routhier committed Nov 20, 2015 734 735  /// expressions are evaluated. The resulting classes will be stored /// in the packet (see @ref isc::dhcp::Pkt4::classes_ and  Francis Dupont committed Nov 20, 2015 736  /// @ref isc::dhcp::Pkt4::inClass).  Tomek Mrugalski committed Dec 31, 2013 737  ///  Tomek Mrugalski committed Dec 30, 2013 738 739 740  /// @param pkt packet to be classified void classifyPacket(const Pkt4Ptr& pkt);  741  /// @brief Performs packet processing specific to a vendor class  Tomek Mrugalski committed Dec 30, 2013 742  ///  Marcin Siodelski committed Mar 12, 2015 743 744  /// If the selected subnet, query or response in the @c ex object is NULL /// this method returns immediately and returns true.  Tomek Mrugalski committed Dec 30, 2013 745  ///  Marcin Siodelski committed Mar 12, 2015 746 747 748 749  /// @note This processing is a likely candidate to be pushed into hooks. /// /// @param ex The exchange holding both the client's message and the /// server's response.  Tomek Mrugalski committed Dec 30, 2013 750  /// @return true if successful, false otherwise (will prevent sending response)  751  bool vendorClassSpecificProcessing(const Dhcpv4Exchange& ex);  Tomek Mrugalski committed Dec 30, 2013 752   Marcin Siodelski committed Mar 10, 2015 753 754 755 756 757  /// @brief Allocation Engine. /// 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) boost::shared_ptr alloc_engine_;  Tomek Mrugalski committed Dec 30, 2013 758   Marcin Siodelski committed May 22, 2013 759 private:  Tomek Mrugalski committed Dec 31, 2012 760   Francis Dupont committed Nov 20, 2015 761 762 763 764 765 766 767 768  /// @brief Assign class using vendor-class-identifier option /// /// @note This is the first part of @ref classifyPacket /// /// @param pkt packet to be classified /// @param classes a reference to added class names for logging void classifyByVendor(const Pkt4Ptr& pkt, std::string& classes);  Tomek Mrugalski committed Dec 31, 2012 769  /// @brief Constructs netmask option based on subnet4  Tomek Mrugalski committed Jan 08, 2013 770  /// @param subnet subnet for which the netmask will be calculated  Tomek Mrugalski committed Dec 31, 2012 771 772 773 774  /// /// @return Option that contains netmask information static OptionPtr getNetmaskOption(const Subnet4Ptr& subnet);  Tomek Mrugalski committed May 15, 2015 775 776 777 778 779 780 781  /// @brief Updates statistics for received packets /// @param query packet received static void processStatsReceived(const Pkt4Ptr& query); /// @brief Updates statistics for transmitted packets /// @param query packet transmitted static void processStatsSent(const Pkt4Ptr& response);  Tomek Mrugalski committed Dec 31, 2012 782   Marcin Siodelski committed Jul 11, 2013 783 784 785  uint16_t port_; ///< UDP port number on which server listens. bool use_bcast_; ///< Should broadcast be enabled on sockets (if true).  Tomek Mrugalski committed Jul 15, 2013 786 787 788 789  /// Indexes for registered hook points int hook_index_pkt4_receive_; int hook_index_subnet4_select_; int hook_index_pkt4_send_;  Tomek Mrugalski committed Nov 27, 2011 790 791 792 793 794 795 }; }; // namespace isc::dhcp }; // namespace isc #endif // DHCP4_SRV_H