diff options
Diffstat (limited to 'src/lib/dhcpsrv/network.cc')
-rw-r--r-- | src/lib/dhcpsrv/network.cc | 389 |
1 files changed, 389 insertions, 0 deletions
diff --git a/src/lib/dhcpsrv/network.cc b/src/lib/dhcpsrv/network.cc new file mode 100644 index 0000000..30532d8 --- /dev/null +++ b/src/lib/dhcpsrv/network.cc @@ -0,0 +1,389 @@ +// Copyright (C) 2017-2023 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include <config.h> + +#include <dhcp/dhcp4.h> +#include <dhcp/option_custom.h> +#include <dhcp/option_space.h> +#include <dhcpsrv/network.h> +#include <boost/pointer_cast.hpp> + +using namespace isc::asiolink; +using namespace isc::data; +using namespace isc::util; + +namespace isc { +namespace dhcp { + +void +Network::RelayInfo::addAddress(const asiolink::IOAddress& addr) { + if (containsAddress(addr)) { + isc_throw (BadValue, "RelayInfo already contains address: " + << addr.toText()); + } + + addresses_.push_back(addr); +} + +bool +Network::RelayInfo::hasAddresses() const { + return (!addresses_.empty()); +} + +bool +Network::RelayInfo::containsAddress(const asiolink::IOAddress& addr) const { + auto const& index = addresses_.get<IOAddressListSetTag>(); + return (index.find(addr) != index.end()); +} + +const IOAddressList& +Network::RelayInfo::getAddresses() const { + return (addresses_); +} + +void +Network::addRelayAddress(const asiolink::IOAddress& addr) { + relay_.addAddress(addr); +} + +bool +Network::hasRelays() const { + return (relay_.hasAddresses()); +} + +bool +Network::hasRelayAddress(const asiolink::IOAddress& addr) const { + return (relay_.containsAddress(addr)); +} + +const IOAddressList& +Network::getRelayAddresses() const { + return (relay_.getAddresses()); +} + +bool +Network::clientSupported(const isc::dhcp::ClientClasses& classes) const { + if (client_class_.empty()) { + // There is no class defined for this network, so we do + // support everyone. + return (true); + } + + return (classes.contains(client_class_)); +} + +void +Network::allowClientClass(const isc::dhcp::ClientClass& class_name) { + client_class_ = class_name; +} + +void +Network::requireClientClass(const isc::dhcp::ClientClass& class_name) { + if (!required_classes_.contains(class_name)) { + required_classes_.insert(class_name); + } +} + +const ClientClasses& +Network::getRequiredClasses() const { + return (required_classes_); +} + +Optional<IOAddress> +Network::getGlobalProperty(Optional<IOAddress> property, + const int global_index, + const int /*min_index*/, + const int /*max_index*/) const { + if ((global_index >= 0) && fetch_globals_fn_) { + ConstCfgGlobalsPtr globals = fetch_globals_fn_(); + if (globals) { + ConstElementPtr global_param = globals->get(global_index); + if (global_param) { + std::string global_str = global_param->stringValue(); + if (!global_str.empty()) { + return (IOAddress(global_str)); + } + } + } + } + return (property); +} + +ElementPtr +Network::toElement() const { + ElementPtr map = Element::createMap(); + + // Set user-context + contextToElement(map); + + // Set interface + if (!iface_name_.unspecified()) { + map->set("interface", Element::create(iface_name_.get())); + } + + ElementPtr relay_map = Element::createMap(); + ElementPtr address_list = Element::createList(); + const IOAddressList addresses = getRelayAddresses(); + for (auto address = addresses.begin(); address != addresses.end(); ++address) { + address_list->add(Element::create((*address).toText())); + } + + relay_map->set("ip-addresses", address_list); + map->set("relay", relay_map); + + // Set client-class + if (!client_class_.unspecified()) { + map->set("client-class", Element::create(client_class_.get())); + } + + // Set require-client-classes + const ClientClasses& classes = getRequiredClasses(); + if (!classes.empty()) { + ElementPtr class_list = Element::createList(); + for (ClientClasses::const_iterator it = classes.cbegin(); + it != classes.cend(); ++it) { + class_list->add(Element::create(*it)); + } + map->set("require-client-classes", class_list); + } + + // T1, T2, and Valid are optional for SharedNetworks, and + // T1 and T2 are optional for Subnet4 thus we will only + // output them if they are marked as specified. + if (!t1_.unspecified()) { + map->set("renew-timer", + Element::create(static_cast<long long>(t1_.get()))); + } + + // Set rebind-timer + if (!t2_.unspecified()) { + map->set("rebind-timer", + Element::create(static_cast<long long>(t2_.get()))); + } + + // Set valid-lifetime + if (!valid_.unspecified()) { + map->set("valid-lifetime", + Element::create(static_cast<long long>(valid_.get()))); + map->set("min-valid-lifetime", + Element::create(static_cast<long long>(valid_.getMin()))); + map->set("max-valid-lifetime", + Element::create(static_cast<long long>(valid_.getMax()))); + } + + // Set reservations-global + if (!reservations_global_.unspecified()) { + map->set("reservations-global", + Element::create(reservations_global_.get())); + } + + // Set reservations-in-subnet + if (!reservations_in_subnet_.unspecified()) { + map->set("reservations-in-subnet", + Element::create(reservations_in_subnet_.get())); + } + + // Set reservations-out-of-pool + if (!reservations_out_of_pool_.unspecified()) { + map->set("reservations-out-of-pool", + Element::create(reservations_out_of_pool_.get())); + } + + // Set options + ConstCfgOptionPtr opts = getCfgOption(); + map->set("option-data", opts->toElement()); + + // Output calculate-tee-times and percentages if calculation is enabled. + if (!calculate_tee_times_.unspecified()) { + map->set("calculate-tee-times", Element::create(calculate_tee_times_)); + } + + if (!t1_percent_.unspecified()) { + map->set("t1-percent", Element::create(t1_percent_)); + } + + if (!t2_percent_.unspecified()) { + map->set("t2-percent", Element::create(t2_percent_)); + } + + if (!ddns_send_updates_.unspecified()) { + map->set("ddns-send-updates", Element::create(ddns_send_updates_)); + } + + if (!ddns_override_no_update_.unspecified()) { + map->set("ddns-override-no-update", Element::create(ddns_override_no_update_)); + } + + if (!ddns_override_client_update_.unspecified()) { + map->set("ddns-override-client-update", Element::create(ddns_override_client_update_)); + } + + if (!ddns_replace_client_name_mode_.unspecified()) { + map->set("ddns-replace-client-name", + Element::create(D2ClientConfig:: + replaceClientNameModeToString(ddns_replace_client_name_mode_))); + } + + if (!ddns_generated_prefix_.unspecified()) { + map->set("ddns-generated-prefix", Element::create(ddns_generated_prefix_)); + } + + if (!ddns_qualifying_suffix_.unspecified()) { + map->set("ddns-qualifying-suffix", Element::create(ddns_qualifying_suffix_)); + } + + if (!ddns_ttl_percent_.unspecified()) { + map->set("ddns-ttl-percent", Element::create(ddns_ttl_percent_)); + } + + if (!hostname_char_set_.unspecified()) { + map->set("hostname-char-set", Element::create(hostname_char_set_)); + } + + if (!hostname_char_replacement_.unspecified()) { + map->set("hostname-char-replacement", Element::create(hostname_char_replacement_)); + } + + if (!store_extended_info_.unspecified()) { + map->set("store-extended-info", Element::create(store_extended_info_)); + } + + if (!cache_threshold_.unspecified()) { + map->set("cache-threshold", Element::create(cache_threshold_)); + } + + if (!cache_max_age_.unspecified()) { + map->set("cache-max-age", + Element::create(static_cast<long long>(cache_max_age_))); + } + + if (!ddns_update_on_renew_.unspecified()) { + map->set("ddns-update-on-renew", Element::create(ddns_update_on_renew_)); + } + + if (!ddns_use_conflict_resolution_.unspecified()) { + map->set("ddns-use-conflict-resolution", Element::create(ddns_use_conflict_resolution_)); + } + + if (!allocator_type_.unspecified()) { + map->set("allocator", Element::create(allocator_type_)); + } + + return (map); +} + +void +Network4::setSiaddr(const Optional<IOAddress>& siaddr) { + if (!siaddr.get().isV4()) { + isc_throw(BadValue, "Can't set siaddr to non-IPv4 address " + << siaddr); + } + siaddr_ = siaddr; +} + +void +Network4::setSname(const Optional<std::string>& sname) { + sname_ = sname; +} + +void +Network4::setFilename(const Optional<std::string>& filename) { + filename_ = filename; +} + +ElementPtr +Network4::toElement() const { + ElementPtr map = Network::toElement(); + + // Set match-client-id + if (!match_client_id_.unspecified()) { + map->set("match-client-id", Element::create(match_client_id_.get())); + } + + // Set authoritative + if (!authoritative_.unspecified()) { + map->set("authoritative", Element::create(authoritative_.get())); + } + + // Set next-server + if (!siaddr_.unspecified()) { + map->set("next-server", Element::create(siaddr_.get().toText())); + } + + // Set server-hostname + if (!sname_.unspecified()) { + map->set("server-hostname", Element::create(sname_.get())); + } + + // Set boot-file-name + if (!filename_.unspecified()) { + map->set("boot-file-name",Element::create(filename_.get())); + } + + // Set offer-lifetime + if (!offer_lft_.unspecified()) { + map->set("offer-lifetime",Element::create(offer_lft_.get())); + } + + return (map); +} + +IOAddress +Network4::getServerId() const { + try { + OptionCustomPtr opt_server_id = boost::dynamic_pointer_cast<OptionCustom> + (cfg_option_->get(DHCP4_OPTION_SPACE, DHO_DHCP_SERVER_IDENTIFIER).option_); + if (opt_server_id) { + return (opt_server_id->readAddress()); + } + } catch (const std::exception&) { + // Ignore any exceptions and simply return empty buffer. + } + + return (IOAddress::IPV4_ZERO_ADDRESS()); +} + +ElementPtr +Network6::toElement() const { + ElementPtr map = Network::toElement(); + + // Set preferred-lifetime + if (!preferred_.unspecified()) { + map->set("preferred-lifetime", + Element::create(static_cast<long long>(preferred_.get()))); + map->set("min-preferred-lifetime", + Element::create(static_cast<long long>(preferred_.getMin()))); + map->set("max-preferred-lifetime", + Element::create(static_cast<long long>(preferred_.getMax()))); + } + + // Set interface-id + if (interface_id_) { + std::vector<uint8_t> bin = interface_id_->getData(); + std::string ifid; + ifid.resize(bin.size()); + if (!bin.empty()) { + std::memcpy(&ifid[0], &bin[0], bin.size()); + } + map->set("interface-id", Element::create(ifid)); + } + + // Set rapid-commit + if (!rapid_commit_.unspecified()) { + map->set("rapid-commit", Element::create(rapid_commit_.get())); + } + + // Set pd-allocator + if (!pd_allocator_type_.unspecified()) { + map->set("pd-allocator", Element::create(pd_allocator_type_)); + } + + return (map); +} + +} // end of namespace isc::dhcp +} // end of namespace isc |