Title: inet-superserver configuration by maintainer scripts
DEP: 9
State: OBSOLETE
Date: 2012-06-03
Drivers: Serafeim Zanikolas <sez@debian.org>
URL: http://dep.debian.net/deps/dep9
Source: http://anonscm.debian.org/viewvc/dep/web/deps/dep9.mdwn
License: http://www.jclark.com/xml/copying.txt
Abstract:
 Motivation, requirements and functional overview of a successor
 configuration tool for inetd superservers.
  1. Introduction
  2. Motivation
  3. Outline of reconf-inetd operation
  4. Configuration of new server packages
  5. Transition of "Depends: update-inetd" packages
  6. Requirements for xinetd/reconf-inetd fragments
  7. xinetd support
  8. Clarification of behaviour on package removal versus package purge
  9. Current status
  10. Source code repo

Introduction

The inet-superserver facility (typically provided by the openbsd-inetd package) listens to certain sockets and invokes the right server upon the arrival of an incoming request. Servers that are meant to be invoked by inetd must add a service entry to /etc/inetd.conf upon package installation (and remove the entry upon package purge). Maintainer scripts that modify inetd.conf must currently do so using a utility called update-inetd, as per Policy 11.2.

However, update-inetd has a problematic interface that leads to several kinds of bugs, including cross-package ones. Fixing update-inetd is largely a matter of fixing its interface, which would break backwards-compatibility. With that cost as a given (ie. the cost of revising all maintainer scripts of update-inetd's reverse-depends), one might as well create a successor tool with a cleaner interface.

This DEP proposes such a successor inetd configuration tool, hereafter called reconf-inetd. reconf-inetd, in addition to providing the existing functionality, must meet the following requirements:

Note that the first requirement above implies that inetd.conf entries that have been (i) added by reconf-inetd and (ii) were subsequently modified by the user, shall not be removed even on package purge.

Motivation

The main problem of update-inetd is that the service entry to be enabled, disabled or removed, is selected in terms of a service name, such as "ftp". This limitation typically leads to cross-package bugs because of the difficulty to distinguish between independent implementations (eg. ftpd-ssl versus proftpd), or an ipv4 versus an ipv6 implementation of the same kind of service. As an example, in #168847, ftpd-ssl's invocation of update-inetd enables the service entry of (the previously uninstalled) proftpd because both packages' entries have an "ftp" service name.

As of now, one can try to avoid the above problem as follows. A maintainer script may (i) further specify the acted-upon service entry in terms of a regular expression (which is matched against the whole service entry, instead of just the service name); (ii) override the default comment-prefix ("#<off># "), to distinguish service entries of different packages that provide the same kind of service (eg. "#<off-ftpd-ssl-ipv4># " vs "#<off-proftpd-ipv4># "). These features work when used correctly, but at the cost of fragile logic in maintainer scripts.

To summarise, the interface of update-inetd is inadequate in that it does not require that the following three elements are specified to select an entry: service name, protocol type, and path to server program.

A secondary issue, but nevertheless one that would be nice to solve, is support for configuration updates of xinetd (#8927). xinetd has a relatively low popcon but one could argue that may be the case because it is not well integrated in Debian.

Outline of reconf-inetd operation

reconf-inetd will operate similarly to update-inetd, ie. add, remove, enable and disable service entries in /etc/inetd.conf. The main difference is that where update-inetd uses command-line arguments, reconf-inetd will use xinetd.conf(5) configuration fragments under /usr/share/reconf-inetd (hereafter called reconf-inetd fragments, for brevity). Moreover, reconf-inetd will be invoked via a dpkg trigger, as opposed to from maintainer scripts.

With reconf-inetd, inet-superserver configuration will occur as follows:

An inetd.conf service entry will be considered to be "matching" a reconf-inetd fragment when the following fields are equal: service name, protocol, and server program. In reconf-inetd fragments with "flags = NAMEINARGS" (eg. a tcpd service entry), the actual server path will be extracted from the server_args field, as per xinetd.conf(5).

Upon adding an entry to inetd.conf, reconf-inetd will make a shadow copy of the related reconf-inetd fragment under /var/lib/reconf-inetd. This would allow to determine the following after the uninstallation of the related package:

All reconf-inetd fragments will be considered enabled, regardless of the value of the "disable" field, if such field exists. Servers that support inetd mode but default to standalone operation must therefore not install a reconf-inetd fragment (and should instead provide a sample inetd.conf entry that the user has to add manually to /etc/inetd.conf).

/etc/inetd.conf (and /etc/xinetd.d) will remain the authoritative configuration file for inetd (and xinetd). reconf-inetd fragments are only meant for updating the standard configuration files.

An invocation of reconf-inetd (because of a fragment being installed or removed from /usr/share/reconf-inetd) may result in a modification of /etc/inetd.conf as summarised in the table below.


   | server  | status of  | matching     | shadow     | reconf-inetd
   | program | inetd.conf | reconf-inetd | fragment   | action
   | exists  | entry      | fragment     | status     |
---+---------+------------+--------------+------------+-----------
  0|      no |   disabled |         no   |  identical |    remove
  1|      no |    enabled |         no   |  identical |    remove
---+---------+------------+--------------+------------+-----------
  2|     yes |   disabled |        yes   |  different |    enable
  3|     yes |   disabled |        yes   |  identical |    enable
---+---------+------------+--------------+------------+-----------
  4|     yes |    missing |        yes   |        n/a |       add
---+---------+------------+--------------+------------+-----------
  5| commented-out inetd.conf entry                   |      none
---+---------+------------+--------------+------------+-----------
  6| any other combination                            |      none

An inetd.conf entry is considered disabled when it starts with "#<off># ", and disabled by a user when commented-out simply with '#'.

A shadow fragment status (ie. the fragment under /var/lib/reconf-inetd) is considered identical to a matching inetd.conf entry, by comparing the server arguments, if any.

Follows a detailed description of the aforementioned scenarios.

Meaning of the above listed actions:

Configuration of new server packages

Packages that have never used update-inetd must do the following:

Transition of "Depends: update-inetd" packages

A time-limited transition is not a strict requirement, since reconf-inetd and update-inetd can co-exist without problems.

reconf-inetd will not touch any entries that have not been added by itself, including entries added by update-inetd. Thus, a server package that is meant to transition from update-inetd to reconf-inetd, must remove any entries that it previously added using update-inetd.

Server packages that depend on update-inetd can be converted as follows:

0) in the first stable Debian release in which reconf-inetd is used by the package:

Below is an example postinst snippet for the ftpd-ssl server package:

    # exact inetd.conf entry previously added using update-inetd
    OLD_FTPENTRY="ftp   stream  tcp nowait  root    /usr/sbin/tcpd  /usr/sbin/in.ftpd"
    # first release that uses reconf-inetd
    REL="x.y.z"

    case $1 in
        configure)
            # remove inetd.conf entry if not modified locally, and not managed
            # already by reconf-inetd
            if dpkg --compare-versions "$2" lt-nl "$REL"; then
                if fgrep -qx "$OLD_FTPENTRY" /etc/inetd.conf || \
                   fgrep -qx "#<off># $OLD_FTPENTRY" /etc/inetd.conf; then
                    # remove all inetd.conf entries for ftpd-ssl
                    update-inetd --multi --pattern ftpd-ssl --remove ftp || true
                    # re-add entries that are managed by reconf-inetd
                    reconf-inetd || true
                fi
            fi
        ;;
    esac

If you are going to invoke update-inetd using --multi as shown above (to avoid prompting the user about multiple entries) you need update-inetd (>= 4.43).

1) in later stable Debian releases, simply drop update-inetd all together (dependency and postinst snippet)

Requirements for xinetd/reconf-inetd fragments

According to xinetd.conf(5), xinetd fragments must have the following fields:

  socket_type       (mandatory)
  wait              (mandatory)
  user              (non-internal services only)
  server            (non-internal services only)
  protocol          (RPC and unlisted services only)
  port              (unlisted non-RPC services only)

If the protocol field is omitted and the service is listed, reconf-inetd will assume the protocol of the first matching entry from /etc/services. That will be tcp or udp, which currently implies IPv4, so if the intention is IPv6, then tcp6 or udp6 should be explicitly specified in the protocol field.

Unlike, regular xinetd fragment files, reconf-inetd fragment files must have only one service per file. If your package provides more than one service, please install a separate fragment file for each service. This is the case to allow for removal of individual services, by simply removing the related file.

The disable field in reconf-inetd fragments is completely ignored. reconf-inetd has no notion of maintainer-disabled inetd.conf entries

xinetd support

xinetd configuration with reconf-inetd will become trivial because server packages will have to ship reconf-inetd (ie. xinetd.conf(5) compatible) fragments anyway.

Synchronisation between inetd.conf and reconf-inetd fragments is outside this DEP's scope. The fact that inetd.conf (and /etc/xinetd.d) remains the authoritative configuration file implies that any synchronisation requires a user-initiated action, and is thus best implemented as a separate tool.

Clarification of behaviour on package removal versus package purge

According to rules 0 and 1 in the previously listed table, reconf-inetd does not distinguish between package removal and purge. In other words, /etc/inetd.conf entries that were added by reconf-inetd will be removed upon package removal, as long as they have not been locally modified. Similarly, a locally-modified inetd.conf entry will not be removed even if the associated package is purged. This is in line with Debian policy, on the basis that inetd.conf is a configuration file, but not a conffile.

Current status

As of Feb 2014: With a dynamic init system in Debian finally being adopted, inetd is irrelevant, hence reconf-inetd too, so I mark this DEP as obsolete, since it's not worth the migration effort.

As of Jun 2012: reconf-inetd is in wheezy. I'll file a bug against all "Depends: update-inetd" packages, as soon as wheezy is released.

http://packages.qa.debian.org/r/reconf-inetd.html

Source code repo

http://git.debian.org/?p=collab-maint/reconf-inetd.git;a=summary