reconf-inetd-1.120603/0000755000000000000000000000000011762761700011220 5ustar reconf-inetd-1.120603/manpage.txt0000644000000000000000000001263411745042017013371 0ustar [synopsis] \fIreconf-inetd\fR \fI[\-\-verbose]\fR .br \fIreconf-inetd\fR \fI\-\-sanity-check=fragment [... fragment]\fR [description] reconf\-inetd is a maintainer tool that updates inetd.conf. Such updates are based on xinetd.conf-like configuration fragments in /usr/share/reconf-inetd (where server packages install their fragments) and /usr/lib/reconf\-inetd (where reconf-inetd keeps track of which inetd.conf entries have been added by itself). reconf\-inetd identifies every inetd.conf entry based on the combination of three fields: service name, protocol, and server path. This allows multiple inetd.conf entries for the same service, eg. for IPv4 and IPv6 versions, as well as for different upstreams (eg. proftpd versus ftpd\-ssl). reconf\-inetd will not add inetd.conf entries for services whose server path is non\-existent, or whose combination of protocol, service name and server path matches an existing inetd.conf entry. reconf\-inetd does not support internal services. [fragment structure] reconf-inetd fragments are a much simplified version of xinetd.conf(5) fragments. They have this structure: .RS .nf .ft B .sp service { .RS .ft B = ... .I "..." .RE } .ft R .fi .RE .LP Of the wide range of fields foreseen by xinetd.conf(5), reconf-inetd honors only these fields: socket_type protocol (optional, except for RPC and unlisted services) port (optional, except for unlisted non\-RPC services) wait user server server_args (optional) 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. A package that provides more than one service must 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. /usr/share/reconf\-inetd fragments are not configuration files; they're just input to reconf\-inetd. Local admin configuration should be applied to inetd.conf tcpd-configured service fragments will typically have server set to /usr/sbin/tcpd and server_args will start with the path to the actual server executable. Follows a reproduction of valid atrribute values from xinetd.conf(5): .B socket_type Possible values for this attribute include: .RS .TP 12 .I stream stream-based service .TP .I dgram datagram-based service .TP .I raw service that requires direct access to IP .TP .I seqpacket service that requires reliable sequential datagram transmission .RE .TP .B protocol determines the protocol that is employed by the service. The protocol must exist in .I /etc/protocols. If this attribute is not defined, the default protocol employed by the service will be used. .TP .B port determines the service port. .TP .B wait This attribute determines if the service is single-threaded or multi-threaded and whether or not xinetd accepts the connection or the server program accepts the connection. If its value is \fIyes\fP, the service is single-threaded; this means that \fBxinetd\fP will start the server and then it will stop handling requests for the service until the server dies and that the server software will accept the connection. If the attribute value is \fIno\fP, the service is multi-threaded and \fBxinetd\fP will keep handling new service requests and xinetd will accept the connection. It should be noted that udp/dgram services normally expect the value to be yes since udp is not connection oriented, while tcp/stream servers normally expect the value to be no. .TP .B user determines the uid for the server process. The user attribute can either be numeric or a name. If a name is given (recommended), the user name must exist in .I /etc/passwd. This attribute is ineffective if the effective user ID of \fBxinetd\fP is not super-user. .TP .B server determines the program to execute for this service. .TP .B server_args determines the arguments passed to the server. [fragment examples] Here is an example fragment: \fBservice\fP finger { \fBsocket_type\fP = stream \fBprotocol\fP = tcp6 \fBwait\fP = no \fBuser\fP = nobody \fBserver\fP = /usr/sbin/fingerd } and it's tcpd-enabled version: \fBservice\fP finger { \fBsocket_type\fP = stream \fBprotocol\fP = tcp6 \fBwait\fP = no \fBuser\fP = nobody \fBserver\fP = /usr/sbin/tcpd \fBserver_args\fP = /usr/sbin/fingerd } [files] reconf\-inetd declares a file\-based dpkg trigger on /usr/share/reconf\-inetd. Shadow fragment files are stored in /var/lib/reconf\-inetd. A log file is kept at /var/log/reconf\-inetd.log [bugs] Known issues and missing features are listed in /usr/share/doc/reconf\-inetd/TODO [history] reconf\-inetd is a replacement for update\-inetd. The motivation for and design of reconf\-inetd is detailed at the Debian Enhancement Proposal 9, at http://dep.debian.net/deps/dep9/, a copy of which is locally available at /usr/share/doc/reconf-inetd/dep9.html [author] \fBreconf\-inetd\fR was designed, documented and implemented by Serafeim Zanikolas [see also] inetd.conf(5), xinetd.conf(5), inetd(8), update\-inetd(8), deb-triggers(5) reconf-inetd-1.120603/features/0000755000000000000000000000000011762756467013054 5ustar reconf-inetd-1.120603/features/data/0000755000000000000000000000000011762761700013747 5ustar reconf-inetd-1.120603/features/data/inetd.conf0000644000000000000000000000270011614741126015714 0ustar # /etc/inetd.conf: see inetd(8) for further informations. # # Internet superserver configuration database # # # Lines starting with "#:LABEL:" or "##" should not # be changed unless you know what you are doing! # # If you want to disable an entry so it isn't touched during # package updates just comment it out with a single '#' character. # # Packages should modify this file by using update-inetd(8) # # # #:INTERNAL: Internal services #discard stream tcp nowait root internal #discard dgram udp wait root internal #daytime stream tcp nowait root internal #time stream tcp nowait root internal #:STANDARD: These are standard services. ## ftp stream tcp nowait root /usr/sbin/tcpd /usr/sbin/proftpd #:BSD: Shell, login, exec and talk are BSD protocols. #:MAIL: Mail, news and uucp services. #:INFO: Info services ## finger stream tcp nowait root /usr/sbin/tcpd /usr/sbin/cfingerd #:BOOT: TFTP service is provided primarily for booting. Most sites # run this only on machines acting as "boot servers." tftp dgram udp4 wait nobody /usr/sbin/tcpd /usr/sbin/in.tftpd --tftpd-timeout 300 --retry-timeout 5 --mcast-port 1758 --mcast-addr 239.239.239.0-255 --mcast-ttl 1 --maxthread 100 --verbose=5 /var/lib/tftpboot #:RPC: RPC based services #:HAM-RADIO: amateur-radio services #:OTHER: Other services 9999 stream tcp nowait approx /usr/sbin/approx /usr/sbin/approx reconf-inetd-1.120603/features/tcpd-service-enable.feature0000644000000000000000000000235411762756467020251 0ustar Feature: tcpd service enable Scenario: tcpd service enable-01 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl service entry in inetd.conf is enabled And inetd is restarted Scenario: tcpd service enable-02 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl service entry in inetd.conf is enabled And inetd is restarted reconf-inetd-1.120603/features/tcpd-service-removal.feature0000644000000000000000000000301011762756467020456 0ustar Feature: tcpd service removal Scenario: tcpd service removal-01 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl service entry is removed from inetd.conf And the matching shadow fragment with identical server arguments for ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl is removed And inetd is restarted Scenario: tcpd service removal-02 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl service entry is removed from inetd.conf And the matching shadow fragment with identical server arguments for ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl is removed And inetd is restarted reconf-inetd-1.120603/features/step-generator.pyc0000644000000000000000000001305311745004753016513 0ustar Ñò ¢ ”Oc@srdefd„ƒYZd„ZedjoBhdd6dd6Zx+eiƒD]\ZZeeeƒqMWndS( tScenarioParamscBs,eZd„Zd„Zd„Zd„ZRS(cCsDh|_g}|iƒD]\}}||i||ƒq~dS(N(tparamstitemstadd_item(tselfRt_[1]tkeyt description((sB/home/sez/git/reconf-inetd/reconf-inetd/features/step-generator.pyt__init__s cCs |iiƒS(N(Rtiterkeys(R((sB/home/sez/git/reconf-inetd/reconf-inetd/features/step-generator.pyt__iter__scCs |i|S(N(R(RR((sB/home/sez/git/reconf-inetd/reconf-inetd/features/step-generator.pytdescribescCsN|iddƒidƒiddƒiƒ}|i||ƒ||i|~|i|ƒq“Wq†WqyWqlWg}ˆiƒD]}||iƒq†~dS(1Ns an enabledsa maintainer_disabledsa user_disableds a missings)Given an inetd.conf file with %s entry %stexistssdoes not exists"And a matching server file that %st identicalt differentsSAnd a matching shadow fragment with %s server arguments for the %s inetd.conf entrytmissingsAnd no matching shadow fragments a matchings no matchings/And %s reconf-inetd fragment for the service %siics‚ˆi|ƒ}|djoDd|iddƒ}t|dƒ}|ˆ|s s    reconf-inetd-1.120603/features/step-generator.py0000755000000000000000000001735611745004642016362 0ustar #!/usr/bin/python # scenario generator for reconf-inetd - reconfigure and restart inetd # Copyright (C) 2011, 2012 Serafeim Zanikolas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA class ScenarioParams(object): def __init__(self, params): self.params = {} [self.add_item(key, description) for key, description in params.items()] def __iter__(self): return self.params.iterkeys() def describe(self, key): return self.params[key] def add_item(self, key, description): normalised_key = key.replace('an ', '').lstrip('a ').replace(' ', '_').upper() self.__setattr__(normalised_key, normalised_key) self.params[normalised_key] = description def main(test_tag, test_service): conf_entry_status_values = ScenarioParams( dict([ (s, 'Given an inetd.conf file with %s entry %s' % (s, test_service)) for s in ['an enabled', 'a maintainer_disabled', 'a user_disabled', 'a missing'] ])) server_path_values = ScenarioParams( dict([ (s, 'And a matching server file that %s' % s) for s in ['exists', 'does not exist'] ])) shadow_fragment_status_values = ScenarioParams( dict([ (s, 'And a matching shadow fragment with %s server arguments for the %s inetd.conf entry' % (s, test_service)) for s in ['identical', 'different'] ]) ) shadow_fragment_status_values.add_item('missing', 'And no matching shadow fragment') reconf_fragment_values = ScenarioParams( dict([ (s, 'And %s reconf-inetd fragment for the service %s' % (s, test_service)) for s in ['a matching', 'no matching'] ])) files = {} counters = {} SCENARIO_INDENTATION=4 STEP_INDENTATION=SCENARIO_INDENTATION*2 def get_or_open_file(feature): fd = files.get(feature) if fd is None: fname = '%s.feature' % (feature.replace(' ', '-')) fd = open(fname, 'w') files[feature] = fd counters[feature] = 1 return (fd, 1) else: counters[feature] += 1 return (fd, counters[feature]) def writeline(line, indentation=STEP_INDENTATION): output_file.write('%s%s\n' % (' '*indentation, line)) seen_scenarios = set() for conf_entry_status in conf_entry_status_values: for server_path in server_path_values: for reconf_fragment in reconf_fragment_values: for shadow_fragment_status in shadow_fragment_status_values: # service addition scenarios if server_path == server_path_values.EXISTS and \ conf_entry_status == conf_entry_status_values.MISSING and \ reconf_fragment == reconf_fragment_values.MATCHING: feature = '%s service addition' % test_tag action = ''.join([ 'Then a new entry is added to inetd.conf ', 'for service %s\n' + ' '*STEP_INDENTATION, 'And a matching shadow fragment with ', 'identical server arguments for %s ', 'is created\n' + ' '*STEP_INDENTATION, 'And inetd is restarted']) % (test_service, test_service) # service removal scenarios elif server_path == server_path_values.DOES_NOT_EXIST and \ conf_entry_status in (conf_entry_status_values.ENABLED, conf_entry_status_values.MAINTAINER_DISABLED) and \ reconf_fragment == reconf_fragment_values.NO_MATCHING and \ shadow_fragment_status == shadow_fragment_status_values.IDENTICAL: feature = '%s service removal' % test_tag action = ''.join([ 'Then the %s service entry is removed ', 'from inetd.conf\n' + ' '*STEP_INDENTATION, 'And the matching shadow fragment with ', 'identical server arguments for %s ', 'is removed\n' + ' '*STEP_INDENTATION, 'And inetd is restarted']) % (test_service, test_service) # service enable scenarios elif server_path == server_path_values.EXISTS and \ conf_entry_status == conf_entry_status_values.MAINTAINER_DISABLED and \ reconf_fragment == reconf_fragment_values.MATCHING and \ shadow_fragment_status in (shadow_fragment_status_values.IDENTICAL, shadow_fragment_status_values.DIFFERENT): feature = '%s service enable' % test_tag action = ''.join([ 'Then the %s service entry in inetd.conf is ' 'enabled\n' + ' '*STEP_INDENTATION, 'And inetd is restarted']) % test_service # no action scenarios else: action = 'Then inetd.conf must remain unchanged' feature = '%s no action' % test_tag output_file, scenario_counter = get_or_open_file(feature) scenario = '%s-%02d' % (feature, scenario_counter) scenario_steps = [ conf_entry_status_values.describe(conf_entry_status), server_path_values.describe(server_path), reconf_fragment_values.describe(reconf_fragment) ] if conf_entry_status != conf_entry_status_values.MISSING: descr = shadow_fragment_status_values.describe(shadow_fragment_status) scenario_steps.append(descr) scenario_steps.extend(['When I run reconf-inetd', action + '\n']) scenario_fingerprint = hash(''.join(scenario_steps)) if scenario_fingerprint in seen_scenarios: print 'skipping already seen scenario:', scenario continue print 'writing %s scenario' % scenario if scenario_counter == 1: writeline('Feature: %s\n' % feature, indentation=0) writeline('Scenario: %s' % scenario, indentation=SCENARIO_INDENTATION) [writeline(line) for line in scenario_steps] seen_scenarios.add(scenario_fingerprint) [f.close() for f in files.values()] if __name__ == '__main__': test_services = { 'plain' : 'ftpd_ssl,tcp,/usr/sbin/ftpd_ssl', 'tcpd' : 'ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl' } for test_tag, test_service in test_services.items(): main(test_tag, test_service) reconf-inetd-1.120603/features/tcpd-no-action.feature0000644000000000000000000004026311762756467017255 0ustar Feature: tcpd no action Scenario: tcpd no action-01 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-02 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-03 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-04 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-05 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-06 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-07 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-08 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-09 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-10 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-11 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-12 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-13 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-14 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-15 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-16 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-17 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-18 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-19 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-20 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-21 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-22 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-23 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-24 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-25 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-26 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-27 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-28 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-29 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-30 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-31 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-32 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-33 Given an inetd.conf file with a missing entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-36 Given an inetd.conf file with a missing entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: tcpd no action-39 Given an inetd.conf file with a missing entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl When I run reconf-inetd Then inetd.conf must remain unchanged reconf-inetd-1.120603/features/plain-service-enable.feature0000644000000000000000000000216711745004642020402 0ustar Feature: plain service enable Scenario: plain service enable-01 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl service entry in inetd.conf is enabled And inetd is restarted Scenario: plain service enable-02 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl service entry in inetd.conf is enabled And inetd is restarted reconf-inetd-1.120603/features/terain.py0000644000000000000000000000161411676377350014704 0ustar #!/usr/bin/python # reconf-inetd - reconfigure and restart inetd # Copyright (C) 2011 Serafeim Zanikolas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA from lettuce import world class Context(object): pass world.scc = Context() reconf-inetd-1.120603/features/plain-service-addition.feature0000644000000000000000000000107511745004642020744 0ustar Feature: plain service addition Scenario: plain service addition-01 Given an inetd.conf file with a missing entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl When I run reconf-inetd Then a new entry is added to inetd.conf for service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for ftpd_ssl,tcp,/usr/sbin/ftpd_ssl is created And inetd is restarted reconf-inetd-1.120603/features/plain-no-action.feature0000644000000000000000000003562111762756467017430 0ustar Feature: plain no action Scenario: plain no action-01 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-02 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-03 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-04 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-05 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-06 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-07 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-08 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-09 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-10 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-11 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-12 Given an inetd.conf file with a user_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-13 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-14 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-15 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-16 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-17 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-18 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-19 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-20 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-21 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-22 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-23 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-24 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-25 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-26 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-27 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-28 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-29 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-30 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-31 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with different server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-32 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And no matching shadow fragment When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-33 Given an inetd.conf file with a missing entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-36 Given an inetd.conf file with a missing entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl When I run reconf-inetd Then inetd.conf must remain unchanged Scenario: plain no action-39 Given an inetd.conf file with a missing entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that exists And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl When I run reconf-inetd Then inetd.conf must remain unchanged reconf-inetd-1.120603/features/terain.pyc0000644000000000000000000000066211676377620015051 0ustar Ñò èþùNc@s6ddklZdefd„ƒYZeƒe_dS(iÿÿÿÿ(tworldtContextcBseZRS((t__name__t __module__(((s:/home/sez/git/reconf-inetd/reconf-inetd/features/terain.pyRsN(tlettuceRtobjectRtscc(((s:/home/sez/git/reconf-inetd/reconf-inetd/features/terain.pytsreconf-inetd-1.120603/features/tcpd-service-addition.feature0000644000000000000000000000116711762756467020617 0ustar Feature: tcpd service addition Scenario: tcpd service addition-01 Given an inetd.conf file with a missing entry ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching server file that exists And a matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl When I run reconf-inetd Then a new entry is added to inetd.conf for service ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for ftpd_ssl,tcp,/usr/sbin/tcpd /usr/sbin/ftpd_ssl is created And inetd is restarted reconf-inetd-1.120603/features/steps.py0000644000000000000000000003413411745004642014547 0ustar #!/usr/bin/python # reconf-inetd - reconfigure and restart inetd # Copyright (C) 2011 Serafeim Zanikolas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import shutil import os import re import sys import subprocess import logging from cStringIO import StringIO from tempfile import mkdtemp, TemporaryFile from glob import glob import commands import reconf_inetd from lettuce import * test_data_dir = './features/data' default_inetd_conf = os.path.join(test_data_dir, 'inetd.conf') reconf_script_fname = './reconf_inetd.py' service_spec_re = '([^,]+),([^,]+),([^,]+)' DEFAULT_SRV_ARGS = '-d -l' @before.each_scenario def before(sc): world.scc.logger = logging.getLogger() handler = logging.FileHandler('steps.log') world.scc.logger.addHandler(handler) world.scc.logger.setLevel(logging.DEBUG) world.scc.test_data_dir = test_data_dir world.scc.default_inetd_conf = default_inetd_conf world.scc.tempdir = mkdtemp() world.scc.pseudo_root = os.path.join(world.scc.tempdir, 'root') world.scc.inetd_conf_fname = os.path.join(world.scc.tempdir, 'inetd.conf') world.scc.reconf_fragments_dir = os.path.join(world.scc.tempdir, 'reconf_fragments') world.scc.shadow_fragments_dir = os.path.join(world.scc.tempdir, 'shadow_fragments') os.mkdir(world.scc.reconf_fragments_dir) os.mkdir(world.scc.shadow_fragments_dir) def load_inetd_service_container(): container = reconf_inetd.InetdServiceContainer(world.scc.logger) world.scc.logger.debug('loading: %s' % world.scc.inetd_conf_fname) with open(world.scc.inetd_conf_fname) as inetd_conf_fd: container.load_service_entries(inetd_conf_fd) return container def create_inetd_service_container(): shutil.copy(world.scc.default_inetd_conf, world.scc.inetd_conf_fname) return load_inetd_service_container() def create_shadow_fragment_container(): shadow_files = glob('%s/*' % world.scc.shadow_fragments_dir) return reconf_inetd.XFragmentContainer(world.scc.logger, shadow_files) def prefix_paths(paths, prefix): return ['%s/%s' % (prefix, path) for path in paths.split()] def server_path_and_args(server_path): """return a dictionary based on a one or two-path string""" attrs = {} server_paths = prefix_paths(server_path, world.scc.pseudo_root) if len(server_paths) > 1: attrs['server_args'] = server_paths[1] attrs['server'] = server_paths[0] else: attrs['server'] = server_paths[0] if world.scc.default_srv_args: if attrs.has_key('server_args'): attrs['server_args'] += ' ' + world.scc.default_srv_args else: attrs['server_args'] = world.scc.default_srv_args world.scc.logger.debug('server_paths: "%s"' % server_paths) world.scc.logger.debug('server: "%s"' % attrs['server']) world.scc.logger.debug('server_args: "%s"' % attrs['server_args']) if attrs['server'].endswith('/tcpd'): attrs['flags'] = 'nameinargs' return attrs def make_service(name, protocol, server_path, srv_status=reconf_inetd.InetdService.ENABLED): if protocol.startswith('tcp'): socket_type = 'stream' else: socket_type = 'dgram' attrs = { 'service' : name, 'socket_type' : socket_type, 'wait' : 'nowait', 'protocol' : protocol } attrs = dict(attrs.items() + server_path_and_args(server_path).items()) # special case: server_path is /usr/sbin/tcpd /path/to/server logger = logging.getLogger() lineno = 1 srv = reconf_inetd.InetdService(attrs, lineno, logger) srv.set_status(srv_status) return srv def create_inetd_conf_without_entry(srv_name, protocol, srv_path): world.scc.service = make_service(srv_name, protocol, srv_path) world.scc.inetd_service_container = create_inetd_service_container() assert not world.scc.inetd_service_container.has_matching_entry(world.scc.service) def write_file(name, content): with open(name, 'w') as fd: fd.write(content) def create_inetd_conf_with_entry(srv_name, protocol, srv_path, srv_status): world.scc.service = make_service(srv_name, protocol, srv_path, srv_status) world.scc.inetd_service_container = create_inetd_service_container() fd = StringIO(str(world.scc.service)) world.scc.inetd_service_container.load_service_entries(fd) # for debugging #write_file('/tmp/srv', str(world.scc.service)) #world.scc.inetd_service_container.persist('/tmp/inetd.conf') assert world.scc.inetd_service_container.has_matching_entry(world.scc.service) world.scc.logger.debug('storing "%s" to %s' % (str(world.scc.service), world.scc.inetd_conf_fname)) shadow_files = glob('%s/*' % world.scc.shadow_fragments_dir) shadow_container = reconf_inetd.XFragmentContainer(world.scc.logger, shadow_files) world.scc.inetd_service_container.persist(world.scc.inetd_conf_fname) @step("an inetd.conf file with (an? \S+) entry %s" % service_spec_re) def an_inetd_conf_file_with_a_entry(step, entry_status, srv_name, protocol, srv_path): entry_status_key = entry_status.split()[1] # omit a/at article status_map = { 'enabled' : reconf_inetd.InetdService.ENABLED, 'maintainer_disabled' : reconf_inetd.InetdService.MAINT_DISABLED, 'user_disabled' : reconf_inetd.InetdService.USER_DISABLED, 'missing' : 'missing' } entry_status_flag = status_map.get(entry_status_key) world.scc.default_srv_args = DEFAULT_SRV_ARGS world.scc.logger.debug('srv name: %s; protocol: %s; srv_path: %s' % (srv_name, protocol, srv_path)) if entry_status_flag == 'missing': create_inetd_conf_without_entry(srv_name, protocol, srv_path) elif entry_status_flag is None: raise Exception('invalid entry status: %s' % entry_status_flag) else: create_inetd_conf_with_entry(srv_name, protocol, srv_path, entry_status_flag) @step('a matching server file that exists') def a_matching_server_file_that_exists(step): server_path = world.scc.service.get_server() server_dir = os.path.dirname(server_path) os.path.exists(server_dir) or os.makedirs(server_dir) open(server_path, 'w').close() @step('a matching server file that does not exist') def assert_missing_server_file(step): server_path = world.scc.service.get_server() assert not os.path.exists(server_path) @step('a matching shadow fragment with identical server arguments for the %s inetd.conf entry' % service_spec_re) def create_shadow_fragment_file(step, srv_name, protocol, srv_path): # TODO: filename should include protocol and server_path (replacing / with # smth else) fragment_filename = os.path.join(world.scc.shadow_fragments_dir, srv_name) fragment = reconf_inetd.XFragment(srv_name, world.scc.logger, fragment_filename) # TODO do this in a cleaner way fragment.attrs['socket_type'] = world.scc.service.attrs['socket_type'] fragment.attrs['wait'] = 'no' fragment.attrs['user'] = 'root' fragment.attrs['protocol'] = protocol fragment.attrs = dict(fragment.attrs.items() + server_path_and_args(srv_path).items()) fragment.store(fragment_filename) fd = StringIO(str(fragment.to_inetd())) world.scc.logger.debug('to_inetd:\n%s' % fragment.to_inetd()) world.scc.inetd_service_container.load_service_entries(fd) assert world.scc.inetd_service_container.has_matching_entry_with_identical_srv_args(fragment) # TODO do not make any assumptions about file names of shadow fragments; parse # their contents instead @step('no matching shadow fragment') def and_no_matching_shadow_fragment(step): srv_name = world.scc.service.get_name() fragment_filename = os.path.join(world.scc.shadow_fragments_dir, srv_name) assert not os.path.exists(fragment_filename) @step('a matching reconf-inetd fragment for the service %s' % service_spec_re) def create_inetd_conf_fragment_file(step, srv_name, protocol, server_path): # TODO: filename should include protocol and server_path (replacing / with # smth else) fragment_filename = os.path.join(world.scc.reconf_fragments_dir, srv_name) fragment = reconf_inetd.XFragment(srv_name, world.scc.logger, fragment_filename) # TODO do this in a cleaner way fragment.attrs['socket_type'] = world.scc.service.attrs['socket_type'] fragment.attrs['wait'] = 'no' fragment.attrs['user'] = 'root' fragment.attrs['protocol'] = protocol fragment.attrs = dict(fragment.attrs.items() + server_path_and_args(server_path).items()) fragment.store(fragment_filename) @step('no matching reconf-inetd fragment for the service %s' % service_spec_re) def assert_missing_fragment_file(step, srv_name, protocol, srv_path): # TODO: filename should include protocol and server_path (replacing / with # smth else) fragment_filename = os.path.join(world.scc.reconf_fragments_dir, srv_name) assert not os.path.exists(fragment_filename) @step('a new entry is added to inetd.conf for service %s' % service_spec_re) def check_inetd_conf_contains_service(step, srv_name, protocol, srv_path): service = make_service(srv_name, protocol, srv_path) inetd_service_container = load_inetd_service_container() assert inetd_service_container.has_matching_entry(service) @step('the %s service entry is removed from inetd.conf' % service_spec_re) def check_service_removal(step, srv_name, protocol, srv_path): service = make_service(srv_name, protocol, srv_path) # reload service container inetd_service_container = load_inetd_service_container() assert not inetd_service_container.has_matching_entry(service), \ dump(world.scc.inetd_conf_fname) @step('the %s service entry in inetd.conf is enabled' % service_spec_re) def check_service_enable(step, srv_name, protocol, srv_path): service = make_service(srv_name, protocol, srv_path) inetd_service_container = load_inetd_service_container() assert inetd_service_container.has_matching_enabled_entry(service), \ dump(world.scc.inetd_conf_fname) @step('I run reconf-inetd') def run_reconf_inetd(step): world.scc.inetd_conf_orig_fname = '%s.orig' % world.scc.default_inetd_conf shutil.copy(world.scc.inetd_conf_fname, world.scc.inetd_conf_orig_fname) env = { 'UPDATE_INETD_FAKE_IT' : '1', 'RECONF_INETD_LOGLEVEL' : str(logging.DEBUG), 'RECONF_INETD_LOG' : './features.log', 'INETD_CONF_FILENAME' : world.scc.inetd_conf_fname, 'RECONF_INETD_FRAGMENTS_DIR' : world.scc.reconf_fragments_dir, 'SHADOW_FRAGMENTS_DIR' : world.scc.shadow_fragments_dir } world.scc.logger.debug('env: ' + str(env)) args = [reconf_script_fname, '--verbose'] output_fd = TemporaryFile('rw') job = subprocess.Popen(args, env=env, stdout=output_fd, stderr=subprocess.STDOUT) job.wait() output_fd.seek(0) world.scc.invocation_output = output_fd.read() world.scc.logger.debug('stdout/stderr:\n%s' % world.scc.invocation_output) @step("inetd.conf must remain unchanged") def check_no_changes(step): cmd = 'diff %s %s' % (world.scc.inetd_conf_orig_fname, world.scc.inetd_conf_fname) world.scc.logger.debug(cmd) retcode, output = commands.getstatusoutput(cmd) assert retcode == 0, output @after.each_scenario def cleanup(sc): shutil.rmtree(world.scc.tempdir) def dump(f): print open(f).read() @step(u'And a matching shadow fragment with different server arguments for the %s inetd.conf entry' % service_spec_re) def create_shadow_fragment_file_with_diff_args(step, srv_name, protocol, srv_path): # TODO: filename should include protocol and server_path (replacing / with # smth else) fragment_filename = os.path.join(world.scc.shadow_fragments_dir, srv_name) fragment = reconf_inetd.XFragment(srv_name, world.scc.logger, fragment_filename) # TODO do this in a cleaner way fragment.attrs['socket_type'] = world.scc.service.attrs['socket_type'] fragment.attrs['wait'] = 'no' fragment.attrs['user'] = 'root' fragment.attrs['protocol'] = protocol fragment.attrs = dict(fragment.attrs.items() + server_path_and_args(srv_path).items()) if fragment.attrs.has_key('server_args'): fragment.attrs['server_args'] += ' -d some-other-value -v' else: fragment.attrs['server_args'] = '-d some-other-value -v' fragment.store(fragment_filename) assert world.scc.inetd_service_container.has_matching_entry(fragment) assert not world.scc.inetd_service_container.has_matching_entry_with_identical_srv_args(fragment) def service_has_matching_shadow_fragment(srv_name, protocol, srv_path): shadow_container = create_shadow_fragment_container() world.scc.default_srv_args = DEFAULT_SRV_ARGS return shadow_container.has_matching_entry(world.scc.service) @step(u'And the matching shadow fragment with identical server arguments for %s is removed' % service_spec_re) def assert_no_matching_shadow_fragment(step, srv_name, protocol, srv_path): assert not service_has_matching_shadow_fragment(srv_name, protocol, srv_path) @step(u'And a matching shadow fragment with identical server arguments for %s is created' % service_spec_re) def assert_matching_fragment_exists(step, srv_name, protocol, srv_path): assert service_has_matching_shadow_fragment(srv_name, protocol, srv_path) @step("inetd is restarted") def assert_restart_or_sighup(step): assert "inetd via invoke-rc.d" in world.scc.invocation_output reconf-inetd-1.120603/features/plain-service-removal.feature0000644000000000000000000000256511745004642020623 0ustar Feature: plain service removal Scenario: plain service removal-01 Given an inetd.conf file with an enabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl service entry is removed from inetd.conf And the matching shadow fragment with identical server arguments for ftpd_ssl,tcp,/usr/sbin/ftpd_ssl is removed And inetd is restarted Scenario: plain service removal-02 Given an inetd.conf file with a maintainer_disabled entry ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching server file that does not exist And no matching reconf-inetd fragment for the service ftpd_ssl,tcp,/usr/sbin/ftpd_ssl And a matching shadow fragment with identical server arguments for the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl inetd.conf entry When I run reconf-inetd Then the ftpd_ssl,tcp,/usr/sbin/ftpd_ssl service entry is removed from inetd.conf And the matching shadow fragment with identical server arguments for ftpd_ssl,tcp,/usr/sbin/ftpd_ssl is removed And inetd is restarted reconf-inetd-1.120603/features/steps.pyc0000644000000000000000000003417111745004753014716 0ustar Ñò ¢ ”Oc@sÙddkZddkZddkZddkZddkZddkZddklZddkl Z l Z ddk l Z ddk Z ddk Z ddkTdZeiiedƒZdZd Zd Zeid „ƒZd „Zd „Zd„Zd„Zd„Ze iid„Zd„Z d„Z!d„Z"e#deƒd„ƒZ$e#dƒd„ƒZ%e#dƒd„ƒZ&e#deƒd„ƒZ'e#dƒd„ƒZ(e#deƒd „ƒZ)e#d!eƒd"„ƒZ*e#d#eƒd$„ƒZ+e#d%eƒd&„ƒZ,e#d'eƒd(„ƒZ-e#d)ƒd*„ƒZ.e#d+ƒd,„ƒZ/e0id-„ƒZ1d.„Z2e#d/eƒd0„ƒZ3d1„Z4e#d2eƒd3„ƒZ5e#d4eƒd5„ƒZ6e#d6ƒd7„ƒZ7dS(8iÿÿÿÿN(tStringIO(tmkdtempt TemporaryFile(tglob(t*s./features/datas inetd.confs./reconf_inetd.pys([^,]+),([^,]+),([^,]+)s-d -lcCstiƒti_tidƒ}tiii|ƒtiiitiƒt ti_ t ti_ t ƒti_ t iitii dƒti_t iitii dƒti_t iitii dƒti_t iitii dƒti_t itiiƒt itiiƒdS(Ns steps.logtroots inetd.conftreconf_fragmentstshadow_fragments(tloggingt getLoggertworldtscctloggert FileHandlert addHandlertsetLeveltDEBUGt test_data_dirtdefault_inetd_confRttempdirtostpathtjoint pseudo_roottinetd_conf_fnametreconf_fragments_dirtshadow_fragments_dirtmkdir(tscthandler((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytbefore)s  !!!!cCsrtitiiƒ}tiiidtiiƒttiiƒii ƒ}z|~}|i |ƒWdQX|S(Ns loading: %s( t reconf_inetdtInetdServiceContainerR R R tdebugRtopent__exit__t __enter__tload_service_entries(t containert_[1]t inetd_conf_fd((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytload_inetd_service_container<s )cCs#titiitiiƒtƒS(N(tshutiltcopyR R RRR)(((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytcreate_inetd_service_containerCscCs,tdtiiƒ}titii|ƒS(Ns%s/*(RR R RRtXFragmentContainerR (t shadow_files((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pyt create_shadow_fragment_containerGscCs/g}|iƒD]}|d||fq~S(Ns%s/%s(tsplit(tpathstprefixR'R((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pyt prefix_pathsKscCsh}t|tiiƒ}t|ƒdjo |d|d<|d|dR tlinenotsrv((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pyt make_serviceds   "  cCsOt|||ƒti_tƒti_tiiitiiƒ pt‚dS(N(RRR R RDR,tinetd_service_containerthas_matching_entrytAssertionError(tsrv_nameRHtsrv_path((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytcreate_inetd_conf_without_entryyscCs=t|dƒiiƒ}z|~}|i|ƒWdQXdS(Ntw(R"R#R$twrite(RNtcontentR'tfd((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pyt write_file~s&cCsòt||||ƒti_tƒti_tttiiƒƒ}tiii|ƒtiii tiiƒpt ‚tii i dttiiƒtii fƒtdtiiƒ}titii |ƒ}tiiitii ƒdS(Nsstoring "%s" to %ss%s/*(RRR R RDR,RSRtstrR%RTRUR R!RRRRR-tpersist(RVRHRWROR\R.tshadow_container((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytcreate_inetd_conf_with_entry‚s# s*an inetd.conf file with (an? \S+) entry %scCsØ|iƒd}htiid6tiid6tiid6dd6}|i|ƒ}tti _ ti i i d|||fƒ|djot |||ƒn5|djotd|ƒ‚nt||||ƒdS(Nitenabledtmaintainer_disabledt user_disabledtmissings(srv name: %s; protocol: %s; srv_path: %ssinvalid entry status: %s(R0RRLtENABLEDtMAINT_DISABLEDt USER_DISABLEDtgettDEFAULT_SRV_ARGSR R R:R R!RXtNonet ExceptionRa(tstept entry_statusRVRHRWtentry_status_keyt status_maptentry_status_flag((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytan_inetd_conf_file_with_a_entry•s         s"a matching server file that existscCs[tiiiƒ}tii|ƒ}tii|ƒp ti|ƒt |dƒi ƒdS(NRY( R R RDt get_serverRRtdirnametexiststmakedirsR"tclose(RmR=t server_dir((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pyt"a_matching_server_file_that_exists«s s*a matching server file that does not existcCs1tiiiƒ}tii|ƒ pt‚dS(N(R R RDRsRRRuRU(RmR=((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytassert_missing_server_file²ssVa matching shadow fragment with identical server arguments for the %s inetd.conf entrycCstiitii|ƒ}ti|tii|ƒ}tii i d|i dRJRKR@tstoreRR^tto_inetdR!RSR%t*has_matching_entry_with_identical_srv_argsRU(RmRVRHRWtfragment_filenametfragmentR\((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytcreate_shadow_fragment_file·s   ( sno matching shadow fragmentcCsLtiiiƒ}tiitii|ƒ}tii|ƒ pt ‚dS(N( R R RDtget_nameRRRRRuRU(RmRVR((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytand_no_matching_shadow_fragmentÍss3a matching reconf-inetd fragment for the service %scCs°tiitii|ƒ}ti|tii|ƒ}tii i d|i dRJRKR@R~(RmRVRHR=RR‚((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytcreate_inetd_conf_fragment_fileÓs   (s4no matching reconf-inetd fragment for the service %scCs:tiitii|ƒ}tii|ƒ pt‚dS(N(RRRR R RRuRU(RmRVRHRWR((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytassert_missing_fragment_fileâss1a new entry is added to inetd.conf for service %scCs6t|||ƒ}tƒ}|i|ƒpt‚dS(N(RRR)RTRU(RmRVRHRWRDRS((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pyt!check_inetd_conf_contains_serviceés s/the %s service entry is removed from inetd.confcCsFt|||ƒ}tƒ}|i|ƒ ptttiiƒ‚dS(N(RRR)RTRUtdumpR R R(RmRVRHRWRDRS((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytcheck_service_removalïs s-the %s service entry in inetd.conf is enabledcCsEt|||ƒ}tƒ}|i|ƒptttiiƒ‚dS(N(RRR)thas_matching_enabled_entryRUR‰R R R(RmRVRHRWRDRS((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytcheck_service_enable÷s sI run reconf-inetdcCs dtiiti_titiitiiƒhdd6tti ƒd6dd6tiid6tii d6tii d 6}tii i d t|ƒƒtd g}td ƒ}ti|d |d|dtiƒ}|iƒ|idƒ|iƒti_tii i dtiiƒdS(Ns%s.origt1tUPDATE_INETD_FAKE_ITtRECONF_INETD_LOGLEVELs./features.logtRECONF_INETD_LOGtINETD_CONF_FILENAMEtRECONF_INETD_FRAGMENTS_DIRtSHADOW_FRAGMENTS_DIRsenv: s --verbosetrwtenvtstdouttstderrisstdout/stderr: %s(R R Rtinetd_conf_orig_fnameR*R+RR^RRRRR R!treconf_script_fnameRt subprocesstPopentSTDOUTRGtseektreadtinvocation_output(RmR•targst output_fdtjob((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytrun_reconf_inetdþs$       s inetd.conf must remain unchangedcCs_dtiitiif}tiii|ƒti|ƒ\}}|djp t|‚dS(Ns diff %s %si( R R R˜RR R!tcommandstgetstatusoutputRU(Rmtcmdtretcodetoutput((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytcheck_no_changess  cCstitiiƒdS(N(R*trmtreeR R R(R((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytcleanupscCst|ƒiƒGHdS(N(R"Rž(tf((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pyR‰ suZAnd a matching shadow fragment with different server arguments for the %s inetd.conf entrycCs"tiitii|ƒ}ti|tii|ƒ}tii i d|i dRJRKR@R;R~RSRTRUR€(RmRVRHRWRR‚((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pyt*create_shadow_fragment_file_with_diff_args#s   (  cCs(tƒ}tti_|itiiƒS(N(R/RjR R R:RTRD(RVRHRWR`((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pyt$service_has_matching_shadow_fragment9s  uRAnd the matching shadow fragment with identical server arguments for %s is removedcCst|||ƒ pt‚dS(N(R®RU(RmRVRHRW((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pyt"assert_no_matching_shadow_fragment?s uPAnd a matching shadow fragment with identical server arguments for %s is createdcCst|||ƒpt‚dS(N(R®RU(RmRVRHRW((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytassert_matching_fragment_existsDssinetd is restartedcCsdtiijpt‚dS(Nsinetd via invoke-rc.d(R R RŸRU(Rm((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytassert_restart_or_sighupHs(8R*RtretsysRšRt cStringIORttempfileRRRR¤RtlettuceRRRRR™tservice_spec_reRjRt each_scenarioR)R,R/R3R@RLRfRRRXR]RaRmRrRyRzRƒR…R†R‡RˆRŠRŒR£R©tafterR«R‰R­R®R¯R°R±(((s9/home/sez/git/reconf-inetd/reconf-inetd/features/steps.pytsZ                   reconf-inetd-1.120603/README0000644000000000000000000000051711751544106012100 0ustar reconf-inetd is a replacement for update-inetd, as per DEP9. for more details, including how to migrate packages away from update-inetd see reconf-inetd(8) and http://dep.debian.net/deps/dep9/ (a local copy of the latter is at /usr/share/doc/reconf-inetd/dep9.html) reconf-inetd does not support: - internal services - rpc services reconf-inetd-1.120603/Makefile0000644000000000000000000000306111762757670012673 0ustar all: todo tests man tests: unit_tests #system-tests unit_tests: reconf_inetd.py SERVICES_FILENAME=test-data/services ./tests.py system_tests: reconf_inetd.py lettuce VERSION=$(shell (grep '^reconf-inetd' debian/changelog | head -n 1 | sed -e 's/.*(//' -e 's/).*//')) reconf-inetd: reconf-inetd.source debian/changelog @sed "s/RECONF_INETD_VERSION/${VERSION}/" reconf-inetd.source >reconf-inetd @chmod 755 reconf-inetd reconf_inetd.py: reconf-inetd $(shell (test -f reconf_inetd.py || ln -s reconf-inetd reconf_inetd.py)) view-man: man man ./reconf-inetd.8 man: reconf-inetd.8 reconf-inetd.8: reconf-inetd manpage.txt Makefile @help2man -s 8 -n "utility to update /etc/inetd.conf and restart inetd" \ --include=manpage.txt -N ./reconf-inetd --output=- | \ egrep -v '(Syntax|Usage):' | \ fgrep -v 'reconf\-inetd \fB\-\-sanity\-check\fR fragment [... fragment]' | \ fgrep -v 'reconf\-inetd [\-\-verbose]' \ >reconf-inetd.8 uml.png: reconf_inetd.py pyreverse reconf_inetd.py dot classes_No_Name.dot -Tpng -o uml.png uml: uml.png qiv uml.png todo: TODO TODO: reconf-inetd todo.in @cp todo.in TODO @grep TODO reconf-inetd | sed 's/^ *# *TODO //' >> TODO clean: @rm -f *.pyc freshen/*.pyc uml.png classes_No_Name.dot reconf-inetd.8 \ reconf_inetd.py,cover .coverage* reconf-inetd.log steps.log \ tests.log features.log reconf_inetd.py reconf-inetd TODO \ features/data/inetd.conf.orig reconf_inetd.py,cover: reconf_inetd.py tests coverage-listing: reconf_inetd.py,cover python-coverage -a reconf_inetd.py ${PAGER} reconf_inetd.py,cover .PHONY: tests reconf-inetd-1.120603/debian/0000755000000000000000000000000011762761341012443 5ustar reconf-inetd-1.120603/debian/lintian-overrides0000644000000000000000000000005711713757060016025 0ustar reconf-inetd: package-contains-empty-directory reconf-inetd-1.120603/debian/postrm0000644000000000000000000000031611720566661013714 0ustar #!/bin/sh set -e #DEBHELPER# case "$1" in purge) rm -f /var/log/reconf-inetd.log if [ ! -e /etc/inetd.conf ]; then rm -rf /var/lib/reconf-inetd fi ;; esac reconf-inetd-1.120603/debian/install0000644000000000000000000000007411716557663014046 0ustar reconf-inetd /usr/sbin/ reconf-inetd.8 /usr/share/man/man8/ reconf-inetd-1.120603/debian/postinst0000644000000000000000000000016111716560674014254 0ustar #!/bin/sh set -e # we should never fail in a way that breaks an installation reconf-inetd || true #DEBHELPER# reconf-inetd-1.120603/debian/docs0000644000000000000000000000002611722503433013304 0ustar README TODO dep9.html reconf-inetd-1.120603/debian/doc-base0000644000000000000000000000057311744774450014055 0ustar Document: reconf-inetd-spec Title: DEP-9: inet-superserver configuration by maintainer scripts Author: Serafeim Zanikolas Abstract: Motivation, requirements and functional overview of a successor configuration tool for inetd superservers Section: System/Package Management Format: HTML Index: /usr/share/doc/reconf-inetd/dep9.html Files: /usr/share/doc/reconf-inetd/dep9.html reconf-inetd-1.120603/debian/dirs0000644000000000000000000000005611712633277013331 0ustar /usr/share/reconf-inetd /var/lib/reconf-inetd reconf-inetd-1.120603/debian/copyright0000644000000000000000000000057211756210723014376 0ustar Files: * Copyright: 2011-2012 Serafeim Zanikolas License: GPL-2+ License: GPL-2 On Debian systems, the complete text of the GNU General Public License can be found in the file /usr/share/common-licenses/GPL-2. License: GPL-3 On Debian systems, the complete text of the GNU General Public License can be found in the file /usr/share/common-licenses/GPL-3. reconf-inetd-1.120603/debian/changelog0000644000000000000000000000622411762761341014321 0ustar reconf-inetd (1.120603) unstable; urgency=medium * add prerm script to remove reconf-inetd fragments upon package removal (closes: #675679; setting medium urgency due to RC); thanks to Jonathan McCrohan for the bug report * ensure that inetd.conf entries are never concatenated (closes: #675589) * update local copy of dep9 -- Serafeim Zanikolas Sun, 03 Jun 2012 19:24:02 +0200 reconf-inetd (1.120523) unstable; urgency=low * fix logrotate file (closes: #674095) * do not spam log file about a standard inetd.conf comment being an invalid entry -- Serafeim Zanikolas Wed, 23 May 2012 11:30:59 +0200 reconf-inetd (1.120520) unstable; urgency=low * declare binary package as Multi-Arch: foreign * update local copy of dep9 * port debian/copyright to the dep5 format -- Serafeim Zanikolas Sun, 20 May 2012 16:31:05 +0200 reconf-inetd (1.120422) unstable; urgency=low * add support for tcpd-enabled services (closes: #668140) * update local copy of dep9 * log invalid fragments and list them in stdout in verbose mode; also, log which services are added/removed (closes: #669317) * update manpage: - document reconf-inetd fragment format (closes: #669515) - fix typo; thanks to Jonathan McCrohan (closes: #669315) -- Serafeim Zanikolas Sun, 22 Apr 2012 15:39:40 +0200 reconf-inetd (0.120226) unstable; urgency=low * add /usr/share/doc/reconf-inetd/dep9.html and mention it in the man page and the README file (closes: #661300) * register dep9.html to doc-base and add 'Suggests: doc-base' * man page: mention /var/log/reconf-inetd.log and cite deb-triggers(5) * bump standards version to 3.9.3 (no changes) -- Serafeim Zanikolas Sun, 26 Feb 2012 20:34:28 +0100 reconf-inetd (0.120221) unstable; urgency=low * default stdout log level to ERROR, or INFO if verbose is set; set logfile always to INFO; add timestamps in log file entries * add postrm to wipe /var/log/reconf-inetd and /var/lib/reconf-inetd (the latter only if /etc/inetd.conf does not exist) upon package purge * add debian/logrotate * rename build-time test log files and update make clean target -- Serafeim Zanikolas Tue, 21 Feb 2012 01:59:45 +0100 reconf-inetd (0.120214) unstable; urgency=low * target unstable. * add manpage * rename /usr/bin/reconf_inetd to /usr/sbin/reconf-inetd * make verbose mode actually print something (in particular, INFO priority messages) * make version and sanity-check modes print to stdout instead of logging to /var/log/reconf-inetd.log (so that they can run without root privileges) * sanity check mode: mention filename of problematic fragment, and do not print backtrace * quit with error message when ran in default mode without root privileges * remove unimplemented command-line switch for dry-run mode -- Serafeim Zanikolas Tue, 14 Feb 2012 22:17:48 +0100 reconf-inetd (0.120206) experimental; urgency=low * Initial release. -- Serafeim Zanikolas Mon, 06 Feb 2012 19:18:53 +0100 reconf-inetd-1.120603/debian/source/0000755000000000000000000000000011713751706013743 5ustar reconf-inetd-1.120603/debian/source/format0000644000000000000000000000001511713751706015152 0ustar 3.0 (native) reconf-inetd-1.120603/debian/control0000644000000000000000000000136211756200124014036 0ustar Source: reconf-inetd Section: net Priority: optional Maintainer: Serafeim Zanikolas Build-Depends: python (<<3), debhelper (>= 7), help2man Standards-Version: 3.9.3 Vcs-Git: git://git.debian.org/collab-maint/reconf-inetd.git Vcs-Browser: http://git.debian.org/?p=collab-maint/reconf-inetd.git Package: reconf-inetd Architecture: all Multi-Arch: foreign Depends: ${misc:Depends}, python (<<3) Suggests: doc-base Description: maintainer script for programmatic updates of inetd.conf reconf-inetd is invoked by maintainer scripts to update the configuration of the internet superserver. It is a replacement for update-inetd, as per DEP9. . If the above does not mean anything to you, then you most certainly do not need this package. reconf-inetd-1.120603/debian/triggers0000644000000000000000000000004111615606612014203 0ustar interest /usr/share/reconf-inetd reconf-inetd-1.120603/debian/logrotate0000644000000000000000000000012111757126352014361 0ustar /var/log/reconf-inetd.log { rotate 6 weekly compress missingok } reconf-inetd-1.120603/debian/prerm0000644000000000000000000000016111762716610013510 0ustar #!/bin/sh set -e # we should never fail in a way that breaks an installation reconf-inetd || true #DEBHELPER# reconf-inetd-1.120603/debian/compat0000644000000000000000000000000211441724155013635 0ustar 7 reconf-inetd-1.120603/debian/rules0000755000000000000000000000022111713754743013522 0ustar #!/usr/bin/make -f # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 export DEBUILD_DPKG_BUILDPACKAGE_OPTS="-i -I.git" %: dh $@ reconf-inetd-1.120603/reconf-inetd.source0000644000000000000000000010301711762761341015022 0ustar #!/usr/bin/python # reconf-inetd - reconfigure and restart inetd # Copyright (C) 2011, 2012 Serafeim Zanikolas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import os import re import sys import shutil import logging import logging.handlers import commands from glob import glob __author__ = "Serafeim Zanikolas " __copyright__ = "Copyright (c) 2011-2012 Serafeim Zanikolas" __license__ = "GPL-2+" __version__ = "RECONF_INETD_VERSION" INETD_USER = 'root' RECONF_INETD_FRAGMENTS_DIR = '/usr/share/reconf-inetd' SHADOW_FRAGMENTS_DIR = '/var/lib/reconf-inetd' SERVICES_FILENAME = os.environ.get('SERVICES_FILENAME') or '/etc/services' class InvalidEntryException(Exception): """Exception thrown for invalid entries within an XFragment file.""" pass class MissingFieldException(Exception): """Exception thrown for xfragment entries with a missing mandatory field.""" pass class UnsupportedOperatorException(Exception): """Exception thrown for invalid unsupported operators within an XFragment entry. The only currently supported operator is '='. """ pass class UnimplementedException(Exception): """Exception thrown when a subclass does not implement a method.""" pass class BaseService(object): """Format-independent service entry.""" def __init__(self, attrs, logger): """Called by subclasses InetdService and XFragment. self.service_id and self.hash are not defined until the first call to self.__hash__(), because the attributes that are used to construct the service_id are not necessarily available during the instantiation of a BaseService object.""" self.attrs = attrs self.logger = logger self.service_id = None self.hash = None self.existing_server_path = None def get_name(self): return self.attrs.get('service') def get_protocol(self): return self.attrs.get('protocol') def get_server(self): raise UnimplementedException def __hash__(self): """Base the object's hash on memoized service_id.""" if self.service_id is None: self._init_service_id() self.hash = hash(self.service_id) return self.hash def _init_service_id(self): """Construct a unique string for this service. DEP9: 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. See the constructor's docstring on why this code is not there instead.""" name = self.get_name() protocol = self.get_protocol() server = self.get_server() self.service_id = "%s|%s|%s" % (name, protocol, server) def __eq__(self, other): return self.service_id == other.service_id def __ne__(self, other): return not self.__eq__(other) def get_server_args(self): return self.attrs['server_args'] def has_existing_server_path(self): """Return True when server_path is defined and refers to an existing file.""" if self.existing_server_path is None: srv_path = self.get_server() self.existing_server_path = srv_path and os.path.exists(srv_path) return self.existing_server_path class BaseServiceContainer(object): """A wrapper for a set of BaseService objects. This base class is inherited by InetdServiceContainer and XFragmentContainer.""" def __init__(self, logger): self.logger = logger self.all_services = {} def get_all_services(self): return self.all_services.values() def get_matching_entry(self, srv): """returns matching entry or None, if there isn't one""" return self.all_services.get(srv) def has_matching_entry(self, srv): return srv in self.all_services def has_matching_enabled_entry(self, srv): match = self.get_matching_entry(srv) return match is not None and match.is_enabled() def has_matching_entry_with_identical_srv_args(self, srv): """return True if the container has a matching service entry with identical command line server arguments""" match = self.get_matching_entry(srv) return match is not None and \ match.get_server_args() == srv.get_server_args() def add_service(self, service): self.logger.debug('adding service %s' % service.get_name()) self.all_services[service] = service def remove_service(self, service): self.logger.debug('removing service %s' % service.get_name()) del self.all_services[service] class InetdService(BaseService): """A representation of an inetd.conf line.""" mandatory_attrs = ['service', 'socket_type', 'wait', 'protocol', 'server'] # MAINT_DISABLED: lines starting with '## ' may be re-enabled # USER_DISABLED: lines starting with '# ' are local policy and must not be # touched ENABLED, MAINT_DISABLED, USER_DISABLED = 0, 1, 2 STATUS_STR = ['', '## ', '# '] def __init__(self, attrs, lineno, logger): """lineno is the line number at which this service is stored in inetd.conf""" super(InetdService, self).__init__(attrs, logger) if self.attrs.get('user') is None: self.attrs['user'] = 'nobody' self.lineno = lineno self.is_valid = all([attrs.get(i) for i in InetdService.mandatory_attrs]) self.set_status(self.ENABLED) self.logger.debug('loaded %s; is_valid: %s' % (attrs['service'], self.is_valid)) def set_status(self, status): self.attrs['status'] = status def status_str(self): return InetdService.STATUS_STR[self.attrs['status']] def enable(self): self.attrs['status'] = InetdService.ENABLED def is_enabled(self): return self.attrs['status'] == InetdService.ENABLED def is_maint_disabled(self): return self.attrs['status'] == InetdService.MAINT_DISABLED def is_user_disabled(self): return self.attrs['status'] == InetdService.USER_DISABLED def __repr__(self): """one-line representation of the service as it would appear in inetd.conf""" srv_args = self.attrs.get('server_args') return '%s%s%s' % (self.status_str(), ('%(service)s %(socket_type)s %(protocol)s ' '%(wait)s %(user)s %(server)s') % self.attrs, ' %s' % srv_args if srv_args else '') def get_server(self): server = self.attrs.get('server') if server and server.endswith('/tcpd') or server.endswith('/rpcd'): server_args = self.attrs.get('server_args') if server_args: server = server_args.split()[0] return server class InetdConfChangeSet(object): """Encapsulates the logic for finding out which services must be added, removed or enabled in inetd.conf, as well as which shadow fragment files must be created or removed, given: an inetd.conf file, a set of reconf-inetd fragment files, and a set of shadow fragment files.""" def __init__(self, inetd_serv_container, fragment_container, shadow_container, logger): self.inetd_serv_container = inetd_serv_container self.fragment_container = fragment_container self.shadow_container = shadow_container self.logger = logger self.to_enable, self.to_add, self.to_remove = None, None, None def services_to_enable(self): """Memoized list of InetdService objects that represent previously maintainer_disabled inetd.conf entries that must be enabled.""" if self.to_enable is None: self.to_enable = \ [s for s in self.inetd_serv_container.get_all_services() if (s.is_maint_disabled()) and (s.has_existing_server_path()) and (s in self.fragment_container.get_all_services()) and (s in self.shadow_container.get_all_services())] return self.to_enable def services_to_add(self): """Memoized list of XFragment objects that represent services to be added to inetd.conf.""" if self.to_add is None: self.to_add = \ [f for f in self.fragment_container.get_valid_services() if not self.inetd_serv_container.has_matching_entry(f)] return self.to_add def services_to_remove(self): """Memorized set of InetdService objects that represent entries to be removed from inetd.conf. This will fail if called _after_ services have been added, because they've be added as XFragment objects which do not implement is_user_disabled().""" if self.to_remove is None: self.to_remove = \ [s for s in self.inetd_serv_container.get_all_services() if (not s.is_user_disabled()) and (not s.has_existing_server_path()) and (s not in self.fragment_container.get_all_services()) and (self.shadow_container.has_matching_entry_with_identical_srv_args(s))] return self.to_remove def is_not_empty(self): """return True if there are no changes""" return any(self.services_to_enable()) or \ any(self.services_to_add()) or any(self.services_to_remove()) def update_shadow_fragments(self, shadow_dir): self._create_shadow_fragments(shadow_dir) self._remove_shadow_fragments() def _create_shadow_fragments(self, shadow_dir): """Create a shadow fragment for every service that's added to inetd.conf.""" for srv in self.services_to_add(): basename = os.path.basename(srv.source_filename) shadow_filename = '%s/%s' % (shadow_dir, basename) self.logger.debug('creating shadow file %s' % shadow_filename) shutil.copy(srv.source_filename, shadow_filename) def _remove_shadow_fragments(self): """Remove a shadow fragment for every service that is removed from inetd.conf.""" for srv in self.services_to_remove(): fragment = self.shadow_container.get_matching_entry(srv) if fragment is None: self.logger.warning(('unable to determine the source ' 'filename for "%s"') % str(srv)) continue shadow_filename = fragment.source_filename if os.path.exists(shadow_filename): self.logger.debug('removing shadow file %s' % shadow_filename) os.remove(shadow_filename) else: self.logger.debug(('not removing shadow file %s ' '(does not exist)') % shadow_filename) class InetdServiceContainer(BaseServiceContainer): """Representation of an inetd.conf file, and related logic for managing service entries therein.""" def __init__(self, logger): super(InetdServiceContainer, self).__init__(logger) self.inetd_conf_lines = [] self.removed_services = [] def load_service_entries(self, inetd_conf_fd): InetdConfParser(self.logger, self, inetd_conf_fd) def get_enabled_services(self): """Return a list of services that are neither maintainer- nor user-disabled.""" return [s for s in self.all_services.values() if s['status'] == InetdService.ENABLED] def prepare_changes(self, change_set): """Apply a given set of changes to self.inetd_conf_lines, a list representation of inetd.conf. The changes are not effective until the persist method is called. Note that service disable is not foreseen according to DEP9.""" self.logger.debug('preparing changes') self._remove_services(change_set.services_to_remove()) self._enable_services(change_set.services_to_enable()) self._add_services(change_set.services_to_add()) def _add_services(self, to_add): """Add the given XFragment objects as inetd.conf entries.""" self.logger.info('adding %d new service(s)' % (len(to_add))) for srv in to_add: self.inetd_conf_lines.append(srv.to_inetd()) if srv.lineno is None: srv.lineno = len(self.inetd_conf_lines) + 1 self.logger.info('adding service %s' % srv.service_id) self.add_service(srv) def _remove_services(self, to_remove): """Remove the inetd.conf entries that match the given InetdService objects.""" self.logger.debug('removing %d service(s)' % (len(to_remove))) for srv in to_remove: self.logger.info('removing service %s (line %d)' % (srv.get_name(), srv.lineno)) self.inetd_conf_lines[srv.lineno] = '' self.logger.info('removing service %s' % srv.service_id) self.remove_service(srv) def _enable_services(self, to_enable): """Enable the inetd.conf entries that match the given InetdService objects.""" self.logger.debug('enabling %d service(s)' % (len(to_enable))) for srv in to_enable: self.logger.info('enabling service %s (line %d)' % (srv.get_name(), srv.lineno)) srv.enable() self.logger.info('enabling service %s' % srv.service_id) self.inetd_conf_lines[srv.lineno] = str(srv) def persist(self, filename): """Actually store on-disk whatever changes were made.""" self.logger.debug('storing %s' % filename) lines = [self._terminate_line(line) for line in self.inetd_conf_lines] with open(filename, 'w') as fd: fd.writelines(lines) def _terminate_line(self, line): """Terminate the given line, unless it's already terminated.""" if line == '' or line[-1] == '\n': return line return '%s\n' % line class InetdConfParser(object): space_pat = re.compile("\s+") def __init__(self, logger, container, inetd_conf_fd): self.logger = logger self.container = container new_lines = inetd_conf_fd.readlines() self.container.inetd_conf_lines.extend(new_lines) for i, line in enumerate(new_lines): self.logger.debug('line %d: %s' % (i, line)) self.parse_line(line, i) def parse_line(self, line, lineno): attrs = {} fields = InetdConfParser.space_pat.split(line) nfields = len(fields) if nfields < 6: if line and not line.startswith('#') and not line.isspace(): self.logger.warn('skipping invalid line %d: %s"\n' % (lineno, line)) return if line.startswith('## '): status = InetdService.MAINT_DISABLED fields = fields[1:] elif line.startswith('# '): status = InetdService.USER_DISABLED fields = fields[1:] elif line.startswith('#'): # skip comment line self.logger.debug('skipping comment line %d: %s' % (lineno, line)) return else: status = InetdService.ENABLED try: attrs['service'] = fields[0] attrs['socket_type'] = fields[1] attrs['protocol'] = fields[2] #[,sndbuf=size][,rcvbuf=size] attrs['wait'] = fields[3] #wait/nowait[.max] attrs['user'] = fields[4] #user[.group] or user[:group] attrs['server'] = fields[5] if nfields > 6: attrs['server_args'] = ' '.join(fields[6:]).strip() else: attrs['server_args'] = '' except IndexError: # log invalid entries, but not about the standard inetd.conf header if line != "# Internet superserver configuration database\n": self.logger.warning('skipping line with invalid number of fields: "%s"' % line) return srv = InetdService(attrs, lineno, self.logger) srv.set_status(status) if srv.is_valid: self.container.add_service(srv) else: self.logger.warn('skipping invalid entry in line %d' % lineno) class XFragment(BaseService): """A container for a single xinetd configuration fragment, and associated methods.""" mandatory_keys = { 'socket_type' : set(['stream', 'dgram', 'raw', 'seqpacket']), 'wait' : set(['yes', 'no']) } map_per_field = { 'wait' : { 'yes' : 'wait', 'no' : 'nowait'}} def __init__(self, service_name, logger, source_filename): attrs = { 'service' : service_name, 'server_args' : '' } super(XFragment, self).__init__(attrs, logger) self.errors = [] self.valid = None self.enabled = None self.lineno = None self.source_filename = source_filename def add_attr(self, key, val): # check for validity of attr and val self.attrs[key] = val def get_server(self): server = self.attrs.get('server') flags = self.attrs.get('flags') if server and server.endswith('/tcpd') or server.endswith('/rpcd') \ or (flags and 'NAMEINARGS' in flags.upper()): server_args = self.attrs.get('server_args') if server_args: server = server_args.split()[0] return server def is_valid(self): """Return memoized validation result.""" if self.valid is None: self.validate() return self.valid def validate(self): """Return a (errors, warnings) tuple for missing mandatory fields, invalid values, etc. From xinetd.conf(5): socket_type (mandatory) wait (mandatory) user (non-internal services only) server (non-internal services only) protocol (RPC and unlisted services only) rpc_version (RPC services only) rpc_number (unlisted RPC services only) port (unlisted non-RPC services only) """ warnings = [] for key, valid_values in XFragment.mandatory_keys.iteritems(): value = self.attrs.get(key) if value is None: msg = 'missing mandatory key "%s"' % key if self.attrs['service']: msg = '%s in fragment for "%s"' % (msg, self.attrs['service']) self.errors.append(msg) elif value not in valid_values: warnings.append('unknown value for key %s: %s\n' % (key, value)) # protocol key is mandatory only for non-listed services if not self.attrs.has_key('protocol'): protocol = self.guess_protocol() if protocol is None: msg = 'missing protocol key for unlisted service %s' self.errors.append(msg % self.attrs['service']) else: self.attrs['protocol'] = protocol # user and server keys are mandatory, unless type=internal if (not self.attrs.has_key('user') or \ not self.attrs.has_key('server')): if not self.attrs.has_key('type') or \ self.attrs['type'].lower() != 'internal': self.errors.append(('"user" and "server" keys are mandatory, ' 'unless type=internal (which is not the ' 'case)')) else: if not self.attrs.has_key('user'): self.attrs['user'] = INETD_USER if not self.attrs.has_key('server'): self.attrs['server'] = 'internal' self.valid = self.errors == [] return [self.errors, warnings] def _translate(self, key): """Translates a value from an xinetd fragment to the corresponding one for /etc/inetd.conf, if applicable (or returns the same value). """ value = self.attrs[key] try: return XFragment.map_per_field[key][value] except KeyError: return value def to_inetd(self): """Return fragment as an inetd service entry.""" translated_attrs = dict([(k, self._translate(k)) for k in self.attrs.iterkeys()]) r = ('%(service)s %(socket_type)s %(protocol)s %(wait)s %(user)s ' '%(server)s') % translated_attrs if translated_attrs['server_args']: return '%s %s\n' % (r, self.attrs['server_args']) return '%s\n' % r def create_shadow_fragment(self, shadow_dir): shadow_filename = '%s/%s' % (shadow_dir, self.source_filename) self.logger.debug('creating shadow file %s' % shadow_filename) shutil.copy(self.source_filename, shadow_filename) def store(self, filename): """Store as a fragment file.""" with open(filename, 'w') as fd: content = ['service %s' % self.get_name(), '{', '\n'.join(['%s = %s' % (k, v) for k, v in self.attrs.iteritems()]), '}'] fd.write('\n'.join(content)) def guess_protocol(self): if os.path.exists(SERVICES_FILENAME): srv_name = self.get_name() for line in open(SERVICES_FILENAME): try: fields = line.split() if fields[0] == srv_name: return fields[1].split('/')[1] except IndexError: # ignore malformed line continue class XFragmentParser(object): """Parse an extended internet services deamon configuration file, with one or more fragments, using a simple FSM. The FSM determines which *_state method should be invoked, at any point of the input data.""" space_pat = re.compile(r'[ \t]+') def __init__(self, fragment_container, logger): self.logger = logger self._fragment = None self.container = fragment_container def load_files(self, fragment_files): """Load a list of xfragment files into the container.""" for fname in [os.path.abspath(f) for f in fragment_files]: # is readable if not os.path.isfile(fname): self.logger.warn(('%s does not exist or is not a regular' 'file\n') % fname) continue prev_services_count = len(self.container.get_all_services()) with open(fname, 'r') as fd: try: self.current_filename = fname self.parse(fd) except InvalidEntryException, exc: self.logger.error('in file %s:\n%s\n' % (fname, str(exc))) new_services_count = len(self.container.get_all_services()) if prev_services_count == new_services_count: self.logger.warn("%s does not contain a valid service fragment" % fname) def _initial_state(self, tokens): if tokens[0] == 'service' and len(tokens) == 2: service_name = tokens[1] self._fragment = XFragment(service_name, self.logger, self.current_filename) self.parse_func = self._open_brace_state def _open_brace_state(self, tokens): if tokens[0] == '{' and len(tokens) == 1: self.parse_func = self._key_value_state def _key_value_state(self, tokens): if len(tokens) == 1 and tokens[0] == '}': self._close_brace_state() elif len(tokens) >= 3: key = tokens[0] operator = tokens[1] value = " ".join(tokens[2:]) # TODO add support for += and -= operators if operator != '=': raise UnsupportedOperatorException(operator) self._fragment.add_attr(key, value) def _close_brace_state(self): (errors, warnings) = self._fragment.validate() if errors == []: self.container.add_service(self._fragment) else: self.logger.error('errors for %s: %s;\n' % (self.current_filename, "".join(errors))) raise MissingFieldException('%s;\n' % "\n".join(errors)) if warnings: self.logger.warn('warnings for %s: %s;\n' % (self.current_filename, "".join(warnings))) self.parse_func = self._initial_state def parse(self, input_fd): """Parse one or more configuration fragments from the supplied file descriptor, usin *_state methods.""" raw_fragment = input_fd.read() # normalise spacing lines = XFragmentParser.space_pat.sub(' ', raw_fragment) lines = [k.lstrip().rstrip() for k in lines.split('\n')] self.parse_func = self._initial_state i = None for i, line in enumerate(lines): if line.startswith("#") or line.isspace() or line == '': continue tokens = line.split() self.parse_func(tokens) if self.parse_func != self._initial_state: msg = 'fragment does not end with a "}"%s' % \ '' if i is None else (' in line %d\n' % i) raise InvalidEntryException(msg) class XFragmentContainer(BaseServiceContainer): """Encapsulates the object representation of xfragment files.""" def __init__(self, logger, fragment_files=None): super(XFragmentContainer, self).__init__(logger) if fragment_files: self.load_files(fragment_files) def load_files(self, fragment_files): XFragmentParser(self, self.logger).load_files(fragment_files) def get_valid_services(self): return [srv for srv in self.all_services.values() if srv.has_existing_server_path()] class CmdLineArguments(object): """Class to parse, check and encapsulate command-line argument values.""" def __init__(self): from optparse import OptionParser usage = \ """ %prog [--verbose] %prog --sanity-check fragment [... fragment]""" parser = OptionParser(usage) #parser.add_option('-d', '--dry-run', dest='dry_run', default=False, # help="""do not actually update inetd.conf, just show # what would have happened""") parser.add_option('-c', '--sanity-check', dest='fragments_to_check', default='', help="""test the validity of the xinetd.conf-like configuration fragments, as specified by a space-separated list of files""") parser.add_option('-v', '--verbose', action='store_true', dest='verbose', default=False, help='explain what happens') parser.add_option('-V', '--version', dest='show_version', action="store_true", default=False, help='show version and exit') (options, args) = parser.parse_args() if options.show_version: self.display_version_and_exit() #self.dry_run = options.dry_run self.verbose = options.verbose if options.fragments_to_check: self.update_mode = False self.fragments_to_check = [options.fragments_to_check] + args else: self.update_mode = True args and parser.error("Unknown argument %s" % " ".join(args)) self.inetd_conf_fname = os.environ.get('INETD_CONF_FILENAME') \ or '/etc/inetd.conf' self.fragments_dir = os.environ.get('RECONF_INETD_FRAGMENTS_DIR') \ or RECONF_INETD_FRAGMENTS_DIR self.shadow_fragments_dir = os.environ.get('SHADOW_FRAGMENTS_DIR') \ or SHADOW_FRAGMENTS_DIR def display_version_and_exit(self): sys.stdout.write('reconf-inetd %s\n' % __version__) exit(0) class InetdRestarter(object): FAKE_INVOCATION = os.environ.get("UPDATE_INETD_FAKE_IT") def __init__(self, change_set, logger): self.logger = logger if any(change_set.services_to_remove()) and \ not (any(change_set.services_to_add()) or \ any(change_set.services_to_enable())): self.sysv_action = 'force-reload' else: self.sysv_action = 'restart' def restart(self): sysv_script = glob('/etc/init.d/*inetd') self.logger.debug("About to %s inetd via invoke-rc.d\n" % self.sysv_action) if not InetdRestarter.FAKE_INVOCATION and sysv_script != []: service = os.path.basename(sysv_script[0]) cmd = '/usr/sbin/invoke-rc.d %s %s' % (service, self.sysv_action) self.logger.info("about to run: %s" % cmd) status, output = commands.getstatusoutput(cmd) if status != 0: self.logger.error('failed to restart %s via invoke-rc.d: %s' % (service, output)) def update_inetd_conf(logger, inetd_conf_fname, fragment_files, shadow_files, shadow_fragments_dir): """Update inetd.conf and add/remove shadow fragment files, if applicable.""" inetd_serv_container = InetdServiceContainer(logger) with open(inetd_conf_fname) as inetd_conf_fd: inetd_serv_container.load_service_entries(inetd_conf_fd) fragment_container = XFragmentContainer(logger, fragment_files) shadow_container = XFragmentContainer(logger, shadow_files) change_set = InetdConfChangeSet(inetd_serv_container, fragment_container, shadow_container, logger) if change_set.is_not_empty(): inetd_serv_container.prepare_changes(change_set) inetd_serv_container.persist(inetd_conf_fname) change_set.update_shadow_fragments(shadow_fragments_dir) InetdRestarter(change_set, logger).restart() else: logger.info('no changes to be made') def die_unless_root_or_testing(): # no point in running for real unless we have root privileges if os.environ.get('RECONF_INETD_LOG') is None \ and os.environ.get('INETD_CONF_FILENAME') is None \ and os.getuid() != 0: sys.stderr.write("reconf-inetd in default mode requires root privileges\n") exit(0) def main(): args = CmdLineArguments() logger = logging.getLogger('InetdConfLogger') logger.setLevel(logging.DEBUG) # to be overriden by specific handlers stdout_loglevel = os.environ.get('RECONF_INETD_LOGLEVEL') if stdout_loglevel is not None: stdout_loglevel = int(stdout_loglevel) elif args.verbose: stdout_loglevel = logging.INFO else: stdout_loglevel = logging.ERROR stdout_handler = logging.StreamHandler(sys.stdout) logger.addHandler(stdout_handler) stdout_handler.setLevel(stdout_loglevel) if args.update_mode: die_unless_root_or_testing() LOG_FILENAME = os.environ.get('RECONF_INETD_LOG') \ or '/var/log/reconf-inetd.log' file_handler = logging.FileHandler(LOG_FILENAME) file_handler.setLevel(logging.INFO) log_formatter = logging.Formatter("%(asctime)s - %(message)s") file_handler.setFormatter(log_formatter) logger.addHandler(file_handler) if not os.path.exists(args.inetd_conf_fname) or \ not os.path.exists(args.fragments_dir): logger.debug('either or both of %s, %s are missing; nothing to do' % (args.inetd_conf_fname, args.fragments_dir)) exit(0) if not os.path.isfile(args.inetd_conf_fname): logger.error('%s is not a regular file\n' % args.inetd_conf_fname) exit(0) if not os.path.isdir(args.fragments_dir): logger.error('%s is not a directory\n' % args.fragments_dir) exit(0) fragment_files = glob('%s/*' % args.fragments_dir) shadow_files = glob('%s/*' % args.shadow_fragments_dir) if not fragment_files and not shadow_files: logger.debug('no reconf/shadow fragments found; nothing to do') exit(0) update_inetd_conf(logger, args.inetd_conf_fname, fragment_files, shadow_files, args.shadow_fragments_dir) else: try: XFragmentContainer(logger, args.fragments_to_check) except MissingFieldException: # just catch it; errors are logged where the exception is thrown pass if __name__ == "__main__": try: main() except Exception: import traceback sys.stderr.write(('reconf-inetd terminated unexpectedly! Please file ' 'a bug report against\nthe reconf-inetd package ' 'with the following info:\n')) traceback.print_exc() exit(0) # we must always exit successfully reconf-inetd-1.120603/off/0000755000000000000000000000000011745004420011760 5ustar reconf-inetd-1.120603/dep9.html0000644000000000000000000003713111762761341012755 0ustar DEP-9: inet-superserver configuration by maintainer scripts
Title: inet-superserver configuration by maintainer scripts
DEP: 9
State: CANDIDATE
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.

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:

  • the standard configuration files of inetd and xinetd must remain the authoritative files;
  • the solution must not change the way system administrators configure inetd, and must have no impact on maintainers of "Provides: inet-superserver" packages;
  • reconf-inetd must be capable of co-existing with update-inetd, so as to allow a gradual transition.

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:

  • reconf-inetd will provide the directory /usr/share/reconf-inetd, and declare a dpkg trigger for that directory
  • server packages that can use inetd, will depend on reconf-inetd and install a reconf-inetd fragment in /usr/share/reconf-inetd
  • reconf-inetd will be invoked via a dpkg trigger to update /etc/inetd.conf using the fragments in /usr/share/reconf-inetd

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:

  • to identify inetd.conf entries that have been added by reconf-inetd (as opposed to update-inetd or a user)
  • to determine whether an inetd.conf entry, that has been previously added by reconf-inetd, is intact or has had local modifications

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.

  • an non-commented-out inetd.conf entry will be removed, regardless of whether it is enabled or disabled, when it:

    • refers to a non-existing server file
    • has no matching reconf-inetd fragment
    • is identical to a matching shadow fragment
  • a disabled inetd.conf entry will be enabled when it

    • refers to an existing server file
    • it has a matching reconf-inetd fragment
    • and a matching shadow fragment (identical or not)
  • a new inetd.conf entry will be added when there exists a reconf-inetd fragment that:

    • refers to an existing server file
    • has no matching (enabled, disabled, commented-out or not) inetd.conf entry
    • has a matching reconf-inetd fragment

Meaning of the above listed actions:

  • add: add inetd.conf entry and a matching shadow fragment
  • remove: remove inetd.conf entry and matching shadow fragment
  • enable: enable inetd.conf entry

Configuration of new server packages

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

  • depend on reconf-inetd
  • install a reconf-inetd fragment in /usr/share/reconf-inetd, as a regular file (ie. not as a conffile);

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:

  • depend on both update-inetd and reconf-inetd
  • install a reconf-inetd fragment in /usr/share/reconf-inetd, as a regular file (ie. not as a conffile);
  • drop any references to update-inetd in postrm
  • modify postinst to (i) remove any inetd.conf entries for that package that were previously added using update-inetd, assuming they have not had local changes; (ii) run reconf-inetd to re-add new inetd.conf entries that might have been removed by update-inetd (if the reconf-inetd trigger ran before postinst)

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" || fgrep -qx '## $OLD_FTPENTRY"; 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

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

Source code repo

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

reconf-inetd-1.120603/tests.py0000755000000000000000000003107611745004642012742 0ustar #!/usr/bin/python # reconf-inetd - reconfigure and restart inetd # Copyright (C) 2010, 2011, 2012 Serafeim Zanikolas # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import unittest import logging from StringIO import StringIO from reconf_inetd import XFragmentContainer, XFragmentParser, InetdService, \ InetdServiceContainer, InetdConfParser, InvalidEntryException, \ MissingFieldException logger = logging.getLogger() logger.addHandler(logging.FileHandler('tests.log')) logger.setLevel(logging.DEBUG) class TestFragmentData(unittest.TestCase): fragment1 = \ """service ftpd-ssl { disable = yes type = INTERNAL id = ftpd-ssl-stream socket_type = stream protocol = tcp user = root wait = no server = /usr/sbin/ftpd-ssl server_args = -d }""" finger_fragment = \ """service finger { disable = no socket_type = stream protocol = tcp flags = IPv6 wait = no user = root server = /path/to/non-existent-server log_type = SYSLOG daemon info log_on_success = HOST log_on_failure = HOST }""" fragment_unlisted_srv_without_protocol = \ """service nonstd_service { disable = no flags = IPv6 socket_type = stream wait = no user = root server = /usr/sbin/in.ftpd server_args = -l log_type = SYSLOG daemon info log_on_failure = HOST }""" fragment_listed_srv_without_protocol = \ """service ftp { disable = no flags = IPv6 socket_type = stream wait = no user = root server = /usr/sbin/in.ftpd server_args = -l log_type = SYSLOG daemon info log_on_failure = HOST }""" tcpd_fragment = \ """service nntp { socket_type = stream protocol = tcp wait = no user = news flags = NAMEINARGS server = /usr/sbin/tcpd server_args = /usr/sbin/leafnode }""" result1 = 'ftpd-ssl stream tcp nowait root /usr/sbin/ftpd-ssl -d\n' result2 = 'proftpd stream tcp nowait root /usr/sbin/proftpd\n' listed_srv_without_protocol = 'ftp stream tcp nowait root /usr/sbin/in.ftpd -l\n' tcpd_result = "nntp stream tcp nowait news /usr/sbin/tcpd /usr/sbin/leafnode\n" # wait: no --> nowait; yes --> wait # del id, disable def _get_first_service(self, container, service): self.assertTrue(len(container.all_services), 1) srv = [s for s in container.all_services if s.get_name() == service] self.assertTrue(srv) return srv[0] def _get_fragment_parser(self): fc = XFragmentContainer(logger) x = XFragmentParser(fc, logger) x.current_filename = 'some-file' return x def _get_conf_parser(self): inetd_serv_container = InetdServiceContainer(logger) return InetdConfParser(logger, inetd_serv_container, StringIO()) class TestXFragmentParser(TestFragmentData): # test successful parsing of valid input # XXX add a test case for rpc from xinetd readme def test_success1(self): x = self._get_fragment_parser() x.parse(StringIO(TestXFragmentParser.fragment1)) fragment = self._get_first_service(x, service) self.assertEqual(fragment['disable'], 'yes') self.assertEqual(fragment['type'], 'INTERNAL') self.assertEqual(fragment['id'], 'ftpd-ssl-stream') self.assertEqual(fragment['socket_type'], 'stream') self.assertEqual(fragment['protocol'], 'tcp') self.assertEqual(fragment['user'], 'root') self.assertEqual(fragment['wait'], 'no') self.assertEqual(fragment['server_args'], '-d') # test exception throwing for invalid input def test_missing_opening_brace(self): x = self._get_fragment_parser() f = StringIO(TestXFragmentParser.fragment1.replace('{', '')) self.assertRaises(InvalidEntryException, x.parse, f) def test_missing_closing_brace(self): x = self._get_fragment_parser() f = StringIO(TestXFragmentParser.fragment1.replace('}', '')) self.assertRaises(InvalidEntryException, x.parse, f) def test_typo1(self): x = self._get_fragment_parser() f = StringIO(TestXFragmentParser.fragment1.replace('}', '}a')) self.assertRaises(InvalidEntryException, x.parse, f) def test_typo2(self): x = self._get_fragment_parser() f = StringIO(TestXFragmentParser.fragment1.replace('}', '} a')) self.assertRaises(InvalidEntryException, x.parse, f) def test_missing_mandatory_field(self): x = self._get_fragment_parser() f = StringIO(TestXFragmentParser.fragment_unlisted_srv_without_protocol) self.assertRaises(MissingFieldException, x.parse, f) # convertion of xinetd fragments to /etc/inetd.conf entries def test_guessed_protocol_for_listed_service(self): x = self._get_fragment_parser() x.parse(StringIO(TestXFragmentParser.fragment_listed_srv_without_protocol)) fragment = self._get_first_service(x.container, 'ftp') self.assertEqual(fragment.to_inetd(), TestXFragmentParser.listed_srv_without_protocol) def test_success1(self): x = self._get_fragment_parser() x.parse(StringIO(TestXFragmentParser.fragment1)) fragment = self._get_first_service(x.container, 'ftpd-ssl') self.assertEqual(fragment.to_inetd(), TestXFragmentParser.result1) def test_success1(self): x = self._get_fragment_parser() x.parse(StringIO(TestXFragmentParser.tcpd_fragment)) fragment = self._get_first_service(x.container, 'nntp') self.assertEqual(fragment.to_inetd(), TestXFragmentParser.tcpd_result) class TestXFragmentContainer(TestFragmentData): def test_disable_is_no_but_non_existing_server_path(self): x = self._get_fragment_parser() x.parse(StringIO(self.finger_fragment)) self.assertEqual(x.container.get_valid_services(), []) def test_disable_is_yes_and_non_existing_server_path(self): x = self._get_fragment_parser() f = self.finger_fragment.replace('disable = no', 'disable = yes') x.parse(StringIO(self.finger_fragment)) self.assertEqual(x.container.get_valid_services(), []) # obsolete test case; we ignore the 'disable' field in fragment files # def test_existing_server_path_but_disable_is_yes(self): # x = self._get_fragment_parser() # f = self.finger_fragment.replace('disable = no', # 'disable = yes') # # set server path to something that's guaranteed to exist # f = f.replace('server = /path/to/non-existent-server', # 'server = /bin/ls') # x.parse(StringIO(f)) # self.assertEqual(x.container.get_valid_services(), []) def test_existing_server_path(self): x = self._get_fragment_parser() # set server path to something that's guaranteed to exist f = self.finger_fragment.replace( 'server = /path/to/non-existent-server', 'server = /bin/ls') x.parse(StringIO(f)) enabled_services = x.container.get_valid_services() self.assertEqual(len(enabled_services), 1) self.assertEqual(enabled_services[0].get_name(), 'finger') class TestInetdConfParser(TestFragmentData): entry1 = 'proftpd stream tcp nowait root /usr/sbin/proftpd -d' result1 = dict([ \ ['service', 'proftpd'], ['socket_type', 'stream'], ['protocol', 'tcp'], ['user', 'root'], ['wait', 'nowait'], ['server', '/usr/sbin/proftpd'], ['server_args', '-d'], ['status', InetdService.ENABLED]]) entry2 = "nntp stream tcp nowait news /usr/sbin/tcpd /usr/sbin/leafnode\n" result2 = dict([ ['service', 'nntp'], ['socket_type', 'stream'], ['protocol', 'tcp'], ['user', 'news'], ['wait', 'nowait'], ['server', '/usr/sbin/tcpd'], ['server_args', '/usr/sbin/leafnode'], ['flags', 'NAMEINARGS'], ['status', InetdService.ENABLED]]) def _get_first_service(self, container, service): self.assertTrue(len(container.all_services), 1) srv = [s for s in container.all_services if s.get_name() == service] self.assertTrue(srv) return srv[0] def test_enabled(self): p = self._get_conf_parser() p.parse_line(TestInetdConfParser.entry1, 1) result = self._get_first_service(p.container, 'proftpd') for key, expected_value in TestInetdConfParser.result1.iteritems(): self.assertEqual(result.attrs[key], expected_value) def test_user_disabled(self): p = self._get_conf_parser() p.parse_line("# %s" % TestInetdConfParser.entry1, 1) result = self._get_first_service(p.container, 'proftpd') expected_result = TestInetdConfParser.result1.copy() expected_result['status'] = InetdService.USER_DISABLED for key, expected_value in expected_result.iteritems(): self.assertEqual(result.attrs[key], expected_value) def test_maintainer_disabled(self): p = self._get_conf_parser() p.parse_line("## %s" % TestInetdConfParser.entry1, 1) result = self._get_first_service(p.container, 'proftpd') expected_result = TestInetdConfParser.result1.copy() expected_result['status'] = InetdService.MAINT_DISABLED for key, expected_value in expected_result.iteritems(): self.assertEqual(result.attrs[key], expected_value) def test_has_matching_entry(self): inetd_conf_parser = self._get_conf_parser() inetd_conf_parser.parse_line(TestInetdConfParser.entry1, 1) self.assertEqual(len(inetd_conf_parser.container.all_services), 1) fragment_parser = self._get_fragment_parser() raw_fragment = "service proftpd\n{\n %s }" % "".join(["%s = %s\n" % (k,v) for k,v in TestInetdConfParser.result1.iteritems()]) fragment_parser.parse(StringIO(raw_fragment)) self.assertEqual(len(fragment_parser.container.all_services), 1) fragment = fragment_parser.container.all_services.values()[0] self.assertTrue(inetd_conf_parser.container.has_matching_entry(fragment)) def test_has_matching_entry_with_different_srv_args(self): # same as above but with a different server argument inetd_conf_parser = self._get_conf_parser() inetd_conf_parser.parse_line(TestInetdConfParser.entry1, 1) self.assertEqual(len(inetd_conf_parser.container.all_services), 1) fragment_parser = self._get_fragment_parser() fragment_elements = TestInetdConfParser.result1.copy() fragment_elements['server_args'] = '--debug' raw_fragment = "service proftpd\n{\n %s }" % "".join(["%s = %s\n" % (k,v) for k,v in fragment_elements.iteritems()]) fragment_parser.parse(StringIO(raw_fragment)) self.assertEqual(len(fragment_parser.container.all_services), 1) fragment = fragment_parser.container.all_services.values()[0] self.assertTrue(inetd_conf_parser.container.has_matching_entry(fragment)) def test_has_matching_entry_with_tcpd(self): inetd_conf_parser = self._get_conf_parser() inetd_conf_parser.parse_line(TestInetdConfParser.entry2, 1) self.assertEqual(len(inetd_conf_parser.container.all_services), 1) fragment_parser = self._get_fragment_parser() raw_fragment = "service nntp\n{\n %s }" % "".join(["%s = %s\n" % (k,v) for k,v in TestInetdConfParser.result2.iteritems()]) fragment_parser.parse(StringIO(raw_fragment)) self.assertEqual(len(fragment_parser.container.all_services), 1) fragment = fragment_parser.container.all_services.values()[0] self.assertTrue(inetd_conf_parser.container.has_matching_entry(fragment)) if __name__ == "__main__": unittest.main() reconf-inetd-1.120603/todo.in0000644000000000000000000000023111716556262012515 0ustar do not give up entire run if just a single fragment is invalid enable system tests during build-time, once lettuce is packaged in Debian support python3 reconf-inetd-1.120603/test-data/0000755000000000000000000000000011740500603013073 5ustar reconf-inetd-1.120603/test-data/valid-fragments/0000755000000000000000000000000011612623203016156 5ustar reconf-inetd-1.120603/test-data/valid-fragments/time-stream0000644000000000000000000000217611612623203020336 0ustar # This is the configuration for the tcp/stream time service. service time { # This is for quick on or off of the service disable = yes # The next attributes are mandatory for all services id = time-stream type = INTERNAL wait = no socket_type = stream # protocol = socket type is usually enough # External services must fill out the following # user = # group = # server = # server_args = # External services not listed in /etc/services must fill out the next one # port = # RPC based services must fill out these # rpc_version = # rpc_number = # Logging options # log_type = # log_on_success = # log_on_failure = # Networking options # flags = # bind = # redirect = # v6only = # Access restrictions # only_from = # no_access = # access_times = # cps = 50 10 # instances = UNLIMITED # per_source = UNLIMITED # max_load = 0 # deny_time = 120 # mdns = yes # Environmental options # env = # passenv = # nice = 0 # umask = 022 # groups = yes # rlimit_as = # rlimit_cpu = # rlimit_data = # rlimit_rss = # rlimit_stack = # Banner options. (Banners aren't normally used) # banner = # banner_success = # banner_fail = } reconf-inetd-1.120603/test-data/valid-fragments/tcpmux-server0000644000000000000000000000227411612623203020732 0ustar # This is the configuration of the tcpmux server. It must be enabled in # order to add any other tcpmux services. service tcpmux { # This is for quick on or off of the service disable = yes # The next attributes are mandatory for all services id = tcpmux-server type = INTERNAL wait = no socket_type = stream # protocol = socket type is usually enough # External services must fill out the following # user = root # group = # server = # server_args = # External services not listed in /etc/services must fill out the next one # port = # RPC based services must fill out these # rpc_version = # rpc_number = # Logging options # log_type = # log_on_success = # log_on_failure = # Networking options # flags = # bind = # redirect = # v6only = # Access restrictions # only_from = # no_access = # access_times = # cps = 50 10 # instances = UNLIMITED # per_source = UNLIMITED # max_load = 0 # deny_time = 120 # mdns = yes # Environmental options # env = # passenv = # nice = 0 # umask = 022 # groups = yes # rlimit_as = # rlimit_cpu = # rlimit_data = # rlimit_rss = # rlimit_stack = # Banner options. (Banners aren't normally used) # banner = # banner_success = # banner_fail = } reconf-inetd-1.120603/test-data/valid-fragments/ftp-sensor0000644000000000000000000000251411612623203020203 0ustar # This is an example sensor running on the ftp port. Xinetd sensors are # a form of intrusion detection aimed at locating hosts that are trying # to access an unadvertised service. Once tripped, they are denied # access to everything until the deny_time expires. service ftp { # This is for quick on or off of the service disable = yes # The next attributes are mandatory for all services id = ftp-sensor type = INTERNAL wait = no socket_type = stream # protocol = socket type is usually enough # External services must fill out the following # user = # group = # server = # server_args = # External services not listed in /etc/services must fill out the next one # port = # RPC based services must fill out these # rpc_version = # rpc_number = # Logging options # log_type = # log_on_success = # log_on_failure = # Networking options flags = SENSOR # bind = # redirect = # v6only = # Access restrictions # only_from = # no_access = # access_times = # cps = 50 10 # instances = UNLIMITED # per_source = UNLIMITED # max_load = 0 deny_time = 120 # mdns = yes # Environmental options # env = # passenv = # nice = 0 # umask = 022 # groups = yes # rlimit_as = # rlimit_cpu = # rlimit_data = # rlimit_rss = # rlimit_stack = # Banner options. (Banners aren't normally used) # banner = # banner_success = # banner_fail = } reconf-inetd-1.120603/test-data/valid-fragments/daytime-stream0000644000000000000000000000220711612623203021027 0ustar # This is the configuration for the tcp/stream daytime service. service daytime { # This is for quick on or off of the service disable = yes # The next attributes are mandatory for all services id = daytime-stream type = INTERNAL wait = no socket_type = stream # protocol = socket type is usually enough # External services must fill out the following # user = # group = # server = # server_args = # External services not listed in /etc/services must fill out the next one # port = # RPC based services must fill out these # rpc_version = # rpc_number = # Logging options # log_type = # log_on_success = # log_on_failure = # Networking options # flags = # bind = # redirect = # v6only = # Access restrictions # only_from = # no_access = # access_times = # cps = 50 10 # instances = UNLIMITED # per_source = UNLIMITED # max_load = 0 # deny_time = 120 # mdns = yes # Environmental options # env = # passenv = # nice = 0 # umask = 022 # groups = yes # rlimit_as = # rlimit_cpu = # rlimit_data = # rlimit_rss = # rlimit_stack = # Banner options. (Banners aren't normally used) # banner = # banner_success = # banner_fail = } reconf-inetd-1.120603/test-data/valid-fragments/discard-stream0000644000000000000000000000220711612623203021004 0ustar # This is the configuration for the tcp/stream discard service. service discard { # This is for quick on or off of the service disable = yes # The next attributes are mandatory for all services id = discard-stream type = INTERNAL wait = no socket_type = stream # protocol = socket type is usually enough # External services must fill out the following # user = # group = # server = # server_args = # External services not listed in /etc/services must fill out the next one # port = # RPC based services must fill out these # rpc_version = # rpc_number = # Logging options # log_type = # log_on_success = # log_on_failure = # Networking options # flags = # bind = # redirect = # v6only = # Access restrictions # only_from = # no_access = # access_times = # cps = 50 10 # instances = UNLIMITED # per_source = UNLIMITED # max_load = 0 # deny_time = 120 # mdns = yes # Environmental options # env = # passenv = # nice = 0 # umask = 022 # groups = yes # rlimit_as = # rlimit_cpu = # rlimit_data = # rlimit_rss = # rlimit_stack = # Banner options. (Banners aren't normally used) # banner = # banner_success = # banner_fail = } reconf-inetd-1.120603/test-data/valid-fragments/discard-dgram0000644000000000000000000000220511612623203020601 0ustar # This is the configuration for the udp/dgram discard service. service discard { # This is for quick on or off of the service disable = yes # The next attributes are mandatory for all services id = discard-dgram type = INTERNAL wait = yes socket_type = dgram # protocol = socket type is usually enough # External services must fill out the following # user = # group = # server = # server_args = # External services not listed in /etc/services must fill out the next one # port = # RPC based services must fill out these # rpc_version = # rpc_number = # Logging options # log_type = # log_on_success = # log_on_failure = # Networking options # flags = # bind = # redirect = # v6only = # Access restrictions # only_from = # no_access = # access_times = # cps = 50 10 # instances = UNLIMITED # per_source = UNLIMITED # max_load = 0 # deny_time = 120 # mdns = yes # Environmental options # env = # passenv = # nice = 0 # umask = 022 # groups = yes # rlimit_as = # rlimit_cpu = # rlimit_data = # rlimit_rss = # rlimit_stack = # Banner options. (Banners aren't normally used) # banner = # banner_success = # banner_fail = } reconf-inetd-1.120603/test-data/valid-fragments/echo-dgram0000644000000000000000000000217411612623203020113 0ustar # This is the configuration for the udp/dgram echo service. service echo { # This is for quick on or off of the service disable = yes # The next attributes are mandatory for all services id = echo-dgram type = INTERNAL wait = yes socket_type = dgram # protocol = socket type is usually enough # External services must fill out the following # user = # group = # server = # server_args = # External services not listed in /etc/services must fill out the next one # port = # RPC based services must fill out these # rpc_version = # rpc_number = # Logging options # log_type = # log_on_success = # log_on_failure = # Networking options # flags = # bind = # redirect = # v6only = # Access restrictions # only_from = # no_access = # access_times = # cps = 50 10 # instances = UNLIMITED # per_source = UNLIMITED # max_load = 0 # deny_time = 120 # mdns = yes # Environmental options # env = # passenv = # nice = 0 # umask = 022 # groups = yes # rlimit_as = # rlimit_cpu = # rlimit_data = # rlimit_rss = # rlimit_stack = # Banner options. (Banners aren't normally used) # banner = # banner_success = # banner_fail = } reconf-inetd-1.120603/test-data/valid-fragments/chargen-stream0000644000000000000000000000220711612623203021002 0ustar # This is the configuration for the tcp/stream chargen service. service chargen { # This is for quick on or off of the service disable = yes # The next attributes are mandatory for all services id = chargen-stream type = INTERNAL wait = no socket_type = stream # protocol = socket type is usually enough # External services must fill out the following # user = # group = # server = # server_args = # External services not listed in /etc/services must fill out the next one # port = # RPC based services must fill out these # rpc_version = # rpc_number = # Logging options # log_type = # log_on_success = # log_on_failure = # Networking options # flags = # bind = # redirect = # v6only = # Access restrictions # only_from = # no_access = # access_times = # cps = 50 10 # instances = UNLIMITED # per_source = UNLIMITED # max_load = 0 # deny_time = 120 # mdns = yes # Environmental options # env = # passenv = # nice = 0 # umask = 022 # groups = yes # rlimit_as = # rlimit_cpu = # rlimit_data = # rlimit_rss = # rlimit_stack = # Banner options. (Banners aren't normally used) # banner = # banner_success = # banner_fail = } reconf-inetd-1.120603/test-data/valid-fragments/time-dgram0000644000000000000000000000217511612623203020134 0ustar # This is the configuration for the udp/dgram time service. service time { # This is for quick on or off of the service disable = yes # The next attributes are mandatory for all services id = time-dgram type = INTERNAL wait = yes socket_type = dgram # protocol = socket type is usually enough # External services must fill out the following # user = # group = # server = # server_args = # External services not listed in /etc/services must fill out the next one # port = # RPC based services must fill out these # rpc_version = # rpc_number = # Logging options # log_type = # log_on_success = # log_on_failure = # Networking options # flags = # bind = # redirect = # v6only = # Access restrictions # only_from = # no_access = # access_times = # cps = 50 10 # instances = UNLIMITED # per_source = UNLIMITED # max_load = 0 # deny_time = 120 # mdns = yes # Environmental options # env = # passenv = # nice = 0 # umask = 022 # groups = yes # rlimit_as = # rlimit_cpu = # rlimit_data = # rlimit_rss = # rlimit_stack = # Banner options. (Banners aren't normally used) # banner = # banner_success = # banner_fail = } reconf-inetd-1.120603/test-data/valid-fragments/chargen-dgram0000644000000000000000000000220511612623203020577 0ustar # This is the configuration for the udp/dgram chargen service. service chargen { # This is for quick on or off of the service disable = yes # The next attributes are mandatory for all services id = chargen-dgram type = INTERNAL wait = yes socket_type = dgram # protocol = socket type is usually enough # External services must fill out the following # user = # group = # server = # server_args = # External services not listed in /etc/services must fill out the next one # port = # RPC based services must fill out these # rpc_version = # rpc_number = # Logging options # log_type = # log_on_success = # log_on_failure = # Networking options # flags = # bind = # redirect = # v6only = # Access restrictions # only_from = # no_access = # access_times = # cps = 50 10 # instances = UNLIMITED # per_source = UNLIMITED # max_load = 0 # deny_time = 120 # mdns = yes # Environmental options # env = # passenv = # nice = 0 # umask = 022 # groups = yes # rlimit_as = # rlimit_cpu = # rlimit_data = # rlimit_rss = # rlimit_stack = # Banner options. (Banners aren't normally used) # banner = # banner_success = # banner_fail = } reconf-inetd-1.120603/test-data/valid-fragments/echo-stream0000644000000000000000000000217611612623203020316 0ustar # This is the configuration for the tcp/stream echo service. service echo { # This is for quick on or off of the service disable = yes # The next attributes are mandatory for all services id = echo-stream type = INTERNAL wait = no socket_type = stream # protocol = socket type is usually enough # External services must fill out the following # user = # group = # server = # server_args = # External services not listed in /etc/services must fill out the next one # port = # RPC based services must fill out these # rpc_version = # rpc_number = # Logging options # log_type = # log_on_success = # log_on_failure = # Networking options # flags = # bind = # redirect = # v6only = # Access restrictions # only_from = # no_access = # access_times = # cps = 50 10 # instances = UNLIMITED # per_source = UNLIMITED # max_load = 0 # deny_time = 120 # mdns = yes # Environmental options # env = # passenv = # nice = 0 # umask = 022 # groups = yes # rlimit_as = # rlimit_cpu = # rlimit_data = # rlimit_rss = # rlimit_stack = # Banner options. (Banners aren't normally used) # banner = # banner_success = # banner_fail = } reconf-inetd-1.120603/test-data/valid-fragments/daytime-dgram0000644000000000000000000000220511612623203020624 0ustar # This is the configuration for the udp/dgram daytime service. service daytime { # This is for quick on or off of the service disable = yes # The next attributes are mandatory for all services id = daytime-dgram type = INTERNAL wait = yes socket_type = dgram # protocol = socket type is usually enough # External services must fill out the following # user = # group = # server = # server_args = # External services not listed in /etc/services must fill out the next one # port = # RPC based services must fill out these # rpc_version = # rpc_number = # Logging options # log_type = # log_on_success = # log_on_failure = # Networking options # flags = # bind = # redirect = # v6only = # Access restrictions # only_from = # no_access = # access_times = # cps = 50 10 # instances = UNLIMITED # per_source = UNLIMITED # max_load = 0 # deny_time = 120 # mdns = yes # Environmental options # env = # passenv = # nice = 0 # umask = 022 # groups = yes # rlimit_as = # rlimit_cpu = # rlimit_data = # rlimit_rss = # rlimit_stack = # Banner options. (Banners aren't normally used) # banner = # banner_success = # banner_fail = } reconf-inetd-1.120603/test-data/services0000644000000000000000000004552111713620314014652 0ustar # Network services, Internet style # # Note that it is presently the policy of IANA to assign a single well-known # port number for both TCP and UDP; hence, officially ports have two entries # even if the protocol doesn't support UDP operations. # # Updated from http://www.iana.org/assignments/port-numbers and other # sources like http://www.freebsd.org/cgi/cvsweb.cgi/src/etc/services . # New ports will be added on request if they have been officially assigned # by IANA and used in the real-world or are needed by a debian package. # If you need a huge list of used numbers please install the nmap package. tcpmux 1/tcp # TCP port service multiplexer echo 7/tcp echo 7/udp discard 9/tcp sink null discard 9/udp sink null systat 11/tcp users daytime 13/tcp daytime 13/udp netstat 15/tcp qotd 17/tcp quote msp 18/tcp # message send protocol msp 18/udp chargen 19/tcp ttytst source chargen 19/udp ttytst source ftp-data 20/tcp ftp 21/tcp fsp 21/udp fspd ssh 22/tcp # SSH Remote Login Protocol ssh 22/udp telnet 23/tcp smtp 25/tcp mail time 37/tcp timserver time 37/udp timserver rlp 39/udp resource # resource location nameserver 42/tcp name # IEN 116 whois 43/tcp nicname tacacs 49/tcp # Login Host Protocol (TACACS) tacacs 49/udp re-mail-ck 50/tcp # Remote Mail Checking Protocol re-mail-ck 50/udp domain 53/tcp # Domain Name Server domain 53/udp mtp 57/tcp # deprecated tacacs-ds 65/tcp # TACACS-Database Service tacacs-ds 65/udp bootps 67/tcp # BOOTP server bootps 67/udp bootpc 68/tcp # BOOTP client bootpc 68/udp tftp 69/udp gopher 70/tcp # Internet Gopher gopher 70/udp rje 77/tcp netrjs finger 79/tcp http 80/tcp www # WorldWideWeb HTTP http 80/udp # HyperText Transfer Protocol link 87/tcp ttylink kerberos 88/tcp kerberos5 krb5 kerberos-sec # Kerberos v5 kerberos 88/udp kerberos5 krb5 kerberos-sec # Kerberos v5 supdup 95/tcp hostnames 101/tcp hostname # usually from sri-nic iso-tsap 102/tcp tsap # part of ISODE acr-nema 104/tcp dicom # Digital Imag. & Comm. 300 acr-nema 104/udp dicom csnet-ns 105/tcp cso-ns # also used by CSO name server csnet-ns 105/udp cso-ns rtelnet 107/tcp # Remote Telnet rtelnet 107/udp pop2 109/tcp postoffice pop-2 # POP version 2 pop2 109/udp pop-2 pop3 110/tcp pop-3 # POP version 3 pop3 110/udp pop-3 sunrpc 111/tcp portmapper # RPC 4.0 portmapper sunrpc 111/udp portmapper auth 113/tcp authentication tap ident sftp 115/tcp uucp-path 117/tcp nntp 119/tcp readnews untp # USENET News Transfer Protocol ntp 123/tcp ntp 123/udp # Network Time Protocol pwdgen 129/tcp # PWDGEN service pwdgen 129/udp loc-srv 135/tcp epmap # Location Service loc-srv 135/udp epmap netbios-ns 137/tcp # NETBIOS Name Service netbios-ns 137/udp netbios-dgm 138/tcp # NETBIOS Datagram Service netbios-dgm 138/udp netbios-ssn 139/tcp # NETBIOS session service netbios-ssn 139/udp imap2 143/tcp imap # Interim Mail Access P 2 and 4 imap2 143/udp imap snmp 161/tcp # Simple Net Mgmt Protocol snmp 161/udp snmp-trap 162/tcp snmptrap # Traps for SNMP snmp-trap 162/udp snmptrap cmip-man 163/tcp # ISO mgmt over IP (CMOT) cmip-man 163/udp cmip-agent 164/tcp cmip-agent 164/udp mailq 174/tcp # Mailer transport queue for Zmailer mailq 174/udp xdmcp 177/tcp # X Display Mgr. Control Proto xdmcp 177/udp nextstep 178/tcp NeXTStep NextStep # NeXTStep window nextstep 178/udp NeXTStep NextStep # server bgp 179/tcp # Border Gateway Protocol bgp 179/udp prospero 191/tcp # Cliff Neuman's Prospero prospero 191/udp irc 194/tcp # Internet Relay Chat irc 194/udp smux 199/tcp # SNMP Unix Multiplexer smux 199/udp at-rtmp 201/tcp # AppleTalk routing at-rtmp 201/udp at-nbp 202/tcp # AppleTalk name binding at-nbp 202/udp at-echo 204/tcp # AppleTalk echo at-echo 204/udp at-zis 206/tcp # AppleTalk zone information at-zis 206/udp qmtp 209/tcp # Quick Mail Transfer Protocol qmtp 209/udp z3950 210/tcp wais # NISO Z39.50 database z3950 210/udp wais ipx 213/tcp # IPX ipx 213/udp imap3 220/tcp # Interactive Mail Access imap3 220/udp # Protocol v3 pawserv 345/tcp # Perf Analysis Workbench pawserv 345/udp zserv 346/tcp # Zebra server zserv 346/udp fatserv 347/tcp # Fatmen Server fatserv 347/udp rpc2portmap 369/tcp rpc2portmap 369/udp # Coda portmapper codaauth2 370/tcp codaauth2 370/udp # Coda authentication server clearcase 371/tcp Clearcase clearcase 371/udp Clearcase ulistserv 372/tcp # UNIX Listserv ulistserv 372/udp ldap 389/tcp # Lightweight Directory Access Protocol ldap 389/udp imsp 406/tcp # Interactive Mail Support Protocol imsp 406/udp svrloc 427/tcp # Server Location svrloc 427/udp https 443/tcp # http protocol over TLS/SSL https 443/udp snpp 444/tcp # Simple Network Paging Protocol snpp 444/udp microsoft-ds 445/tcp # Microsoft Naked CIFS microsoft-ds 445/udp kpasswd 464/tcp kpasswd 464/udp saft 487/tcp # Simple Asynchronous File Transfer saft 487/udp isakmp 500/tcp # IPsec - Internet Security Association isakmp 500/udp # and Key Management Protocol rtsp 554/tcp # Real Time Stream Control Protocol rtsp 554/udp nqs 607/tcp # Network Queuing system nqs 607/udp npmp-local 610/tcp dqs313_qmaster # npmp-local / DQS npmp-local 610/udp dqs313_qmaster npmp-gui 611/tcp dqs313_execd # npmp-gui / DQS npmp-gui 611/udp dqs313_execd hmmp-ind 612/tcp dqs313_intercell # HMMP Indication / DQS hmmp-ind 612/udp dqs313_intercell qmqp 628/tcp qmqp 628/udp ipp 631/tcp # Internet Printing Protocol ipp 631/udp # # UNIX specific services # exec 512/tcp biff 512/udp comsat login 513/tcp who 513/udp whod shell 514/tcp cmd # no passwords used syslog 514/udp printer 515/tcp spooler # line printer spooler talk 517/udp ntalk 518/udp route 520/udp router routed # RIP timed 525/udp timeserver tempo 526/tcp newdate courier 530/tcp rpc conference 531/tcp chat netnews 532/tcp readnews netwall 533/udp # for emergency broadcasts gdomap 538/tcp # GNUstep distributed objects gdomap 538/udp uucp 540/tcp uucpd # uucp daemon klogin 543/tcp # Kerberized `rlogin' (v5) kshell 544/tcp krcmd # Kerberized `rsh' (v5) dhcpv6-client 546/tcp dhcpv6-client 546/udp dhcpv6-server 547/tcp dhcpv6-server 547/udp afpovertcp 548/tcp # AFP over TCP afpovertcp 548/udp idfp 549/tcp idfp 549/udp remotefs 556/tcp rfs_server rfs # Brunhoff remote filesystem nntps 563/tcp snntp # NNTP over SSL nntps 563/udp snntp submission 587/tcp # Submission [RFC4409] submission 587/udp ldaps 636/tcp # LDAP over SSL ldaps 636/udp tinc 655/tcp # tinc control port tinc 655/udp silc 706/tcp silc 706/udp kerberos-adm 749/tcp # Kerberos `kadmin' (v5) # webster 765/tcp # Network dictionary webster 765/udp rsync 873/tcp rsync 873/udp ftps-data 989/tcp # FTP over SSL (data) ftps 990/tcp telnets 992/tcp # Telnet over SSL telnets 992/udp imaps 993/tcp # IMAP over SSL imaps 993/udp ircs 994/tcp # IRC over SSL ircs 994/udp pop3s 995/tcp # POP-3 over SSL pop3s 995/udp # # From ``Assigned Numbers'': # #> The Registered Ports are not controlled by the IANA and on most systems #> can be used by ordinary user processes or programs executed by ordinary #> users. # #> Ports are used in the TCP [45,106] to name the ends of logical #> connections which carry long term conversations. For the purpose of #> providing services to unknown callers, a service contact port is #> defined. This list specifies the port used by the server process as its #> contact port. While the IANA can not control uses of these ports it #> does register or list uses of these ports as a convienence to the #> community. # socks 1080/tcp # socks proxy server socks 1080/udp proofd 1093/tcp proofd 1093/udp rootd 1094/tcp rootd 1094/udp openvpn 1194/tcp openvpn 1194/udp rmiregistry 1099/tcp # Java RMI Registry rmiregistry 1099/udp kazaa 1214/tcp kazaa 1214/udp nessus 1241/tcp # Nessus vulnerability nessus 1241/udp # assessment scanner lotusnote 1352/tcp lotusnotes # Lotus Note lotusnote 1352/udp lotusnotes ms-sql-s 1433/tcp # Microsoft SQL Server ms-sql-s 1433/udp ms-sql-m 1434/tcp # Microsoft SQL Monitor ms-sql-m 1434/udp ingreslock 1524/tcp ingreslock 1524/udp prospero-np 1525/tcp # Prospero non-privileged prospero-np 1525/udp datametrics 1645/tcp old-radius datametrics 1645/udp old-radius sa-msg-port 1646/tcp old-radacct sa-msg-port 1646/udp old-radacct kermit 1649/tcp kermit 1649/udp groupwise 1677/tcp groupwise 1677/udp l2f 1701/tcp l2tp l2f 1701/udp l2tp radius 1812/tcp radius 1812/udp radius-acct 1813/tcp radacct # Radius Accounting radius-acct 1813/udp radacct msnp 1863/tcp # MSN Messenger msnp 1863/udp unix-status 1957/tcp # remstats unix-status server log-server 1958/tcp # remstats log server remoteping 1959/tcp # remstats remoteping server cisco-sccp 2000/tcp # Cisco SCCP cisco-sccp 2000/udp search 2010/tcp ndtp pipe-server 2010/tcp pipe_server nfs 2049/tcp # Network File System nfs 2049/udp # Network File System gnunet 2086/tcp gnunet 2086/udp rtcm-sc104 2101/tcp # RTCM SC-104 IANA 1/29/99 rtcm-sc104 2101/udp gsigatekeeper 2119/tcp gsigatekeeper 2119/udp gris 2135/tcp # Grid Resource Information Server gris 2135/udp cvspserver 2401/tcp # CVS client/server operations cvspserver 2401/udp venus 2430/tcp # codacon port venus 2430/udp # Venus callback/wbc interface venus-se 2431/tcp # tcp side effects venus-se 2431/udp # udp sftp side effect codasrv 2432/tcp # not used codasrv 2432/udp # server port codasrv-se 2433/tcp # tcp side effects codasrv-se 2433/udp # udp sftp side effect mon 2583/tcp # MON traps mon 2583/udp dict 2628/tcp # Dictionary server dict 2628/udp f5-globalsite 2792/tcp f5-globalsite 2792/udp gsiftp 2811/tcp gsiftp 2811/udp gpsd 2947/tcp gpsd 2947/udp gds-db 3050/tcp gds_db # InterBase server gds-db 3050/udp gds_db icpv2 3130/tcp icp # Internet Cache Protocol icpv2 3130/udp icp mysql 3306/tcp mysql 3306/udp nut 3493/tcp # Network UPS Tools nut 3493/udp distcc 3632/tcp # distributed compiler distcc 3632/udp daap 3689/tcp # Digital Audio Access Protocol daap 3689/udp svn 3690/tcp subversion # Subversion protocol svn 3690/udp subversion suucp 4031/tcp # UUCP over SSL suucp 4031/udp sysrqd 4094/tcp # sysrq daemon sysrqd 4094/udp sieve 4190/tcp # ManageSieve Protocol epmd 4369/tcp # Erlang Port Mapper Daemon epmd 4369/udp remctl 4373/tcp # Remote Authenticated Command Service remctl 4373/udp f5-iquery 4353/tcp # F5 iQuery f5-iquery 4353/udp iax 4569/tcp # Inter-Asterisk eXchange iax 4569/udp mtn 4691/tcp # monotone Netsync Protocol mtn 4691/udp radmin-port 4899/tcp # RAdmin Port radmin-port 4899/udp rfe 5002/udp # Radio Free Ethernet rfe 5002/tcp mmcc 5050/tcp # multimedia conference control tool (Yahoo IM) mmcc 5050/udp sip 5060/tcp # Session Initiation Protocol sip 5060/udp sip-tls 5061/tcp sip-tls 5061/udp aol 5190/tcp # AIM aol 5190/udp xmpp-client 5222/tcp jabber-client # Jabber Client Connection xmpp-client 5222/udp jabber-client xmpp-server 5269/tcp jabber-server # Jabber Server Connection xmpp-server 5269/udp jabber-server cfengine 5308/tcp cfengine 5308/udp mdns 5353/tcp # Multicast DNS mdns 5353/udp postgresql 5432/tcp postgres # PostgreSQL Database postgresql 5432/udp postgres freeciv 5556/tcp rptp # Freeciv gameplay freeciv 5556/udp amqp 5672/tcp amqp 5672/udp amqp 5672/sctp ggz 5688/tcp # GGZ Gaming Zone ggz 5688/udp x11 6000/tcp x11-0 # X Window System x11 6000/udp x11-0 x11-1 6001/tcp x11-1 6001/udp x11-2 6002/tcp x11-2 6002/udp x11-3 6003/tcp x11-3 6003/udp x11-4 6004/tcp x11-4 6004/udp x11-5 6005/tcp x11-5 6005/udp x11-6 6006/tcp x11-6 6006/udp x11-7 6007/tcp x11-7 6007/udp gnutella-svc 6346/tcp # gnutella gnutella-svc 6346/udp gnutella-rtr 6347/tcp # gnutella gnutella-rtr 6347/udp sge-qmaster 6444/tcp sge_qmaster # Grid Engine Qmaster Service sge-qmaster 6444/udp sge_qmaster sge-execd 6445/tcp sge_execd # Grid Engine Execution Service sge-execd 6445/udp sge_execd mysql-proxy 6446/tcp # MySQL Proxy mysql-proxy 6446/udp afs3-fileserver 7000/tcp bbs # file server itself afs3-fileserver 7000/udp bbs afs3-callback 7001/tcp # callbacks to cache managers afs3-callback 7001/udp afs3-prserver 7002/tcp # users & groups database afs3-prserver 7002/udp afs3-vlserver 7003/tcp # volume location database afs3-vlserver 7003/udp afs3-kaserver 7004/tcp # AFS/Kerberos authentication afs3-kaserver 7004/udp afs3-volser 7005/tcp # volume managment server afs3-volser 7005/udp afs3-errors 7006/tcp # error interpretation service afs3-errors 7006/udp afs3-bos 7007/tcp # basic overseer process afs3-bos 7007/udp afs3-update 7008/tcp # server-to-server updater afs3-update 7008/udp afs3-rmtsys 7009/tcp # remote cache manager service afs3-rmtsys 7009/udp font-service 7100/tcp xfs # X Font Service font-service 7100/udp xfs http-alt 8080/tcp webcache # WWW caching service http-alt 8080/udp bacula-dir 9101/tcp # Bacula Director bacula-dir 9101/udp bacula-fd 9102/tcp # Bacula File Daemon bacula-fd 9102/udp bacula-sd 9103/tcp # Bacula Storage Daemon bacula-sd 9103/udp xmms2 9667/tcp # Cross-platform Music Multiplexing System xmms2 9667/udp nbd 10809/tcp # Linux Network Block Device zabbix-agent 10050/tcp # Zabbix Agent zabbix-agent 10050/udp zabbix-trapper 10051/tcp # Zabbix Trapper zabbix-trapper 10051/udp amanda 10080/tcp # amanda backup services amanda 10080/udp hkp 11371/tcp # OpenPGP HTTP Keyserver hkp 11371/udp bprd 13720/tcp # VERITAS NetBackup bprd 13720/udp bpdbm 13721/tcp # VERITAS NetBackup bpdbm 13721/udp bpjava-msvc 13722/tcp # BP Java MSVC Protocol bpjava-msvc 13722/udp vnetd 13724/tcp # Veritas Network Utility vnetd 13724/udp bpcd 13782/tcp # VERITAS NetBackup bpcd 13782/udp vopied 13783/tcp # VERITAS NetBackup vopied 13783/udp dcap 22125/tcp # dCache Access Protocol gsidcap 22128/tcp # GSI dCache Access Protocol wnn6 22273/tcp # wnn6 wnn6 22273/udp # # Datagram Delivery Protocol services # rtmp 1/ddp # Routing Table Maintenance Protocol nbp 2/ddp # Name Binding Protocol echo 4/ddp # AppleTalk Echo Protocol zip 6/ddp # Zone Information Protocol #========================================================================= # The remaining port numbers are not as allocated by IANA. #========================================================================= # Kerberos (Project Athena/MIT) services # Note that these are for Kerberos v4, and are unofficial. Sites running # v4 should uncomment these and comment out the v5 entries above. # kerberos4 750/udp kerberos-iv kdc # Kerberos (server) kerberos4 750/tcp kerberos-iv kdc kerberos-master 751/udp kerberos_master # Kerberos authentication kerberos-master 751/tcp passwd-server 752/udp passwd_server # Kerberos passwd server krb-prop 754/tcp krb_prop krb5_prop hprop # Kerberos slave propagation krbupdate 760/tcp kreg # Kerberos registration swat 901/tcp # swat kpop 1109/tcp # Pop with Kerberos knetd 2053/tcp # Kerberos de-multiplexor zephyr-srv 2102/udp # Zephyr server zephyr-clt 2103/udp # Zephyr serv-hm connection zephyr-hm 2104/udp # Zephyr hostmanager eklogin 2105/tcp # Kerberos encrypted rlogin # Hmmm. Are we using Kv4 or Kv5 now? Worrying. # The following is probably Kerberos v5 --- ajt@debian.org (11/02/2000) kx 2111/tcp # X over Kerberos iprop 2121/tcp # incremental propagation # # Unofficial but necessary (for NetBSD) services # supfilesrv 871/tcp # SUP server supfiledbg 1127/tcp # SUP debugging # # Services added for the Debian GNU/Linux distribution # linuxconf 98/tcp # LinuxConf poppassd 106/tcp # Eudora poppassd 106/udp ssmtp 465/tcp smtps # SMTP over SSL moira-db 775/tcp moira_db # Moira database moira-update 777/tcp moira_update # Moira update protocol moira-ureg 779/udp moira_ureg # Moira user registration spamd 783/tcp # spamassassin daemon omirr 808/tcp omirrd # online mirror omirr 808/udp omirrd customs 1001/tcp # pmake customs server customs 1001/udp skkserv 1178/tcp # skk jisho server port predict 1210/udp # predict -- satellite tracking rmtcfg 1236/tcp # Gracilis Packeten remote config server wipld 1300/tcp # Wipl network monitor xtel 1313/tcp # french minitel xtelw 1314/tcp # french minitel support 1529/tcp # GNATS cfinger 2003/tcp # GNU Finger frox 2121/tcp # frox: caching ftp proxy ninstall 2150/tcp # ninstall service ninstall 2150/udp zebrasrv 2600/tcp # zebra service zebra 2601/tcp # zebra vty ripd 2602/tcp # ripd vty (zebra) ripngd 2603/tcp # ripngd vty (zebra) ospfd 2604/tcp # ospfd vty (zebra) bgpd 2605/tcp # bgpd vty (zebra) ospf6d 2606/tcp # ospf6d vty (zebra) ospfapi 2607/tcp # OSPF-API isisd 2608/tcp # ISISd vty (zebra) afbackup 2988/tcp # Afbackup system afbackup 2988/udp afmbackup 2989/tcp # Afmbackup system afmbackup 2989/udp xtell 4224/tcp # xtell server fax 4557/tcp # FAX transmission service (old) hylafax 4559/tcp # HylaFAX client-server protocol (new) distmp3 4600/tcp # distmp3host daemon munin 4949/tcp lrrd # Munin enbd-cstatd 5051/tcp # ENBD client statd enbd-sstatd 5052/tcp # ENBD server statd pcrd 5151/tcp # PCR-1000 Daemon noclog 5354/tcp # noclogd with TCP (nocol) noclog 5354/udp # noclogd with UDP (nocol) hostmon 5355/tcp # hostmon uses TCP (nocol) hostmon 5355/udp # hostmon uses UDP (nocol) rplay 5555/udp # RPlay audio service nrpe 5666/tcp # Nagios Remote Plugin Executor nsca 5667/tcp # Nagios Agent - NSCA mrtd 5674/tcp # MRT Routing Daemon bgpsim 5675/tcp # MRT Routing Simulator canna 5680/tcp # cannaserver sane-port 6566/tcp sane saned # SANE network scanner daemon ircd 6667/tcp # Internet Relay Chat zope-ftp 8021/tcp # zope management by ftp tproxy 8081/tcp # Transparent Proxy omniorb 8088/tcp # OmniORB omniorb 8088/udp clc-build-daemon 8990/tcp # Common lisp build daemon xinetd 9098/tcp mandelspawn 9359/udp mandelbrot # network mandelbrot git 9418/tcp # Git Version Control System zope 9673/tcp # zope server webmin 10000/tcp kamanda 10081/tcp # amanda backup services (Kerberos) kamanda 10081/udp amandaidx 10082/tcp # amanda backup services amidxtape 10083/tcp # amanda backup services smsqp 11201/tcp # Alamin SMS gateway smsqp 11201/udp xpilot 15345/tcp # XPilot Contact Port xpilot 15345/udp sgi-cmsd 17001/udp # Cluster membership services daemon sgi-crsd 17002/udp sgi-gcd 17003/udp # SGI Group membership daemon sgi-cad 17004/tcp # Cluster Admin daemon isdnlog 20011/tcp # isdn logging system isdnlog 20011/udp vboxd 20012/tcp # voice box system vboxd 20012/udp binkp 24554/tcp # binkp fidonet protocol asp 27374/tcp # Address Search Protocol asp 27374/udp csync2 30865/tcp # cluster synchronization tool dircproxy 57000/tcp # Detachable IRC Proxy tfido 60177/tcp # fidonet EMSI over telnet fido 60179/tcp # fidonet EMSI over TCP # Local services reconf-inetd-1.120603/test-data/invalid-fragments/0000755000000000000000000000000011612623203016505 5ustar reconf-inetd-1.120603/test-data/invalid-fragments/chargen-dgram-missing-closing-brace0000644000000000000000000000031611612623203025304 0ustar service chargen { # This is for quick on or off of the service disable = yes # The next attributes are mandatory for all services id = chargen-dgram type = INTERNAL wait = yes socket_type = dgram reconf-inetd-1.120603/test-data/invalid-fragments/chargen-dgram-missing-required-key0000644000000000000000000000033211612623203025200 0ustar service chargen { # This is for quick on or off of the service disable = yes # The next attributes are mandatory for all services id = chargen-dgram type = INTERNAL # protocol = socket type is usually enough } reconf-inetd-1.120603/test-data/existing-frags0000644000000000000000000000131511612623203015750 0ustar /home/sez/git/misc/update-inetd-rdepends/pysieved-1.0/contrib/pysieved.xinetd /home/sez/git/misc/update-inetd-rdepends/midentd-2.3.1/midentd.xinetd /home/sez/git/misc/update-inetd-rdepends/bsd-finger-0.17/debian/local/finger.xinetd /home/sez/git/misc/update-inetd-rdepends/xinetd-2.3.14/contrib/xinetd.conf /home/sez/git/misc/update-inetd-rdepends/cfingerd-1.4.3/debian/cfingerd.xinetd /home/sez/git/misc/update-inetd-rdepends/samba-3.5.4~dfsg/packaging/LSB/samba.xinetd /home/sez/git/misc/update-inetd-rdepends/gnats-4.1.0/debian/gnats.xinetd.in /home/sez/git/misc/update-inetd-rdepends/amanda-3.1.0/example/xinetd.amandaclient.in /home/sez/git/misc/update-inetd-rdepends/amanda-3.1.0/example/xinetd.amandaserver.in