summaryrefslogtreecommitdiffstats
path: root/src/lib/dhcpsrv/parsers/ifaces_config_parser.cc
blob: adc821f2d62077a8ce44d8ed20e7dfc2f7e5ce30 (plain)
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
130
131
// Copyright (C) 2015-2022 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 <boost/foreach.hpp>
#include <string>
#include <sys/types.h>

using namespace isc::data;

namespace isc {
namespace dhcp {

void
IfacesConfigParser::parseInterfacesList(const CfgIfacePtr& cfg_iface,
                                        ConstElementPtr ifaces_list) {
    BOOST_FOREACH(ConstElementPtr 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;
    BOOST_FOREACH(ConfigPair 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