1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
|
<!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.71 ">
<link rel="HOME" title=" LPRng-HOWTO" href="index.htm">
<link rel="PREVIOUS" title="\LPRng accounting.pl Utility" href=
"x9588.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-HOWTO: 1 Apr 2002
(For LPRng-3.8.10)</th>
</tr>
<tr>
<td width="10%" align="left" valign="bottom"><a href=
"x9588.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">Chapter 19. RFC 1179 - Line Printer
Daemon Protocol</a></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="x9971.htm">Data File Transfer</a></dt>
<dt>19.5. <a href="x10007.htm">Control File
Contents</a></dt>
<dt>19.6. <a href="x10210.htm"><b class=
"APPLICATION">lpq</b> Requests</a></dt>
<dt>19.7. <a href="x10233.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="x10436.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 <i class="EMPHASIS">informational</i> 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><tt class="LITERAL">lpd_port=</tt><i class=
"EMPHASIS">Port for <b class="APPLICATION">lpd</b> to
accept connection</i></p>
</li>
<li>
<p><tt class="LITERAL">originate_port=</tt><i class=
"EMPHASIS">Ports to originate connections on</i></p>
</li>
<li>
<p><tt class="LITERAL">reuse_addr</tt> FLAG <i class=
"EMPHASIS">Set SO_REUSEADDR flag on connection</i></p>
</li>
<li>
<p><tt class="LITERAL">retry_econnrefused</tt> FLAG <i
class="EMPHASIS">Retry on connect ECONNREFUSED
error</i></p>
</li>
<li>
<p><tt class="LITERAL">retry_nolink</tt> FLAG <i class=
"EMPHASIS">Retry on device open or connection
ffailure</i></p>
</li>
<li>
<p><tt class="LITERAL">socket_linger=</tt><i class=
"EMPHASIS">socket linger timeout</i></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="AEN9672"></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 <i class=
"EMPHASIS">reserved</i> and <i class=
"EMPHASIS">privileged</i> ports. By convention, ports in
the range 1-1023 can only <i class="EMPHASIS">bound</i> 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 <tt
class="LITERAL">lpd_port=printer</tt> configuration option
to set the actual port to be use. By default, this is port
515, but can be set to other values.</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 <i class="EMPHASIS">stale</i>
packets. When a connection between <tt class=
"LITERAL">sourcehost, sourceport</tt> and <tt class=
"LITERAL">desthost, destport</tt> 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 <tt class="LITERAL">sourcehost,
sourceport</tt> and <tt class="LITERAL">desthost,
destport</tt> for a period long enough for all <i class=
"EMPHASIS">stale</i> 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 <i class=
"EMPHASIS">originating</i> 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 <i class="EMPHASIS">to</i> 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: <tt class="LITERAL">host 1, port 721</tt> and
<tt class="LITERAL">host 2, port 515</tt> <tt class=
"LITERAL">host 1, port 722</tt> and <tt class=
"LITERAL">host 2, port 515</tt> <tt class="LITERAL">host 1,
port 723</tt> and <tt class="LITERAL">host 2, port 515</tt>
<tt class="LITERAL">host 1, port 724</tt> and <tt class=
"LITERAL">host 2, port 515</tt> <tt class="LITERAL">host 1,
port 725</tt> and <tt class="LITERAL">host 2, port 515</tt>
<tt class="LITERAL">host 1, port 726</tt> and <tt class=
"LITERAL">host 2, port 515</tt> <tt class="LITERAL">host 1,
port 727</tt> and <tt class="LITERAL">host 2, port 515</tt>
<tt class="LITERAL">host 1, port 728</tt> and <tt class=
"LITERAL">host 2, port 515</tt> <tt class="LITERAL">host 1,
port 729</tt> and <tt class="LITERAL">host 2, port 515</tt>
<tt class="LITERAL">host 1, port 730</tt> and <tt class=
"LITERAL">host 2, port 515</tt> <tt class="LITERAL">host 1,
port 731</tt> and <tt class="LITERAL">host 2, port
515</tt></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 <tt class="LITERAL">originate_port=512
1023</tt> 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 <tt class="LITERAL">originate_port=721 731</tt>,
but it turns out that most BSD <b class=
"APPLICATION">lpd</b> based implementations only check for
a <i class="EMPHASIS">reserved</i> 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 <tt class=
"FUNCTION">getsockopt()</tt> and <tt class=
"FUNCTION">setsockopt()</tt> 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 <tt
class="FUNCTION">setsockopt()</tt> facility can be used to
set the <tt class="LITERAL">SO_REUSEADDR</tt> 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 <tt class=
"LITERAL">SO_REUSEADDR</tt> on the originating end that we
have solved our problems. However, unless the destination
end of the connection sets its <tt class=
"LITERAL">SO_REUSEADDR</tt> 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 <tt class="LITERAL">reuse_addr</tt> flag (default
off) forces the <b class="APPLICATION">LPRng</b> software
to set the <tt class="LITERAL">SO_REUSEADDR</tt> 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 <tt class="LITERAL">reuse_addr</tt> 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 <tt
class="FUNCTION">connect()</tt> 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 <tt class="LITERAL">retry_econnrefused</tt> (default
on) flag is used to specify that we retry connections in
this manner. When this is set, a <tt class=
"LITERAL">connection refused</tt> 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 <tt class=
"LITERAL">retry_nolink</tt> (default on) will cause the
attempt to be retried indefinitely. The combination of <tt
class="LITERAL">retry_econnrefused</tt> and <tt class=
"LITERAL">retry_nolink</tt> 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 <tt class="FUNCTION">setsockopt()</tt> 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 <tt class=
"LITERAL">socket_linger</tt> period. If <tt class=
"LITERAL">socket_linger</tt> 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 <tt
class="LITERAL">reuse_port</tt> flag, and you should see a
reduction. Check to ensure that the <tt class=
"LITERAL">retry_econnrefused</tt> and <tt class=
"LITERAL">retry_nolink</tt> 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 <tt class="LITERAL">connect_retry</tt> interval,
say <tt class="LITERAL">connect_retry=120</tt> (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=
"x9588.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>
|