<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta name="generator" content="HTML Tidy, see www.w3.org">
<title>RFC 1179 - Line Printer Daemon Protocol</title>
<meta name="GENERATOR" content=
"Modular DocBook HTML Stylesheet Version 1.7">
<link rel="HOME" title=" LPRng Reference Manual" href=
"index.htm">
<link rel="PREVIOUS" title="LPRng accounting.pl Utility" href=
"x9886.htm">
<link rel="NEXT" title="Protocol Requests and Replies " href=
"remotesupport.htm">
</head>
<body class="CHAPTER" bgcolor="#FFFFFF" text="#000000" link=
"#0000FF" vlink="#840084" alink="#0000FF">
<div class="NAVHEADER">
<table summary="Header navigation table" width="100%" border=
"0" cellpadding="0" cellspacing="0">
<tr>
<th colspan="3" align="center">LPRng Reference Manual: 24
Sep 2004 (For LPRng-3.8.28)</th>
</tr>
<tr>
<td width="10%" align="left" valign="bottom"><a href=
"x9886.htm" accesskey="P">Prev</a></td>
<td width="80%" align="center" valign="bottom">
</td>
<td width="10%" align="right" valign="bottom"><a href=
"remotesupport.htm" accesskey="N">Next</a></td>
</tr>
</table>
<hr align="LEFT" width="100%">
</div>
<div class="CHAPTER">
<h1><a name="RFC1179REF"></a>Chapter 19. RFC 1179 - Line
Printer Daemon Protocol</h1>
<div class="TOC">
<dl>
<dt><b>Table of Contents</b></dt>
<dt>19.1. <a href="rfc1179ref.htm#LPDPORT">Ports and
Connections</a></dt>
<dt>19.2. <a href="remotesupport.htm">Protocol Requests
and Replies</a></dt>
<dt>19.3. <a href="jobtransfer.htm">Job Transfer</a></dt>
<dt>19.4. <a href="x10290.htm">Data File
Transfer</a></dt>
<dt>19.5. <a href="x10326.htm">Control File
Contents</a></dt>
<dt>19.6. <a href="x10529.htm"><b class=
"APPLICATION">lpq</b> Requests</a></dt>
<dt>19.7. <a href="x10552.htm"><b class=
"APPLICATION">lprm</b> Requests</a></dt>
<dt>19.8. <a href="lpcreread.htm">LPC Requests</a></dt>
<dt>19.9. <a href="sendblockformat.htm">Block Job
Transfer</a></dt>
<dt>19.10. <a href="x10755.htm">Authenticated
Transfer</a></dt>
</dl>
</div>
<p>RFC1179 can be obtained from the <b class=
"APPLICATION">LPRng</b> distribution, in the
LPRng_DOC/rfc1179 directory, or from one of many sites which
mirror the RFCs.</p>
<p>This RFC is an <span class="emphasis"><i class=
"EMPHASIS">informational</i></span> RFC, which means that the
information in it is meant as a guide to users, and not as a
fixed standard. In addition, the RFC tried to document the
behavior of the BSD <b class="APPLICATION">lpd</b> print
server, and left out many details dealing with error recover,
error messages, extensions to the protocol, etc.</p>
<p>In this section, I will try to explain what RFC1179
specifies as a protocol, and many of the problems encountered
in trying to use it.</p>
<div class="SECT1">
<h1 class="SECT1"><a name="LPDPORT">19.1. Ports and
Connections</a></h1>
<p>Options used:</p>
<ul>
<li>
<p><var class="LITERAL">lpd_port=</var><span class=
"emphasis"><i class="EMPHASIS">Port for <b class=
"APPLICATION">lpd</b> connections</i></span></p>
</li>
<li>
<p><var class="LITERAL">lpd_listen_port=</var><span
class="emphasis"><i class="EMPHASIS">Port for <b class=
"APPLICATION">lpd</b> to accept
connection</i></span></p>
</li>
<li>
<p><var class="LITERAL">originate_port=</var><span
class="emphasis"><i class="EMPHASIS">Ports to originate
connections on</i></span></p>
</li>
<li>
<p><var class="LITERAL">reuse_addr</var> FLAG <span
class="emphasis"><i class="EMPHASIS">Set SO_REUSEADDR
flag on connection</i></span></p>
</li>
<li>
<p><var class="LITERAL">retry_econnrefused</var> FLAG
<span class="emphasis"><i class="EMPHASIS">Retry on
connect ECONNREFUSED error</i></span></p>
</li>
<li>
<p><var class="LITERAL">retry_nolink</var> FLAG <span
class="emphasis"><i class="EMPHASIS">Retry on device
open or connection ffailure</i></span></p>
</li>
<li>
<p><var class="LITERAL">unix_socket_path</var> PATH
<span class="emphasis"><i class="EMPHASIS">UNIX FIFO
pathname for local connections</i></span></p>
</li>
<li>
<p><var class="LITERAL">socket_linger=</var><span
class="emphasis"><i class="EMPHASIS">socket linger
timeout</i></span></p>
</li>
</ul>
<br>
<br>
<p>RFC1179 requires that the <b class="APPLICATION">lpd</b>
server listen for TCP/IP connections on port 515. This port
is registered with the Internet Naming Authority, and the
<tt class="FILENAME">/etc/services</tt> file or TCP/IP
services database usually has an entry:</p>
<div class="INFORMALEXAMPLE">
<a name="AEN9979"></a>
<pre class="SCREEN">
printer 515/tcp spooler # line printer spooler
</pre>
</div>
<br>
<br>
<p>RFC1179 explicitly states that all connections to port
515 must originate from ports 721-731. The reason for this
restriction is due to the UNIX concept of <span class=
"emphasis"><i class="EMPHASIS">reserved</i></span> and
<span class="emphasis"><i class=
"EMPHASIS">privileged</i></span> ports. By convention,
ports in the range 1-1023 can only <span class=
"emphasis"><i class="EMPHASIS">bound</i></span> by
processes whose Effective User ID (EUID) is 0 (root). This,
ordinary users could not originate a connection from the
reserved or privileged port range.</p>
<p>In a UNIX environment, this means that the user programs
<b class="APPLICATION">lpr</b>, <b class=
"APPLICATION">lpq</b>, <b class="APPLICATION">lprm</b>, and
<b class="APPLICATION">lpc</b> would have to be SETUID
root.</p>
<p>As experience has shown, for security purposes, the
fewer programs that need to have privileged status, the
better. <b class="APPLICATION">LPRng</b> uses the <var
class="LITERAL">lpd_port=printer</var> configuration option
to set the port for the connections to a <b class=
"APPLICATION">lpd</b> server. By default, this is port 515,
but can be set to other values. This port value is used to
make connections to a remote <b class="APPLICATION">lpd</b>
server. The <var class=
"LITERAL">lpd_listen_port=printer</var> configuration
option can be used to specify a port for the <b class=
"APPLICATION">lpd</b> to listen for incoming requests. If
no <var class="LITERAL">lpd_listen_port</var> value is
specified the <var class="LITERAL">lpd_port</var> value
will be used as the <b class="APPLICATION">lpd</b>
listening port.</p>
<p>The <var class="LITERAL">unix_socket_path</var> option
specifies the pathname of a UNIX FIFO or socket that can be
used for connections the <b class="APPLICATION">lpd</b>
server if the client and server are on the same host. The
use of a local FIFO restricts connections from outside
hosts. The UNIX FIFO path should be to a node in a
directory that is writable by by the <b class=
"APPLICATION">lpd</b> server and not other non-privileged
processes.</p>
<p>The restriction of originating ports to 721-731 causes
another set of problems. Part of the TCP/IP protocol is
concerned with avoiding communications problems resulting
from the arrival of old or <span class="emphasis"><i class=
"EMPHASIS">stale</i></span> packets. When a connection
between <var class="LITERAL">sourcehost, sourceport</var>
and <var class="LITERAL">desthost, destport</var> is made,
a set of sequence numbers is established and used for
sending and acknowledgement of data. When the connection
terminates, the TCP/IP protocol restricts the establishment
of a new connection between <var class=
"LITERAL">sourcehost, sourceport</var> and <var class=
"LITERAL">desthost, destport</var> for a period long enough
for all <span class="emphasis"><i class=
"EMPHASIS">stale</i></span> packets to be removed from the
system. This is approximately 10 minutes long.</p>
<p>In order to simplify assignments of ports, timing out
connections, and other matters, many TCP/IP packages do
keep track of explicit connections <span class=
"emphasis"><i class="EMPHASIS">originating</i></span> from
a port, but simply prevent the port from being reused for
either origination or reception of a connection. They do,
however, keep track of the active connections <span class=
"emphasis"><i class="EMPHASIS">to</i></span> a port, and
perform timeouts on these. This is usually much simpler to
implement, as it can be done with a list attached to the
port.</p>
<p>This implementation method creates some problems when a
large number of connections must be originated from a
relatively small number of port numbers. Observe what
happens when host 1 tries to send a large number of jobs to
a server 2. The following connections are established and
terminated: <var class="LITERAL">host 1, port 721</var> and
<var class="LITERAL">host 2, port 515</var> <var class=
"LITERAL">host 1, port 722</var> and <var class=
"LITERAL">host 2, port 515</var> <var class="LITERAL">host
1, port 723</var> and <var class="LITERAL">host 2, port
515</var> <var class="LITERAL">host 1, port 724</var> and
<var class="LITERAL">host 2, port 515</var> <var class=
"LITERAL">host 1, port 725</var> and <var class=
"LITERAL">host 2, port 515</var> <var class="LITERAL">host
1, port 726</var> and <var class="LITERAL">host 2, port
515</var> <var class="LITERAL">host 1, port 727</var> and
<var class="LITERAL">host 2, port 515</var> <var class=
"LITERAL">host 1, port 728</var> and <var class=
"LITERAL">host 2, port 515</var> <var class="LITERAL">host
1, port 729</var> and <var class="LITERAL">host 2, port
515</var> <var class="LITERAL">host 1, port 730</var> and
<var class="LITERAL">host 2, port 515</var> <var class=
"LITERAL">host 1, port 731</var> and <var class=
"LITERAL">host 2, port 515</var></p>
<p>Now according to the RFC1179 rules and the TCP/IP
protocol, we will have to wait until one of these
connections terminates before we can make another. On the
originating system, if the TCP/IP implementation does
timeouts on the originating port, we will have to wait for
the timeout to elapse before we can make a new connection.
Unfortunately, there is no way to find out what the status
of the port is, so we will have to try them each in turn
until we get a successful connection.</p>
<p>The <b class="APPLICATION">LPRng</b> code has tried to
provide several methods to deal with these problems.
Firstly, the <var class="LITERAL">originate_port=512
1023</var> option specifies the range of ports used to
originate connections when the software is running either
as ROOT or SETUID root. By strict RFC1179 rules, this
should be <var class="LITERAL">originate_port=721
731</var>, but it turns out that most BSD <b class=
"APPLICATION">lpd</b> based implementations only check for
a <span class="emphasis"><i class=
"EMPHASIS">reserved</i></span> originating port. By using
512 ports we get a greatly reduced rate of errors due to
lack of ports due to pending timeouts.</p>
<p>However, on some systems which are acting as servers for
a large number of printers even increasing this port range
is insufficient, and steps need to be taken use the
originating port numbers more efficiently. The Berkeley
TCP/IP implementation <code class=
"FUNCTION">getsockopt()</code> and <code class=
"FUNCTION">setsockopt()</code> allows the user to
manipulate some of the underlying timeouts and options of
the TCP/IP network. When a TCP/IP connection is
established, the <code class="FUNCTION">setsockopt()</code>
facility can be used to set the <var class=
"LITERAL">SO_REUSEADDR</var> flag on the connection. This
flag effectively sets the timeout value on the ports and
connections to 0, allowing immediate reuse of the ports.
When done on an originating end of a connection, this will
allow the originating port number to be reused
immediately.</p>
<p>It would appear that by setting <var class=
"LITERAL">SO_REUSEADDR</var> on the originating end that we
have solved our problems. However, unless the destination
end of the connection sets its <var class=
"LITERAL">SO_REUSEADDR</var> flag on the connection, it
will still do a timeout. Thus when we try to make a
connection from a port that was active within a short
period of time to the same host, then it will reject the
connection until the timeout is over.</p>
<p>The <var class="LITERAL">reuse_addr</var> flag (default
off) forces the <b class="APPLICATION">LPRng</b> software
to set the <var class="LITERAL">SO_REUSEADDR</var> flag on
originating connections. As indicated, this will allow
ports to be reused immediately for outgoing connections,
rather than waiting for a timeout.</p>
<p>While the <var class="LITERAL">reuse_addr</var> flag
usually allows us to reuse ports, there is still the
problem of dealing with connections failing due to the
remote site rejecting the connection due to a pending
timeout from a previous connection. A careful study of the
original BSD TCP/IP network code and of some others
indicates that when a connection fails due to a pending
timeout, an ECONNREFUSED error code is returned to a <code
class="FUNCTION">connect()</code> system call. If this
happens and we suspect that the remote site is rejecting
the connection due to a timeout problem, then we should
retry making the connection but from a new port, and
continue retrying until all possible ports are used.</p>
<p>The <var class="LITERAL">retry_econnrefused</var>
(default on) flag is used to specify that we retry
connections in this manner. When this is set, a <var class=
"LITERAL">connection refused</var> error causes the
connection to be retried using a new port. This will be
repeated until all available ports have been tried.</p>
<p>When printing a job and the <b class=
"APPLICATION">lpd</b> server connection to a remote site or
device open fails, the <var class=
"LITERAL">retry_nolink</var> (default on) will cause the
attempt to be retried indefinitely. The combination of <var
class="LITERAL">retry_econnrefused</var> and <var class=
"LITERAL">retry_nolink</var> will provide robust connection
attempts to remote systems.</p>
<p>While the above problems cause difficulties when making
connections, there are also problems when terminating
connections. After closing a socket, the TCP/IP software
will try to flush any pending data to the destination.
Unfortunately, on some systems it will only do this while
the process is active. This has caused problems on systems
which terminate a process it has received an abnormal
(signal caused) termination.</p>
<p>The <code class="FUNCTION">setsockopt()</code> SO_LINGER
option allows the user to specify that when a socket is
closed normally, that the process should block until
pending data is flushed or for the <var class=
"LITERAL">socket_linger</var> period. If <var class=
"LITERAL">socket_linger</var> is 0, then no SO_LINGER
operation is done.</p>
<p>In summary, if you experience problems with connection
failures due to port exhaustion, first try setting the <var
class="LITERAL">reuse_port</var> flag, and you should see a
reduction. Check to ensure that the <var class=
"LITERAL">retry_econnrefused</var> and <var class=
"LITERAL">retry_nolink</var> flags are set, and the error
code in the log and status files. If the failures continue,
then the problem is caused by the remote end having timeout
limitations and there is little you can do except to set a
very long <var class="LITERAL">connect_retry</var>
interval, say <var class="LITERAL">connect_retry=120</var>
(2 minutes).</p>
</div>
</div>
<div class="NAVFOOTER">
<hr align="LEFT" width="100%">
<table summary="Footer navigation table" width="100%" border=
"0" cellpadding="0" cellspacing="0">
<tr>
<td width="33%" align="left" valign="top"><a href=
"x9886.htm" accesskey="P">Prev</a></td>
<td width="34%" align="center" valign="top"><a href=
"index.htm" accesskey="H">Home</a></td>
<td width="33%" align="right" valign="top"><a href=
"remotesupport.htm" accesskey="N">Next</a></td>
</tr>
<tr>
<td width="33%" align="left" valign="top"><b class=
"APPLICATION">LPRng</b> accounting.pl Utility</td>
<td width="34%" align="center" valign="top"> </td>
<td width="33%" align="right" valign="top">Protocol
Requests and Replies</td>
</tr>
</table>
</div>
</body>
</html>
syntax highlighted by Code2HTML, v. 0.9.1