ifaces_config_parser.cc 4.13 KB
Newer Older
1
// Copyright (C) 2015-2020 Internet Systems Consortium, Inc. ("ISC")
2
//
3 4 5
// 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/.
6

7
#include <config.h>
8 9
#include <cc/data.h>
#include <dhcpsrv/cfgmgr.h>
10
#include <dhcpsrv/dhcpsrv_log.h>
11 12 13 14 15 16 17 18 19 20 21
#include <dhcpsrv/parsers/ifaces_config_parser.h>
#include <boost/foreach.hpp>
#include <string>
#include <sys/types.h>

using namespace isc::data;

namespace isc {
namespace dhcp {

void
22
IfacesConfigParser::parseInterfacesList(const CfgIfacePtr& cfg_iface,
23
                                        ConstElementPtr ifaces_list) {
24
    BOOST_FOREACH(ConstElementPtr iface, ifaces_list->listValue()) {
25 26
        std::string iface_name = iface->stringValue();
        try {
27
            cfg_iface->use(protocol_, iface_name);
28 29 30

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

36 37
IfacesConfigParser::IfacesConfigParser(const uint16_t protocol, bool test_mode)
    : protocol_(protocol), test_mode_(test_mode) {
38 39 40
}

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

44 45 46 47 48
    // Close sockets if not in test mode.
    if (!test_mode_) {
        IfaceMgr::instance().closeSockets();
    }

49
    // Check for re-detect before calling parseInterfacesList()
Francis Dupont's avatar
Francis Dupont committed
50 51
    bool re_detect = getBoolean(ifaces_config, "re-detect");
    cfg->setReDetect(re_detect);
52
    if (re_detect && !test_mode_) {
Francis Dupont's avatar
Francis Dupont committed
53 54 55 56
        IfaceMgr::instance().clearIfaces();
        IfaceMgr::instance().detectIfaces();
    }

57
    bool socket_type_specified = false;
58 59
    BOOST_FOREACH(ConfigPair element, ifaces_config->mapValue()) {
        try {
60 61 62 63
            if (element.first == "re-detect") {
                continue;
            }

64 65 66 67 68
            if (element.first == "interfaces") {
                parseInterfacesList(cfg, element.second);
                continue;

            }
69

70 71 72 73 74 75 76 77 78
            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");
                }
79
            }
80 81 82 83 84 85 86 87 88 89 90 91

            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");
                }
            }
92 93 94 95 96

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

Tomek Mrugalski's avatar
Tomek Mrugalski committed
98 99 100 101 102
            // 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 '"
103
                      << element.first << "'");
104 105 106 107 108 109
        } catch (const std::exception& ex) {
            // Append line number where the error occurred.
            isc_throw(DhcpConfigError, ex.what() << " ("
                      << element.second->getPosition() << ")");
        }
    }
110 111

    // User hasn't specified the socket type. Log that we are using
Tomek Mrugalski's avatar
Tomek Mrugalski committed
112 113 114
    // the default type. Log it only if this is DHCPv4. (DHCPv6 does not use
    // raw sockets).
    if (!socket_type_specified && (protocol_ == AF_INET) ) {
115 116 117
        LOG_INFO(dhcpsrv_logger, DHCPSRV_CFGMGR_SOCKET_TYPE_DEFAULT)
            .arg(cfg->socketTypeToText());
    }
118 119 120 121
}

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