1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Copyright (C) 2015-2024 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 <cc/data.h>
#include <dhcpsrv/cfgmgr.h>
#include <dhcpsrv/dhcpsrv_log.h>
#include <dhcpsrv/parsers/ifaces_config_parser.h>
#include <string><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <sys/types.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

using namespace isc::data;

namespace isc {
namespace dhcp {

void
IfacesConfigParser::parseInterfacesList(const CfgIfacePtr& cfg_iface,
                                        ConstElementPtr ifaces_list) {
    for (auto const& iface : ifaces_list->listValue()) {
        std::string iface_name = iface->stringValue();
        try {
            cfg_iface->use(protocol_, iface_name);

        } catch (const std::exception& ex) {
            isc_throw(DhcpConfigError, "Failed to select interface: "
                      << ex.what() << " (" << iface->getPosition() << ")");
        }
    }
}

IfacesConfigParser::IfacesConfigParser(const uint16_t protocol, bool test_mode)
    : protocol_(protocol), test_mode_(test_mode) {
}

void
IfacesConfigParser::parse(const CfgIfacePtr& cfg,
                          const isc::data::ConstElementPtr& ifaces_config) {

    // Check for re-detect before calling parseInterfacesList()
    bool re_detect = getBoolean(ifaces_config, "re-detect");
    cfg->setReDetect(re_detect);
    if (re_detect && !test_mode_) {
        IfaceMgr::instance().clearIfaces();
        IfaceMgr::instance().detectIfaces();
    }

    bool socket_type_specified = false;
    for (auto const& element : ifaces_config->mapValue()) {
        try {
            if (element.first == "re-detect") {
                continue;
            }

            if (element.first == "interfaces") {
                parseInterfacesList(cfg, element.second);
                continue;
            }

            if (element.first == "dhcp-socket-type") {
                if (protocol_ == AF_INET) {
                    cfg->useSocketType(AF_INET, element.second->stringValue());
                    socket_type_specified = true;
                    continue;
                } else {
                    isc_throw(DhcpConfigError,
                              "dhcp-socket-type is not supported in DHCPv6");
                }
            }

            if (element.first == "outbound-interface") {
                if (protocol_ == AF_INET) {
                    CfgIface::OutboundIface type =
                        CfgIface::textToOutboundIface(element.second->stringValue());
                    cfg->setOutboundIface(type);
                    continue;
                } else {
                    isc_throw(DhcpConfigError,
                              "outbound-interface is not supported in DHCPv6");
                }
            }

            if (element.first == "service-sockets-require-all") {
                cfg->setServiceSocketsRequireAll(element.second->boolValue());
                continue;
            }

            if (element.first == "service-sockets-retry-wait-time") {
                cfg->setServiceSocketsRetryWaitTime(static_cast<uint32_t>(element.second->intValue()));
                continue;
            }

            if (element.first == "service-sockets-max-retries") {
                cfg->setServiceSocketsMaxRetries(static_cast<uint32_t>(element.second->intValue()));
                continue;
            }

            if (element.first == "user-context") {
                cfg->setContext(element.second);
                continue;
            }

            // This should never happen as the input produced by the parser
            // see (src/bin/dhcpX/dhcpX_parser.yy) should not produce any
            // other parameter, so this case is only to catch bugs in
            // the parser.
            isc_throw(DhcpConfigError, "unsupported parameter '"
                      << element.first << "'");
        } catch (const std::exception& ex) {
            // Append line number where the error occurred.
            isc_throw(DhcpConfigError, ex.what() << " ("
                      << element.second->getPosition() << ")");
        }
    }

    // User hasn't specified the socket type. Log that we are using
    // the default type. Log it only if this is DHCPv4. (DHCPv6 does not use
    // raw sockets).
    if (!socket_type_specified && (protocol_ == AF_INET) ) {
        LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_SOCKET_TYPE_DEFAULT)
            .arg(cfg->socketTypeToText());
    }
}

} // end of namespace isc::dhcp
} // end of namespace isc