module infix-services {
  yang-version 1.1;
  namespace "urn:ietf:params:xml:ns:yang:infix-services";
  prefix infix-svc;

  import ietf-interfaces {
    prefix if;
  }
  import ietf-inet-types {
    prefix inet;
    reference
      "RFC 6991: Common YANG Data Types";
  }
  import infix-crypto-types {
    prefix infix-ct;
    reference
      "RFC 9640: YANG Data Types and Groupings for Cryptography";
  }

  import ietf-keystore {
    prefix ks;
  }

  organization "KernelKit";
  contact      "kernelkit@googlegroups.com";
  description  "Infix services, generic.";

  revision 2025-12-10 {
    description "Adapt to changes in final version of ietf-keystore";
    reference "internal";
  }
  revision 2024-12-03 {
    description "Add support for SSH server configuration";
    reference "internal";
  }
  revision 2024-12-02 {
    description "Expand mdns options: domain, allow/deny interfaces, reflector.";
    reference "internal";
  }

  revision 2024-06-08 {
    description "Add support for RESTCONF enable/disable as a web service.";
    reference "internal";
  }
  revision 2024-05-30 {
    description "Add support for RESTCONF enable/disable as a web service.";
    reference "internal";
  }
  revision 2024-04-08 {
    description "Initial support for web services.";
    reference "internal";
  }
  revision 2023-10-16 {
    description "Drop SSDP support, mDNS-SD is now available in Windows 10.";
    reference "internal";
  }
  revision 2023-08-22 {
    description "Initial revision, add SSDP and mDNS-SD enable/disable only.";
    reference "internal";
  }

  /*
   * Data nodes
   */

  container mdns {
    description "Advertise system and services over mDNS-SD, IPv4 and IPv6.";

    leaf enabled {
      description "Globally enable or disable mDNS/SD on all interfaces.";
      type boolean;
    }

    leaf domain {
      description "LAN domain name to register host name and services in.

                   Most common is .local, but some also use .lan, or .office,
                   usually this setting can be left as-is.";
      default "local";
      type inet:domain-name;
    }

    container interfaces {
      description "Filter interfaces to act on.";

      leaf-list allow {
        description "Enabled on interfaces, can be combined with deny-interfaces.

                     By default all, except loopback and point-to-point links.";
        type if:interface-ref;
      }

      leaf-list deny {
        description "Disabled on interfaces (always wins).

                     Other not specified interfaces will be used, except loopback
                     and point-to-point, unless combined with allow-interfaces.

                     This option takes precedence over allow-interfaces.";
        type if:interface-ref;
      }
    }

    container reflector {
      description "Reflect incoming mDNS requests to local interfaces.";

      leaf enabled {
        description "Enable mDNS reflector on local interfaces.";
        type boolean;
      }

      leaf-list service-filter {
        description "Filter mDNS service names to reflect.

                     Example, for AirPlay and AirTunes, use:

                       - _airplay._tcp.local
                       - _raop._tcp.local

                     For AirPrint use:

                       - _printer._tcp.local
                       - _ipp._tcp.local
                       - _pdl-datastream._tcp.local

                     By default all services are reflected.";
        type string;
      }
    }
  }
  container ssh {
    description "Configuration for the SSH daemon";
    leaf enabled {
      description "Enable or disable SSH daemon";
      type boolean;
      must ". = 'false' or (count(../listen) > 0 and count(../hostkey) > 0)" {
        error-message "Must be at least one listen address and a private key.";
      }
    }

    leaf-list hostkey {
      description "Reference to asymmetric key in central keystore.

             The hostkey can be shared with NETCONF, by default 'genkey' is used.";
      must "not(deref(.)/../ks:public-key-format) or "
        + "(derived-from-or-self(deref(.)/../ks:public-key-format,  'infix-ct:ssh-public-key-format') and"
        + "derived-from-or-self(deref(.)/../ks:private-key-format,  'infix-ct:rsa-private-key-format'))" {
        error-message "Only RSA hostkeys are supported.";
      }
      type ks:central-asymmetric-key-ref;
    }

    list listen {
      key name;
      description "List of IP addresses and ports the SSH daemon should listen on.

         Each entry represents a unique listening socket configuration
         that allows incoming SSH connections. Multiple entries can be
         configured to listen on different addresses or ports.";
      leaf name {
        description "A unique identifier for this listening configuration.

           This name helps administrators distinguish between multiple
           listening configurations. It can reflect the purpose or
           network segment of the listener, e.g., 'management',
           'internal', or 'public'.";
        type string;
      }

      leaf address {
        description "Local IP address to listen on for inbound SSH connections.

           INADDR_ANY (0.0.0.0) or INADDR6_ANY (0:0:0:0:0:0:0:0 a.k.a. ::) MUST be
           used when the server is to listen on all IPv4 or
           IPv6 addresses, respectively.";
        type inet:ip-address;
      }
      leaf port {
        description "Local port for SSH daemon to listen on.";
        type inet:port-number;
      }
      must "port and address" {
        error-message "Both address and port must be configured";
      }
    }
  }

  container web {
    description "Web services";

    leaf enabled {
      description "Enable or disable on all web services.

                   Enabling this setting activates a web proxy server reponsible
                   for routing requests to other web applications, as well as it
                   redirecting all insecure HTTP requests to HTTPS.

                   Disabling this setting disables the web proxy server and all
                   other services/applications that run behind it.";
      type boolean;
    }

    container console {
      description "Web console interface.";

      leaf enabled {
        description "Enable or disable web console interface on port 7681.";
        type boolean;
      }
    }

    container netbrowse {
      description "mDNS Network Browser.";

      leaf enabled {
        description "Enable or disable mDNS Network Browser at https://network.local.";
        type boolean;
      }
    }

    container restconf {
      description "IETF RESTCONF Server.";

      leaf enabled {
        description "Enable or disable RESTCONF server.";
        type boolean;
      }
    }
  }
}
