module kea-dhcp6-server {
  yang-version 1.1;
  namespace "urn:ietf:params:xml:ns:yang:kea-dhcp6-server";
  prefix "kea-dhcp6-server";

  import ietf-inet-types {
    prefix inet;
  }
  import kea-types {
    prefix kea;
    revision-date 2019-08-12;
  }
  import kea-dhcp-types {
    prefix dhcp;
    revision-date 2024-05-29;
  }

  organization "Internet Systems Consortium";
  contact "kea-dev@lists.isc.org";
  description "This model defines a YANG data model that can be
               used to configure and manage a Kea DHCPv6 server.";

  revision 2024-05-29 {
    description "Removed reservation-mode and added
                 ddns-conflict-resolution-mode.";
  }

  revision 2024-01-31 {
    description "Added data to the set of keys for option-data to facilitate
                 configuring options with same code and space, but different
                 data.";
  }

  revision 2023-06-28 {
    description "Added pool ID. Renamed statistic declined-nas to
                 declined-addresses";
  }

  revision 2023-05-31 {
    description "Added allocator, ddns-ttl-percent, pd-allocator,
                 read-timeout, tcp-user-timeout, write-timeout.
                 Removed contact-points, keyspace.";
  }

  revision 2022-12-27 {
    description "Added never-send to option-data.";
  }

  revision 2022-11-30 {
    description "Added the template-test node for client classes.";
  }

  revision 2022-07-27 {
    description "Added TLS parameters for database connections: trust-anchor,
                 cert-file, key-file, cipher-list. Added parameters which govern
                 the way the server behaves regarding detection of configured
                 interfaces: service-sockets-require-all,
                 service-sockets-max-retries, service-sockets-retry-wait-time.
                 Added parameters which govern reservations lookup:
                 early-global-reservations-lookup, reservations-lookup-first.";
  }

  revision 2021-11-24 {
    description "Fixed store-extended-info. Added several containers and leaves:
                 compatibility, lenient-option-parsing, multi-threading,
                 enable-multi-threading, packet-queue-size, thread-pool-size,
                 valid-lifetime, min-valid-lifetime, max-valid-lifetime,
                 preferred-lifetime, min-preferred-lifetime,
                 max-preferred-lifetime, cache-max-age, cache-threshold,
                 ddns-generated-prefix, ddns-override-client-update,
                 ddns-override-no-update, ddns-qualifying-suffix,
                 ddns-replace-client-name, ddns-send-updates,
                 ddns-update-on-renew, ddns-use-conflict-resolution,
                 ip-reservations-unique, parked-packet-limit,
                 reservations-global, reservations-in-subnet,
                 reservations-out-of-pool, statistic-default-sample-age,
                 statistic-default-sample-count, store-extended-info, on-fail.";
  }

  revision 2021-08-25 {
    description "Added store-extended-info";
  }

  revision 2019-08-12 {
    description "Initial revision";
  }

  /*
  * Typedefs
  */
  typedef host-identifier-type {
    type enumeration {
      enum "duid" {
        description "DUID";
      }
      enum "hw-address" {
        description "Hardware address";
      }
      enum "flex-id" {
        description "Flexible identifier";
      }
    }
    description "Host identifier type.";
  }

  /*
  * Groupings
  */
  grouping data-directory {
    description "Data directory grouping.";
    leaf data-directory {
      type string;
      description "Server data directory.";
    }
  }

  grouping preferred-lifetime {
    description "Preferred lifetime grouping.";
    leaf preferred-lifetime {
      type uint32;
      units "seconds";
      description "Preferred lifetime.";
    }
  }

  grouping min-preferred-lifetime {
    description "Minimum preferred lifetime grouping.";
    leaf min-preferred-lifetime {
      type uint32;
      units "seconds";
      description "Minimum preferred lifetime.";
    }
  }

  grouping max-preferred-lifetime {
    description "Maximum preferred lifetime grouping.";
    leaf max-preferred-lifetime {
      type uint32;
      units "seconds";
      description "Maximum preferred lifetime.";
    }
  }

  grouping interface-id {
    description "Interface ID grouping.";
    leaf interface-id {
      type string;
      description "Interface ID entry.";
    }
  }

  grouping relay {
    description "Relay grouping.";
    leaf-list ip-addresses {
      type inet:ipv6-address;
      description "IPv6 addresses.";
    }
  }

  grouping rapid-commit {
    description "Rapid commit grouping.";
    leaf rapid-commit {
      type boolean;
      description "Rapid commit entry.";
    }
  }

  grouping host {
    description "Host grouping.";
    leaf identifier-type {
      type host-identifier-type;
      mandatory true;
      description "Host identifier type.";
    }
    uses dhcp:host-identifier;
    leaf-list ip-addresses {
      type inet:ipv6-address;
      description "Host reserved IP addresses.";
    }
    leaf-list prefixes {
      type inet:ipv6-prefix;
      description "Host reserved IP prefixes.";
    }
    uses dhcp:host-hostname;
    uses dhcp:host-client-classes;
    uses option-data-list;
    uses dhcp:host-user-context;
  }

  grouping reservations {
    description "Host reservations grouping.";
    list host {
      key "identifier-type identifier";
      description "Host reservation list.";
      uses host;
    }
  }

  grouping subnet6-list {
    description "Subnet6 list grouping.";
    list subnet6 {
      key id;
      ordered-by user;
      description "List of IPv6 subnets.";
      uses dhcp:allocator;
      uses dhcp:pd-allocator;
      uses preferred-lifetime;
      uses min-preferred-lifetime;
      uses max-preferred-lifetime;
      uses dhcp:valid-lifetime;
      uses dhcp:min-valid-lifetime;
      uses dhcp:max-valid-lifetime;
      uses dhcp:renew-timer;
      uses dhcp:rebind-timer;
      uses dhcp:calculate-tee-times;
      uses dhcp:t1-percent;
      uses dhcp:t2-percent;
      uses option-data-list;
      list pool {
        key "start-address end-address";
        ordered-by user;
        description "Pool list.";
        leaf prefix {
          type inet:ipv6-prefix;
          description "Pool prefix.";
        }
        leaf start-address {
          type inet:ipv6-address;
          mandatory true;
          description "First IPv6 address in a pool.";
        }
        leaf end-address {
          type inet:ipv6-address;
          mandatory true;
          description "Last IPv6 address in a pool.";
        }
        uses option-data-list;
        uses dhcp:pool-client-class;
        uses dhcp:pool-require-client-classes;
        uses dhcp:pool-id;
        uses dhcp:pool-user-context;
      }
      list pd-pool {
        key prefix;
        ordered-by user;
        description "Prefix delegation pool list.";
        leaf prefix {
          type inet:ipv6-prefix;
          mandatory true;
          description "IPv6 pool prefix.";
        }
        leaf delegated-len {
          type uint8;
          description "Prefix pool delegated length.";
        }
        uses option-data-list;
        uses dhcp:client-class {
          refine client-class {
            description "Prefix pool client class guard. (only
                         clients belonging to this class will be
                         allowed in this pool).";
          }
        }
        uses dhcp:require-client-classes {
          refine require-client-classes {
            description "Prefix pool require client classes.";
          }
        }
        leaf excluded-prefix {
          type inet:ipv6-prefix;
          description "Prefix pool excluded prefix.";
        }
        uses dhcp:pool-id;
        uses kea:user-context {
          refine user-context {
            description "Prefix pool user context. Arbitrary JSON data
                         can be stored here.";
          }
        }
      }
      leaf subnet {
        type inet:ipv6-prefix;
        mandatory true;
        description "IPv6 subnet prefix.";
      }
      uses dhcp:subnet-interface;
      uses interface-id {
        refine interface-id {
          description "Subnet interface-id option.";
        }
      }
      uses dhcp:subnet-id;
      uses rapid-commit {
        refine rapid-commit {
          description "Subnet rapid commit flag.";
        }
      }
      uses dhcp:subnet-client-class;
      uses dhcp:require-client-classes;
      uses reservations {
        refine host {
          description "Subnet host reservations list.";
        }
      }
      container relay {
        description "Optional information about relay agent.";
        uses relay;
      }
      uses dhcp:cache-max-age;
      uses dhcp:cache-threshold;
      uses dhcp:ddns-generated-prefix;
      uses dhcp:ddns-override-client-update;
      uses dhcp:ddns-override-no-update;
      uses dhcp:ddns-qualifying-suffix;
      uses dhcp:ddns-replace-client-name;
      uses dhcp:ddns-send-updates;
      uses dhcp:ddns-ttl-percent;
      uses dhcp:ddns-update-on-renew;
      uses dhcp:ddns-use-conflict-resolution;
      uses dhcp:ddns-conflict-resolution-mode;
      uses dhcp:hostname-char-replacement;
      uses dhcp:hostname-char-set;
      uses dhcp:reservations-global;
      uses dhcp:reservations-in-subnet;
      uses dhcp:reservations-out-of-pool;
      uses dhcp:store-extended-info;
      uses dhcp:subnet-user-context;
    }
  }

  grouping client-classes {
    description "Client class grouping.";
    list client-class {
      key name;
      ordered-by user;
      description "List of client classes.";
      uses dhcp:class-name;
      uses dhcp:class-test;
      uses dhcp:template-test;
      uses dhcp:class-only-if-required;
      uses option-data-list;
      uses preferred-lifetime;
      uses min-preferred-lifetime;
      uses max-preferred-lifetime;
      uses dhcp:valid-lifetime;
      uses dhcp:min-valid-lifetime;
      uses dhcp:max-valid-lifetime;
      uses dhcp:class-user-context;
    }
  }

  grouping option-def-list {
    description "Option definition list grouping.";
    list option-def {
      key "code space";
      description "Option definition entry.";
      leaf code {
        type uint16;
        mandatory true;
        description "Option code to be used by the new option definition.";
      }
      leaf space {
        type string;
        mandatory true;
        description "Option space for the new option (typically dhcp6).";
      }
      uses dhcp:option-def-name;
      uses dhcp:option-def-type;
      uses dhcp:option-def-record-types;
      uses dhcp:option-def-encapsulate;
      uses dhcp:option-def-array;
      uses dhcp:option-def-user-context;
    }
  }

  grouping option-data-list {
    description "Option data list grouping.";
    list option-data {
      key "code space data";
      description "Option data entry.";
      leaf code {
        type uint16;
        description "Option code.";
      }
      leaf space {
        type string;
        description "Option space.";
      }
      uses dhcp:option-data-name;
      uses dhcp:option-data-data;
      uses dhcp:option-data-csv-format;
      uses dhcp:option-data-always-send;
      uses dhcp:option-data-never-send;
      uses dhcp:option-data-user-context;
    }
  }

  /*
  * Data Nodes
  */

  container config {
    // config true;
    description "Contains DHCPv6 server configuration.";

    uses dhcp:allocator;
    uses dhcp:pd-allocator;
    uses data-directory;
    uses preferred-lifetime;
    uses min-preferred-lifetime;
    uses max-preferred-lifetime;
    uses dhcp:valid-lifetime;
    uses dhcp:min-valid-lifetime;
    uses dhcp:max-valid-lifetime;
    uses dhcp:renew-timer;
    uses dhcp:rebind-timer;
    uses dhcp:calculate-tee-times;
    uses dhcp:t1-percent;
    uses dhcp:t2-percent;
    uses dhcp:decline-probation-period;
    uses subnet6-list;

    list shared-network {
      key name;
      uses dhcp:network-name;
      description "List of IPv4 shared networks.";
      uses dhcp:allocator;
      uses dhcp:pd-allocator;
      uses subnet6-list;
      uses dhcp:network-interface;
      uses interface-id {
        refine interface-id {
          description "Shared network interface-id option.";
        }
      }
      uses dhcp:renew-timer;
      uses dhcp:rebind-timer;
      uses option-data-list;
      container relay {
        description "Optional information about relay agent.";
        uses relay;
      }
      uses dhcp:network-client-class;
      uses dhcp:require-client-classes;
      uses preferred-lifetime;
      uses min-preferred-lifetime;
      uses max-preferred-lifetime;
      uses rapid-commit {
        refine rapid-commit {
          description "Shared network rapid commit flag.";
        }
      }
      uses dhcp:valid-lifetime;
      uses dhcp:min-valid-lifetime;
      uses dhcp:max-valid-lifetime;
      uses dhcp:calculate-tee-times;
      uses dhcp:t1-percent;
      uses dhcp:t2-percent;
      uses dhcp:cache-max-age;
      uses dhcp:cache-threshold;
      uses dhcp:ddns-generated-prefix;
      uses dhcp:ddns-override-client-update;
      uses dhcp:ddns-override-no-update;
      uses dhcp:ddns-qualifying-suffix;
      uses dhcp:ddns-replace-client-name;
      uses dhcp:ddns-send-updates;
      uses dhcp:ddns-ttl-percent;
      uses dhcp:ddns-update-on-renew;
      uses dhcp:ddns-use-conflict-resolution;
      uses dhcp:ddns-conflict-resolution-mode;
      uses dhcp:hostname-char-replacement;
      uses dhcp:hostname-char-set;
      uses dhcp:reservations-global;
      uses dhcp:reservations-in-subnet;
      uses dhcp:reservations-out-of-pool;
      uses dhcp:store-extended-info;
      uses dhcp:network-user-context;
    }

    container interfaces-config {
      description "Network interfaces configuration.";
      leaf-list interfaces {
        type string;
        description "Name of the interface (e.g. eth0) or name/address
                     (e.g. eth0/2001:db8::1) or * (use all interfaces).";
      }
      uses dhcp:interfaces-re-detect;
      uses dhcp:interfaces-service-sockets-require-all;
      uses dhcp:interfaces-service-sockets-max-retries;
      uses dhcp:interfaces-service-sockets-retry-wait-time;
      uses dhcp:interfaces-user-context;
    }

    uses dhcp:databases;

    leaf-list relay-supplied-options {
      type string;
      description "Relay supplied options.";
    }

    leaf-list mac-sources {
      type string;
      description "MAC address sources.";
    }

    leaf-list host-reservation-identifiers {
      type host-identifier-type;
      description "Host reservation identifiers.";
    }

    uses client-classes;
    uses option-def-list;
    uses option-data-list;
    uses kea:hooks-libraries;
    uses dhcp:expired-leases-processing;

    container server-id {
      presence "Have server ID.";
      description "Server DUID.";
      leaf type {
        type enumeration {
          enum "LLT" {
            description "Link-layer address and timestamp.";
          }
          enum "EN" {
            description "Enterprise number.";
          }
          enum "LL" {
            description "Link-layer address.";
          }
        }
        description "Server DIOD type.";
      }
      leaf identifier {
        type string;
        description "Server DUID identifier.";
      }
      leaf time {
        type uint32;
        description "Server DUID time.";
      }
      leaf htype {
        type uint16;
        description "Server DUID hardware type.";
      }
      leaf enterprise-id {
        type uint32;
        description "Server DUID enterprise ID.";
      }
      leaf persist {
        type boolean;
        description "Server DUID persist flag.";
      }
      leaf user-context {
        type kea:user-context;
        description "Server DUID user context.";
      }
    }

    uses dhcp:dhcp4o6-port;
    uses kea:control-socket;
    uses dhcp:hostname-char-set;
    uses dhcp:hostname-char-replacement;
    uses dhcp:dhcp-ddns;
    uses kea:user-context {
      refine user-context {
        description "DHCPv6 server user context. Arbitrary JSON data can
                     be stored here.";
      }
    }
    uses dhcp:sanity-checks;
    uses reservations {
      refine host {
        description "Global host reservations list.";
      }
    }
    uses dhcp:config-control;
    uses dhcp:server-tag;
    uses dhcp:dhcp-queue-control;
    uses kea:loggers;
    uses dhcp:cache-max-age;
    uses dhcp:cache-threshold;
    container compatibility {
      uses dhcp:common-compatibility;
    }
    uses dhcp:ddns-generated-prefix;
    uses dhcp:ddns-override-client-update;
    uses dhcp:ddns-override-no-update;
    uses dhcp:ddns-qualifying-suffix;
    uses dhcp:ddns-replace-client-name;
    uses dhcp:ddns-send-updates;
    uses dhcp:ddns-ttl-percent;
    uses dhcp:ddns-update-on-renew;
    uses dhcp:ddns-use-conflict-resolution;
    uses dhcp:ddns-conflict-resolution-mode;
    uses dhcp:ip-reservations-unique;
    uses dhcp:early-global-reservations-lookup;
    uses dhcp:reservations-lookup-first;
    uses dhcp:multi-threading;
    uses dhcp:parked-packet-limit;
    uses dhcp:reservations-global;
    uses dhcp:reservations-in-subnet;
    uses dhcp:reservations-out-of-pool;
    uses dhcp:statistic-default-sample-age;
    uses dhcp:statistic-default-sample-count;
    uses dhcp:store-extended-info;
  }

  /*
  * State data
  */
  container state {
    config false;
    description "State of Kea DHCPv6 server.";

    container leases {
      description "Kea DHCPv6 leases.";
      list lease {
        key ip-address;
        description "List of Kea DHCPv6 leases.";
        leaf ip-address {
          type inet:ipv6-address;
          mandatory true;
          description "Lease IP address.";
        }
        leaf duid {
          type binary;
          mandatory true;
          description "Lease DUID.";
        }
        uses dhcp:valid-lifetime {
          refine valid-lifetime {
            mandatory true;
          }
        }
        leaf cltt {
          type uint32;
          units "seconds";
          mandatory true;
          description "Lease client last transmission time.";
        }
        leaf subnet-id {
          type uint32;
          mandatory true;
          description "Lease subnet ID.";
        }
        leaf preferred-lifetime {
          type uint32;
          units "seconds";
          mandatory true;
          description "Lease preferred lifetime.";
        }
        leaf lease-type {
          type enumeration {
            enum "IA_NA" {
              description "Identity association for non-temporary addresses.";
            }
            enum "IA_TA" {
              description "Identity association for temporary addresses.";
            }
            enum "IA_PD" {
              description "Identity association for prefix delegation.";
            }
          }
          mandatory true;
          description "Lease IA type.";
        }
        leaf iaid {
          type uint32;
          mandatory true;
          description "Lease IA ID.";
        }
        leaf prefix-length {
          type uint8 {
            range 0..128;
          }
          description "Lease prefix length.";
        }
        leaf fqdn-fwd {
          type boolean;
          description "Lease FQDN forward flag.";
        }
        leaf fqdn-rev {
          type boolean;
          description "Lease FQDN reverse lag.";
        }
        leaf hostname {
          type string;
          description "Lease hostname.";
        }
        leaf state {
          type dhcp:lease-state;
          description "Lease state.";
        }
        leaf user-context {
          type kea:user-context;
          description "Lease user context.";
        }
        leaf hw-address {
          type string;
          description "Lease hardware address.";
        }
      }
    }

    container lease-stats {
      description "Lease statistics.";
      list subnet {
        key subnet-id;
        description "List of IPv6 subnets.";
        leaf subnet-id {
          type uint32;
          mandatory true;
          description "Subnet ID.";
        }
        leaf total-nas {
          type uint32;
          mandatory true;
          description "Total non-temporary addresses counter.";
        }
        leaf assigned-nas {
          type uint32;
          mandatory true;
          description "Assigned non-temporary counter.";
        }
        leaf declined-addresses {
          type uint32;
          mandatory true;
          description "Declined non-temporary addresses counter.";
        }
        leaf total-pds {
          type uint32;
          mandatory true;
          description "Total delegated prefixes counter.";
        }
        leaf assigned-pds {
          type uint32;
          mandatory true;
          description "Assigned delegated prefixe counter.";
        }
      }
    }

    container hosts {
      description "Kea DHCPv6 hosts.";
      list host {
        key "subnet-id identifier-type identifier";
        description "List of Kea DHCPv6 hosts.";
        uses host;
        uses dhcp:host-subnet-id;
        leaf auth-key {
          type string;
          description "Host authentication key.";
        }
      }
    }
  }
}
