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
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
// Copyright (C) 2013-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/.

#ifndef DHCP_PARSERS_H
#define DHCP_PARSERS_H

#include <asiolink/io_address.h>
#include <cc/data.h>
#include <dhcp/option_definition.h>
#include <dhcp/option_space_container.h>
#include <dhcpsrv/d2_client_cfg.h>
#include <dhcpsrv/cfg_iface.h>
#include <dhcpsrv/cfg_option.h>
#include <dhcpsrv/network.h>
#include <dhcpsrv/subnet.h>
#include <dhcpsrv/cfg_option_def.h>
#include <dhcpsrv/cfg_mac_source.h>
#include <dhcpsrv/srv_config.h>
#include <dhcpsrv/parsers/base_network_parser.h>
#include <dhcpsrv/parsers/option_data_parser.h>
#include <cc/simple_parser.h>
#include <exceptions/exceptions.h>
#include <util/optional.h>

#include <boost/shared_ptr.hpp><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <stdint.h><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <string><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <vector><--- Include file:  not found. Please note: Cppcheck does not need standard library headers to get proper results.

namespace isc {
namespace dhcp {

/// Collection of containers holding option spaces. Each container within
/// a particular option space holds so-called option descriptors.
typedef OptionSpaceContainer<OptionContainer, OptionDescriptor,
                             std::string> OptionStorage;
/// @brief Shared pointer to option storage.
typedef boost::shared_ptr<OptionStorage> OptionStoragePtr;

/// @brief A template class that stores named elements of a given data type.
///
/// This template class is provides data value storage for configuration
/// parameters of a given data type.  The values are stored by parameter name
/// and as instances of type "ValueType". Each value held in the storage has
/// a corresponding position within a configuration string (file) specified
/// as a: file name, line number and position within the line. The position
/// information is used for logging when the particular configuration value
/// causes a configuration error.
///
/// @tparam ValueType is the data type of the elements to store.
template<typename ValueType>
class ValueStorage {
public:
    /// @brief  Stores the parameter, its value and the position in the
    /// store.
    ///
    /// If the parameter does not exist in the store, then it will be added,
    /// otherwise its data value and the position will be updated with the
    /// given values.
    ///
    /// @param name is the name of the parameter to store.
    /// @param value is the data value to store.
    /// @param position is the position of the data element within a
    /// configuration string (file).
    void setParam(const std::string& name, const ValueType& value,
                  const data::Element::Position& position) {
        values_[name] = value;
        positions_[name] = position;
    }

    /// @brief Returns the data value for the given parameter.
    ///
    /// Finds and returns the data value for the given parameter.
    /// @param name is the name of the parameter for which the data
    /// value is desired.
    ///
    /// @return The parameter's data value of type @c ValueType.
    /// @throw DhcpConfigError if the parameter is not found.
    ValueType getParam(const std::string& name) const {
        typename std::map<std::string, ValueType>::const_iterator param
            = values_.find(name);

        if (param == values_.end()) {
            isc_throw(DhcpConfigError, "Missing parameter '"
                      << name << "'");
        }

        return (param->second);
    }

    /// @brief Returns position of the data element in the configuration string.
    ///
    /// The returned object comprises file name, line number and the position
    /// within the particular line of the configuration string where the data
    /// element holding a particular value is located.
    ///
    /// @param name is the name of the parameter which position is desired.
    /// @param parent Pointer to a data element which position should be
    /// returned when position of the specified parameter is not found.
    ///
    /// @return Position of the data element or the position holding empty
    /// file name and two zeros if the position hasn't been specified for the
    /// particular value.
    const data::Element::Position&
    getPosition(const std::string& name, const data::ConstElementPtr parent =
                data::ConstElementPtr()) const {
        typename std::map<std::string, data::Element::Position>::const_iterator
            pos = positions_.find(name);
        if (pos == positions_.end()) {
            return (parent ? parent->getPosition() :
                    data::Element::ZERO_POSITION());
        }

        return (pos->second);
    }

    /// @brief Returns the data value for an optional parameter.
    ///
    /// Finds and returns the data value for the given parameter or
    /// a supplied default value if it is not found.
    ///
    /// @param name is the name of the parameter for which the data
    /// value is desired.
    /// @param default_value value to use the default
    ///
    /// @return The parameter's data value of type @c ValueType.
    ValueType getOptionalParam(const std::string& name,
                               const ValueType& default_value) const {
        typename std::map<std::string, ValueType>::const_iterator param
            = values_.find(name);

        if (param == values_.end()) {
            return (default_value);
        }

        return (param->second);
    }

    /// @brief  Remove the parameter from the store.
    ///
    /// Deletes the entry for the given parameter from the store if it
    /// exists.
    ///
    /// @param name is the name of the parameter to delete.
    void delParam(const std::string& name) {
        values_.erase(name);
        positions_.erase(name);
    }

    /// @brief Deletes all of the entries from the store.
    ///
    void clear() {
        values_.clear();
        positions_.clear();
    }

private:
    /// @brief An std::map of the data values, keyed by parameter names.
    std::map<std::string, ValueType> values_;

    /// @brief An std::map holding positions of the data elements in the
    /// configuration, which values are held in @c values_.
    ///
    /// The position is used for logging, when the particular value
    /// causes a configuration error.
    std::map<std::string, data::Element::Position> positions_;

};

/// @brief Combination of parameter name and configuration contents
typedef std::pair<std::string, isc::data::ConstElementPtr> ConfigPair;

/// @brief a collection of elements that store uint32 values
typedef ValueStorage<uint32_t> Uint32Storage;
typedef boost::shared_ptr<Uint32Storage> Uint32StoragePtr;

/// @brief a collection of elements that store string values
typedef ValueStorage<std::string> StringStorage;
typedef boost::shared_ptr<StringStorage> StringStoragePtr;

/// @brief Storage for parsed boolean values.
typedef ValueStorage<bool> BooleanStorage;
typedef boost::shared_ptr<BooleanStorage> BooleanStoragePtr;

/// @brief parser for MAC/hardware acquisition sources
///
/// This parser handles Dhcp6/mac-sources entry.
/// It contains a list of MAC/hardware acquisition source, i.e. methods how
/// MAC address can possibly by obtained in DHCPv6. For a currently supported
/// methods, see @ref isc::dhcp::Pkt::getMAC.
class MACSourcesListConfigParser : public isc::data::SimpleParser {
public:
    /// @brief parses parameters value
    ///
    /// Parses configuration entry (list of sources) and adds each element
    /// to the sources list.
    ///
    /// @param value pointer to the content of parsed values
    /// @param mac_sources parsed sources will be stored here
    void parse(CfgMACSource& mac_sources, isc::data::ConstElementPtr value);
};

/// @brief Parser for the control-socket structure
///
/// It does not parse anything, simply stores the element in
/// the staging config.
class ControlSocketParser : public isc::data::SimpleParser {
public:
    /// @brief "Parses" control-socket structure
    ///
    /// Since the SrvConfig structure takes the socket definition
    /// as ConstElementPtr, there's really nothing to parse here.
    /// It only does basic sanity checks and throws DhcpConfigError
    /// if the value is null or is not a map.
    ///
    /// @param srv_cfg parsed values will be stored here
    /// @param value pointer to the content of parsed values
    void parse(SrvConfig& srv_cfg, isc::data::ConstElementPtr value);
};

/// @brief Parser for a single option definition.
///
/// This parser creates an instance of a single option definition.
class OptionDefParser : public isc::data::SimpleParser {
public:
    /// @brief Constructor.
    ///
    /// @param address_family Address family: @c AF_INET or @c AF_INET6.
    OptionDefParser(const uint16_t address_family);

    /// @brief Parses an entry that describes single option definition.
    ///
    /// @param option_def a configuration entry to be parsed.
    /// @return option definition of the parsed structure.
    ///
    /// @throw DhcpConfigError if parsing was unsuccessful.
    OptionDefinitionPtr parse(isc::data::ConstElementPtr option_def);

private:
    /// @brief Address family: @c AF_INET or @c AF_INET6.
    uint16_t address_family_;
};

/// @brief Parser for a list of option definitions.
///
/// This parser iterates over all configuration entries that define
/// option definitions and creates instances of these definitions.
/// If the parsing is successful, the collection of created definitions
/// is put into the provided storage.
class OptionDefListParser : public isc::data::SimpleParser {
public:
    /// @brief Constructor.
    ///
    /// @param address_family Address family: @c AF_INET or @c AF_INET6.
    OptionDefListParser(const uint16_t address_family);

    /// @brief Parses a list of option definitions, create them and store in cfg
    ///
    /// This method iterates over def_list, which is a JSON list of option definitions,
    /// then creates corresponding option definitions and store them in the
    /// configuration structure.
    ///
    /// @param def_list JSON list describing option definitions
    /// @param cfg parsed option definitions will be stored here
    void parse(CfgOptionDefPtr cfg, isc::data::ConstElementPtr def_list);

private:
    /// @brief Address family: @c AF_INET or @c AF_INET6.
    uint16_t address_family_;
};

/// @brief a collection of pools
///
/// That type is used as intermediate storage, when pools are parsed, but there is
/// no subnet object created yet to store them.
typedef std::vector<PoolPtr> PoolStorage;
typedef boost::shared_ptr<PoolStorage> PoolStoragePtr;

/// @brief parser for a single pool definition
///
/// This abstract parser handles pool definitions, i.e. a list of entries of one
/// of two syntaxes: min-max and prefix/len. Pool objects are created
/// and stored in chosen PoolStorage container.
///
/// It is useful for parsing Dhcp<4/6>/subnet<4/6>[X]/pools[X] structure.
class PoolParser : public isc::data::SimpleParser {
public:

    /// @brief destructor.
    virtual ~PoolParser() {
    }

    /// @brief parses the actual structure
    ///
    /// This method parses the actual list of interfaces.
    /// No validation is done at this stage, everything is interpreted as
    /// interface name.
    /// @param pools is the storage in which to store the parsed pool
    /// @param pool_structure a single entry on a list of pools
    /// @param address_family AF_INET (for DHCPv4) or AF_INET6 (for DHCPv6).
    /// @param encapsulate_options a boolean parameter indicating if the
    /// parsed options should be encapsulated with suboptions.
    /// @throw isc::dhcp::DhcpConfigError when pool parsing fails
    virtual void parse(PoolStoragePtr pools,
                       isc::data::ConstElementPtr pool_structure,
                       const uint16_t address_family,
                       bool encapsulate_options = true);

protected:
    /// @brief Creates a Pool object given a IPv4 prefix and the prefix length.
    ///
    /// @param addr is the IP  prefix of the pool.
    /// @param len is the prefix length.
    /// @param ptype is the type of pool to create.
    /// @return returns a PoolPtr to the new Pool object.
    virtual PoolPtr poolMaker(isc::asiolink::IOAddress &addr, uint32_t len,<--- Virtual function in base class<--- Virtual function in base class
                              int32_t ptype = 0) = 0;

    /// @brief Creates a Pool object given starting and ending IP addresses.
    ///
    /// @param min is the first IP address in the pool.
    /// @param max is the last IP address in the pool.
    /// @param ptype is the type of pool to create (not used by all derivations)
    /// @return returns a PoolPtr to the new Pool object.
    virtual PoolPtr poolMaker(isc::asiolink::IOAddress &min,<--- Virtual function in base class<--- Virtual function in base class
                              isc::asiolink::IOAddress &max,
                              int32_t ptype = 0) = 0;

    /// @brief Returns an instance of the @c OptionDataListParser to
    /// be used in parsing the option-data structure.
    ///
    /// This function can be overridden in the child classes to supply
    /// a custom parser for option data.
    ///
    /// @param address_family AF_INET (for DHCPv4) or AF_INET6 (for DHCPv6).
    ///
    /// @return an instance of the @c OptionDataListParser.
    virtual boost::shared_ptr<OptionDataListParser>
    createOptionDataListParser(const uint16_t address_family) const;
};

/// @brief Parser for IPv4 pool definitions.
///
/// This is the IPv4 derivation of the PoolParser class and handles pool
/// definitions, i.e. a list of entries of one of two syntaxes: min-max and
/// prefix/len for IPv4 pools. Pool4 objects are created and stored in chosen
/// PoolStorage container.
///
/// It is useful for parsing Dhcp4/subnet4[X]/pool parameters.
class Pool4Parser : public PoolParser {
protected:
    /// @brief Creates a Pool4 object given a IPv4 prefix and the prefix length.
    ///
    /// @param addr is the IPv4 prefix of the pool.
    /// @param len is the prefix length.
    /// @param ignored dummy parameter to provide symmetry between the
    /// PoolParser derivations. The V6 derivation requires a third value.
    /// @return returns a PoolPtr to the new Pool4 object.
    PoolPtr poolMaker (asiolink::IOAddress &addr, uint32_t len,<--- Function in derived class
                       int32_t ignored);

    /// @brief Creates a Pool4 object given starting and ending IPv4 addresses.
    ///
    /// @param min is the first IPv4 address in the pool.
    /// @param max is the last IPv4 address in the pool.
    /// @param ignored dummy parameter to provide symmetry between the
    /// PoolParser derivations. The V6 derivation requires a third value.
    /// @return returns a PoolPtr to the new Pool4 object.
    PoolPtr poolMaker (asiolink::IOAddress &min, asiolink::IOAddress &max,<--- Function in derived class
                       int32_t ignored);
};

/// @brief Parser for a list of pools
///
/// This parser parses a list pools. Each element on that list gets its own
/// parser, created with poolParserMaker() method. That method must be specified
/// for each protocol family (v4 or v6) separately.
class PoolsListParser : public isc::data::SimpleParser {
public:

    /// @brief destructor.
    virtual ~PoolsListParser() {
    }

    /// @brief parses the actual structure
    ///
    /// This method parses the actual list of pools.
    ///
    /// @param pools is the storage in which to store the parsed pools.
    /// @param pools_list a list of pool structures
    /// @param encapsulate_options a boolean parameter indicating if the
    /// parsed options should be encapsulated with suboptions.
    /// @throw isc::dhcp::DhcpConfigError when pool parsing fails
    virtual void parse(PoolStoragePtr pools,
                       isc::data::ConstElementPtr pools_list,
                       bool encapsulate_options) = 0;

protected:

    /// @brief Returns an instance of the @c PoolParser to be used in
    /// parsing the address pools.
    ///
    /// This function can be overridden in the child classes to supply
    /// a custom parser for the pools.
    ///
    /// @return an instance of the @c PoolParser.
    virtual boost::shared_ptr<PoolParser> createPoolConfigParser() const = 0;<--- Virtual function in base class<--- Virtual function in base class
};

/// @brief Specialization of the pool list parser for DHCPv4
class Pools4ListParser : public PoolsListParser {
public:

    /// @brief parses the actual structure
    ///
    /// This method parses the actual list of pools.
    ///
    /// @param pools storage container in which to store the parsed pool.
    /// @param pools_list a list of pool structures
    /// @param encapsulate_options a boolean parameter indicating if the
    /// parsed options should be encapsulated with suboptions.
    /// @throw isc::dhcp::DhcpConfigError when pool parsing fails
    void parse(PoolStoragePtr pools, data::ConstElementPtr pools_list,
               bool encapsulate_options = true);

protected:

    /// @brief Returns an instance of the @c Pool4Parser to be used in
    /// parsing the address pools.
    ///
    /// This function can be overridden in the child classes to supply
    /// a custom parser for the pools.
    ///
    /// @return an instance of the @c Pool4Parser.
    virtual boost::shared_ptr<PoolParser> createPoolConfigParser() const;<--- Function in derived class
};

/// @brief parser for additional relay information
///
/// This concrete parser handles RelayInfo structure definitions.
/// So far that structure holds only relay IP (v4 or v6) address, but it
/// is expected that the number of parameters will increase over time.
///
/// It is useful for parsing Dhcp<4/6>/subnet<4/6>[x]/relay parameters.
class RelayInfoParser : public isc::data::SimpleParser {
public:

    /// @brief constructor
    /// @param family specifies protocol family (IPv4 or IPv6)
    explicit RelayInfoParser(const isc::dhcp::Option::Universe& family);

    /// @brief parses the actual relay parameters
    ///
    /// The elements currently supported are:
    /// -# ip-address
    /// -# ip-addresses
    ///
    /// Note that ip-address and ip-addresses are mutually exclusive, with
    /// former being deprecated.  The use of ip-address will cause an debug
    /// log to be emitted, reminded users to switch.
    ///
    /// @param relay_info configuration will be stored here
    /// @param relay_elem Element tree containing the relay and its members
    /// @throw isc::dhcp::DhcpConfigError if both or neither of ip-address
    /// and ip-addresses are specified.
    void parse(const isc::dhcp::Network::RelayInfoPtr& relay_info,
               isc::data::ConstElementPtr relay_elem);

    /// @brief Attempts to add an IP address to list of relay addresses
    ///
    /// @param name name of the element supplying the address string, (either
    /// "ip-address" or "ip-addresses")
    /// @param address_str string form of the IP address to add
    /// @param relay_elem parent relay element (needed for position info)
    /// @param relay_info RelayInfo to which the address should be added
    /// @throw isc::dhcp::DhcpConfigError if the address string is not a valid
    /// IP address, is an address of the wrong family, or is already in the
    /// relay address list
    void addAddress(const std::string& name, const std::string& address_str,
                    isc::data::ConstElementPtr relay_elem,
                    const isc::dhcp::Network::RelayInfoPtr& relay_info);
private:

    /// Protocol family (IPv4 or IPv6)
    Option::Universe family_;
};

/// @brief this class parses a single subnet
///
/// There are dedicated @ref Subnet4ConfigParser and @ref Subnet6ConfigParser
/// classes. They provide specialized parse() methods that return Subnet4Ptr
/// or Subnet6Ptr.
///
/// This class parses the whole subnet definition. This class attempts to
/// unify the code between v4 and v6 as much as possible. As a result, the flow
/// is somewhat complex and it looks as follows:
///
///     ------- Base class
///    /
///    | /----- Derived class
/// 1.   * SubnetXConfigParser::parse() is called.
/// 2. *   SubnetConfigParser::parse() is called.
/// 3. *   SubnetConfigParser::createSubnet() is called.
/// 4.   * SubnetXConfigParser::initSubnet() is called (Subnet4 or Subnet6 is
///        instantiated here and family specific parameters are set)
/// 5.     Control returns to createSubnet() (step 3) and common parameters
///        are set.
class SubnetConfigParser : public BaseNetworkParser {
public:

    /// @brief constructor
    ///
    /// @param family address family: @c AF_INET or @c AF_INET6
    /// @param check_iface Check if the specified interface exists in
    /// the system.
    explicit SubnetConfigParser(uint16_t family, bool check_iface = true);

    /// @brief virtual destructor (does nothing)
    virtual ~SubnetConfigParser() { }

protected:
    /// @brief parses a subnet description and returns Subnet{4,6} structure
    ///
    /// This method is called from specialized (Subnet4ConfigParser or
    /// Subnet6ConfigParser) classes.
    ///
    /// @param subnet pointer to the content of subnet definition
    /// @param encapsulate_options a boolean parameter indicating if the
    /// parsed options should be encapsulated with suboptions.
    /// @return a pointer to newly created subnet
    ///
    /// @throw isc::DhcpConfigError if subnet configuration parsing failed.
    SubnetPtr parse(isc::data::ConstElementPtr subnet,
                    bool encapsulate_options);

    /// @brief Instantiates the subnet based on a given IP prefix and prefix
    /// length.
    ///
    /// @param params configuration parameters for that subnet
    /// @param addr is the IP prefix of the subnet.
    /// @param len is the prefix length
    virtual void initSubnet(isc::data::ConstElementPtr params,<--- Virtual function in base class<--- Virtual function in base class
                            isc::asiolink::IOAddress addr, uint8_t len) = 0;

protected:

    /// @brief Create a new subnet using a data from child parsers.
    ///
    /// @param data Element map that describes the subnet
    /// @throw isc::dhcp::DhcpConfigError if subnet configuration parsing
    /// failed.
    void createSubnet(isc::data::ConstElementPtr data);

    /// @brief Returns an instance of the @c OptionDataListParser to
    /// be used in parsing the option-data structure.
    ///
    /// This function can be overridden in the child classes to supply
    /// a custom parser for option data.
    ///
    /// @return an instance of the @c OptionDataListParser.
    virtual boost::shared_ptr<OptionDataListParser> createOptionDataListParser() const;

    /// @brief Returns an instance of the @c PoolsListParser to be used
    /// in parsing the address pools.
    ///
    /// This function can be overridden in the child classes to supply
    /// a custom parser for the pools.
    ///
    /// @return an instance of the @c PoolsListParser.
    virtual boost::shared_ptr<PoolsListParser>
    createPoolsListParser() const = 0;<--- Virtual function in base class<--- Virtual function in base class

    /// Storage for pools belonging to this subnet.
    PoolStoragePtr pools_;

    /// Pointer to the created subnet object.
    isc::dhcp::SubnetPtr subnet_;

    /// @brief Address family: @c AF_INET or @c AF_INET6
    uint16_t address_family_;

    /// Pointer to relay information
    isc::dhcp::Network::RelayInfoPtr relay_info_;

    /// Check if the specified interface exists in the system.
    bool check_iface_;
};

/// @anchor Subnet4ConfigParser
/// @brief This class parses a single IPv4 subnet.
///
/// This is the IPv4 derivation of the SubnetConfigParser class and it parses
/// the whole subnet definition. It creates parsersfor received configuration
/// parameters as needed.
class Subnet4ConfigParser : public SubnetConfigParser {
public:
    /// @brief Constructor
    ///
    /// stores global scope parameters, options, option definitions.
    ///
    /// @param check_iface Check if the specified interface exists in
    /// the system.
    Subnet4ConfigParser(bool check_iface = true);

    /// @brief Parses a single IPv4 subnet configuration and adds to the
    /// Configuration Manager.
    ///
    /// @param subnet A new subnet being configured.
    /// @param encapsulate_options a boolean parameter indicating if the
    /// parsed options should be encapsulated with suboptions.
    /// @return a pointer to created Subnet4 object
    Subnet4Ptr parse(data::ConstElementPtr subnet,
                     bool encapsulate_options = true);

protected:

    /// @brief Instantiates the IPv4 Subnet based on a given IPv4 address
    /// and prefix length.
    ///
    /// @param params Data structure describing a subnet.
    /// @param addr is IPv4 address of the subnet.
    /// @param len is the prefix length
    void initSubnet(data::ConstElementPtr params,<--- Function in derived class
                    asiolink::IOAddress addr, uint8_t len);

    /// @brief Verifies the host reservation address is in the subnet range
    ///
    /// @param subnet pointer to the subnet
    /// @param host pointer to the host reservation
    /// @throw DhcpConfigError when the address is not in the subnet range.
    void validateResv(const Subnet4Ptr& subnet, ConstHostPtr host);

    /// @brief Returns an instance of the @c Pools4ListParser to be used
    /// in parsing the address pools.
    ///
    /// This function can be overridden in the child classes to supply
    /// a custom parser for the pools.
    ///
    /// @return an instance of the @c Pools4ListParser.
    virtual boost::shared_ptr<PoolsListParser>
    createPoolsListParser() const;<--- Function in derived class
};

/// @brief this class parses list of DHCP4 subnets
///
/// This is a wrapper parser that handles the whole list of Subnet4
/// definitions. It iterates over all entries and creates Subnet4ConfigParser
/// for each entry.
class Subnets4ListConfigParser : public isc::data::SimpleParser {
public:

    /// @brief constructor
    ///
    /// @param check_iface Check if the specified interface exists in
    /// the system.
    Subnets4ListConfigParser(bool check_iface = true);

    /// @brief Virtual destructor.
    virtual ~Subnets4ListConfigParser() {
    }

    /// @brief parses contents of the list
    ///
    /// Iterates over all entries on the list, parses its content
    /// (by instantiating Subnet6ConfigParser) and adds to specified
    /// configuration.
    ///
    /// @param cfg Pointer to server configuration.
    /// @param subnets_list pointer to a list of IPv4 subnets
    /// @param encapsulate_options a boolean parameter indicating if the
    /// parsed options should be encapsulated with suboptions.
    /// @return number of subnets created
    size_t parse(SrvConfigPtr cfg, data::ConstElementPtr subnets_list,
                 bool encapsulate_options = true);

    /// @brief Parses contents of the subnet4 list.
    ///
    /// @param [out] subnets Container where parsed subnets will be stored.
    /// @param subnets_list pointer to a list of IPv4 subnets
    /// @param encapsulate_options a boolean parameter indicating if the
    /// parsed options should be encapsulated with suboptions.
    /// @return Number of subnets created.
    size_t parse(Subnet4Collection& subnets,
                 data::ConstElementPtr subnets_list,
                 bool encapsulate_options = true);

protected:

    /// @brief Returns an instance of the @c Subnet4ConfigParser to be
    /// used in parsing the subnets.
    ///
    /// This function can be overridden in the child classes to supply
    /// a custom parser for the subnets.
    ///
    /// @return an instance of the @c Subnet4ConfigParser.
    virtual boost::shared_ptr<Subnet4ConfigParser> createSubnetConfigParser() const;

    /// Check if the specified interface exists in the system.
    bool check_iface_;
};

/// @brief Parser for IPv6 pool definitions.
///
/// This is the IPv6 derivation of the PoolParser class and handles pool
/// definitions, i.e. a list of entries of one of two syntaxes: min-max and
/// prefix/len for IPv6 pools. Pool6 objects are created and stored in chosen
/// PoolStorage container.
///
/// It is useful for parsing Dhcp6/subnet6[X]/pool parameters.
class Pool6Parser : public PoolParser {
protected:
    /// @brief Creates a Pool6 object given a IPv6 prefix and the prefix length.
    ///
    /// @param addr is the IPv6 prefix of the pool.
    /// @param len is the prefix length.
    /// @param ptype is the type of IPv6 pool (Pool::PoolType). Note this is
    /// passed in as an int32_t and cast to PoolType to accommodate a
    /// polymorphic interface.
    /// @return returns a PoolPtr to the new Pool4 object.
    PoolPtr poolMaker (asiolink::IOAddress &addr, uint32_t len, int32_t ptype);<--- Function in derived class

    /// @brief Creates a Pool6 object given starting and ending IPv6 addresses.
    ///
    /// @param min is the first IPv6 address in the pool.
    /// @param max is the last IPv6 address in the pool.
    /// @param ptype is the type of IPv6 pool (Pool::PoolType). Note this is
    /// passed in as an int32_t and cast to PoolType to accommodate a
    /// polymorphic interface.
    /// @return returns a PoolPtr to the new Pool4 object.
    PoolPtr poolMaker (asiolink::IOAddress &min, asiolink::IOAddress &max,<--- Function in derived class
                       int32_t ptype);
};

/// @brief Specialization of the pool list parser for DHCPv6
class Pools6ListParser : public PoolsListParser {
public:

    /// @brief parses the actual structure
    ///
    /// This method parses the actual list of pools.
    ///
    /// @param pools storage container in which to store the parsed pool.
    /// @param pools_list a list of pool structures
    /// @param encapsulate_options a boolean parameter indicating if the
    /// parsed options should be encapsulated with suboptions.
    /// @throw isc::dhcp::DhcpConfigError when pool parsing fails
    void parse(PoolStoragePtr pools, data::ConstElementPtr pools_list,
               bool encapsulate_options = true);

protected:

    /// @brief Returns an instance of the @c Pool6Parser to be used in
    /// parsing the address pools.
    ///
    /// This function can be overridden in the child classes to supply
    /// a custom parser for the pools.
    ///
    /// @return an instance of the @c Pool6Parser.
    virtual boost::shared_ptr<PoolParser> createPoolConfigParser() const;<--- Function in derived class
};

/// @brief Parser for IPv6 prefix delegation definitions.
///
/// This class handles prefix delegation pool definitions for IPv6 subnets
/// Pool6 objects are created and stored in the given PoolStorage container.
///
/// PdPool definitions currently support three elements: prefix, prefix-len,
/// and delegated-len, as shown in the example JSON text below:
///
/// @code
///
/// {
///     "prefix": "2001:db8:1::",
///     "prefix-len": 64,
///     "delegated-len": 128
/// }
/// @endcode
///
class PdPoolParser : public isc::data::SimpleParser {
public:

    /// @brief Constructor.
    ///
    PdPoolParser();

    /// @brief Virtual destructor.
    virtual ~PdPoolParser() {
    }

    /// @brief Builds a prefix delegation pool from the given configuration
    ///
    /// This function parses configuration entries and creates an instance
    /// of a dhcp::Pool6 configured for prefix delegation.
    ///
    /// @param pools storage container in which to store the parsed pool.
    /// @param pd_pool_ pointer to an element that holds configuration entries
    /// that define a prefix delegation pool.
    /// @param encapsulate_options a boolean parameter indicating if the
    /// parsed options should be encapsulated with suboptions.
    ///
    /// @throw DhcpConfigError if configuration parsing fails.
    void parse(PoolStoragePtr pools, data::ConstElementPtr pd_pool_,
               bool encapsulate_options = true);

protected:

    /// @brief Returns an instance of the @c OptionDataListParser to
    /// be used in parsing the option-data structure.
    ///
    /// This function can be overridden in the child classes to supply
    /// a custom parser for option data.
    ///
    /// @return an instance of the @c OptionDataListParser.
    virtual boost::shared_ptr<OptionDataListParser>
    createOptionDataListParser() const;

    /// Pointer to the created pool object.
    isc::dhcp::Pool6Ptr pool_;

    /// @brief User context (optional, may be null)
    ///
    /// User context is arbitrary user data, to be used by hooks.
    isc::data::ConstElementPtr user_context_;

    /// @brief Client class (a client has to belong to to use this pd-pool)
    ///
    /// If null, everyone is allowed.
    isc::data::ConstElementPtr client_class_;
};

/// @brief Parser for a list of prefix delegation pools.
///
/// This parser iterates over a list of prefix delegation pool entries and
/// creates pool instances for each one. If the parsing is successful, the
/// collection of pools is committed to the provided storage.
class PdPoolsListParser : public isc::data::SimpleParser {
public:

    /// @brief Virtual destructor.
    virtual ~PdPoolsListParser() {
    }

    /// @brief Parse configuration entries.
    ///
    /// This function parses configuration entries and creates instances
    /// of prefix delegation pools .
    ///
    /// @param pools is the pool storage in which to store the parsed
    /// @param pd_pool_list pointer to an element that holds entries
    /// that define a prefix delegation pool.
    ///
    /// @throw DhcpConfigError if configuration parsing fails.
    void parse(PoolStoragePtr pools, data::ConstElementPtr pd_pool_list);

protected:

    /// @brief Returns an instance of the @c PdPoolParser to be used in
    /// parsing the prefix delegation pools.
    ///
    /// This function can be overridden in the child classes to supply
    /// a custom parser for the pools.
    ///
    /// @return an instance of the @c PdPool6Parser.
    virtual boost::shared_ptr<PdPoolParser>
    createPdPoolConfigParser() const;
};

/// @anchor Subnet6ConfigParser
/// @brief This class parses a single IPv6 subnet.
///
/// This is the IPv6 derivation of the SubnetConfigParser class and it parses
/// the whole subnet definition. It creates parsersfor received configuration
/// parameters as needed.
class Subnet6ConfigParser : public SubnetConfigParser {
public:

    /// @brief Constructor
    ///
    /// stores global scope parameters, options, option definitions.
    ///
    /// @param check_iface Check if the specified interface exists in
    /// the system.
    Subnet6ConfigParser(bool check_iface = true);

    /// @brief Parses a single IPv6 subnet configuration and adds to the
    /// Configuration Manager.
    ///
    /// @param subnet A new subnet being configured.
    /// @param encapsulate_options a boolean parameter indicating if the
    /// parsed options should be encapsulated with suboptions.
    /// @return a pointer to created Subnet6 object
    Subnet6Ptr parse(data::ConstElementPtr subnet,
                     bool encapsulate_options = true);

protected:
    /// @brief Issues a DHCP6 server specific warning regarding duplicate subnet
    /// options.
    ///
    /// @param code is the numeric option code of the duplicate option
    /// @param addr is the subnet address
    /// @todo A means to know the correct logger and perhaps a common
    /// message would allow this message to be emitted by the base class.
    virtual void duplicateOptionWarning(uint32_t code,
                                        asiolink::IOAddress& addr);

    /// @brief Instantiates the IPv6 Subnet based on a given IPv6 address
    /// and prefix length.
    ///
    /// @param params Data structure describing a subnet.
    /// @param addr is IPv6 prefix of the subnet.
    /// @param len is the prefix length
    void initSubnet(isc::data::ConstElementPtr params,<--- Function in derived class
                    isc::asiolink::IOAddress addr, uint8_t len);

    /// @brief Verifies host reservation addresses are in the subnet range
    ///
    /// @param subnet pointer to the subnet
    /// @param host pointer to the host reservation
    /// @throw DhcpConfigError when an address is not in the subnet range.
    void validateResvs(const Subnet6Ptr& subnet, ConstHostPtr host);

    /// @brief Returns an instance of the @c Pools6ListParser to be used
    /// in parsing the address pools.
    ///
    /// This function can be overridden in the child classes to supply
    /// a custom parser for the pools.
    ///
    /// @return an instance of the @c Pools6ListParser.
    virtual boost::shared_ptr<PoolsListParser>
    createPoolsListParser() const;<--- Function in derived class

    /// @brief Returns an instance of the @c PdPools6ListParser to be used
    /// in parsing the prefix delegation pools.
    ///
    /// This function can be overridden in the child classes to supply
    /// a custom parser for the pools.
    ///
    /// @return an instance of the @c PdPools6ListParser.
    virtual boost::shared_ptr<PdPoolsListParser>
    createPdPoolsListParser() const;
};


/// @brief this class parses a list of DHCP6 subnets
///
/// This is a wrapper parser that handles the whole list of Subnet6
/// definitions. It iterates over all entries and creates Subnet6ConfigParser
/// for each entry.
class Subnets6ListConfigParser : public isc::data::SimpleParser {
public:

    /// @brief constructor
    ///
    /// @param check_iface Check if the specified interface exists in
    /// the system.
    Subnets6ListConfigParser(bool check_iface = true);

    /// @brief Virtual destructor.
    virtual ~Subnets6ListConfigParser() {
    }

    /// @brief parses contents of the list
    ///
    /// Iterates over all entries on the list, parses its content
    /// (by instantiating Subnet6ConfigParser) and adds to specified
    /// configuration.
    ///
    /// @param cfg configuration (parsed subnets will be stored here)
    /// @param subnets_list pointer to a list of IPv6 subnets
    /// @param encapsulate_options a boolean parameter indicating if the
    /// parsed options should be encapsulated with suboptions.
    ///
    /// @throw DhcpConfigError if CfgMgr rejects the subnet (e.g. subnet-id is a duplicate)
    size_t parse(SrvConfigPtr cfg, data::ConstElementPtr subnets_list,
                 bool encapsulate_options = true);

    /// @brief Parses contents of the subnet6 list.
    ///
    /// @param [out] subnets Container where parsed subnets will be stored.
    /// @param subnets_list pointer to a list of IPv6 subnets
    /// @param encapsulate_options a boolean parameter indicating if the
    /// parsed options should be encapsulated with suboptions.
    ///
    /// @return Number of subnets created.
    size_t parse(Subnet6Collection& subnets,
                 data::ConstElementPtr subnets_list,
                 bool encapsulate_options = true);

protected:

    /// @brief Returns an instance of the @c Subnet6ConfigParser to be
    /// used in parsing the subnets.
    ///
    /// This function can be overridden in the child classes to supply
    /// a custom parser for the subnets.
    ///
    /// @return an instance of the @c Subnet6ConfigParser.
    virtual boost::shared_ptr<Subnet6ConfigParser> createSubnetConfigParser() const;

    /// Check if the specified interface exists in the system.
    bool check_iface_;
};

/// @brief Parser for D2ClientConfig
///
/// This class parses the configuration element "dhcp-ddns" common to the
/// config files for both dhcp4 and dhcp6. It creates an instance of a
/// D2ClientConfig.
class D2ClientConfigParser : public isc::data::SimpleParser {
public:

    /// @brief Parses a given dhcp-ddns element into D2ClientConfig.
    ///
    /// @param d2_client_cfg is the "dhcp-ddns" configuration to parse
    ///
    /// The elements currently supported are (see isc::dhcp::D2ClientConfig
    /// for details on each):
    /// -# enable-updates
    /// -# server-ip
    /// -# server-port
    /// -# sender-ip
    /// -# sender-port
    /// -# max-queue-size
    /// -# ncr-protocol
    /// -# ncr-format
    ///
    /// @return returns a pointer to newly created D2ClientConfig.
    D2ClientConfigPtr parse(isc::data::ConstElementPtr d2_client_cfg);

    /// @brief Defaults for the D2 client configuration.
    static const isc::data::SimpleDefaults D2_CLIENT_CONFIG_DEFAULTS;

    /// @brief Sets all defaults for D2 client configuration.
    ///
    /// This method sets defaults value. It must not be called
    /// before the short cut disabled updates condition was checked.
    ///
    /// @param d2_config d2 client configuration (will be const cast
    //  to ElementPtr)
    /// @return number of parameters inserted
    static size_t setAllDefaults(isc::data::ConstElementPtr d2_config);

private:

    /// @brief Returns a value converted to NameChangeProtocol
    ///
    /// Instantiation of getAndConvert() to NameChangeProtocol
    ///
    /// @param scope specified parameter will be extracted from this scope
    /// @param name name of the parameter
    /// @return a NameChangeProtocol value
    dhcp_ddns::NameChangeProtocol
    getProtocol(isc::data::ConstElementPtr scope, const std::string& name);

    /// @brief Returns a value converted to NameChangeFormat
    ///
    /// Instantiation of getAndConvert() to NameChangeFormat
    ///
    /// @param scope specified parameter will be extracted from this scope
    /// @param name name of the parameter
    /// @return a NameChangeFormat value
    dhcp_ddns::NameChangeFormat
    getFormat(isc::data::ConstElementPtr scope, const std::string& name);

    /// @brief Returns a value converted to ReplaceClientNameMode
    ///
    /// Instantiation of getAndConvert() to ReplaceClientNameMode
    ///
    /// @param scope specified parameter will be extracted from this scope
    /// @param name name of the parameter
    /// @return a NameChangeFormat value
    D2ClientConfig::ReplaceClientNameMode
    getMode(isc::data::ConstElementPtr scope, const std::string& name);<--- Unused private function: 'D2ClientConfigParser::getMode'
};

class CompatibilityParser : public isc::data::SimpleParser {
public:
    /// @brief Parse compatibility flags
    ///
    /// @param cfg The configuration element to be parsed
    /// @param srv_cfg The configuration where the parameters are stored
    void parse(isc::data::ConstElementPtr cfg, isc::dhcp::SrvConfig& srv_cfg);
};

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

#endif // DHCP_PARSERS_H