1 |
/* |
/* Copyright (C) 1998,2001 Free Software Foundation, Inc. |
|
* Copyright (c) 1989, 1993 |
|
|
* The Regents of the University of California. All rights reserved. |
|
|
* |
|
|
* Redistribution and use in source and binary forms, with or without |
|
|
* modification, are permitted provided that the following conditions |
|
|
* are met: |
|
|
* 1. Redistributions of source code must retain the above copyright |
|
|
* notice, this list of conditions and the following disclaimer. |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
|
|
* notice, this list of conditions and the following disclaimer in the |
|
|
* documentation and/or other materials provided with the distribution. |
|
|
* 4. Neither the name of the University nor the names of its contributors |
|
|
* may be used to endorse or promote products derived from this software |
|
|
* without specific prior written permission. |
|
|
* |
|
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
|
* SUCH DAMAGE. |
|
|
*/ |
|
2 |
|
|
3 |
#ifndef lint |
This file is part of GNU Inetutils. |
|
static char sccsid[] = "@(#)utility.c 8.4 (Berkeley) 5/30/95"; |
|
|
#endif /* not lint */ |
|
4 |
|
|
5 |
#ifdef HAVE_CONFIG_H |
GNU Inetutils is free software; you can redistribute it and/or modify |
6 |
#include <config.h> |
it under the terms of the GNU General Public License as published by |
7 |
|
the Free Software Foundation; either version 2, or (at your option) |
8 |
|
any later version. |
9 |
|
|
10 |
|
GNU Inetutils is distributed in the hope that it will be useful, |
11 |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
|
MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE. See the |
13 |
|
GNU General Public License for more details. |
14 |
|
|
15 |
|
You should have received a copy of the GNU General Public License |
16 |
|
along with GNU Inetutils; see the file COPYING. If not, write to |
17 |
|
the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
18 |
|
Boston, MA 02111-1307, USA. */ |
19 |
|
|
20 |
|
#define TELOPTS |
21 |
|
#define TELCMDS |
22 |
|
#define SLC_NAMES |
23 |
|
#include "telnetd.h" |
24 |
|
#include <stdarg.h> |
25 |
|
#include <termio.h> |
26 |
|
|
27 |
|
#if defined(AUTHENTICATION) || defined(ENCRYPTION) |
28 |
|
# include <libtelnet/misc.h> |
29 |
|
# define NET_ENCRYPT net_encrypt |
30 |
|
#else |
31 |
|
# define NET_ENCRYPT() |
32 |
#endif |
#endif |
33 |
|
|
34 |
#define PRINTOPTIONS |
static char netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp; |
35 |
#include "telnetd.h" |
static char *neturg; /* one past last byte of urgent data */ |
36 |
|
|
37 |
/* |
static char ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp; |
|
* utility functions performing io related tasks |
|
|
*/ |
|
38 |
|
|
39 |
/* |
static char netibuf[BUFSIZ], *netip; |
40 |
* ttloop |
static int ncc; |
41 |
|
|
42 |
|
static char ptyibuf[BUFSIZ], *ptyip; |
43 |
|
static int pcc; |
44 |
|
|
45 |
|
int not42; |
46 |
|
|
47 |
|
static int |
48 |
|
readstream (int p, char *ibuf, int bufsize) |
49 |
|
{ |
50 |
|
#ifndef HAVE_STREAMSPTY |
51 |
|
return read (p, ibuf, bufsize); |
52 |
|
#else |
53 |
|
int flags = 0; |
54 |
|
int ret = 0; |
55 |
|
struct termios *tsp; |
56 |
|
struct termio *tp; |
57 |
|
struct iocblk *ip; |
58 |
|
char vstop, vstart; |
59 |
|
int ixon; |
60 |
|
int newflow; |
61 |
|
struct strbuf strbufc, strbufd; |
62 |
|
unsigned char ctlbuf[BUFSIZ]; |
63 |
|
static int flowstate = -1; |
64 |
|
|
65 |
|
strbufc.maxlen = BUFSIZ; |
66 |
|
strbufc.buf = (char *)ctlbuf; |
67 |
|
strbufd.maxlen = bufsize-1; |
68 |
|
strbufd.len = 0; |
69 |
|
strbufd.buf = ibuf+1; |
70 |
|
ibuf[0] = 0; |
71 |
|
|
72 |
|
ret = getmsg(p, &strbufc, &strbufd, &flags); |
73 |
|
if (ret < 0) /* error of some sort -- probably EAGAIN */ |
74 |
|
return -1; |
75 |
|
|
76 |
|
if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) |
77 |
|
{ |
78 |
|
/* data message */ |
79 |
|
if (strbufd.len > 0) /* real data */ |
80 |
|
return strbufd.len + 1; /* count header char */ |
81 |
|
else |
82 |
|
{ |
83 |
|
/* nothing there */ |
84 |
|
errno = EAGAIN; |
85 |
|
return -1; |
86 |
|
} |
87 |
|
} |
88 |
|
|
89 |
|
/* |
90 |
|
* It's a control message. Return 1, to look at the flag we set |
91 |
|
*/ |
92 |
|
|
93 |
|
switch (ctlbuf[0]) |
94 |
|
{ |
95 |
|
case M_FLUSH: |
96 |
|
if (ibuf[1] & FLUSHW) |
97 |
|
ibuf[0] = TIOCPKT_FLUSHWRITE; |
98 |
|
return 1; |
99 |
|
|
100 |
|
case M_IOCTL: |
101 |
|
ip = (struct iocblk *) (ibuf+1); |
102 |
|
|
103 |
|
switch (ip->ioc_cmd) |
104 |
|
{ |
105 |
|
case TCSETS: |
106 |
|
case TCSETSW: |
107 |
|
case TCSETSF: |
108 |
|
tsp = (struct termios *) (ibuf + 1 + sizeof(struct iocblk)); |
109 |
|
vstop = tsp->c_cc[VSTOP]; |
110 |
|
vstart = tsp->c_cc[VSTART]; |
111 |
|
ixon = tsp->c_iflag & IXON; |
112 |
|
break; |
113 |
|
|
114 |
|
case TCSETA: |
115 |
|
case TCSETAW: |
116 |
|
case TCSETAF: |
117 |
|
tp = (struct termio *) (ibuf + 1 + sizeof(struct iocblk)); |
118 |
|
vstop = tp->c_cc[VSTOP]; |
119 |
|
vstart = tp->c_cc[VSTART]; |
120 |
|
ixon = tp->c_iflag & IXON; |
121 |
|
break; |
122 |
|
|
123 |
|
default: |
124 |
|
errno = EAGAIN; |
125 |
|
return -1; |
126 |
|
} |
127 |
|
|
128 |
|
newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0; |
129 |
|
if (newflow != flowstate) /* it's a change */ |
130 |
|
{ |
131 |
|
flowstate = newflow; |
132 |
|
ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP; |
133 |
|
return 1; |
134 |
|
} |
135 |
|
} |
136 |
|
|
137 |
|
/* nothing worth doing anything about */ |
138 |
|
errno = EAGAIN; |
139 |
|
return -1; |
140 |
|
#endif /* HAVE_STREAMSPTY */ |
141 |
|
} |
142 |
|
|
143 |
|
/* ************************************************************************* */ |
144 |
|
/* Net and PTY I/O functions */ |
145 |
|
|
146 |
|
void |
147 |
|
io_setup () |
148 |
|
{ |
149 |
|
pfrontp = pbackp = ptyobuf; |
150 |
|
nfrontp = nbackp = netobuf; |
151 |
|
netip = netibuf; |
152 |
|
} |
153 |
|
|
154 |
|
void |
155 |
|
set_neturg () |
156 |
|
{ |
157 |
|
neturg = nfrontp - 1; |
158 |
|
} |
159 |
|
|
160 |
|
/* net-buffers */ |
161 |
|
|
162 |
|
void |
163 |
|
net_output_byte (int c) |
164 |
|
{ |
165 |
|
*nfrontp++ = c; |
166 |
|
} |
167 |
|
|
168 |
|
int |
169 |
|
net_output_data (const char *format,...) |
170 |
|
{ |
171 |
|
va_list args; |
172 |
|
size_t remaining, ret; |
173 |
|
|
174 |
|
va_start (args, format); |
175 |
|
remaining = BUFSIZ - (nfrontp - netobuf); |
176 |
|
/* try a netflush() if the room is too low */ |
177 |
|
if (strlen (format) > remaining || BUFSIZ / 4 > remaining) |
178 |
|
{ |
179 |
|
netflush (); |
180 |
|
remaining = BUFSIZ - (nfrontp - netobuf); |
181 |
|
} |
182 |
|
ret = vsnprintf (nfrontp, remaining, format, args); |
183 |
|
nfrontp += ((ret < remaining - 1) ? ret : remaining - 1); |
184 |
|
va_end (args); |
185 |
|
return ret; |
186 |
|
} |
187 |
|
|
188 |
|
int |
189 |
|
net_output_datalen (const void *buf, size_t l) |
190 |
|
{ |
191 |
|
size_t remaining; |
192 |
|
|
193 |
|
remaining = BUFSIZ - (nfrontp - netobuf); |
194 |
|
if (remaining < l) |
195 |
|
{ |
196 |
|
netflush (); |
197 |
|
remaining = BUFSIZ - (nfrontp - netobuf); |
198 |
|
} |
199 |
|
if (remaining < l) |
200 |
|
return -1; |
201 |
|
memmove (nfrontp, buf, l); |
202 |
|
nfrontp += l; |
203 |
|
return (int) l; |
204 |
|
} |
205 |
|
|
206 |
|
int |
207 |
|
net_input_level () |
208 |
|
{ |
209 |
|
return ncc; |
210 |
|
} |
211 |
|
|
212 |
|
int |
213 |
|
net_output_level () |
214 |
|
{ |
215 |
|
return nfrontp - nbackp; |
216 |
|
} |
217 |
|
|
218 |
|
int |
219 |
|
net_buffer_is_full () |
220 |
|
{ |
221 |
|
return (&netobuf[BUFSIZ] - nfrontp) < 2; |
222 |
|
} |
223 |
|
|
224 |
|
int |
225 |
|
net_get_char (int peek) |
226 |
|
{ |
227 |
|
if (peek) |
228 |
|
return *netip; |
229 |
|
else if (ncc > 0) |
230 |
|
{ |
231 |
|
ncc--; |
232 |
|
return *netip++ & 0377; |
233 |
|
} |
234 |
|
} |
235 |
|
|
236 |
|
int |
237 |
|
net_read () |
238 |
|
{ |
239 |
|
ncc = read (net, netibuf, sizeof (netibuf)); |
240 |
|
if (ncc < 0 && errno == EWOULDBLOCK) |
241 |
|
ncc = 0; |
242 |
|
else if (ncc == 0) |
243 |
|
{ |
244 |
|
syslog (LOG_INFO, "telnetd: peer died"); |
245 |
|
cleanup(0); |
246 |
|
} |
247 |
|
else if (ncc > 0) |
248 |
|
{ |
249 |
|
netip = netibuf; |
250 |
|
DEBUG(debug_report,1, |
251 |
|
debug_output_data ("td: netread %d chars\r\n", ncc)); |
252 |
|
DEBUG(debug_net_data,1, |
253 |
|
printdata("nd", netip, ncc)); |
254 |
|
} |
255 |
|
return ncc; |
256 |
|
} |
257 |
|
|
258 |
|
/* PTY buffer functions */ |
259 |
|
|
260 |
|
int |
261 |
|
pty_buffer_is_full () |
262 |
|
{ |
263 |
|
return (&ptyobuf[BUFSIZ] - pfrontp) < 2; |
264 |
|
} |
265 |
|
|
266 |
|
void |
267 |
|
pty_output_byte (int c) |
268 |
|
{ |
269 |
|
*pfrontp++ = c; |
270 |
|
} |
271 |
|
|
272 |
|
void |
273 |
|
pty_output_datalen (const void *data, size_t len) |
274 |
|
{ |
275 |
|
if ((&ptyobuf[BUFSIZ] - pfrontp) > len) |
276 |
|
ptyflush (); |
277 |
|
memcpy (pfrontp, data, len); |
278 |
|
pfrontp += len; |
279 |
|
} |
280 |
|
|
281 |
|
int |
282 |
|
pty_input_level () |
283 |
|
{ |
284 |
|
return pcc; |
285 |
|
} |
286 |
|
|
287 |
|
int |
288 |
|
pty_output_level () |
289 |
|
{ |
290 |
|
return pfrontp - pbackp; |
291 |
|
} |
292 |
|
|
293 |
|
void |
294 |
|
ptyflush() |
295 |
|
{ |
296 |
|
int n; |
297 |
|
|
298 |
|
if ((n = pfrontp - pbackp) > 0) |
299 |
|
{ |
300 |
|
DEBUG(debug_report, 1, |
301 |
|
debug_output_data ("td: ptyflush %d chars\r\n", n)); |
302 |
|
DEBUG(debug_pty_data, 1, |
303 |
|
printdata("pd", pbackp, n)); |
304 |
|
n = write(pty, pbackp, n); |
305 |
|
} |
306 |
|
|
307 |
|
if (n < 0) |
308 |
|
{ |
309 |
|
if (errno == EWOULDBLOCK || errno == EINTR) |
310 |
|
return; |
311 |
|
cleanup(0); |
312 |
|
} |
313 |
|
|
314 |
|
pbackp += n; |
315 |
|
if (pbackp == pfrontp) |
316 |
|
pbackp = pfrontp = ptyobuf; |
317 |
|
} |
318 |
|
|
319 |
|
int |
320 |
|
pty_get_char (int peek) |
321 |
|
{ |
322 |
|
if (peek) |
323 |
|
return *ptyip; |
324 |
|
else if (pcc > 0) |
325 |
|
{ |
326 |
|
pcc--; |
327 |
|
return *ptyip++ & 0377; |
328 |
|
} |
329 |
|
} |
330 |
|
|
331 |
|
int |
332 |
|
pty_read () |
333 |
|
{ |
334 |
|
pcc = readstream (pty, ptyibuf, BUFSIZ); |
335 |
|
if (pcc < 0 |
336 |
|
&& (errno == EWOULDBLOCK |
337 |
|
#ifdef EAGAIN |
338 |
|
|| errno == EAGAIN |
339 |
|
#endif |
340 |
|
|| errno == EIO)) |
341 |
|
pcc = 0; |
342 |
|
ptyip = ptyibuf; |
343 |
|
|
344 |
|
DEBUG(debug_report,1, |
345 |
|
debug_output_data ("ptyread %d chars\r\n", pcc)); |
346 |
|
DEBUG(debug_pty_data,1, |
347 |
|
printdata("pty", ptyip, pcc)); |
348 |
|
return pcc; |
349 |
|
} |
350 |
|
|
351 |
|
/* ************************************************************************* */ |
352 |
|
|
353 |
|
|
354 |
|
/* io_drain () |
355 |
|
* |
356 |
* |
* |
357 |
* A small subroutine to flush the network output buffer, get some data |
* A small subroutine to flush the network output buffer, get some data |
358 |
* from the network, and pass it through the telnet state machine. We |
* from the network, and pass it through the telnet state machine. We |
361 |
*/ |
*/ |
362 |
|
|
363 |
void |
void |
364 |
ttloop() |
io_drain () |
365 |
{ |
{ |
366 |
void netflush(); |
DEBUG(debug_report, 1, debug_output_data("td: ttloop\r\n")); |
367 |
|
if (nfrontp - nbackp > 0) |
368 |
DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop\r\n"); |
netflush (); |
369 |
nfrontp += strlen(nfrontp);}); |
|
370 |
if (nfrontp-nbackp) { |
again: |
371 |
netflush(); |
ncc = read (net, netibuf, sizeof netibuf); |
372 |
} |
if (ncc < 0) |
373 |
ncc = read(net, netibuf, sizeof netibuf); |
{ |
374 |
if (ncc < 0) { |
if (errno == EAGAIN) |
375 |
syslog(LOG_INFO, "ttloop: read: %m\n"); |
{ |
376 |
exit(1); |
syslog (LOG_INFO, "ttloop: retrying"); |
377 |
} else if (ncc == 0) { |
goto again; |
378 |
syslog(LOG_INFO, "ttloop: peer died: %m\n"); |
} |
379 |
exit(1); |
syslog (LOG_INFO, "ttloop: read: %m\n"); |
380 |
} |
exit (1); |
381 |
DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop read %d chars\r\n", ncc); |
} |
382 |
nfrontp += strlen(nfrontp);}); |
else if (ncc == 0) |
383 |
netip = netibuf; |
{ |
384 |
telrcv(); /* state machine */ |
syslog (LOG_INFO, "ttloop: peer died: %m\n"); |
385 |
if (ncc > 0) { |
exit (1); |
386 |
pfrontp = pbackp = ptyobuf; |
} |
387 |
telrcv(); |
DEBUG(debug_report, 1, |
388 |
|
debug_output_data ("td: ttloop read %d chars\r\n", ncc)); |
389 |
|
netip = netibuf; |
390 |
|
telrcv (); /* state machine */ |
391 |
|
if (ncc > 0) |
392 |
|
{ |
393 |
|
pfrontp = pbackp = ptyobuf; |
394 |
|
telrcv (); |
395 |
} |
} |
396 |
} /* end of ttloop */ |
} /* end of ttloop */ |
397 |
|
|
400 |
*/ |
*/ |
401 |
/* int s; socket number */ |
/* int s; socket number */ |
402 |
int |
int |
403 |
stilloob(int s) |
stilloob (int s) |
404 |
{ |
{ |
405 |
static struct timeval timeout = { 0 }; |
static struct timeval timeout = { 0 }; |
406 |
fd_set excepts; |
fd_set excepts; |
407 |
int value; |
int value; |
408 |
|
|
409 |
do { |
do |
410 |
FD_ZERO(&excepts); |
{ |
411 |
FD_SET(s, &excepts); |
FD_ZERO (&excepts); |
412 |
value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout); |
FD_SET (s, &excepts); |
413 |
} while ((value == -1) && (errno == EINTR)); |
value = select (s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout); |
|
|
|
|
if (value < 0) { |
|
|
fatalperror(pty, "select"); |
|
|
} |
|
|
if (FD_ISSET(s, &excepts)) { |
|
|
return 1; |
|
|
} else { |
|
|
return 0; |
|
414 |
} |
} |
415 |
} |
while (value == -1 && errno == EINTR); |
416 |
|
|
417 |
void |
if (value < 0) |
418 |
ptyflush() |
fatalperror (pty, "select"); |
|
{ |
|
|
int n; |
|
419 |
|
|
420 |
if ((n = pfrontp - pbackp) > 0) { |
return FD_ISSET (s, &excepts); |
|
DIAG((TD_REPORT | TD_PTYDATA), |
|
|
{ sprintf(nfrontp, "td: ptyflush %d chars\r\n", n); |
|
|
nfrontp += strlen(nfrontp); }); |
|
|
DIAG(TD_PTYDATA, printdata("pd", pbackp, n)); |
|
|
n = write(pty, pbackp, n); |
|
|
} |
|
|
if (n < 0) { |
|
|
if (errno == EWOULDBLOCK || errno == EINTR) |
|
|
return; |
|
|
cleanup(0); |
|
|
} |
|
|
pbackp += n; |
|
|
if (pbackp == pfrontp) |
|
|
pbackp = pfrontp = ptyobuf; |
|
421 |
} |
} |
422 |
|
|
423 |
/* |
/* |
431 |
* character. |
* character. |
432 |
*/ |
*/ |
433 |
char * |
char * |
434 |
nextitem(char *current) |
nextitem (char *current) |
435 |
{ |
{ |
436 |
if ((*current&0xff) != IAC) { |
if ((*current&0xff) != IAC) |
437 |
return current+1; |
return current+1; |
438 |
} |
|
439 |
switch (*(current+1)&0xff) { |
switch (*(current+1)&0xff) |
440 |
|
{ |
441 |
case DO: |
case DO: |
442 |
case DONT: |
case DONT: |
443 |
case WILL: |
case WILL: |
444 |
case WONT: |
case WONT: |
445 |
return current+3; |
return current+3; |
446 |
|
|
447 |
case SB: /* loop forever looking for the SE */ |
case SB: /* loop forever looking for the SE */ |
448 |
{ |
{ |
449 |
register char *look = current+2; |
register char *look = current+2; |
450 |
|
|
451 |
for (;;) { |
for (;;) |
452 |
if ((*look++&0xff) == IAC) { |
if ((*look++&0xff) == IAC |
453 |
if ((*look++&0xff) == SE) { |
&& (*look++&0xff) == SE) |
454 |
return look; |
return look; |
455 |
} |
|
456 |
} |
default: |
|
} |
|
|
} |
|
|
default: |
|
457 |
return current+2; |
return current+2; |
458 |
|
} |
459 |
} |
} |
460 |
} /* end of nextitem */ |
} /* end of nextitem */ |
461 |
|
|
476 |
* caller should be setting the urgent data pointer AFTER calling |
* caller should be setting the urgent data pointer AFTER calling |
477 |
* us in any case. |
* us in any case. |
478 |
*/ |
*/ |
479 |
|
#define wewant(p) \ |
480 |
|
((nfrontp > p) && ((*p&0xff) == IAC) && \ |
481 |
|
((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) |
482 |
|
|
483 |
|
|
484 |
void |
void |
485 |
netclear() |
netclear () |
486 |
{ |
{ |
487 |
register char *thisitem, *next; |
register char *thisitem, *next; |
488 |
char *good; |
char *good; |
489 |
#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ |
|
|
((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) |
|
|
|
|
490 |
#ifdef ENCRYPTION |
#ifdef ENCRYPTION |
491 |
thisitem = nclearto > netobuf ? nclearto : netobuf; |
thisitem = nclearto > netobuf ? nclearto : netobuf; |
492 |
#else /* ENCRYPTION */ |
#else /* ENCRYPTION */ |
493 |
thisitem = netobuf; |
thisitem = netobuf; |
494 |
#endif /* ENCRYPTION */ |
#endif /* ENCRYPTION */ |
495 |
|
|
496 |
while ((next = nextitem(thisitem)) <= nbackp) { |
while ((next = nextitem (thisitem)) <= nbackp) |
497 |
thisitem = next; |
thisitem = next; |
|
} |
|
498 |
|
|
499 |
/* Now, thisitem is first before/at boundary. */ |
/* Now, thisitem is first before/at boundary. */ |
500 |
|
|
501 |
#ifdef ENCRYPTION |
#ifdef ENCRYPTION |
502 |
good = nclearto > netobuf ? nclearto : netobuf; |
good = nclearto > netobuf ? nclearto : netobuf; |
503 |
#else /* ENCRYPTION */ |
#else /* ENCRYPTION */ |
504 |
good = netobuf; /* where the good bytes go */ |
good = netobuf; /* where the good bytes go */ |
505 |
#endif /* ENCRYPTION */ |
#endif /* ENCRYPTION */ |
506 |
|
|
507 |
while (nfrontp > thisitem) { |
while (nfrontp > thisitem) |
508 |
if (wewant(thisitem)) { |
{ |
509 |
int length; |
if (wewant (thisitem)) |
510 |
|
{ |
511 |
next = thisitem; |
int length; |
512 |
do { |
|
513 |
next = nextitem(next); |
for (next = thisitem; wewant (next) && nfrontp > next; |
514 |
} while (wewant(next) && (nfrontp > next)); |
next = nextitem(next)) |
515 |
length = next-thisitem; |
; |
516 |
memmove(good, thisitem, length); |
|
517 |
good += length; |
length = next - thisitem; |
518 |
thisitem = next; |
memmove (good, thisitem, length); |
519 |
} else { |
good += length; |
520 |
thisitem = nextitem(thisitem); |
thisitem = next; |
521 |
|
} |
522 |
|
else |
523 |
|
{ |
524 |
|
thisitem = nextitem (thisitem); |
525 |
} |
} |
526 |
} |
} |
527 |
|
|
528 |
nbackp = netobuf; |
nbackp = netobuf; |
529 |
nfrontp = good; /* next byte to be sent */ |
nfrontp = good; /* next byte to be sent */ |
530 |
neturg = 0; |
neturg = 0; |
531 |
} /* end of netclear */ |
} /* end of netclear */ |
532 |
|
|
533 |
/* |
/* |
536 |
* handling requests for urgent data. |
* handling requests for urgent data. |
537 |
*/ |
*/ |
538 |
void |
void |
539 |
netflush() |
netflush () |
540 |
{ |
{ |
541 |
int n; |
int n; |
542 |
extern int not42; |
|
543 |
|
if ((n = nfrontp - nbackp) > 0) |
544 |
if ((n = nfrontp - nbackp) > 0) { |
{ |
545 |
DIAG(TD_REPORT, |
NET_ENCRYPT () |
546 |
{ sprintf(nfrontp, "td: netflush %d chars\r\n", n); |
|
547 |
n += strlen(nfrontp); /* get count first */ |
/* |
548 |
nfrontp += strlen(nfrontp); /* then move pointer */ |
* if no urgent data, or if the other side appears to be an |
549 |
}); |
* old 4.2 client (and thus unable to survive TCP urgent data), |
550 |
#ifdef ENCRYPTION |
* write the entire buffer in non-OOB mode. |
551 |
if (encrypt_output) { |
*/ |
552 |
char *s = nclearto ? nclearto : nbackp; |
if (!neturg || !not42) |
553 |
if (nfrontp - s > 0) { |
n = write (net, nbackp, n); /* normal write */ |
554 |
(*encrypt_output)((unsigned char *)s, nfrontp-s); |
else |
555 |
nclearto = nfrontp; |
{ |
556 |
} |
n = neturg - nbackp; |
557 |
} |
/* |
558 |
#endif /* ENCRYPTION */ |
* In 4.2 (and 4.3) systems, there is some question about |
559 |
/* |
* what byte in a sendOOB operation is the "OOB" data. |
560 |
* if no urgent data, or if the other side appears to be an |
* To make ourselves compatible, we only send ONE byte |
561 |
* old 4.2 client (and thus unable to survive TCP urgent data), |
* out of band, the one WE THINK should be OOB (though |
562 |
* write the entire buffer in non-OOB mode. |
* we really have more the TCP philosophy of urgent data |
563 |
*/ |
* rather than the Unix philosophy of OOB data). |
564 |
if ((neturg == 0) || (not42 == 0)) { |
*/ |
565 |
n = write(net, nbackp, n); /* normal write */ |
if (n > 1) |
566 |
} else { |
n = send (net, nbackp, n-1, 0); /* send URGENT all by itself */ |
567 |
n = neturg - nbackp; |
else |
568 |
/* |
n = send (net, nbackp, n, MSG_OOB); /* URGENT data */ |
|
* In 4.2 (and 4.3) systems, there is some question about |
|
|
* what byte in a sendOOB operation is the "OOB" data. |
|
|
* To make ourselves compatible, we only send ONE byte |
|
|
* out of band, the one WE THINK should be OOB (though |
|
|
* we really have more the TCP philosophy of urgent data |
|
|
* rather than the Unix philosophy of OOB data). |
|
|
*/ |
|
|
if (n > 1) { |
|
|
n = send(net, nbackp, n-1, 0); /* send URGENT all by itself */ |
|
|
} else { |
|
|
n = send(net, nbackp, n, MSG_OOB); /* URGENT data */ |
|
|
} |
|
569 |
} |
} |
570 |
} |
} |
571 |
if (n < 0) { |
if (n < 0) |
572 |
if (errno == EWOULDBLOCK || errno == EINTR) |
{ |
573 |
return; |
if (errno == EWOULDBLOCK || errno == EINTR) |
574 |
cleanup(0); |
return; |
575 |
|
cleanup (0); |
576 |
} |
} |
577 |
nbackp += n; |
|
578 |
|
nbackp += n; |
579 |
#ifdef ENCRYPTION |
#ifdef ENCRYPTION |
580 |
if (nbackp > nclearto) |
if (nbackp > nclearto) |
581 |
nclearto = 0; |
nclearto = 0; |
582 |
#endif /* ENCRYPTION */ |
#endif /* ENCRYPTION */ |
583 |
if (nbackp >= neturg) { |
if (nbackp >= neturg) |
584 |
neturg = 0; |
neturg = 0; |
585 |
} |
|
586 |
if (nbackp == nfrontp) { |
if (nbackp == nfrontp) |
587 |
nbackp = nfrontp = netobuf; |
{ |
588 |
|
nbackp = nfrontp = netobuf; |
589 |
#ifdef ENCRYPTION |
#ifdef ENCRYPTION |
590 |
nclearto = 0; |
nclearto = 0; |
591 |
#endif /* ENCRYPTION */ |
#endif /* ENCRYPTION */ |
592 |
} |
} |
593 |
return; |
DEBUG(debug_report, 1, |
594 |
|
debug_output_data ("td: netflush %d chars\r\n", n)); |
595 |
|
|
596 |
} /* end of netflush */ |
} /* end of netflush */ |
597 |
|
|
|
|
|
|
/* |
|
|
* writenet |
|
|
* |
|
|
* Just a handy little function to write a bit of raw data to the net. |
|
|
* It will force a transmit of the buffer if necessary |
|
|
* |
|
|
* arguments |
|
|
* ptr - A pointer to a character string to write |
|
|
* len - How many bytes to write |
|
|
*/ |
|
|
void |
|
|
writenet(register unsigned char * ptr, register int len) |
|
|
{ |
|
|
/* flush buffer if no room for new data) */ |
|
|
if ((&netobuf[BUFSIZ] - nfrontp) < len) { |
|
|
/* if this fails, don't worry, buffer is a little big */ |
|
|
netflush(); |
|
|
} |
|
|
|
|
|
memmove(nfrontp, ptr, len); |
|
|
nfrontp += len; |
|
|
|
|
|
} /* end of writenet */ |
|
|
|
|
|
|
|
598 |
/* |
/* |
599 |
* miscellaneous functions doing a variety of little jobs follow ... |
* miscellaneous functions doing a variety of little jobs follow ... |
600 |
*/ |
*/ |
601 |
|
|
|
|
|
602 |
void |
void |
603 |
fatal(int f, char *msg) |
fatal (int f, char *msg) |
604 |
{ |
{ |
605 |
char buf[BUFSIZ]; |
char buf[BUFSIZ]; |
606 |
|
|
607 |
snprintf (buf, sizeof buf, "telnetd: %s.\r\n", msg); |
snprintf (buf, sizeof buf, "telnetd: %s.\r\n", msg); |
608 |
#ifdef ENCRYPTION |
#ifdef ENCRYPTION |
609 |
if (encrypt_output) { |
if (encrypt_output) |
610 |
/* |
{ |
611 |
* Better turn off encryption first.... |
/* |
612 |
* Hope it flushes... |
* Better turn off encryption first.... |
613 |
*/ |
* Hope it flushes... |
614 |
encrypt_send_end(); |
*/ |
615 |
netflush(); |
encrypt_send_end (); |
616 |
} |
netflush (); |
617 |
|
} |
618 |
#endif /* ENCRYPTION */ |
#endif /* ENCRYPTION */ |
619 |
(void) write(f, buf, (int)strlen(buf)); |
write (f, buf, (int)strlen (buf)); |
620 |
sleep(1); /*XXX*/ |
sleep (1); /*FIXME*/ |
621 |
exit(1); |
exit (1); |
622 |
} |
} |
623 |
|
|
624 |
void |
void |
625 |
fatalperror(int f, char *msg) |
fatalperror (int f, char *msg) |
626 |
{ |
{ |
627 |
char buf[BUFSIZ]; |
char buf[BUFSIZ]; |
628 |
|
|
629 |
snprintf (buf, sizeof buf, "%s: %s", msg, strerror(errno)); |
snprintf (buf, sizeof buf, "%s: %s", msg, strerror (errno)); |
630 |
fatal(f, buf); |
fatal (f, buf); |
631 |
} |
} |
632 |
|
|
633 |
char editedhost[32]; |
/* ************************************************************************* */ |
634 |
|
/* Terminal determination */ |
635 |
|
|
636 |
void |
static unsigned char ttytype_sbbuf[] = |
637 |
edithost(register char *pat, register char *host) |
{ |
638 |
|
IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE |
639 |
|
}; |
640 |
|
|
641 |
|
static void |
642 |
|
_gettermname () |
643 |
{ |
{ |
644 |
register char *res = editedhost; |
if (his_state_is_wont (TELOPT_TTYPE)) |
645 |
#ifndef strncpy |
return; |
646 |
char *strncpy(); |
settimer (baseline); |
647 |
|
net_output_datalen (ttytype_sbbuf, sizeof ttytype_sbbuf); |
648 |
|
ttloop (sequenceIs (ttypesubopt, baseline)); |
649 |
|
} |
650 |
|
|
651 |
|
/* FIXME: should be getterminaltype (char *user_name, size_t size) |
652 |
|
Changes terminaltype. |
653 |
|
*/ |
654 |
|
int |
655 |
|
getterminaltype (char *user_name) |
656 |
|
{ |
657 |
|
int retval = -1; |
658 |
|
|
659 |
|
settimer (baseline); |
660 |
|
#if defined(AUTHENTICATION) |
661 |
|
/* |
662 |
|
* Handle the Authentication option before we do anything else. |
663 |
|
*/ |
664 |
|
send_do (TELOPT_AUTHENTICATION, 1); |
665 |
|
ttloop (his_will_wont_is_changing (TELOPT_AUTHENTICATION)); |
666 |
|
|
667 |
|
if (his_state_is_will (TELOPT_AUTHENTICATION)) |
668 |
|
retval = auth_wait (user_name); |
669 |
#endif |
#endif |
670 |
|
|
671 |
if (!pat) |
#ifdef ENCRYPTION |
672 |
pat = ""; |
send_will (TELOPT_ENCRYPT, 1); |
673 |
while (*pat) { |
#endif /* ENCRYPTION */ |
674 |
switch (*pat) { |
send_do (TELOPT_TTYPE, 1); |
675 |
|
send_do (TELOPT_TSPEED, 1); |
676 |
case '#': |
send_do (TELOPT_XDISPLOC, 1); |
677 |
if (*host) |
send_do (TELOPT_NEW_ENVIRON, 1); |
678 |
host++; |
send_do (TELOPT_OLD_ENVIRON, 1); |
679 |
break; |
|
680 |
|
#ifdef ENCRYPTION |
681 |
case '@': |
ttloop (his_do_dont_is_changing (TELOPT_ENCRYPT) |
682 |
if (*host) |
|| his_will_wont_is_changing (TELOPT_TTYPE) |
683 |
*res++ = *host++; |
|| his_will_wont_is_changing (TELOPT_TSPEED) |
684 |
break; |
|| his_will_wont_is_changing (TELOPT_XDISPLOC) |
685 |
|
|| his_will_wont_is_changing (TELOPT_NEW_ENVIRON) |
686 |
|
|| his_will_wont_is_changing (TELOPT_OLD_ENVIRON)); |
687 |
|
#else |
688 |
|
ttloop (his_will_wont_is_changing (TELOPT_TTYPE) |
689 |
|
|| his_will_wont_is_changing (TELOPT_TSPEED) |
690 |
|
|| his_will_wont_is_changing (TELOPT_XDISPLOC) |
691 |
|
|| his_will_wont_is_changing (TELOPT_NEW_ENVIRON) |
692 |
|
|| his_will_wont_is_changing (TELOPT_OLD_ENVIRON)); |
693 |
|
#endif |
694 |
|
|
695 |
|
#ifdef ENCRYPTION |
696 |
|
if (his_state_is_will (TELOPT_ENCRYPT)) |
697 |
|
encrypt_wait (); |
698 |
|
#endif |
699 |
|
|
700 |
default: |
if (his_state_is_will (TELOPT_TSPEED)) |
701 |
*res++ = *pat; |
{ |
702 |
break; |
static unsigned char sb[] = |
703 |
} |
{IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE}; |
704 |
if (res == &editedhost[sizeof editedhost - 1]) { |
|
705 |
*res = '\0'; |
net_output_datalen (sb, sizeof sb); |
706 |
return; |
} |
707 |
|
if (his_state_is_will (TELOPT_XDISPLOC)) |
708 |
|
{ |
709 |
|
static unsigned char sb[] = |
710 |
|
{IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE}; |
711 |
|
|
712 |
|
net_output_datalen (sb, sizeof sb); |
713 |
|
} |
714 |
|
if (his_state_is_will (TELOPT_NEW_ENVIRON)) |
715 |
|
{ |
716 |
|
static unsigned char sb[] = |
717 |
|
{IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE}; |
718 |
|
|
719 |
|
net_output_datalen (sb, sizeof sb); |
720 |
|
} |
721 |
|
else if (his_state_is_will (TELOPT_OLD_ENVIRON)) |
722 |
|
{ |
723 |
|
static unsigned char sb[] = |
724 |
|
{IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE}; |
725 |
|
|
726 |
|
net_output_datalen (sb, sizeof sb); |
727 |
|
} |
728 |
|
if (his_state_is_will (TELOPT_TTYPE)) |
729 |
|
net_output_datalen (ttytype_sbbuf, sizeof ttytype_sbbuf); |
730 |
|
|
731 |
|
if (his_state_is_will (TELOPT_TSPEED)) |
732 |
|
ttloop (sequenceIs (tspeedsubopt, baseline)); |
733 |
|
if (his_state_is_will (TELOPT_XDISPLOC)) |
734 |
|
ttloop (sequenceIs (xdisplocsubopt, baseline)); |
735 |
|
if (his_state_is_will (TELOPT_NEW_ENVIRON)) |
736 |
|
ttloop (sequenceIs (environsubopt, baseline)); |
737 |
|
if (his_state_is_will (TELOPT_OLD_ENVIRON)) |
738 |
|
ttloop (sequenceIs (oenvironsubopt, baseline)); |
739 |
|
|
740 |
|
if (his_state_is_will (TELOPT_TTYPE)) |
741 |
|
{ |
742 |
|
char *first = NULL, *last = NULL; |
743 |
|
|
744 |
|
ttloop (sequenceIs (ttypesubopt, baseline)); |
745 |
|
/* |
746 |
|
* If the other side has already disabled the option, then |
747 |
|
* we have to just go with what we (might) have already gotten. |
748 |
|
*/ |
749 |
|
if (his_state_is_will (TELOPT_TTYPE) && !terminaltypeok (terminaltype)) |
750 |
|
{ |
751 |
|
if (first) |
752 |
|
free (first); |
753 |
|
first = xstrdup (terminaltype); |
754 |
|
for (;;) |
755 |
|
{ |
756 |
|
/* Save the unknown name, and request the next name. */ |
757 |
|
if (last) |
758 |
|
free (last); |
759 |
|
last = xstrdup (terminaltype); |
760 |
|
_gettermname (); |
761 |
|
if (terminaltypeok (terminaltype)) |
762 |
|
break; |
763 |
|
if ((strcmp (last, terminaltype) == 0) |
764 |
|
|| his_state_is_wont (TELOPT_TTYPE)) |
765 |
|
{ |
766 |
|
/* |
767 |
|
* We've hit the end. If this is the same as |
768 |
|
* the first name, just go with it. |
769 |
|
*/ |
770 |
|
if (strcmp (first, terminaltype) == 0) |
771 |
|
break; |
772 |
|
/* |
773 |
|
* Get the terminal name one more time, so that |
774 |
|
* RFC1091 compliant telnets will cycle back to |
775 |
|
* the start of the list. |
776 |
|
*/ |
777 |
|
_gettermname (); |
778 |
|
if (strcmp (first, terminaltype) != 0) |
779 |
|
{ |
780 |
|
free (terminaltype); |
781 |
|
terminaltype = xstrdup (first); |
782 |
|
} |
783 |
|
break; |
784 |
} |
} |
785 |
pat++; |
} |
786 |
} |
} |
787 |
if (*host) |
if (first) |
788 |
(void) strncpy(res, host, |
free (first); |
789 |
sizeof editedhost - (res - editedhost) -1); |
if (last) |
790 |
else |
free (last); |
791 |
*res = '\0'; |
} |
792 |
editedhost[sizeof editedhost - 1] = '\0'; |
return retval; |
793 |
|
} |
794 |
|
|
795 |
|
int |
796 |
|
terminaltypeok (char *s) |
797 |
|
{ |
798 |
|
char buf[1024]; |
799 |
|
|
800 |
|
if (terminaltype == NULL) |
801 |
|
return 1; |
802 |
|
|
803 |
|
if (tgetent (buf, s) == 0) |
804 |
|
return 0; |
805 |
|
return 1; |
806 |
} |
} |
807 |
|
|
|
static char *putlocation; |
|
808 |
|
|
809 |
void |
/* ************************************************************************* */ |
810 |
putstr(register char *s) |
/* Debugging support */ |
811 |
|
|
812 |
|
static FILE *debug_fp = NULL; |
813 |
|
|
814 |
|
static int |
815 |
|
debug_open () |
816 |
{ |
{ |
817 |
|
int um = umask(077); |
818 |
|
if (!debug_fp) |
819 |
|
debug_fp = fopen ("/tmp/telnet.debug", "a"); |
820 |
|
umask(um); |
821 |
|
return debug_fp == NULL; |
822 |
|
} |
823 |
|
|
824 |
while (*s) |
static int |
825 |
putchr(*s++); |
debug_close () |
826 |
|
{ |
827 |
|
if (debug_fp) |
828 |
|
fclose (debug_fp); |
829 |
|
debug_fp = NULL; |
830 |
} |
} |
831 |
|
|
832 |
void |
void |
833 |
putchr(int cc) |
debug_output_datalen (const char *data, size_t len) |
834 |
{ |
{ |
835 |
*putlocation++ = cc; |
if (debug_open ()) |
836 |
|
return; |
837 |
|
|
838 |
|
fwrite (data, 1, len, debug_fp); |
839 |
|
debug_close (); |
840 |
} |
} |
841 |
|
|
|
/* |
|
|
* This is split on two lines so that SCCS will not see the M |
|
|
* between two % signs and expand it... |
|
|
*/ |
|
|
static char fmtstr[] = { "%l:%M\ |
|
|
%P on %A, %d %B %Y" }; |
|
|
|
|
842 |
void |
void |
843 |
putf(register char *cp, char *where) |
debug_output_data (const char *fmt, ...) |
844 |
{ |
{ |
845 |
char *slash; |
va_list ap; |
846 |
time_t t; |
if (debug_open ()) |
847 |
char db[100]; |
return; |
848 |
#ifdef STREAMSPTY |
va_start (ap, fmt); |
849 |
#ifndef strchr |
vfprintf (debug_fp, fmt, ap); |
850 |
extern char *strchr(); |
va_end (ap); |
851 |
#endif |
debug_close (); |
|
#else |
|
|
#ifndef strrchr |
|
|
extern char *strrchr(); |
|
|
#endif |
|
|
#endif |
|
|
|
|
|
putlocation = where; |
|
|
|
|
|
while (*cp) { |
|
|
if (*cp != '%') { |
|
|
putchr(*cp++); |
|
|
continue; |
|
|
} |
|
|
switch (*++cp) { |
|
|
|
|
|
case 't': |
|
|
#ifdef STREAMSPTY |
|
|
/* names are like /dev/pts/2 -- we want pts/2 */ |
|
|
slash = strchr(line+1, '/'); |
|
|
#else |
|
|
slash = strrchr(line, '/'); |
|
|
#endif |
|
|
if (slash == (char *) 0) |
|
|
putstr(line); |
|
|
else |
|
|
putstr(&slash[1]); |
|
|
break; |
|
|
|
|
|
case 'h': |
|
|
putstr(editedhost); |
|
|
break; |
|
|
|
|
|
case 'd': |
|
|
(void)time(&t); |
|
|
(void)strftime(db, sizeof(db), fmtstr, localtime(&t)); |
|
|
putstr(db); |
|
|
break; |
|
|
|
|
|
case '%': |
|
|
putchr('%'); |
|
|
break; |
|
|
} |
|
|
cp++; |
|
|
} |
|
852 |
} |
} |
853 |
|
|
|
#ifdef DIAGNOSTICS |
|
854 |
/* |
/* |
855 |
* Print telnet options and commands in plain text, if possible. |
* Print telnet options and commands in plain text, if possible. |
856 |
*/ |
*/ |
857 |
void |
void |
858 |
printoption(register char *fmt, register int option) |
printoption(register char *fmt, register int option) |
859 |
{ |
{ |
860 |
if (TELOPT_OK(option)) |
if (TELOPT_OK(option)) |
861 |
sprintf(nfrontp, "%s %s\r\n", fmt, TELOPT(option)); |
debug_output_data ("%s %s\r\n", fmt, TELOPT(option)); |
862 |
else if (TELCMD_OK(option)) |
else if (TELCMD_OK(option)) |
863 |
sprintf(nfrontp, "%s %s\r\n", fmt, TELCMD(option)); |
debug_output_data ("%s %s\r\n", fmt, TELCMD(option)); |
864 |
else |
else |
865 |
sprintf(nfrontp, "%s %d\r\n", fmt, option); |
debug_output_data ("%s %d\r\n", fmt, option); |
|
nfrontp += strlen(nfrontp); |
|
|
return; |
|
866 |
} |
} |
867 |
|
|
868 |
/* char direction; '<' or '>' */ |
/* char direction; '<' or '>' */ |
869 |
/* unsigned char *pointer; where suboption data sits */ |
/* unsigned char *pointer; where suboption data sits */ |
870 |
/* int length; length of suboption data */ |
/* int length; length of suboption data */ |
871 |
void |
void |
872 |
printsub(char direction, unsigned char *pointer, int length) |
printsub(int direction, unsigned char *pointer, int length) |
873 |
{ |
{ |
874 |
register int i; |
register int i; |
875 |
char buf[512]; |
char buf[512]; |
876 |
|
|
877 |
if (!(diagnostic & TD_OPTIONS)) |
if (direction) |
878 |
return; |
{ |
879 |
|
debug_output_data ("td: %s suboption ", |
880 |
|
direction == '<' ? "recv" : "send"); |
881 |
|
if (length >= 3) |
882 |
|
{ |
883 |
|
register int j; |
884 |
|
|
885 |
if (direction) { |
i = pointer[length-2]; |
886 |
sprintf(nfrontp, "td: %s suboption ", |
j = pointer[length-1]; |
887 |
direction == '<' ? "recv" : "send"); |
|
888 |
nfrontp += strlen(nfrontp); |
if (i != IAC || j != SE) |
889 |
if (length >= 3) { |
{ |
890 |
register int j; |
debug_output_data ("(terminated by "); |
891 |
|
if (TELOPT_OK(i)) |
892 |
i = pointer[length-2]; |
debug_output_data ("%s ", TELOPT(i)); |
893 |
j = pointer[length-1]; |
else if (TELCMD_OK(i)) |
894 |
|
debug_output_data ("%s ", TELCMD(i)); |
895 |
if (i != IAC || j != SE) { |
else |
896 |
sprintf(nfrontp, "(terminated by "); |
debug_output_data ("%d ", i); |
897 |
nfrontp += strlen(nfrontp); |
if (TELOPT_OK(j)) |
898 |
if (TELOPT_OK(i)) |
debug_output_data ("%s", TELOPT(j)); |
899 |
sprintf(nfrontp, "%s ", TELOPT(i)); |
else if (TELCMD_OK(j)) |
900 |
else if (TELCMD_OK(i)) |
debug_output_data ("%s", TELCMD(j)); |
901 |
sprintf(nfrontp, "%s ", TELCMD(i)); |
else |
902 |
else |
debug_output_data ("%d", j); |
903 |
sprintf(nfrontp, "%d ", i); |
debug_output_data (", not IAC SE!) "); |
|
nfrontp += strlen(nfrontp); |
|
|
if (TELOPT_OK(j)) |
|
|
sprintf(nfrontp, "%s", TELOPT(j)); |
|
|
else if (TELCMD_OK(j)) |
|
|
sprintf(nfrontp, "%s", TELCMD(j)); |
|
|
else |
|
|
sprintf(nfrontp, "%d", j); |
|
|
nfrontp += strlen(nfrontp); |
|
|
sprintf(nfrontp, ", not IAC SE!) "); |
|
|
nfrontp += strlen(nfrontp); |
|
|
} |
|
904 |
} |
} |
|
length -= 2; |
|
905 |
} |
} |
906 |
if (length < 1) { |
length -= 2; |
907 |
sprintf(nfrontp, "(Empty suboption??\?)"); |
} |
908 |
nfrontp += strlen(nfrontp); |
if (length < 1) |
909 |
return; |
{ |
910 |
} |
debug_output_data ("(Empty suboption??\?)"); |
911 |
switch (pointer[0]) { |
return; |
912 |
case TELOPT_TTYPE: |
} |
|
sprintf(nfrontp, "TERMINAL-TYPE "); |
|
|
nfrontp += strlen(nfrontp); |
|
|
switch (pointer[1]) { |
|
|
case TELQUAL_IS: |
|
|
sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2); |
|
|
break; |
|
|
case TELQUAL_SEND: |
|
|
sprintf(nfrontp, "SEND"); |
|
|
break; |
|
|
default: |
|
|
sprintf(nfrontp, |
|
|
"- unknown qualifier %d (0x%x).", |
|
|
pointer[1], pointer[1]); |
|
|
} |
|
|
nfrontp += strlen(nfrontp); |
|
|
break; |
|
|
case TELOPT_TSPEED: |
|
|
sprintf(nfrontp, "TERMINAL-SPEED"); |
|
|
nfrontp += strlen(nfrontp); |
|
|
if (length < 2) { |
|
|
sprintf(nfrontp, " (empty suboption??\?)"); |
|
|
nfrontp += strlen(nfrontp); |
|
|
break; |
|
|
} |
|
|
switch (pointer[1]) { |
|
|
case TELQUAL_IS: |
|
|
sprintf(nfrontp, " IS %.*s", length-2, (char *)pointer+2); |
|
|
nfrontp += strlen(nfrontp); |
|
|
break; |
|
|
default: |
|
|
if (pointer[1] == 1) |
|
|
sprintf(nfrontp, " SEND"); |
|
|
else |
|
|
sprintf(nfrontp, " %d (unknown)", pointer[1]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
for (i = 2; i < length; i++) { |
|
|
sprintf(nfrontp, " ?%d?", pointer[i]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
} |
|
|
break; |
|
|
} |
|
|
break; |
|
913 |
|
|
914 |
case TELOPT_LFLOW: |
switch (pointer[0]) |
915 |
sprintf(nfrontp, "TOGGLE-FLOW-CONTROL"); |
{ |
916 |
nfrontp += strlen(nfrontp); |
case TELOPT_TTYPE: |
917 |
if (length < 2) { |
debug_output_data ("TERMINAL-TYPE "); |
918 |
sprintf(nfrontp, " (empty suboption??\?)"); |
switch (pointer[1]) |
919 |
nfrontp += strlen(nfrontp); |
{ |
920 |
break; |
case TELQUAL_IS: |
921 |
} |
debug_output_data ("IS \"%.*s\"", length-2, (char *)pointer+2); |
922 |
switch (pointer[1]) { |
break; |
923 |
case LFLOW_OFF: |
|
924 |
sprintf(nfrontp, " OFF"); break; |
case TELQUAL_SEND: |
925 |
case LFLOW_ON: |
debug_output_data ("SEND"); |
926 |
sprintf(nfrontp, " ON"); break; |
break; |
927 |
case LFLOW_RESTART_ANY: |
|
928 |
sprintf(nfrontp, " RESTART-ANY"); break; |
default: |
929 |
case LFLOW_RESTART_XON: |
debug_output_data ("- unknown qualifier %d (0x%x).", |
930 |
sprintf(nfrontp, " RESTART-XON"); break; |
pointer[1], pointer[1]); |
931 |
default: |
} |
932 |
sprintf(nfrontp, " %d (unknown)", pointer[1]); |
break; |
|
} |
|
|
nfrontp += strlen(nfrontp); |
|
|
for (i = 2; i < length; i++) { |
|
|
sprintf(nfrontp, " ?%d?", pointer[i]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
} |
|
|
break; |
|
933 |
|
|
934 |
case TELOPT_NAWS: |
case TELOPT_TSPEED: |
935 |
sprintf(nfrontp, "NAWS"); |
debug_output_data ("TERMINAL-SPEED"); |
936 |
nfrontp += strlen(nfrontp); |
if (length < 2) |
937 |
if (length < 2) { |
{ |
938 |
sprintf(nfrontp, " (empty suboption??\?)"); |
debug_output_data (" (empty suboption??\?)"); |
939 |
nfrontp += strlen(nfrontp); |
break; |
940 |
break; |
} |
|
} |
|
|
if (length == 2) { |
|
|
sprintf(nfrontp, " ?%d?", pointer[1]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
break; |
|
|
} |
|
|
sprintf(nfrontp, " %d %d (%d)", |
|
|
pointer[1], pointer[2], |
|
|
(int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); |
|
|
nfrontp += strlen(nfrontp); |
|
|
if (length == 4) { |
|
|
sprintf(nfrontp, " ?%d?", pointer[3]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
break; |
|
|
} |
|
|
sprintf(nfrontp, " %d %d (%d)", |
|
|
pointer[3], pointer[4], |
|
|
(int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); |
|
|
nfrontp += strlen(nfrontp); |
|
|
for (i = 5; i < length; i++) { |
|
|
sprintf(nfrontp, " ?%d?", pointer[i]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
} |
|
|
break; |
|
941 |
|
|
942 |
case TELOPT_LINEMODE: |
switch (pointer[1]) |
943 |
sprintf(nfrontp, "LINEMODE "); |
{ |
944 |
nfrontp += strlen(nfrontp); |
case TELQUAL_IS: |
945 |
if (length < 2) { |
debug_output_data (" IS %.*s", length-2, (char *)pointer+2); |
946 |
sprintf(nfrontp, " (empty suboption??\?)"); |
break; |
|
nfrontp += strlen(nfrontp); |
|
|
break; |
|
|
} |
|
|
switch (pointer[1]) { |
|
|
case WILL: |
|
|
sprintf(nfrontp, "WILL "); |
|
|
goto common; |
|
|
case WONT: |
|
|
sprintf(nfrontp, "WONT "); |
|
|
goto common; |
|
|
case DO: |
|
|
sprintf(nfrontp, "DO "); |
|
|
goto common; |
|
|
case DONT: |
|
|
sprintf(nfrontp, "DONT "); |
|
|
common: |
|
|
nfrontp += strlen(nfrontp); |
|
|
if (length < 3) { |
|
|
sprintf(nfrontp, "(no option??\?)"); |
|
|
nfrontp += strlen(nfrontp); |
|
|
break; |
|
|
} |
|
|
switch (pointer[2]) { |
|
|
case LM_FORWARDMASK: |
|
|
sprintf(nfrontp, "Forward Mask"); |
|
|
nfrontp += strlen(nfrontp); |
|
|
for (i = 3; i < length; i++) { |
|
|
sprintf(nfrontp, " %x", pointer[i]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
} |
|
|
break; |
|
|
default: |
|
|
sprintf(nfrontp, "%d (unknown)", pointer[2]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
for (i = 3; i < length; i++) { |
|
|
sprintf(nfrontp, " %d", pointer[i]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
} |
|
|
break; |
|
|
} |
|
|
break; |
|
947 |
|
|
948 |
case LM_SLC: |
default: |
949 |
sprintf(nfrontp, "SLC"); |
if (pointer[1] == 1) |
950 |
nfrontp += strlen(nfrontp); |
debug_output_data (" SEND"); |
951 |
for (i = 2; i < length - 2; i += 3) { |
else |
952 |
if (SLC_NAME_OK(pointer[i+SLC_FUNC])) |
debug_output_data (" %d (unknown)", pointer[1]); |
953 |
sprintf(nfrontp, " %s", SLC_NAME(pointer[i+SLC_FUNC])); |
for (i = 2; i < length; i++) { |
954 |
else |
debug_output_data (" ?%d?", pointer[i]); |
955 |
sprintf(nfrontp, " %d", pointer[i+SLC_FUNC]); |
} |
956 |
nfrontp += strlen(nfrontp); |
break; |
957 |
switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { |
} |
958 |
case SLC_NOSUPPORT: |
break; |
|
sprintf(nfrontp, " NOSUPPORT"); break; |
|
|
case SLC_CANTCHANGE: |
|
|
sprintf(nfrontp, " CANTCHANGE"); break; |
|
|
case SLC_VARIABLE: |
|
|
sprintf(nfrontp, " VARIABLE"); break; |
|
|
case SLC_DEFAULT: |
|
|
sprintf(nfrontp, " DEFAULT"); break; |
|
|
} |
|
|
nfrontp += strlen(nfrontp); |
|
|
sprintf(nfrontp, "%s%s%s", |
|
|
pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", |
|
|
pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", |
|
|
pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); |
|
|
nfrontp += strlen(nfrontp); |
|
|
if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| |
|
|
SLC_FLUSHOUT| SLC_LEVELBITS)) { |
|
|
sprintf(nfrontp, "(0x%x)", pointer[i+SLC_FLAGS]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
} |
|
|
sprintf(nfrontp, " %d;", pointer[i+SLC_VALUE]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
if ((pointer[i+SLC_VALUE] == IAC) && |
|
|
(pointer[i+SLC_VALUE+1] == IAC)) |
|
|
i++; |
|
|
} |
|
|
for (; i < length; i++) { |
|
|
sprintf(nfrontp, " ?%d?", pointer[i]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
} |
|
|
break; |
|
959 |
|
|
960 |
case LM_MODE: |
case TELOPT_LFLOW: |
961 |
sprintf(nfrontp, "MODE "); |
debug_output_data ("TOGGLE-FLOW-CONTROL"); |
962 |
nfrontp += strlen(nfrontp); |
if (length < 2) |
963 |
if (length < 3) { |
{ |
964 |
sprintf(nfrontp, "(no mode??\?)"); |
debug_output_data (" (empty suboption??\?)"); |
965 |
nfrontp += strlen(nfrontp); |
break; |
966 |
break; |
} |
|
} |
|
|
{ |
|
|
char tbuf[32]; |
|
|
sprintf(tbuf, "%s%s%s%s%s", |
|
|
pointer[2]&MODE_EDIT ? "|EDIT" : "", |
|
|
pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", |
|
|
pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", |
|
|
pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", |
|
|
pointer[2]&MODE_ACK ? "|ACK" : ""); |
|
|
sprintf(nfrontp, "%s", tbuf[1] ? &tbuf[1] : "0"); |
|
|
nfrontp += strlen(nfrontp); |
|
|
} |
|
|
if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) { |
|
|
sprintf(nfrontp, " (0x%x)", pointer[2]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
} |
|
|
for (i = 3; i < length; i++) { |
|
|
sprintf(nfrontp, " ?0x%x?", pointer[i]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
} |
|
|
break; |
|
|
default: |
|
|
sprintf(nfrontp, "%d (unknown)", pointer[1]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
for (i = 2; i < length; i++) { |
|
|
sprintf(nfrontp, " %d", pointer[i]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
} |
|
|
} |
|
|
break; |
|
967 |
|
|
968 |
case TELOPT_STATUS: { |
switch (pointer[1]) |
969 |
register char *cp; |
{ |
970 |
register int j, k; |
case LFLOW_OFF: |
971 |
|
debug_output_data (" OFF"); |
972 |
|
break; |
973 |
|
|
974 |
|
case LFLOW_ON: |
975 |
|
debug_output_data (" ON"); |
976 |
|
break; |
977 |
|
|
978 |
|
case LFLOW_RESTART_ANY: |
979 |
|
debug_output_data (" RESTART-ANY"); |
980 |
|
break; |
981 |
|
|
982 |
|
case LFLOW_RESTART_XON: |
983 |
|
debug_output_data (" RESTART-XON"); |
984 |
|
break; |
985 |
|
|
986 |
|
default: |
987 |
|
debug_output_data (" %d (unknown)", pointer[1]); |
988 |
|
} |
989 |
|
|
990 |
|
for (i = 2; i < length; i++) |
991 |
|
debug_output_data (" ?%d?", pointer[i]); |
992 |
|
break; |
993 |
|
|
994 |
|
case TELOPT_NAWS: |
995 |
|
debug_output_data ("NAWS"); |
996 |
|
if (length < 2) |
997 |
|
{ |
998 |
|
debug_output_data (" (empty suboption??\?)"); |
999 |
|
break; |
1000 |
|
} |
1001 |
|
if (length == 2) |
1002 |
|
{ |
1003 |
|
debug_output_data (" ?%d?", pointer[1]); |
1004 |
|
break; |
1005 |
|
} |
1006 |
|
|
1007 |
sprintf(nfrontp, "STATUS"); |
debug_output_data (" %d %d (%d)", |
1008 |
nfrontp += strlen(nfrontp); |
pointer[1], pointer[2], |
1009 |
|
(int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); |
1010 |
|
if (length == 4) |
1011 |
|
{ |
1012 |
|
debug_output_data (" ?%d?", pointer[3]); |
1013 |
|
break; |
1014 |
|
} |
1015 |
|
|
1016 |
switch (pointer[1]) { |
debug_output_data (" %d %d (%d)", |
1017 |
|
pointer[3], pointer[4], |
1018 |
|
(int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); |
1019 |
|
for (i = 5; i < length; i++) |
1020 |
|
debug_output_data (" ?%d?", pointer[i]); |
1021 |
|
break; |
1022 |
|
|
1023 |
|
case TELOPT_LINEMODE: |
1024 |
|
debug_output_data ("LINEMODE "); |
1025 |
|
if (length < 2) |
1026 |
|
{ |
1027 |
|
debug_output_data (" (empty suboption??\?)"); |
1028 |
|
break; |
1029 |
|
} |
1030 |
|
|
1031 |
|
switch (pointer[1]) |
1032 |
|
{ |
1033 |
|
case WILL: |
1034 |
|
debug_output_data ("WILL "); |
1035 |
|
goto common; |
1036 |
|
|
1037 |
|
case WONT: |
1038 |
|
debug_output_data ("WONT "); |
1039 |
|
goto common; |
1040 |
|
|
1041 |
|
case DO: |
1042 |
|
debug_output_data ("DO "); |
1043 |
|
goto common; |
1044 |
|
|
1045 |
|
case DONT: |
1046 |
|
debug_output_data ("DONT "); |
1047 |
|
|
1048 |
|
common: |
1049 |
|
if (length < 3) |
1050 |
|
{ |
1051 |
|
debug_output_data ("(no option??\?)"); |
1052 |
|
break; |
1053 |
|
} |
1054 |
|
switch (pointer[2]) |
1055 |
|
{ |
1056 |
|
case LM_FORWARDMASK: |
1057 |
|
debug_output_data ("Forward Mask"); |
1058 |
|
for (i = 3; i < length; i++) |
1059 |
|
debug_output_data (" %x", pointer[i]); |
1060 |
|
break; |
1061 |
|
|
1062 |
default: |
default: |
1063 |
if (pointer[1] == TELQUAL_SEND) |
debug_output_data ("%d (unknown)", pointer[2]); |
1064 |
sprintf(nfrontp, " SEND"); |
for (i = 3; i < length; i++) |
1065 |
else |
debug_output_data (" %d", pointer[i]); |
1066 |
sprintf(nfrontp, " %d (unknown)", pointer[1]); |
break; |
1067 |
nfrontp += strlen(nfrontp); |
} |
1068 |
for (i = 2; i < length; i++) { |
break; |
1069 |
sprintf(nfrontp, " ?%d?", pointer[i]); |
|
1070 |
nfrontp += strlen(nfrontp); |
case LM_SLC: |
1071 |
} |
debug_output_data ("SLC"); |
1072 |
break; |
for (i = 2; i < length - 2; i += 3) |
1073 |
case TELQUAL_IS: |
{ |
1074 |
sprintf(nfrontp, " IS\r\n"); |
if (SLC_NAME_OK(pointer[i+SLC_FUNC])) |
1075 |
nfrontp += strlen(nfrontp); |
debug_output_data (" %s", SLC_NAME(pointer[i+SLC_FUNC])); |
1076 |
|
else |
1077 |
for (i = 2; i < length; i++) { |
debug_output_data (" %d", pointer[i+SLC_FUNC]); |
1078 |
switch(pointer[i]) { |
switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) |
1079 |
case DO: cp = "DO"; goto common2; |
{ |
1080 |
case DONT: cp = "DONT"; goto common2; |
case SLC_NOSUPPORT: |
1081 |
case WILL: cp = "WILL"; goto common2; |
debug_output_data (" NOSUPPORT"); |
1082 |
case WONT: cp = "WONT"; goto common2; |
break; |
1083 |
common2: |
|
1084 |
i++; |
case SLC_CANTCHANGE: |
1085 |
if (TELOPT_OK(pointer[i])) |
debug_output_data (" CANTCHANGE"); |
1086 |
sprintf(nfrontp, " %s %s", cp, TELOPT(pointer[i])); |
break; |
1087 |
else |
|
1088 |
sprintf(nfrontp, " %s %d", cp, pointer[i]); |
case SLC_VARIABLE: |
1089 |
nfrontp += strlen(nfrontp); |
debug_output_data (" VARIABLE"); |
1090 |
|
break; |
1091 |
sprintf(nfrontp, "\r\n"); |
|
1092 |
nfrontp += strlen(nfrontp); |
case SLC_DEFAULT: |
1093 |
break; |
debug_output_data (" DEFAULT"); |
1094 |
|
break; |
1095 |
case SB: |
} |
1096 |
sprintf(nfrontp, " SB "); |
|
1097 |
nfrontp += strlen(nfrontp); |
debug_output_data ("%s%s%s", |
1098 |
i++; |
pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", |
1099 |
j = k = i; |
pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", |
1100 |
while (j < length) { |
pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); |
1101 |
if (pointer[j] == SE) { |
if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| |
1102 |
if (j+1 == length) |
SLC_FLUSHOUT| SLC_LEVELBITS)) |
1103 |
break; |
debug_output_data ("(0x%x)", pointer[i+SLC_FLAGS]); |
1104 |
if (pointer[j+1] == SE) |
debug_output_data (" %d;", pointer[i+SLC_VALUE]); |
1105 |
j++; |
|
1106 |
else |
if ((pointer[i+SLC_VALUE] == IAC) && |
1107 |
break; |
(pointer[i+SLC_VALUE+1] == IAC)) |
1108 |
} |
i++; |
1109 |
pointer[k++] = pointer[j++]; |
} |
1110 |
} |
|
1111 |
printsub(0, &pointer[i], k - i); |
for (; i < length; i++) |
1112 |
if (i < length) { |
debug_output_data (" ?%d?", pointer[i]); |
1113 |
sprintf(nfrontp, " SE"); |
break; |
1114 |
nfrontp += strlen(nfrontp); |
|
1115 |
i = j; |
case LM_MODE: |
1116 |
} else |
debug_output_data ("MODE "); |
1117 |
i = j - 1; |
if (length < 3) |
1118 |
|
{ |
1119 |
sprintf(nfrontp, "\r\n"); |
debug_output_data ("(no mode??\?)"); |
1120 |
nfrontp += strlen(nfrontp); |
break; |
1121 |
|
} |
1122 |
break; |
{ |
1123 |
|
char tbuf[32]; |
1124 |
default: |
snprintf(tbuf, sizeof(tbuf), "%s%s%s%s%s", |
1125 |
sprintf(nfrontp, " %d", pointer[i]); |
pointer[2]&MODE_EDIT ? "|EDIT" : "", |
1126 |
nfrontp += strlen(nfrontp); |
pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", |
1127 |
break; |
pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", |
1128 |
} |
pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", |
1129 |
} |
pointer[2]&MODE_ACK ? "|ACK" : ""); |
1130 |
break; |
debug_output_data ("%s", tbuf[1] ? &tbuf[1] : "0"); |
|
} |
|
|
break; |
|
1131 |
} |
} |
1132 |
|
|
1133 |
case TELOPT_XDISPLOC: |
if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) |
1134 |
sprintf(nfrontp, "X-DISPLAY-LOCATION "); |
debug_output_data (" (0x%x)", pointer[2]); |
|
nfrontp += strlen(nfrontp); |
|
|
switch (pointer[1]) { |
|
|
case TELQUAL_IS: |
|
|
sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2); |
|
|
break; |
|
|
case TELQUAL_SEND: |
|
|
sprintf(nfrontp, "SEND"); |
|
|
break; |
|
|
default: |
|
|
sprintf(nfrontp, "- unknown qualifier %d (0x%x).", |
|
|
pointer[1], pointer[1]); |
|
|
} |
|
|
nfrontp += strlen(nfrontp); |
|
|
break; |
|
1135 |
|
|
1136 |
case TELOPT_NEW_ENVIRON: |
for (i = 3; i < length; i++) |
1137 |
sprintf(nfrontp, "NEW-ENVIRON "); |
debug_output_data (" ?0x%x?", pointer[i]); |
1138 |
goto env_common1; |
break; |
1139 |
case TELOPT_OLD_ENVIRON: |
|
1140 |
sprintf(nfrontp, "OLD-ENVIRON"); |
default: |
1141 |
env_common1: |
debug_output_data ("%d (unknown)", pointer[1]); |
1142 |
nfrontp += strlen(nfrontp); |
for (i = 2; i < length; i++) |
1143 |
switch (pointer[1]) { |
debug_output_data (" %d", pointer[i]); |
1144 |
case TELQUAL_IS: |
} |
1145 |
sprintf(nfrontp, "IS "); |
break; |
|
goto env_common; |
|
|
case TELQUAL_SEND: |
|
|
sprintf(nfrontp, "SEND "); |
|
|
goto env_common; |
|
|
case TELQUAL_INFO: |
|
|
sprintf(nfrontp, "INFO "); |
|
|
env_common: |
|
|
nfrontp += strlen(nfrontp); |
|
|
{ |
|
|
register int noquote = 2; |
|
|
for (i = 2; i < length; i++ ) { |
|
|
switch (pointer[i]) { |
|
|
case NEW_ENV_VAR: |
|
|
sprintf(nfrontp, "\" VAR " + noquote); |
|
|
nfrontp += strlen(nfrontp); |
|
|
noquote = 2; |
|
|
break; |
|
1146 |
|
|
1147 |
case NEW_ENV_VALUE: |
case TELOPT_STATUS: |
1148 |
sprintf(nfrontp, "\" VALUE " + noquote); |
{ |
1149 |
nfrontp += strlen(nfrontp); |
register char *cp; |
1150 |
noquote = 2; |
register int j, k; |
|
break; |
|
1151 |
|
|
1152 |
case ENV_ESC: |
debug_output_data ("STATUS"); |
|
sprintf(nfrontp, "\" ESC " + noquote); |
|
|
nfrontp += strlen(nfrontp); |
|
|
noquote = 2; |
|
|
break; |
|
1153 |
|
|
1154 |
case ENV_USERVAR: |
switch (pointer[1]) { |
1155 |
sprintf(nfrontp, "\" USERVAR " + noquote); |
default: |
1156 |
nfrontp += strlen(nfrontp); |
if (pointer[1] == TELQUAL_SEND) |
1157 |
noquote = 2; |
debug_output_data (" SEND"); |
1158 |
|
else |
1159 |
|
debug_output_data (" %d (unknown)", pointer[1]); |
1160 |
|
for (i = 2; i < length; i++) |
1161 |
|
debug_output_data (" ?%d?", pointer[i]); |
1162 |
|
break; |
1163 |
|
|
1164 |
|
case TELQUAL_IS: |
1165 |
|
debug_output_data (" IS\r\n"); |
1166 |
|
|
1167 |
|
for (i = 2; i < length; i++) |
1168 |
|
{ |
1169 |
|
switch(pointer[i]) |
1170 |
|
{ |
1171 |
|
case DO: |
1172 |
|
cp = "DO"; |
1173 |
|
goto common2; |
1174 |
|
|
1175 |
|
case DONT: |
1176 |
|
cp = "DONT"; |
1177 |
|
goto common2; |
1178 |
|
|
1179 |
|
case WILL: |
1180 |
|
cp = "WILL"; |
1181 |
|
goto common2; |
1182 |
|
|
1183 |
|
case WONT: |
1184 |
|
cp = "WONT"; |
1185 |
|
goto common2; |
1186 |
|
|
1187 |
|
common2: |
1188 |
|
i++; |
1189 |
|
if (TELOPT_OK(pointer[i])) |
1190 |
|
debug_output_data (" %s %s\r\n", cp, TELOPT(pointer[i])); |
1191 |
|
else |
1192 |
|
debug_output_data (" %s %d\r\n", cp, pointer[i]); |
1193 |
|
break; |
1194 |
|
|
1195 |
|
case SB: |
1196 |
|
debug_output_data (" SB "); |
1197 |
|
i++; |
1198 |
|
j = k = i; |
1199 |
|
while (j < length) |
1200 |
|
{ |
1201 |
|
if (pointer[j] == SE) |
1202 |
|
{ |
1203 |
|
if (j+1 == length) |
1204 |
break; |
break; |
1205 |
|
if (pointer[j+1] == SE) |
1206 |
default: |
j++; |
1207 |
def_case: |
else |
|
if (isprint(pointer[i]) && pointer[i] != '"') { |
|
|
if (noquote) { |
|
|
*nfrontp++ = '"'; |
|
|
noquote = 0; |
|
|
} |
|
|
*nfrontp++ = pointer[i]; |
|
|
} else { |
|
|
sprintf(nfrontp, "\" %03o " + noquote, |
|
|
pointer[i]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
noquote = 2; |
|
|
} |
|
1208 |
break; |
break; |
1209 |
} |
} |
1210 |
|
pointer[k++] = pointer[j++]; |
1211 |
} |
} |
1212 |
if (!noquote) |
printsub(0, &pointer[i], k - i); |
1213 |
*nfrontp++ = '"'; |
if (i < length) |
1214 |
break; |
{ |
1215 |
|
debug_output_data (" SE"); |
1216 |
|
i = j; |
1217 |
|
} else |
1218 |
|
i = j - 1; |
1219 |
|
|
1220 |
|
debug_output_data ("\r\n"); |
1221 |
|
break; |
1222 |
|
|
1223 |
|
default: |
1224 |
|
debug_output_data (" %d", pointer[i]); |
1225 |
|
break; |
1226 |
} |
} |
1227 |
} |
} |
1228 |
break; |
break; |
1229 |
|
} |
1230 |
|
break; |
1231 |
|
} |
1232 |
|
|
1233 |
#if defined(AUTHENTICATION) |
case TELOPT_XDISPLOC: |
1234 |
case TELOPT_AUTHENTICATION: |
debug_output_data ("X-DISPLAY-LOCATION "); |
1235 |
sprintf(nfrontp, "AUTHENTICATION"); |
switch (pointer[1]) |
1236 |
nfrontp += strlen(nfrontp); |
{ |
1237 |
|
case TELQUAL_IS: |
1238 |
if (length < 2) { |
debug_output_data ("IS \"%.*s\"", length-2, (char *)pointer+2); |
1239 |
sprintf(nfrontp, " (empty suboption??\?)"); |
break; |
1240 |
nfrontp += strlen(nfrontp); |
case TELQUAL_SEND: |
1241 |
break; |
debug_output_data ("SEND"); |
1242 |
} |
break; |
1243 |
switch (pointer[1]) { |
default: |
1244 |
case TELQUAL_REPLY: |
debug_output_data ("- unknown qualifier %d (0x%x).", |
1245 |
case TELQUAL_IS: |
pointer[1], pointer[1]); |
1246 |
sprintf(nfrontp, " %s ", (pointer[1] == TELQUAL_IS) ? |
} |
1247 |
"IS" : "REPLY"); |
break; |
1248 |
nfrontp += strlen(nfrontp); |
|
1249 |
if (AUTHTYPE_NAME_OK(pointer[2])) |
case TELOPT_NEW_ENVIRON: |
1250 |
sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[2])); |
debug_output_data ("NEW-ENVIRON "); |
1251 |
else |
goto env_common1; |
1252 |
sprintf(nfrontp, "%d ", pointer[2]); |
|
1253 |
nfrontp += strlen(nfrontp); |
case TELOPT_OLD_ENVIRON: |
1254 |
if (length < 3) { |
debug_output_data ("OLD-ENVIRON"); |
1255 |
sprintf(nfrontp, "(partial suboption??\?)"); |
env_common1: |
1256 |
nfrontp += strlen(nfrontp); |
switch (pointer[1]) |
1257 |
|
{ |
1258 |
|
case TELQUAL_IS: |
1259 |
|
debug_output_data ("IS "); |
1260 |
|
goto env_common; |
1261 |
|
|
1262 |
|
case TELQUAL_SEND: |
1263 |
|
debug_output_data ("SEND "); |
1264 |
|
goto env_common; |
1265 |
|
|
1266 |
|
case TELQUAL_INFO: |
1267 |
|
debug_output_data ("INFO "); |
1268 |
|
|
1269 |
|
env_common: |
1270 |
|
{ |
1271 |
|
register int noquote = 2; |
1272 |
|
for (i = 2; i < length; i++ ) |
1273 |
|
{ |
1274 |
|
switch (pointer[i]) |
1275 |
|
{ |
1276 |
|
case NEW_ENV_VAR: |
1277 |
|
debug_output_data ("\" VAR " + noquote); |
1278 |
|
noquote = 2; |
1279 |
|
break; |
1280 |
|
|
1281 |
|
case NEW_ENV_VALUE: |
1282 |
|
debug_output_data ("\" VALUE " + noquote); |
1283 |
|
noquote = 2; |
1284 |
break; |
break; |
|
} |
|
|
sprintf(nfrontp, "%s|%s", |
|
|
((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? |
|
|
"CLIENT" : "SERVER", |
|
|
((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? |
|
|
"MUTUAL" : "ONE-WAY"); |
|
|
nfrontp += strlen(nfrontp); |
|
|
|
|
|
auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); |
|
|
sprintf(nfrontp, "%s", buf); |
|
|
nfrontp += strlen(nfrontp); |
|
|
break; |
|
1285 |
|
|
1286 |
case TELQUAL_SEND: |
case ENV_ESC: |
1287 |
i = 2; |
debug_output_data ("\" ESC " + noquote); |
1288 |
sprintf(nfrontp, " SEND "); |
noquote = 2; |
1289 |
nfrontp += strlen(nfrontp); |
break; |
1290 |
while (i < length) { |
|
1291 |
if (AUTHTYPE_NAME_OK(pointer[i])) |
case ENV_USERVAR: |
1292 |
sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[i])); |
debug_output_data ("\" USERVAR " + noquote); |
1293 |
|
noquote = 2; |
1294 |
|
break; |
1295 |
|
|
1296 |
|
default: |
1297 |
|
def_case: |
1298 |
|
if (isprint(pointer[i]) && pointer[i] != '"') |
1299 |
|
{ |
1300 |
|
if (noquote) |
1301 |
|
{ |
1302 |
|
debug_output_data ("\""); |
1303 |
|
noquote = 0; |
1304 |
|
} |
1305 |
|
debug_output_datalen (&pointer[i], 1); |
1306 |
|
} |
1307 |
else |
else |
1308 |
sprintf(nfrontp, "%d ", pointer[i]); |
{ |
1309 |
nfrontp += strlen(nfrontp); |
debug_output_data ("\" %03o " + noquote, |
1310 |
if (++i >= length) { |
pointer[i]); |
1311 |
sprintf(nfrontp, "(partial suboption??\?)"); |
noquote = 2; |
1312 |
nfrontp += strlen(nfrontp); |
} |
|
break; |
|
|
} |
|
|
sprintf(nfrontp, "%s|%s ", |
|
|
((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? |
|
|
"CLIENT" : "SERVER", |
|
|
((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? |
|
|
"MUTUAL" : "ONE-WAY"); |
|
|
nfrontp += strlen(nfrontp); |
|
|
++i; |
|
|
} |
|
|
break; |
|
|
|
|
|
case TELQUAL_NAME: |
|
|
i = 2; |
|
|
sprintf(nfrontp, " NAME \""); |
|
|
nfrontp += strlen(nfrontp); |
|
|
while (i < length) |
|
|
*nfrontp += pointer[i++]; |
|
|
*nfrontp += '"'; |
|
|
break; |
|
|
|
|
|
default: |
|
|
for (i = 2; i < length; i++) { |
|
|
sprintf(nfrontp, " ?%d?", pointer[i]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
} |
|
1313 |
break; |
break; |
1314 |
} |
} |
1315 |
|
} |
1316 |
|
if (!noquote) |
1317 |
|
debug_output_data ("\""); |
1318 |
break; |
break; |
1319 |
#endif |
} |
1320 |
|
} |
1321 |
#ifdef ENCRYPTION |
break; |
|
case TELOPT_ENCRYPT: |
|
|
sprintf(nfrontp, "ENCRYPT"); |
|
|
nfrontp += strlen(nfrontp); |
|
|
if (length < 2) { |
|
|
sprintf(nfrontp, " (empty suboption??\?)"); |
|
|
nfrontp += strlen(nfrontp); |
|
|
break; |
|
|
} |
|
|
switch (pointer[1]) { |
|
|
case ENCRYPT_START: |
|
|
sprintf(nfrontp, " START"); |
|
|
nfrontp += strlen(nfrontp); |
|
|
break; |
|
|
|
|
|
case ENCRYPT_END: |
|
|
sprintf(nfrontp, " END"); |
|
|
nfrontp += strlen(nfrontp); |
|
|
break; |
|
|
|
|
|
case ENCRYPT_REQSTART: |
|
|
sprintf(nfrontp, " REQUEST-START"); |
|
|
nfrontp += strlen(nfrontp); |
|
|
break; |
|
|
|
|
|
case ENCRYPT_REQEND: |
|
|
sprintf(nfrontp, " REQUEST-END"); |
|
|
nfrontp += strlen(nfrontp); |
|
|
break; |
|
1322 |
|
|
1323 |
case ENCRYPT_IS: |
#if defined(AUTHENTICATION) |
1324 |
case ENCRYPT_REPLY: |
case TELOPT_AUTHENTICATION: |
1325 |
sprintf(nfrontp, " %s ", (pointer[1] == ENCRYPT_IS) ? |
debug_output_data ("AUTHENTICATION"); |
|
"IS" : "REPLY"); |
|
|
nfrontp += strlen(nfrontp); |
|
|
if (length < 3) { |
|
|
sprintf(nfrontp, " (partial suboption??\?)"); |
|
|
nfrontp += strlen(nfrontp); |
|
|
break; |
|
|
} |
|
|
if (ENCTYPE_NAME_OK(pointer[2])) |
|
|
sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[2])); |
|
|
else |
|
|
sprintf(nfrontp, " %d (unknown)", pointer[2]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
|
|
|
encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); |
|
|
sprintf(nfrontp, "%s", buf); |
|
|
nfrontp += strlen(nfrontp); |
|
|
break; |
|
1326 |
|
|
1327 |
case ENCRYPT_SUPPORT: |
if (length < 2) |
1328 |
i = 2; |
{ |
1329 |
sprintf(nfrontp, " SUPPORT "); |
debug_output_data (" (empty suboption??\?)"); |
1330 |
nfrontp += strlen(nfrontp); |
break; |
1331 |
while (i < length) { |
} |
1332 |
if (ENCTYPE_NAME_OK(pointer[i])) |
switch (pointer[1]) |
1333 |
sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[i])); |
{ |
1334 |
else |
case TELQUAL_REPLY: |
1335 |
sprintf(nfrontp, "%d ", pointer[i]); |
case TELQUAL_IS: |
1336 |
nfrontp += strlen(nfrontp); |
debug_output_data (" %s ", (pointer[1] == TELQUAL_IS) ? |
1337 |
i++; |
"IS" : "REPLY"); |
1338 |
|
if (AUTHTYPE_NAME_OK(pointer[2])) |
1339 |
|
debug_output_data ("%s ", AUTHTYPE_NAME(pointer[2])); |
1340 |
|
else |
1341 |
|
debug_output_data ("%d ", pointer[2]); |
1342 |
|
if (length < 3) |
1343 |
|
{ |
1344 |
|
debug_output_data ("(partial suboption??\?)"); |
1345 |
|
break; |
1346 |
|
} |
1347 |
|
debug_output_data ("%s|%s", |
1348 |
|
((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? |
1349 |
|
"CLIENT" : "SERVER", |
1350 |
|
((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? |
1351 |
|
"MUTUAL" : "ONE-WAY"); |
1352 |
|
|
1353 |
|
auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); |
1354 |
|
debug_output_data ("%s", buf); |
1355 |
|
break; |
1356 |
|
|
1357 |
|
case TELQUAL_SEND: |
1358 |
|
i = 2; |
1359 |
|
debug_output_data (" SEND "); |
1360 |
|
while (i < length) |
1361 |
|
{ |
1362 |
|
if (AUTHTYPE_NAME_OK(pointer[i])) |
1363 |
|
debug_output_data ("%s ", AUTHTYPE_NAME(pointer[i])); |
1364 |
|
else |
1365 |
|
debug_output_data ("%d ", pointer[i]); |
1366 |
|
if (++i >= length) |
1367 |
|
{ |
1368 |
|
debug_output_data ("(partial suboption??\?)"); |
1369 |
|
break; |
1370 |
} |
} |
1371 |
break; |
debug_output_data ("%s|%s ", |
1372 |
|
((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? |
1373 |
|
"CLIENT" : "SERVER", |
1374 |
|
((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? |
1375 |
|
"MUTUAL" : "ONE-WAY"); |
1376 |
|
++i; |
1377 |
|
} |
1378 |
|
break; |
1379 |
|
|
1380 |
|
case TELQUAL_NAME: |
1381 |
|
i = 2; |
1382 |
|
debug_output_data (" NAME \""); |
1383 |
|
debug_output_datalen (&pointer[i], length); |
1384 |
|
i += length; |
1385 |
|
debug_output_data ("\""); |
1386 |
|
break; |
1387 |
|
|
1388 |
case ENCRYPT_ENC_KEYID: |
default: |
1389 |
sprintf(nfrontp, " ENC_KEYID", pointer[1]); |
for (i = 2; i < length; i++) |
1390 |
nfrontp += strlen(nfrontp); |
debug_output_data (" ?%d?", pointer[i]); |
1391 |
goto encommon; |
break; |
1392 |
|
} |
1393 |
case ENCRYPT_DEC_KEYID: |
break; |
1394 |
sprintf(nfrontp, " DEC_KEYID", pointer[1]); |
#endif |
|
nfrontp += strlen(nfrontp); |
|
|
goto encommon; |
|
1395 |
|
|
1396 |
default: |
#ifdef ENCRYPTION |
1397 |
sprintf(nfrontp, " %d (unknown)", pointer[1]); |
case TELOPT_ENCRYPT: |
1398 |
nfrontp += strlen(nfrontp); |
debug_output_data ("ENCRYPT"); |
1399 |
encommon: |
if (length < 2) |
1400 |
for (i = 2; i < length; i++) { |
{ |
1401 |
sprintf(nfrontp, " %d", pointer[i]); |
debug_output_data (" (empty suboption??\?)"); |
1402 |
nfrontp += strlen(nfrontp); |
break; |
1403 |
} |
} |
1404 |
break; |
switch (pointer[1]) |
1405 |
} |
{ |
1406 |
break; |
case ENCRYPT_START: |
1407 |
#endif /* ENCRYPTION */ |
debug_output_data (" START"); |
1408 |
|
break; |
1409 |
|
|
1410 |
|
case ENCRYPT_END: |
1411 |
|
debug_output_data (" END"); |
1412 |
|
break; |
1413 |
|
|
1414 |
|
case ENCRYPT_REQSTART: |
1415 |
|
debug_output_data (" REQUEST-START"); |
1416 |
|
break; |
1417 |
|
|
1418 |
|
case ENCRYPT_REQEND: |
1419 |
|
debug_output_data (" REQUEST-END"); |
1420 |
|
break; |
1421 |
|
|
1422 |
|
case ENCRYPT_IS: |
1423 |
|
case ENCRYPT_REPLY: |
1424 |
|
debug_output_data (" %s ", (pointer[1] == ENCRYPT_IS) ? |
1425 |
|
"IS" : "REPLY"); |
1426 |
|
if (length < 3) |
1427 |
|
{ |
1428 |
|
debug_output_data (" (partial suboption??\?)"); |
1429 |
|
break; |
1430 |
|
} |
1431 |
|
if (ENCTYPE_NAME_OK(pointer[2])) |
1432 |
|
debug_output_data ("%s ", ENCTYPE_NAME(pointer[2])); |
1433 |
|
else |
1434 |
|
debug_output_data (" %d (unknown)", pointer[2]); |
1435 |
|
|
1436 |
|
encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); |
1437 |
|
debug_output_data ("%s", buf); |
1438 |
|
break; |
1439 |
|
|
1440 |
|
case ENCRYPT_SUPPORT: |
1441 |
|
i = 2; |
1442 |
|
debug_output_data (" SUPPORT "); |
1443 |
|
while (i < length) |
1444 |
|
{ |
1445 |
|
if (ENCTYPE_NAME_OK(pointer[i])) |
1446 |
|
debug_output_data ("%s ", ENCTYPE_NAME(pointer[i])); |
1447 |
|
else |
1448 |
|
debug_output_data ("%d ", pointer[i]); |
1449 |
|
i++; |
1450 |
|
} |
1451 |
|
break; |
1452 |
|
|
1453 |
|
case ENCRYPT_ENC_KEYID: |
1454 |
|
debug_output_data (" ENC_KEYID", pointer[1]); |
1455 |
|
goto encommon; |
1456 |
|
|
1457 |
|
case ENCRYPT_DEC_KEYID: |
1458 |
|
debug_output_data (" DEC_KEYID", pointer[1]); |
1459 |
|
goto encommon; |
1460 |
|
|
1461 |
default: |
default: |
1462 |
if (TELOPT_OK(pointer[0])) |
debug_output_data (" %d (unknown)", pointer[1]); |
1463 |
sprintf(nfrontp, "%s (unknown)", TELOPT(pointer[0])); |
encommon: |
1464 |
else |
for (i = 2; i < length; i++) |
1465 |
sprintf(nfrontp, "%d (unknown)", pointer[i]); |
debug_output_data (" %d", pointer[i]); |
1466 |
nfrontp += strlen(nfrontp); |
break; |
|
for (i = 1; i < length; i++) { |
|
|
sprintf(nfrontp, " %d", pointer[i]); |
|
|
nfrontp += strlen(nfrontp); |
|
|
} |
|
|
break; |
|
1467 |
} |
} |
1468 |
sprintf(nfrontp, "\r\n"); |
break; |
1469 |
nfrontp += strlen(nfrontp); |
#endif /* ENCRYPTION */ |
1470 |
|
|
1471 |
|
default: |
1472 |
|
if (TELOPT_OK(pointer[0])) |
1473 |
|
debug_output_data ("%s (unknown)", TELOPT(pointer[0])); |
1474 |
|
else |
1475 |
|
debug_output_data ("%d (unknown)", pointer[i]); |
1476 |
|
for (i = 1; i < length; i++) |
1477 |
|
debug_output_data (" %d", pointer[i]); |
1478 |
|
break; |
1479 |
|
} |
1480 |
|
debug_output_data ("\r\n"); |
1481 |
} |
} |
1482 |
|
|
1483 |
/* |
/* |
1484 |
* Dump a data buffer in hex and ascii to the output data stream. |
* Dump a data buffer in hex and ascii to the output data stream. |
1485 |
*/ |
*/ |
1486 |
void |
void |
1487 |
printdata(register char *tag, register char *ptr, register int cnt |
printdata(register char *tag, register char *ptr, register int cnt) |
1488 |
{ |
{ |
1489 |
register int i; |
register int i; |
1490 |
char xbuf[30]; |
char xbuf[30]; |
1491 |
|
|
1492 |
while (cnt) { |
while (cnt) |
1493 |
/* flush net output buffer if no room for new data) */ |
{ |
1494 |
if ((&netobuf[BUFSIZ] - nfrontp) < 80) { |
/* add a line of output */ |
1495 |
netflush(); |
debug_output_data ("%s: ", tag); |
1496 |
} |
for (i = 0; i < 20 && cnt; i++) |
1497 |
|
{ |
1498 |
|
debug_output_data ("%02x", *ptr); |
1499 |
|
xbuf[i] = isprint(*ptr) ? *ptr : '.'; |
1500 |
|
|
1501 |
/* add a line of output */ |
if (i % 2) |
1502 |
sprintf(nfrontp, "%s: ", tag); |
debug_output_data (" "); |
1503 |
nfrontp += strlen(nfrontp); |
cnt--; |
1504 |
for (i = 0; i < 20 && cnt; i++) { |
ptr++; |
|
sprintf(nfrontp, "%02x", *ptr); |
|
|
nfrontp += strlen(nfrontp); |
|
|
if (isprint(*ptr)) { |
|
|
xbuf[i] = *ptr; |
|
|
} else { |
|
|
xbuf[i] = '.'; |
|
|
} |
|
|
if (i % 2) { |
|
|
*nfrontp = ' '; |
|
|
nfrontp++; |
|
|
} |
|
|
cnt--; |
|
|
ptr++; |
|
|
} |
|
|
xbuf[i] = '\0'; |
|
|
sprintf(nfrontp, " %s\r\n", xbuf ); |
|
|
nfrontp += strlen(nfrontp); |
|
1505 |
} |
} |
1506 |
|
|
1507 |
|
xbuf[i] = '\0'; |
1508 |
|
debug_output_data (" %s\r\n", xbuf ); |
1509 |
|
} |
1510 |
} |
} |
1511 |
#endif /* DIAGNOSTICS */ |
|
1512 |
|
#if defined(AUTHENTICATION) || defined(ENCRYPTION) |
1513 |
|
|
1514 |
|
int |
1515 |
|
net_write (unsigned char *str, int len) |
1516 |
|
{ |
1517 |
|
return net_output_datalen (str, len); |
1518 |
|
} |
1519 |
|
|
1520 |
|
void |
1521 |
|
net_encrypt () |
1522 |
|
{ |
1523 |
|
#ifdef ENCRYPTION |
1524 |
|
char *s = (nclearto > nbackp) ? nclearto : nbackp; |
1525 |
|
if (s < nfrontp && encrypt_output) |
1526 |
|
(*encrypt_output)((unsigned char *)s, nfrontp - s); |
1527 |
|
nclearto = nfrontp; |
1528 |
|
#endif /* ENCRYPTION */ |
1529 |
|
} |
1530 |
|
|
1531 |
|
int |
1532 |
|
telnet_spin() |
1533 |
|
{ |
1534 |
|
io_drain (); |
1535 |
|
return 0; |
1536 |
|
} |
1537 |
|
|
1538 |
|
|
1539 |
|
#endif |