diff --git a/src/bin/dhcp4/dhcp4_messages.mes b/src/bin/dhcp4/dhcp4_messages.mes index f8e471b..fc992a0 100644 --- a/src/bin/dhcp4/dhcp4_messages.mes +++ b/src/bin/dhcp4/dhcp4_messages.mes @@ -429,6 +429,11 @@ This error message is issued when preparing an on-wire format of the packet has failed. The first argument identifies the client and the DHCP transaction. The second argument includes the error string. +% DHCP4_PACKET_PROCESS_EXCEPTION exception occurred during packet processing: %1 +This error message indicates that an exception was raised during packet processing +that was not caught by other, more specific exception handlers. This packet will +be dropped and the server will continue operation. + % DHCP4_PACKET_RECEIVED %1: %2 (type %3) received from %4 to %5 on interface %6 A debug message noting that the server has received the specified type of packet on the specified interface. The first argument specifies the diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index 6ade319..1bdfc9a 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -358,6 +358,8 @@ Dhcpv4Srv::run() { Pkt4Ptr rsp; try { + + try { // The lease database backend may install some timers for which // the handlers need to be executed periodically. Retrieve the // maximum interval at which the handlers must be executed from @@ -716,6 +718,20 @@ Dhcpv4Srv::run() { .arg(rsp->getLabel()) .arg(e.what()); } + + } catch (const std::exception& e) { + // General catch-all exception that are not caught by more specific + // catches. This one is for exceptions derived from std::exception. + LOG_ERROR(packet4_logger, DHCP4_PACKET_PROCESS_EXCEPTION) + .arg(e.what()); + } catch (...) { + // General catch-all exception that are not caught by more specific + // catches. This one is for other exceptions, not derived from + // std::exception. + LOG_ERROR(packet4_logger, DHCP4_PACKET_PROCESS_EXCEPTION) + .arg("an unknown exception not derived from std::exception"); + } + } return (true); diff --git a/src/bin/dhcp6/dhcp6_messages.mes b/src/bin/dhcp6/dhcp6_messages.mes index 5b62bb7..9b84797 100644 --- a/src/bin/dhcp6/dhcp6_messages.mes +++ b/src/bin/dhcp6/dhcp6_messages.mes @@ -413,6 +413,11 @@ This is a general catch-all message indicating that the processing of the specified packet type from the indicated address failed. The reason is given in the message. The server will not send a response but will instead ignore the packet. +% DHCP6_PACKET_PROCESS_EXCEPTION exception occurred during packet processing: %1 +This error message indicates that an exception was raised during packet processing +that was not caught by other, more specific exception handlers. This packet will +be dropped and the server will continue operation. + % DHCP6_PACKET_RECEIVED %1: %2 (type %3) received from %4 to %5 on interface %6 A debug message noting that the server has received the specified type of packet on the specified interface. The first argument specifies the diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index 9f29e9d..33f54a0 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@ -315,6 +315,8 @@ bool Dhcpv6Srv::run() { Pkt6Ptr rsp; try { + + try { // The lease database backend may install some timers for which // the handlers need to be executed periodically. Retrieve the // maximum interval at which the handlers must be executed from @@ -710,6 +712,13 @@ bool Dhcpv6Srv::run() { .arg(e.what()); } } + + } catch (const std::exception& e) { + // General catch-all exception that are not caught by more specific + // catches. + LOG_ERROR(packet6_logger, DHCP6_PACKET_PROCESS_EXCEPTION) + .arg(e.what()); + } } return (true); diff --git a/src/lib/dhcp/pkt4.cc b/src/lib/dhcp/pkt4.cc index 44a96ca..2a82969 100644 --- a/src/lib/dhcp/pkt4.cc +++ b/src/lib/dhcp/pkt4.cc @@ -343,15 +343,31 @@ std::string Pkt4::getLabel() const { /// @todo If and when client id is extracted into Pkt4, this method should - /// the instance member rather than fetch it every time. + /// use the instance member rather than fetch it every time. + std::string suffix; ClientIdPtr client_id; OptionPtr client_opt = getOption(DHO_DHCP_CLIENT_IDENTIFIER); - if (client_opt ) { - client_id = ClientIdPtr(new ClientId(client_opt->getData())); + if (client_opt) { + try { + client_id = ClientIdPtr(new ClientId(client_opt->getData())); + } catch (...) { + // ClientId may throw if the client-id is too short. + suffix = " (malformed client-id)"; + } } - return makeLabel(hwaddr_, client_id, transid_); - + std::ostringstream label; + try { + label << makeLabel(hwaddr_, client_id, transid_); + } catch (...) { + // This should not happen with the current code, but we may add extra + // sanity checks in the future that would possibly throw if + // the hwaddr length is 0. + label << " (malformed hw address)"; + } + + label << suffix; + return (label.str()); } std::string diff --git a/src/lib/dhcp/pkt4.h b/src/lib/dhcp/pkt4.h index 549be78..12af2cf 100644 --- a/src/lib/dhcp/pkt4.h +++ b/src/lib/dhcp/pkt4.h @@ -103,6 +103,8 @@ public: /// wrapper around static makeLabel(). See this method for string /// content. /// + /// This method is exception safe. + /// /// @return string with text representation std::string getLabel() const; diff --git a/src/lib/dhcp/pkt6.cc b/src/lib/dhcp/pkt6.cc index 7881672..d0fd5e5 100644 --- a/src/lib/dhcp/pkt6.cc +++ b/src/lib/dhcp/pkt6.cc @@ -544,7 +544,18 @@ Pkt6::toText() const { DuidPtr Pkt6::getClientId() const { OptionPtr opt_duid = getOption(D6O_CLIENTID); - return (opt_duid ? DuidPtr(new DUID(opt_duid->getData())) : DuidPtr()); + try { + // This will throw if the DUID length is larger than 128 bytes + // or is too short. + return (opt_duid ? DuidPtr(new DUID(opt_duid->getData())) : DuidPtr()); + } catch (...) { + // Do nothing. This method is used only by getLabel(), which is + // used for logging purposes. We should not throw, but rather + // report no DUID. We should not log anything, as we're in the + // process of logging something for this packet. So the only + // choice left is to return an empty pointer. + } + return (DuidPtr()); } isc::dhcp::OptionCollection diff --git a/src/lib/dhcp/pkt6.h b/src/lib/dhcp/pkt6.h index febb92d..3228dad 100644 --- a/src/lib/dhcp/pkt6.h +++ b/src/lib/dhcp/pkt6.h @@ -217,6 +217,8 @@ public: /// @brief Retrieves the DUID from the Client Identifier option. /// + /// This method is exception safe. + /// /// @return Pointer to the DUID or NULL if the option doesn't exist. DuidPtr getClientId() const;