1*e044bafaSDavid van Moolenbroek /* $NetBSD: utility.c,v 1.32 2012/01/09 16:36:48 christos Exp $ */
2*e044bafaSDavid van Moolenbroek
3*e044bafaSDavid van Moolenbroek /*
4*e044bafaSDavid van Moolenbroek * Copyright (c) 1989, 1993
5*e044bafaSDavid van Moolenbroek * The Regents of the University of California. All rights reserved.
6*e044bafaSDavid van Moolenbroek *
7*e044bafaSDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
8*e044bafaSDavid van Moolenbroek * modification, are permitted provided that the following conditions
9*e044bafaSDavid van Moolenbroek * are met:
10*e044bafaSDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
11*e044bafaSDavid van Moolenbroek * notice, this list of conditions and the following disclaimer.
12*e044bafaSDavid van Moolenbroek * 2. Redistributions in binary form must reproduce the above copyright
13*e044bafaSDavid van Moolenbroek * notice, this list of conditions and the following disclaimer in the
14*e044bafaSDavid van Moolenbroek * documentation and/or other materials provided with the distribution.
15*e044bafaSDavid van Moolenbroek * 3. Neither the name of the University nor the names of its contributors
16*e044bafaSDavid van Moolenbroek * may be used to endorse or promote products derived from this software
17*e044bafaSDavid van Moolenbroek * without specific prior written permission.
18*e044bafaSDavid van Moolenbroek *
19*e044bafaSDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*e044bafaSDavid van Moolenbroek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*e044bafaSDavid van Moolenbroek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*e044bafaSDavid van Moolenbroek * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*e044bafaSDavid van Moolenbroek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*e044bafaSDavid van Moolenbroek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*e044bafaSDavid van Moolenbroek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*e044bafaSDavid van Moolenbroek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*e044bafaSDavid van Moolenbroek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*e044bafaSDavid van Moolenbroek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*e044bafaSDavid van Moolenbroek * SUCH DAMAGE.
30*e044bafaSDavid van Moolenbroek */
31*e044bafaSDavid van Moolenbroek
32*e044bafaSDavid van Moolenbroek #include <sys/cdefs.h>
33*e044bafaSDavid van Moolenbroek #ifndef lint
34*e044bafaSDavid van Moolenbroek #if 0
35*e044bafaSDavid van Moolenbroek static char sccsid[] = "@(#)utility.c 8.4 (Berkeley) 5/30/95";
36*e044bafaSDavid van Moolenbroek #else
37*e044bafaSDavid van Moolenbroek __RCSID("$NetBSD: utility.c,v 1.32 2012/01/09 16:36:48 christos Exp $");
38*e044bafaSDavid van Moolenbroek #endif
39*e044bafaSDavid van Moolenbroek #endif /* not lint */
40*e044bafaSDavid van Moolenbroek
41*e044bafaSDavid van Moolenbroek #include <sys/utsname.h>
42*e044bafaSDavid van Moolenbroek #include <ctype.h>
43*e044bafaSDavid van Moolenbroek #define PRINTOPTIONS
44*e044bafaSDavid van Moolenbroek #include "telnetd.h"
45*e044bafaSDavid van Moolenbroek
46*e044bafaSDavid van Moolenbroek char *nextitem(char *);
47*e044bafaSDavid van Moolenbroek void putstr(char *);
48*e044bafaSDavid van Moolenbroek
49*e044bafaSDavid van Moolenbroek extern int not42;
50*e044bafaSDavid van Moolenbroek
51*e044bafaSDavid van Moolenbroek /*
52*e044bafaSDavid van Moolenbroek * utility functions performing io related tasks
53*e044bafaSDavid van Moolenbroek */
54*e044bafaSDavid van Moolenbroek
55*e044bafaSDavid van Moolenbroek /*
56*e044bafaSDavid van Moolenbroek * ttloop
57*e044bafaSDavid van Moolenbroek *
58*e044bafaSDavid van Moolenbroek * A small subroutine to flush the network output buffer, get some data
59*e044bafaSDavid van Moolenbroek * from the network, and pass it through the telnet state machine. We
60*e044bafaSDavid van Moolenbroek * also flush the pty input buffer (by dropping its data) if it becomes
61*e044bafaSDavid van Moolenbroek * too full.
62*e044bafaSDavid van Moolenbroek */
63*e044bafaSDavid van Moolenbroek
64*e044bafaSDavid van Moolenbroek void
ttloop(void)65*e044bafaSDavid van Moolenbroek ttloop(void)
66*e044bafaSDavid van Moolenbroek {
67*e044bafaSDavid van Moolenbroek
68*e044bafaSDavid van Moolenbroek DIAG(TD_REPORT, {output_data("td: ttloop\r\n");});
69*e044bafaSDavid van Moolenbroek if (nfrontp - nbackp) {
70*e044bafaSDavid van Moolenbroek netflush();
71*e044bafaSDavid van Moolenbroek }
72*e044bafaSDavid van Moolenbroek ncc = read(net, netibuf, sizeof netibuf);
73*e044bafaSDavid van Moolenbroek if (ncc < 0) {
74*e044bafaSDavid van Moolenbroek syslog(LOG_ERR, "ttloop: read: %m");
75*e044bafaSDavid van Moolenbroek exit(1);
76*e044bafaSDavid van Moolenbroek } else if (ncc == 0) {
77*e044bafaSDavid van Moolenbroek syslog(LOG_INFO, "ttloop: unexpected EOF from peer");
78*e044bafaSDavid van Moolenbroek exit(1);
79*e044bafaSDavid van Moolenbroek }
80*e044bafaSDavid van Moolenbroek DIAG(TD_REPORT, {output_data("td: ttloop read %d chars\r\n", ncc);});
81*e044bafaSDavid van Moolenbroek netip = netibuf;
82*e044bafaSDavid van Moolenbroek telrcv(); /* state machine */
83*e044bafaSDavid van Moolenbroek if (ncc > 0) {
84*e044bafaSDavid van Moolenbroek pfrontp = pbackp = ptyobuf;
85*e044bafaSDavid van Moolenbroek telrcv();
86*e044bafaSDavid van Moolenbroek }
87*e044bafaSDavid van Moolenbroek } /* end of ttloop */
88*e044bafaSDavid van Moolenbroek
89*e044bafaSDavid van Moolenbroek /*
90*e044bafaSDavid van Moolenbroek * Check a descriptor to see if out of band data exists on it.
91*e044bafaSDavid van Moolenbroek */
92*e044bafaSDavid van Moolenbroek int
stilloob(int s)93*e044bafaSDavid van Moolenbroek stilloob(int s /* socket number */)
94*e044bafaSDavid van Moolenbroek {
95*e044bafaSDavid van Moolenbroek struct pollfd set[1];
96*e044bafaSDavid van Moolenbroek int value;
97*e044bafaSDavid van Moolenbroek
98*e044bafaSDavid van Moolenbroek set[0].fd = s;
99*e044bafaSDavid van Moolenbroek set[0].events = POLLPRI;
100*e044bafaSDavid van Moolenbroek do {
101*e044bafaSDavid van Moolenbroek value = poll(set, 1, 0);
102*e044bafaSDavid van Moolenbroek } while ((value == -1) && (errno == EINTR));
103*e044bafaSDavid van Moolenbroek
104*e044bafaSDavid van Moolenbroek if (value < 0) {
105*e044bafaSDavid van Moolenbroek fatalperror(pty, "poll");
106*e044bafaSDavid van Moolenbroek }
107*e044bafaSDavid van Moolenbroek if (set[0].revents & POLLPRI) {
108*e044bafaSDavid van Moolenbroek return 1;
109*e044bafaSDavid van Moolenbroek } else {
110*e044bafaSDavid van Moolenbroek return 0;
111*e044bafaSDavid van Moolenbroek }
112*e044bafaSDavid van Moolenbroek }
113*e044bafaSDavid van Moolenbroek
114*e044bafaSDavid van Moolenbroek void
ptyflush(void)115*e044bafaSDavid van Moolenbroek ptyflush(void)
116*e044bafaSDavid van Moolenbroek {
117*e044bafaSDavid van Moolenbroek int n;
118*e044bafaSDavid van Moolenbroek
119*e044bafaSDavid van Moolenbroek if ((n = pfrontp - pbackp) > 0) {
120*e044bafaSDavid van Moolenbroek DIAG((TD_REPORT | TD_PTYDATA),
121*e044bafaSDavid van Moolenbroek { output_data("td: ptyflush %d chars\r\n", n); });
122*e044bafaSDavid van Moolenbroek DIAG(TD_PTYDATA, printdata("pd", pbackp, n));
123*e044bafaSDavid van Moolenbroek n = write(pty, pbackp, n);
124*e044bafaSDavid van Moolenbroek }
125*e044bafaSDavid van Moolenbroek if (n < 0) {
126*e044bafaSDavid van Moolenbroek if (errno == EWOULDBLOCK || errno == EINTR)
127*e044bafaSDavid van Moolenbroek return;
128*e044bafaSDavid van Moolenbroek cleanup(0);
129*e044bafaSDavid van Moolenbroek }
130*e044bafaSDavid van Moolenbroek pbackp += n;
131*e044bafaSDavid van Moolenbroek if (pbackp == pfrontp)
132*e044bafaSDavid van Moolenbroek pbackp = pfrontp = ptyobuf;
133*e044bafaSDavid van Moolenbroek }
134*e044bafaSDavid van Moolenbroek
135*e044bafaSDavid van Moolenbroek /*
136*e044bafaSDavid van Moolenbroek * nextitem()
137*e044bafaSDavid van Moolenbroek *
138*e044bafaSDavid van Moolenbroek * Return the address of the next "item" in the TELNET data
139*e044bafaSDavid van Moolenbroek * stream. This will be the address of the next character if
140*e044bafaSDavid van Moolenbroek * the current address is a user data character, or it will
141*e044bafaSDavid van Moolenbroek * be the address of the character following the TELNET command
142*e044bafaSDavid van Moolenbroek * if the current address is a TELNET IAC ("I Am a Command")
143*e044bafaSDavid van Moolenbroek * character.
144*e044bafaSDavid van Moolenbroek */
145*e044bafaSDavid van Moolenbroek char *
nextitem(char * current)146*e044bafaSDavid van Moolenbroek nextitem(char *current)
147*e044bafaSDavid van Moolenbroek {
148*e044bafaSDavid van Moolenbroek if ((*current&0xff) != IAC) {
149*e044bafaSDavid van Moolenbroek return current+1;
150*e044bafaSDavid van Moolenbroek }
151*e044bafaSDavid van Moolenbroek switch (*(current+1)&0xff) {
152*e044bafaSDavid van Moolenbroek case DO:
153*e044bafaSDavid van Moolenbroek case DONT:
154*e044bafaSDavid van Moolenbroek case WILL:
155*e044bafaSDavid van Moolenbroek case WONT:
156*e044bafaSDavid van Moolenbroek return current+3;
157*e044bafaSDavid van Moolenbroek case SB: /* loop forever looking for the SE */
158*e044bafaSDavid van Moolenbroek {
159*e044bafaSDavid van Moolenbroek char *look = current+2;
160*e044bafaSDavid van Moolenbroek
161*e044bafaSDavid van Moolenbroek for (;;) {
162*e044bafaSDavid van Moolenbroek if ((*look++&0xff) == IAC) {
163*e044bafaSDavid van Moolenbroek if ((*look++&0xff) == SE) {
164*e044bafaSDavid van Moolenbroek return look;
165*e044bafaSDavid van Moolenbroek }
166*e044bafaSDavid van Moolenbroek }
167*e044bafaSDavid van Moolenbroek }
168*e044bafaSDavid van Moolenbroek }
169*e044bafaSDavid van Moolenbroek default:
170*e044bafaSDavid van Moolenbroek return current+2;
171*e044bafaSDavid van Moolenbroek }
172*e044bafaSDavid van Moolenbroek } /* end of nextitem */
173*e044bafaSDavid van Moolenbroek
174*e044bafaSDavid van Moolenbroek
175*e044bafaSDavid van Moolenbroek /*
176*e044bafaSDavid van Moolenbroek * netclear()
177*e044bafaSDavid van Moolenbroek *
178*e044bafaSDavid van Moolenbroek * We are about to do a TELNET SYNCH operation. Clear
179*e044bafaSDavid van Moolenbroek * the path to the network.
180*e044bafaSDavid van Moolenbroek *
181*e044bafaSDavid van Moolenbroek * Things are a bit tricky since we may have sent the first
182*e044bafaSDavid van Moolenbroek * byte or so of a previous TELNET command into the network.
183*e044bafaSDavid van Moolenbroek * So, we have to scan the network buffer from the beginning
184*e044bafaSDavid van Moolenbroek * until we are up to where we want to be.
185*e044bafaSDavid van Moolenbroek *
186*e044bafaSDavid van Moolenbroek * A side effect of what we do, just to keep things
187*e044bafaSDavid van Moolenbroek * simple, is to clear the urgent data pointer. The principal
188*e044bafaSDavid van Moolenbroek * caller should be setting the urgent data pointer AFTER calling
189*e044bafaSDavid van Moolenbroek * us in any case.
190*e044bafaSDavid van Moolenbroek */
191*e044bafaSDavid van Moolenbroek void
netclear(void)192*e044bafaSDavid van Moolenbroek netclear(void)
193*e044bafaSDavid van Moolenbroek {
194*e044bafaSDavid van Moolenbroek char *thisitem, *next;
195*e044bafaSDavid van Moolenbroek char *good;
196*e044bafaSDavid van Moolenbroek #define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
197*e044bafaSDavid van Moolenbroek ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
198*e044bafaSDavid van Moolenbroek
199*e044bafaSDavid van Moolenbroek #ifdef ENCRYPTION
200*e044bafaSDavid van Moolenbroek thisitem = nclearto > netobuf ? nclearto : netobuf;
201*e044bafaSDavid van Moolenbroek #else /* ENCRYPTION */
202*e044bafaSDavid van Moolenbroek thisitem = netobuf;
203*e044bafaSDavid van Moolenbroek #endif /* ENCRYPTION */
204*e044bafaSDavid van Moolenbroek
205*e044bafaSDavid van Moolenbroek while ((next = nextitem(thisitem)) <= nbackp) {
206*e044bafaSDavid van Moolenbroek thisitem = next;
207*e044bafaSDavid van Moolenbroek }
208*e044bafaSDavid van Moolenbroek
209*e044bafaSDavid van Moolenbroek /* Now, thisitem is first before/at boundary. */
210*e044bafaSDavid van Moolenbroek
211*e044bafaSDavid van Moolenbroek #ifdef ENCRYPTION
212*e044bafaSDavid van Moolenbroek good = nclearto > netobuf ? nclearto : netobuf;
213*e044bafaSDavid van Moolenbroek #else /* ENCRYPTION */
214*e044bafaSDavid van Moolenbroek good = netobuf; /* where the good bytes go */
215*e044bafaSDavid van Moolenbroek #endif /* ENCRYPTION */
216*e044bafaSDavid van Moolenbroek
217*e044bafaSDavid van Moolenbroek while (nfrontp > thisitem) {
218*e044bafaSDavid van Moolenbroek if (wewant(thisitem)) {
219*e044bafaSDavid van Moolenbroek int length;
220*e044bafaSDavid van Moolenbroek
221*e044bafaSDavid van Moolenbroek next = thisitem;
222*e044bafaSDavid van Moolenbroek do {
223*e044bafaSDavid van Moolenbroek next = nextitem(next);
224*e044bafaSDavid van Moolenbroek } while (wewant(next) && (nfrontp > next));
225*e044bafaSDavid van Moolenbroek length = next-thisitem;
226*e044bafaSDavid van Moolenbroek memmove(good, thisitem, length);
227*e044bafaSDavid van Moolenbroek good += length;
228*e044bafaSDavid van Moolenbroek thisitem = next;
229*e044bafaSDavid van Moolenbroek } else {
230*e044bafaSDavid van Moolenbroek thisitem = nextitem(thisitem);
231*e044bafaSDavid van Moolenbroek }
232*e044bafaSDavid van Moolenbroek }
233*e044bafaSDavid van Moolenbroek
234*e044bafaSDavid van Moolenbroek nbackp = netobuf;
235*e044bafaSDavid van Moolenbroek nfrontp = good; /* next byte to be sent */
236*e044bafaSDavid van Moolenbroek neturg = 0;
237*e044bafaSDavid van Moolenbroek } /* end of netclear */
238*e044bafaSDavid van Moolenbroek
239*e044bafaSDavid van Moolenbroek /*
240*e044bafaSDavid van Moolenbroek * netflush
241*e044bafaSDavid van Moolenbroek * Send as much data as possible to the network,
242*e044bafaSDavid van Moolenbroek * handling requests for urgent data.
243*e044bafaSDavid van Moolenbroek */
244*e044bafaSDavid van Moolenbroek void
netflush(void)245*e044bafaSDavid van Moolenbroek netflush(void)
246*e044bafaSDavid van Moolenbroek {
247*e044bafaSDavid van Moolenbroek int n;
248*e044bafaSDavid van Moolenbroek
249*e044bafaSDavid van Moolenbroek if ((n = nfrontp - nbackp) > 0) {
250*e044bafaSDavid van Moolenbroek DIAG(TD_REPORT,
251*e044bafaSDavid van Moolenbroek { output_data("td: netflush %d chars\r\n", n);
252*e044bafaSDavid van Moolenbroek n = nfrontp - nbackp; /* re-compute count */
253*e044bafaSDavid van Moolenbroek });
254*e044bafaSDavid van Moolenbroek #ifdef ENCRYPTION
255*e044bafaSDavid van Moolenbroek if (encrypt_output) {
256*e044bafaSDavid van Moolenbroek char *s = nclearto ? nclearto : nbackp;
257*e044bafaSDavid van Moolenbroek if (nfrontp - s > 0) {
258*e044bafaSDavid van Moolenbroek (*encrypt_output)((unsigned char *)s, nfrontp - s);
259*e044bafaSDavid van Moolenbroek nclearto = nfrontp;
260*e044bafaSDavid van Moolenbroek }
261*e044bafaSDavid van Moolenbroek }
262*e044bafaSDavid van Moolenbroek #endif /* ENCRYPTION */
263*e044bafaSDavid van Moolenbroek /*
264*e044bafaSDavid van Moolenbroek * if no urgent data, or if the other side appears to be an
265*e044bafaSDavid van Moolenbroek * old 4.2 client (and thus unable to survive TCP urgent data),
266*e044bafaSDavid van Moolenbroek * write the entire buffer in non-OOB mode.
267*e044bafaSDavid van Moolenbroek */
268*e044bafaSDavid van Moolenbroek if ((neturg == 0) || (not42 == 0)) {
269*e044bafaSDavid van Moolenbroek n = write(net, nbackp, n); /* normal write */
270*e044bafaSDavid van Moolenbroek } else {
271*e044bafaSDavid van Moolenbroek n = neturg - nbackp;
272*e044bafaSDavid van Moolenbroek /*
273*e044bafaSDavid van Moolenbroek * In 4.2 (and 4.3) systems, there is some question about
274*e044bafaSDavid van Moolenbroek * what byte in a sendOOB operation is the "OOB" data.
275*e044bafaSDavid van Moolenbroek * To make ourselves compatible, we only send ONE byte
276*e044bafaSDavid van Moolenbroek * out of band, the one WE THINK should be OOB (though
277*e044bafaSDavid van Moolenbroek * we really have more the TCP philosophy of urgent data
278*e044bafaSDavid van Moolenbroek * rather than the Unix philosophy of OOB data).
279*e044bafaSDavid van Moolenbroek */
280*e044bafaSDavid van Moolenbroek if (n > 1) {
281*e044bafaSDavid van Moolenbroek n = send(net, nbackp, n-1, 0); /* send URGENT all by itself */
282*e044bafaSDavid van Moolenbroek } else {
283*e044bafaSDavid van Moolenbroek n = send(net, nbackp, n, MSG_OOB); /* URGENT data */
284*e044bafaSDavid van Moolenbroek }
285*e044bafaSDavid van Moolenbroek }
286*e044bafaSDavid van Moolenbroek }
287*e044bafaSDavid van Moolenbroek if (n < 0) {
288*e044bafaSDavid van Moolenbroek if (errno == EWOULDBLOCK || errno == EINTR)
289*e044bafaSDavid van Moolenbroek return;
290*e044bafaSDavid van Moolenbroek cleanup(0);
291*e044bafaSDavid van Moolenbroek }
292*e044bafaSDavid van Moolenbroek nbackp += n;
293*e044bafaSDavid van Moolenbroek #ifdef ENCRYPTION
294*e044bafaSDavid van Moolenbroek if (nbackp > nclearto)
295*e044bafaSDavid van Moolenbroek nclearto = 0;
296*e044bafaSDavid van Moolenbroek #endif /* ENCRYPTION */
297*e044bafaSDavid van Moolenbroek if (nbackp >= neturg) {
298*e044bafaSDavid van Moolenbroek neturg = 0;
299*e044bafaSDavid van Moolenbroek }
300*e044bafaSDavid van Moolenbroek if (nbackp == nfrontp) {
301*e044bafaSDavid van Moolenbroek nbackp = nfrontp = netobuf;
302*e044bafaSDavid van Moolenbroek #ifdef ENCRYPTION
303*e044bafaSDavid van Moolenbroek nclearto = 0;
304*e044bafaSDavid van Moolenbroek #endif /* ENCRYPTION */
305*e044bafaSDavid van Moolenbroek }
306*e044bafaSDavid van Moolenbroek return;
307*e044bafaSDavid van Moolenbroek } /* end of netflush */
308*e044bafaSDavid van Moolenbroek
309*e044bafaSDavid van Moolenbroek
310*e044bafaSDavid van Moolenbroek /*
311*e044bafaSDavid van Moolenbroek * writenet
312*e044bafaSDavid van Moolenbroek *
313*e044bafaSDavid van Moolenbroek * Just a handy little function to write a bit of raw data to the net.
314*e044bafaSDavid van Moolenbroek * It will force a transmit of the buffer if necessary
315*e044bafaSDavid van Moolenbroek *
316*e044bafaSDavid van Moolenbroek * arguments
317*e044bafaSDavid van Moolenbroek * ptr - A pointer to a character string to write
318*e044bafaSDavid van Moolenbroek * len - How many bytes to write
319*e044bafaSDavid van Moolenbroek */
320*e044bafaSDavid van Moolenbroek void
writenet(unsigned char * ptr,int len)321*e044bafaSDavid van Moolenbroek writenet(unsigned char *ptr, int len)
322*e044bafaSDavid van Moolenbroek {
323*e044bafaSDavid van Moolenbroek /* flush buffer if no room for new data) */
324*e044bafaSDavid van Moolenbroek if ((&netobuf[BUFSIZ] - nfrontp) < len) {
325*e044bafaSDavid van Moolenbroek /* if this fails, don't worry, buffer is a little big */
326*e044bafaSDavid van Moolenbroek netflush();
327*e044bafaSDavid van Moolenbroek }
328*e044bafaSDavid van Moolenbroek
329*e044bafaSDavid van Moolenbroek memmove(nfrontp, ptr, len);
330*e044bafaSDavid van Moolenbroek nfrontp += len;
331*e044bafaSDavid van Moolenbroek
332*e044bafaSDavid van Moolenbroek } /* end of writenet */
333*e044bafaSDavid van Moolenbroek
334*e044bafaSDavid van Moolenbroek
335*e044bafaSDavid van Moolenbroek /*
336*e044bafaSDavid van Moolenbroek * miscellaneous functions doing a variety of little jobs follow ...
337*e044bafaSDavid van Moolenbroek */
338*e044bafaSDavid van Moolenbroek void
fatal(int f,const char * msg)339*e044bafaSDavid van Moolenbroek fatal(int f, const char *msg)
340*e044bafaSDavid van Moolenbroek {
341*e044bafaSDavid van Moolenbroek char buf[BUFSIZ];
342*e044bafaSDavid van Moolenbroek
343*e044bafaSDavid van Moolenbroek (void)snprintf(buf, sizeof buf, "telnetd: %s.\r\n", msg);
344*e044bafaSDavid van Moolenbroek #ifdef ENCRYPTION
345*e044bafaSDavid van Moolenbroek if (encrypt_output) {
346*e044bafaSDavid van Moolenbroek /*
347*e044bafaSDavid van Moolenbroek * Better turn off encryption first....
348*e044bafaSDavid van Moolenbroek * Hope it flushes...
349*e044bafaSDavid van Moolenbroek */
350*e044bafaSDavid van Moolenbroek encrypt_send_end();
351*e044bafaSDavid van Moolenbroek netflush();
352*e044bafaSDavid van Moolenbroek }
353*e044bafaSDavid van Moolenbroek #endif /* ENCRYPTION */
354*e044bafaSDavid van Moolenbroek (void)write(f, buf, (int)strlen(buf));
355*e044bafaSDavid van Moolenbroek sleep(1); /*XXX*/
356*e044bafaSDavid van Moolenbroek exit(1);
357*e044bafaSDavid van Moolenbroek }
358*e044bafaSDavid van Moolenbroek
359*e044bafaSDavid van Moolenbroek void
fatalperror(f,msg)360*e044bafaSDavid van Moolenbroek fatalperror(f, msg)
361*e044bafaSDavid van Moolenbroek int f;
362*e044bafaSDavid van Moolenbroek const char *msg;
363*e044bafaSDavid van Moolenbroek {
364*e044bafaSDavid van Moolenbroek char buf[BUFSIZ];
365*e044bafaSDavid van Moolenbroek
366*e044bafaSDavid van Moolenbroek (void)snprintf(buf, sizeof buf, "%s: %s", msg, strerror(errno));
367*e044bafaSDavid van Moolenbroek fatal(f, buf);
368*e044bafaSDavid van Moolenbroek }
369*e044bafaSDavid van Moolenbroek
370*e044bafaSDavid van Moolenbroek char editedhost[MAXHOSTNAMELEN];
371*e044bafaSDavid van Moolenbroek
372*e044bafaSDavid van Moolenbroek void
edithost(const char * pat,const char * host)373*e044bafaSDavid van Moolenbroek edithost(const char *pat, const char *host)
374*e044bafaSDavid van Moolenbroek {
375*e044bafaSDavid van Moolenbroek char *res = editedhost;
376*e044bafaSDavid van Moolenbroek
377*e044bafaSDavid van Moolenbroek if (!pat)
378*e044bafaSDavid van Moolenbroek pat = "";
379*e044bafaSDavid van Moolenbroek while (*pat) {
380*e044bafaSDavid van Moolenbroek switch (*pat) {
381*e044bafaSDavid van Moolenbroek
382*e044bafaSDavid van Moolenbroek case '#':
383*e044bafaSDavid van Moolenbroek if (*host)
384*e044bafaSDavid van Moolenbroek host++;
385*e044bafaSDavid van Moolenbroek break;
386*e044bafaSDavid van Moolenbroek
387*e044bafaSDavid van Moolenbroek case '@':
388*e044bafaSDavid van Moolenbroek if (*host)
389*e044bafaSDavid van Moolenbroek *res++ = *host++;
390*e044bafaSDavid van Moolenbroek break;
391*e044bafaSDavid van Moolenbroek
392*e044bafaSDavid van Moolenbroek default:
393*e044bafaSDavid van Moolenbroek *res++ = *pat;
394*e044bafaSDavid van Moolenbroek break;
395*e044bafaSDavid van Moolenbroek }
396*e044bafaSDavid van Moolenbroek if (res == &editedhost[sizeof editedhost - 1]) {
397*e044bafaSDavid van Moolenbroek *res = '\0';
398*e044bafaSDavid van Moolenbroek return;
399*e044bafaSDavid van Moolenbroek }
400*e044bafaSDavid van Moolenbroek pat++;
401*e044bafaSDavid van Moolenbroek }
402*e044bafaSDavid van Moolenbroek if (*host)
403*e044bafaSDavid van Moolenbroek (void) strncpy(res, host,
404*e044bafaSDavid van Moolenbroek sizeof editedhost - (res - editedhost) -1);
405*e044bafaSDavid van Moolenbroek else
406*e044bafaSDavid van Moolenbroek *res = '\0';
407*e044bafaSDavid van Moolenbroek editedhost[sizeof editedhost - 1] = '\0';
408*e044bafaSDavid van Moolenbroek }
409*e044bafaSDavid van Moolenbroek
410*e044bafaSDavid van Moolenbroek static char *putlocation;
411*e044bafaSDavid van Moolenbroek
412*e044bafaSDavid van Moolenbroek void
putstr(char * s)413*e044bafaSDavid van Moolenbroek putstr(char *s)
414*e044bafaSDavid van Moolenbroek {
415*e044bafaSDavid van Moolenbroek
416*e044bafaSDavid van Moolenbroek while (*s)
417*e044bafaSDavid van Moolenbroek putchr(*s++);
418*e044bafaSDavid van Moolenbroek }
419*e044bafaSDavid van Moolenbroek
420*e044bafaSDavid van Moolenbroek void
putchr(int cc)421*e044bafaSDavid van Moolenbroek putchr(int cc)
422*e044bafaSDavid van Moolenbroek {
423*e044bafaSDavid van Moolenbroek *putlocation++ = cc;
424*e044bafaSDavid van Moolenbroek }
425*e044bafaSDavid van Moolenbroek
426*e044bafaSDavid van Moolenbroek /*
427*e044bafaSDavid van Moolenbroek * This is split on two lines so that SCCS will not see the M
428*e044bafaSDavid van Moolenbroek * between two % signs and expand it...
429*e044bafaSDavid van Moolenbroek */
430*e044bafaSDavid van Moolenbroek static const char fmtstr[] = { "%l:%M\
431*e044bafaSDavid van Moolenbroek %p on %A, %d %B %Y" };
432*e044bafaSDavid van Moolenbroek
433*e044bafaSDavid van Moolenbroek char *
putf(const char * cp,char * where)434*e044bafaSDavid van Moolenbroek putf(const char *cp, char *where)
435*e044bafaSDavid van Moolenbroek {
436*e044bafaSDavid van Moolenbroek char *slash;
437*e044bafaSDavid van Moolenbroek time_t t;
438*e044bafaSDavid van Moolenbroek char db[100];
439*e044bafaSDavid van Moolenbroek struct utsname utsinfo;
440*e044bafaSDavid van Moolenbroek
441*e044bafaSDavid van Moolenbroek uname(&utsinfo);
442*e044bafaSDavid van Moolenbroek
443*e044bafaSDavid van Moolenbroek putlocation = where;
444*e044bafaSDavid van Moolenbroek
445*e044bafaSDavid van Moolenbroek while (*cp) {
446*e044bafaSDavid van Moolenbroek if (*cp != '%') {
447*e044bafaSDavid van Moolenbroek putchr(*cp++);
448*e044bafaSDavid van Moolenbroek continue;
449*e044bafaSDavid van Moolenbroek }
450*e044bafaSDavid van Moolenbroek switch (*++cp) {
451*e044bafaSDavid van Moolenbroek
452*e044bafaSDavid van Moolenbroek case 't':
453*e044bafaSDavid van Moolenbroek if ((slash = strstr(line, "/pts/")) == NULL)
454*e044bafaSDavid van Moolenbroek slash = strrchr(line, '/');
455*e044bafaSDavid van Moolenbroek if (slash == (char *) 0)
456*e044bafaSDavid van Moolenbroek putstr(line);
457*e044bafaSDavid van Moolenbroek else
458*e044bafaSDavid van Moolenbroek putstr(&slash[1]);
459*e044bafaSDavid van Moolenbroek break;
460*e044bafaSDavid van Moolenbroek
461*e044bafaSDavid van Moolenbroek case 'h':
462*e044bafaSDavid van Moolenbroek putstr(editedhost);
463*e044bafaSDavid van Moolenbroek break;
464*e044bafaSDavid van Moolenbroek
465*e044bafaSDavid van Moolenbroek case 'd':
466*e044bafaSDavid van Moolenbroek (void)time(&t);
467*e044bafaSDavid van Moolenbroek (void)strftime(db, sizeof(db), fmtstr, localtime(&t));
468*e044bafaSDavid van Moolenbroek putstr(db);
469*e044bafaSDavid van Moolenbroek break;
470*e044bafaSDavid van Moolenbroek
471*e044bafaSDavid van Moolenbroek case '%':
472*e044bafaSDavid van Moolenbroek putchr('%');
473*e044bafaSDavid van Moolenbroek break;
474*e044bafaSDavid van Moolenbroek
475*e044bafaSDavid van Moolenbroek case 's':
476*e044bafaSDavid van Moolenbroek putstr(utsinfo.sysname);
477*e044bafaSDavid van Moolenbroek break;
478*e044bafaSDavid van Moolenbroek
479*e044bafaSDavid van Moolenbroek case 'm':
480*e044bafaSDavid van Moolenbroek putstr(utsinfo.machine);
481*e044bafaSDavid van Moolenbroek break;
482*e044bafaSDavid van Moolenbroek
483*e044bafaSDavid van Moolenbroek case 'r':
484*e044bafaSDavid van Moolenbroek putstr(utsinfo.release);
485*e044bafaSDavid van Moolenbroek break;
486*e044bafaSDavid van Moolenbroek
487*e044bafaSDavid van Moolenbroek case 'v':
488*e044bafaSDavid van Moolenbroek putstr(utsinfo.version);
489*e044bafaSDavid van Moolenbroek break;
490*e044bafaSDavid van Moolenbroek }
491*e044bafaSDavid van Moolenbroek cp++;
492*e044bafaSDavid van Moolenbroek }
493*e044bafaSDavid van Moolenbroek
494*e044bafaSDavid van Moolenbroek return (putlocation);
495*e044bafaSDavid van Moolenbroek }
496*e044bafaSDavid van Moolenbroek
497*e044bafaSDavid van Moolenbroek #ifdef DIAGNOSTICS
498*e044bafaSDavid van Moolenbroek /*
499*e044bafaSDavid van Moolenbroek * Print telnet options and commands in plain text, if possible.
500*e044bafaSDavid van Moolenbroek */
501*e044bafaSDavid van Moolenbroek void
printoption(const char * fmt,int option)502*e044bafaSDavid van Moolenbroek printoption(const char *fmt, int option)
503*e044bafaSDavid van Moolenbroek {
504*e044bafaSDavid van Moolenbroek if (TELOPT_OK(option))
505*e044bafaSDavid van Moolenbroek output_data("%s %s\r\n", fmt, TELOPT(option));
506*e044bafaSDavid van Moolenbroek else if (TELCMD_OK(option))
507*e044bafaSDavid van Moolenbroek output_data("%s %s\r\n", fmt, TELCMD(option));
508*e044bafaSDavid van Moolenbroek else
509*e044bafaSDavid van Moolenbroek output_data("%s %d\r\n", fmt, option);
510*e044bafaSDavid van Moolenbroek return;
511*e044bafaSDavid van Moolenbroek }
512*e044bafaSDavid van Moolenbroek
513*e044bafaSDavid van Moolenbroek void
printsub(int direction,unsigned char * pointer,int length)514*e044bafaSDavid van Moolenbroek printsub(
515*e044bafaSDavid van Moolenbroek int direction, /* '<' or '>' */
516*e044bafaSDavid van Moolenbroek unsigned char *pointer, /* where suboption data sits */
517*e044bafaSDavid van Moolenbroek int length) /* length of suboption data */
518*e044bafaSDavid van Moolenbroek {
519*e044bafaSDavid van Moolenbroek int i = 0;
520*e044bafaSDavid van Moolenbroek #if defined(AUTHENTICATION) || defined(ENCRYPTION)
521*e044bafaSDavid van Moolenbroek u_char buf[512];
522*e044bafaSDavid van Moolenbroek #endif
523*e044bafaSDavid van Moolenbroek
524*e044bafaSDavid van Moolenbroek if (!(diagnostic & TD_OPTIONS))
525*e044bafaSDavid van Moolenbroek return;
526*e044bafaSDavid van Moolenbroek
527*e044bafaSDavid van Moolenbroek if (direction) {
528*e044bafaSDavid van Moolenbroek output_data("td: %s suboption ",
529*e044bafaSDavid van Moolenbroek direction == '<' ? "recv" : "send");
530*e044bafaSDavid van Moolenbroek if (length >= 3) {
531*e044bafaSDavid van Moolenbroek int j;
532*e044bafaSDavid van Moolenbroek
533*e044bafaSDavid van Moolenbroek i = pointer[length - 2];
534*e044bafaSDavid van Moolenbroek j = pointer[length - 1];
535*e044bafaSDavid van Moolenbroek
536*e044bafaSDavid van Moolenbroek if (i != IAC || j != SE) {
537*e044bafaSDavid van Moolenbroek output_data("(terminated by ");
538*e044bafaSDavid van Moolenbroek if (TELOPT_OK(i))
539*e044bafaSDavid van Moolenbroek output_data("%s ", TELOPT(i));
540*e044bafaSDavid van Moolenbroek else if (TELCMD_OK(i))
541*e044bafaSDavid van Moolenbroek output_data("%s ", TELCMD(i));
542*e044bafaSDavid van Moolenbroek else
543*e044bafaSDavid van Moolenbroek output_data("%d ", i);
544*e044bafaSDavid van Moolenbroek if (TELOPT_OK(j))
545*e044bafaSDavid van Moolenbroek output_data("%s", TELOPT(j));
546*e044bafaSDavid van Moolenbroek else if (TELCMD_OK(j))
547*e044bafaSDavid van Moolenbroek output_data("%s", TELCMD(j));
548*e044bafaSDavid van Moolenbroek else
549*e044bafaSDavid van Moolenbroek output_data("%d", j);
550*e044bafaSDavid van Moolenbroek output_data(", not IAC SE!) ");
551*e044bafaSDavid van Moolenbroek }
552*e044bafaSDavid van Moolenbroek }
553*e044bafaSDavid van Moolenbroek length -= 2;
554*e044bafaSDavid van Moolenbroek }
555*e044bafaSDavid van Moolenbroek if (length < 1) {
556*e044bafaSDavid van Moolenbroek output_data("(Empty suboption??\?)");
557*e044bafaSDavid van Moolenbroek return;
558*e044bafaSDavid van Moolenbroek }
559*e044bafaSDavid van Moolenbroek switch (pointer[0]) {
560*e044bafaSDavid van Moolenbroek case TELOPT_TTYPE:
561*e044bafaSDavid van Moolenbroek output_data("TERMINAL-TYPE ");
562*e044bafaSDavid van Moolenbroek switch (pointer[1]) {
563*e044bafaSDavid van Moolenbroek case TELQUAL_IS:
564*e044bafaSDavid van Moolenbroek output_data("IS \"%.*s\"", length-2, (char *)pointer+2);
565*e044bafaSDavid van Moolenbroek break;
566*e044bafaSDavid van Moolenbroek case TELQUAL_SEND:
567*e044bafaSDavid van Moolenbroek output_data("SEND");
568*e044bafaSDavid van Moolenbroek break;
569*e044bafaSDavid van Moolenbroek default:
570*e044bafaSDavid van Moolenbroek output_data("- unknown qualifier %d (0x%x).",
571*e044bafaSDavid van Moolenbroek pointer[1], pointer[1]);
572*e044bafaSDavid van Moolenbroek }
573*e044bafaSDavid van Moolenbroek break;
574*e044bafaSDavid van Moolenbroek case TELOPT_TSPEED:
575*e044bafaSDavid van Moolenbroek output_data("TERMINAL-SPEED");
576*e044bafaSDavid van Moolenbroek if (length < 2) {
577*e044bafaSDavid van Moolenbroek output_data(" (empty suboption??\?)");
578*e044bafaSDavid van Moolenbroek break;
579*e044bafaSDavid van Moolenbroek }
580*e044bafaSDavid van Moolenbroek switch (pointer[1]) {
581*e044bafaSDavid van Moolenbroek case TELQUAL_IS:
582*e044bafaSDavid van Moolenbroek output_data(" IS %.*s", length-2, (char *)pointer+2);
583*e044bafaSDavid van Moolenbroek break;
584*e044bafaSDavid van Moolenbroek default:
585*e044bafaSDavid van Moolenbroek if (pointer[1] == 1)
586*e044bafaSDavid van Moolenbroek output_data(" SEND");
587*e044bafaSDavid van Moolenbroek else
588*e044bafaSDavid van Moolenbroek output_data(" %d (unknown)", pointer[1]);
589*e044bafaSDavid van Moolenbroek for (i = 2; i < length; i++) {
590*e044bafaSDavid van Moolenbroek output_data(" ?%d?", pointer[i]);
591*e044bafaSDavid van Moolenbroek }
592*e044bafaSDavid van Moolenbroek break;
593*e044bafaSDavid van Moolenbroek }
594*e044bafaSDavid van Moolenbroek break;
595*e044bafaSDavid van Moolenbroek
596*e044bafaSDavid van Moolenbroek case TELOPT_LFLOW:
597*e044bafaSDavid van Moolenbroek output_data("TOGGLE-FLOW-CONTROL");
598*e044bafaSDavid van Moolenbroek if (length < 2) {
599*e044bafaSDavid van Moolenbroek output_data(" (empty suboption??\?)");
600*e044bafaSDavid van Moolenbroek break;
601*e044bafaSDavid van Moolenbroek }
602*e044bafaSDavid van Moolenbroek switch (pointer[1]) {
603*e044bafaSDavid van Moolenbroek case LFLOW_OFF:
604*e044bafaSDavid van Moolenbroek output_data(" OFF"); break;
605*e044bafaSDavid van Moolenbroek case LFLOW_ON:
606*e044bafaSDavid van Moolenbroek output_data(" ON"); break;
607*e044bafaSDavid van Moolenbroek case LFLOW_RESTART_ANY:
608*e044bafaSDavid van Moolenbroek output_data(" RESTART-ANY"); break;
609*e044bafaSDavid van Moolenbroek case LFLOW_RESTART_XON:
610*e044bafaSDavid van Moolenbroek output_data(" RESTART-XON"); break;
611*e044bafaSDavid van Moolenbroek default:
612*e044bafaSDavid van Moolenbroek output_data(" %d (unknown)", pointer[1]);
613*e044bafaSDavid van Moolenbroek }
614*e044bafaSDavid van Moolenbroek for (i = 2; i < length; i++)
615*e044bafaSDavid van Moolenbroek output_data(" ?%d?", pointer[i]);
616*e044bafaSDavid van Moolenbroek break;
617*e044bafaSDavid van Moolenbroek
618*e044bafaSDavid van Moolenbroek case TELOPT_NAWS:
619*e044bafaSDavid van Moolenbroek output_data("NAWS");
620*e044bafaSDavid van Moolenbroek if (length < 2) {
621*e044bafaSDavid van Moolenbroek output_data(" (empty suboption??\?)");
622*e044bafaSDavid van Moolenbroek break;
623*e044bafaSDavid van Moolenbroek }
624*e044bafaSDavid van Moolenbroek if (length == 2) {
625*e044bafaSDavid van Moolenbroek output_data(" ?%d?", pointer[1]);
626*e044bafaSDavid van Moolenbroek break;
627*e044bafaSDavid van Moolenbroek }
628*e044bafaSDavid van Moolenbroek output_data(" %d %d (%d)",
629*e044bafaSDavid van Moolenbroek pointer[1], pointer[2],
630*e044bafaSDavid van Moolenbroek (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
631*e044bafaSDavid van Moolenbroek if (length == 4) {
632*e044bafaSDavid van Moolenbroek output_data(" ?%d?", pointer[3]);
633*e044bafaSDavid van Moolenbroek break;
634*e044bafaSDavid van Moolenbroek }
635*e044bafaSDavid van Moolenbroek output_data(" %d %d (%d)", pointer[3], pointer[4],
636*e044bafaSDavid van Moolenbroek (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
637*e044bafaSDavid van Moolenbroek for (i = 5; i < length; i++) {
638*e044bafaSDavid van Moolenbroek output_data(" ?%d?", pointer[i]);
639*e044bafaSDavid van Moolenbroek }
640*e044bafaSDavid van Moolenbroek break;
641*e044bafaSDavid van Moolenbroek
642*e044bafaSDavid van Moolenbroek case TELOPT_LINEMODE:
643*e044bafaSDavid van Moolenbroek output_data("LINEMODE ");
644*e044bafaSDavid van Moolenbroek if (length < 2) {
645*e044bafaSDavid van Moolenbroek output_data(" (empty suboption??\?)");
646*e044bafaSDavid van Moolenbroek break;
647*e044bafaSDavid van Moolenbroek }
648*e044bafaSDavid van Moolenbroek switch (pointer[1]) {
649*e044bafaSDavid van Moolenbroek case WILL:
650*e044bafaSDavid van Moolenbroek output_data("WILL ");
651*e044bafaSDavid van Moolenbroek goto common;
652*e044bafaSDavid van Moolenbroek case WONT:
653*e044bafaSDavid van Moolenbroek output_data("WONT ");
654*e044bafaSDavid van Moolenbroek goto common;
655*e044bafaSDavid van Moolenbroek case DO:
656*e044bafaSDavid van Moolenbroek output_data("DO ");
657*e044bafaSDavid van Moolenbroek goto common;
658*e044bafaSDavid van Moolenbroek case DONT:
659*e044bafaSDavid van Moolenbroek output_data("DONT ");
660*e044bafaSDavid van Moolenbroek common:
661*e044bafaSDavid van Moolenbroek if (length < 3) {
662*e044bafaSDavid van Moolenbroek output_data("(no option??\?)");
663*e044bafaSDavid van Moolenbroek break;
664*e044bafaSDavid van Moolenbroek }
665*e044bafaSDavid van Moolenbroek switch (pointer[2]) {
666*e044bafaSDavid van Moolenbroek case LM_FORWARDMASK:
667*e044bafaSDavid van Moolenbroek output_data("Forward Mask");
668*e044bafaSDavid van Moolenbroek for (i = 3; i < length; i++)
669*e044bafaSDavid van Moolenbroek output_data(" %x", pointer[i]);
670*e044bafaSDavid van Moolenbroek break;
671*e044bafaSDavid van Moolenbroek default:
672*e044bafaSDavid van Moolenbroek output_data("%d (unknown)", pointer[2]);
673*e044bafaSDavid van Moolenbroek for (i = 3; i < length; i++)
674*e044bafaSDavid van Moolenbroek output_data(" %d", pointer[i]);
675*e044bafaSDavid van Moolenbroek break;
676*e044bafaSDavid van Moolenbroek }
677*e044bafaSDavid van Moolenbroek break;
678*e044bafaSDavid van Moolenbroek
679*e044bafaSDavid van Moolenbroek case LM_SLC:
680*e044bafaSDavid van Moolenbroek output_data("SLC");
681*e044bafaSDavid van Moolenbroek for (i = 2; i < length - 2; i += 3) {
682*e044bafaSDavid van Moolenbroek if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
683*e044bafaSDavid van Moolenbroek output_data(" %s", SLC_NAME(pointer[i+SLC_FUNC]));
684*e044bafaSDavid van Moolenbroek else
685*e044bafaSDavid van Moolenbroek output_data(" %d", pointer[i+SLC_FUNC]);
686*e044bafaSDavid van Moolenbroek switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
687*e044bafaSDavid van Moolenbroek case SLC_NOSUPPORT:
688*e044bafaSDavid van Moolenbroek output_data(" NOSUPPORT"); break;
689*e044bafaSDavid van Moolenbroek case SLC_CANTCHANGE:
690*e044bafaSDavid van Moolenbroek output_data(" CANTCHANGE"); break;
691*e044bafaSDavid van Moolenbroek case SLC_VARIABLE:
692*e044bafaSDavid van Moolenbroek output_data(" VARIABLE"); break;
693*e044bafaSDavid van Moolenbroek case SLC_DEFAULT:
694*e044bafaSDavid van Moolenbroek output_data(" DEFAULT"); break;
695*e044bafaSDavid van Moolenbroek }
696*e044bafaSDavid van Moolenbroek output_data("%s%s%s",
697*e044bafaSDavid van Moolenbroek pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
698*e044bafaSDavid van Moolenbroek pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
699*e044bafaSDavid van Moolenbroek pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
700*e044bafaSDavid van Moolenbroek if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
701*e044bafaSDavid van Moolenbroek SLC_FLUSHOUT| SLC_LEVELBITS)) {
702*e044bafaSDavid van Moolenbroek output_data("(0x%x)", pointer[i+SLC_FLAGS]);
703*e044bafaSDavid van Moolenbroek }
704*e044bafaSDavid van Moolenbroek output_data(" %d;", pointer[i+SLC_VALUE]);
705*e044bafaSDavid van Moolenbroek if ((pointer[i+SLC_VALUE] == IAC) &&
706*e044bafaSDavid van Moolenbroek (pointer[i+SLC_VALUE+1] == IAC))
707*e044bafaSDavid van Moolenbroek i++;
708*e044bafaSDavid van Moolenbroek }
709*e044bafaSDavid van Moolenbroek for (; i < length; i++)
710*e044bafaSDavid van Moolenbroek output_data(" ?%d?", pointer[i]);
711*e044bafaSDavid van Moolenbroek break;
712*e044bafaSDavid van Moolenbroek
713*e044bafaSDavid van Moolenbroek case LM_MODE:
714*e044bafaSDavid van Moolenbroek output_data("MODE ");
715*e044bafaSDavid van Moolenbroek if (length < 3) {
716*e044bafaSDavid van Moolenbroek output_data("(no mode??\?)");
717*e044bafaSDavid van Moolenbroek break;
718*e044bafaSDavid van Moolenbroek }
719*e044bafaSDavid van Moolenbroek {
720*e044bafaSDavid van Moolenbroek char tbuf[32];
721*e044bafaSDavid van Moolenbroek
722*e044bafaSDavid van Moolenbroek (void)snprintf(tbuf, sizeof tbuf, "%s%s%s%s%s",
723*e044bafaSDavid van Moolenbroek pointer[2]&MODE_EDIT ? "|EDIT" : "",
724*e044bafaSDavid van Moolenbroek pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "",
725*e044bafaSDavid van Moolenbroek pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
726*e044bafaSDavid van Moolenbroek pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
727*e044bafaSDavid van Moolenbroek pointer[2]&MODE_ACK ? "|ACK" : "");
728*e044bafaSDavid van Moolenbroek output_data("%s", tbuf[1] ? &tbuf[1] : "0");
729*e044bafaSDavid van Moolenbroek }
730*e044bafaSDavid van Moolenbroek if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK))
731*e044bafaSDavid van Moolenbroek output_data(" (0x%x)", pointer[2]);
732*e044bafaSDavid van Moolenbroek for (i = 3; i < length; i++)
733*e044bafaSDavid van Moolenbroek output_data(" ?0x%x?", pointer[i]);
734*e044bafaSDavid van Moolenbroek break;
735*e044bafaSDavid van Moolenbroek default:
736*e044bafaSDavid van Moolenbroek output_data("%d (unknown)", pointer[1]);
737*e044bafaSDavid van Moolenbroek for (i = 2; i < length; i++)
738*e044bafaSDavid van Moolenbroek output_data(" %d", pointer[i]);
739*e044bafaSDavid van Moolenbroek }
740*e044bafaSDavid van Moolenbroek break;
741*e044bafaSDavid van Moolenbroek
742*e044bafaSDavid van Moolenbroek case TELOPT_STATUS: {
743*e044bafaSDavid van Moolenbroek const char *cp;
744*e044bafaSDavid van Moolenbroek int j, k;
745*e044bafaSDavid van Moolenbroek
746*e044bafaSDavid van Moolenbroek output_data("STATUS");
747*e044bafaSDavid van Moolenbroek
748*e044bafaSDavid van Moolenbroek switch (pointer[1]) {
749*e044bafaSDavid van Moolenbroek default:
750*e044bafaSDavid van Moolenbroek if (pointer[1] == TELQUAL_SEND)
751*e044bafaSDavid van Moolenbroek output_data(" SEND");
752*e044bafaSDavid van Moolenbroek else
753*e044bafaSDavid van Moolenbroek output_data(" %d (unknown)", pointer[1]);
754*e044bafaSDavid van Moolenbroek for (i = 2; i < length; i++)
755*e044bafaSDavid van Moolenbroek output_data(" ?%d?", pointer[i]);
756*e044bafaSDavid van Moolenbroek break;
757*e044bafaSDavid van Moolenbroek case TELQUAL_IS:
758*e044bafaSDavid van Moolenbroek output_data(" IS\r\n");
759*e044bafaSDavid van Moolenbroek
760*e044bafaSDavid van Moolenbroek for (i = 2; i < length; i++) {
761*e044bafaSDavid van Moolenbroek switch(pointer[i]) {
762*e044bafaSDavid van Moolenbroek case DO: cp = "DO"; goto common2;
763*e044bafaSDavid van Moolenbroek case DONT: cp = "DONT"; goto common2;
764*e044bafaSDavid van Moolenbroek case WILL: cp = "WILL"; goto common2;
765*e044bafaSDavid van Moolenbroek case WONT: cp = "WONT"; goto common2;
766*e044bafaSDavid van Moolenbroek common2:
767*e044bafaSDavid van Moolenbroek i++;
768*e044bafaSDavid van Moolenbroek if (TELOPT_OK(pointer[i]))
769*e044bafaSDavid van Moolenbroek output_data(" %s %s", cp, TELOPT(pointer[i]));
770*e044bafaSDavid van Moolenbroek else
771*e044bafaSDavid van Moolenbroek output_data(" %s %d", cp, pointer[i]);
772*e044bafaSDavid van Moolenbroek
773*e044bafaSDavid van Moolenbroek output_data("\r\n");
774*e044bafaSDavid van Moolenbroek break;
775*e044bafaSDavid van Moolenbroek
776*e044bafaSDavid van Moolenbroek case SB:
777*e044bafaSDavid van Moolenbroek output_data(" SB ");
778*e044bafaSDavid van Moolenbroek i++;
779*e044bafaSDavid van Moolenbroek j = k = i;
780*e044bafaSDavid van Moolenbroek while (j < length) {
781*e044bafaSDavid van Moolenbroek if (pointer[j] == SE) {
782*e044bafaSDavid van Moolenbroek if (j+1 == length)
783*e044bafaSDavid van Moolenbroek break;
784*e044bafaSDavid van Moolenbroek if (pointer[j+1] == SE)
785*e044bafaSDavid van Moolenbroek j++;
786*e044bafaSDavid van Moolenbroek else
787*e044bafaSDavid van Moolenbroek break;
788*e044bafaSDavid van Moolenbroek }
789*e044bafaSDavid van Moolenbroek pointer[k++] = pointer[j++];
790*e044bafaSDavid van Moolenbroek }
791*e044bafaSDavid van Moolenbroek printsub(0, &pointer[i], k - i);
792*e044bafaSDavid van Moolenbroek if (i < length) {
793*e044bafaSDavid van Moolenbroek output_data(" SE");
794*e044bafaSDavid van Moolenbroek i = j;
795*e044bafaSDavid van Moolenbroek } else
796*e044bafaSDavid van Moolenbroek i = j - 1;
797*e044bafaSDavid van Moolenbroek
798*e044bafaSDavid van Moolenbroek output_data("\r\n");
799*e044bafaSDavid van Moolenbroek
800*e044bafaSDavid van Moolenbroek break;
801*e044bafaSDavid van Moolenbroek
802*e044bafaSDavid van Moolenbroek default:
803*e044bafaSDavid van Moolenbroek output_data(" %d", pointer[i]);
804*e044bafaSDavid van Moolenbroek break;
805*e044bafaSDavid van Moolenbroek }
806*e044bafaSDavid van Moolenbroek }
807*e044bafaSDavid van Moolenbroek break;
808*e044bafaSDavid van Moolenbroek }
809*e044bafaSDavid van Moolenbroek break;
810*e044bafaSDavid van Moolenbroek }
811*e044bafaSDavid van Moolenbroek
812*e044bafaSDavid van Moolenbroek case TELOPT_XDISPLOC:
813*e044bafaSDavid van Moolenbroek output_data("X-DISPLAY-LOCATION ");
814*e044bafaSDavid van Moolenbroek switch (pointer[1]) {
815*e044bafaSDavid van Moolenbroek case TELQUAL_IS:
816*e044bafaSDavid van Moolenbroek output_data("IS \"%.*s\"", length - 2, (char *)pointer + 2);
817*e044bafaSDavid van Moolenbroek break;
818*e044bafaSDavid van Moolenbroek case TELQUAL_SEND:
819*e044bafaSDavid van Moolenbroek output_data("SEND");
820*e044bafaSDavid van Moolenbroek break;
821*e044bafaSDavid van Moolenbroek default:
822*e044bafaSDavid van Moolenbroek output_data("- unknown qualifier %d (0x%x).",
823*e044bafaSDavid van Moolenbroek pointer[1], pointer[1]);
824*e044bafaSDavid van Moolenbroek }
825*e044bafaSDavid van Moolenbroek break;
826*e044bafaSDavid van Moolenbroek
827*e044bafaSDavid van Moolenbroek case TELOPT_NEW_ENVIRON:
828*e044bafaSDavid van Moolenbroek output_data("NEW-ENVIRON ");
829*e044bafaSDavid van Moolenbroek goto env_common1;
830*e044bafaSDavid van Moolenbroek case TELOPT_OLD_ENVIRON:
831*e044bafaSDavid van Moolenbroek output_data("OLD-ENVIRON");
832*e044bafaSDavid van Moolenbroek env_common1:
833*e044bafaSDavid van Moolenbroek switch (pointer[1]) {
834*e044bafaSDavid van Moolenbroek case TELQUAL_IS:
835*e044bafaSDavid van Moolenbroek output_data("IS ");
836*e044bafaSDavid van Moolenbroek goto env_common;
837*e044bafaSDavid van Moolenbroek case TELQUAL_SEND:
838*e044bafaSDavid van Moolenbroek output_data("SEND ");
839*e044bafaSDavid van Moolenbroek goto env_common;
840*e044bafaSDavid van Moolenbroek case TELQUAL_INFO:
841*e044bafaSDavid van Moolenbroek output_data("INFO ");
842*e044bafaSDavid van Moolenbroek env_common:
843*e044bafaSDavid van Moolenbroek {
844*e044bafaSDavid van Moolenbroek static const char NQ[] = "\" ";
845*e044bafaSDavid van Moolenbroek const char *noquote = NQ;
846*e044bafaSDavid van Moolenbroek for (i = 2; i < length; i++ ) {
847*e044bafaSDavid van Moolenbroek switch (pointer[i]) {
848*e044bafaSDavid van Moolenbroek case NEW_ENV_VAR:
849*e044bafaSDavid van Moolenbroek output_data("%sVAR ", noquote);
850*e044bafaSDavid van Moolenbroek noquote = NQ;
851*e044bafaSDavid van Moolenbroek break;
852*e044bafaSDavid van Moolenbroek
853*e044bafaSDavid van Moolenbroek case NEW_ENV_VALUE:
854*e044bafaSDavid van Moolenbroek output_data("%sVALUE ", noquote);
855*e044bafaSDavid van Moolenbroek noquote = NQ;
856*e044bafaSDavid van Moolenbroek break;
857*e044bafaSDavid van Moolenbroek
858*e044bafaSDavid van Moolenbroek case ENV_ESC:
859*e044bafaSDavid van Moolenbroek output_data("%sESC ", noquote);
860*e044bafaSDavid van Moolenbroek noquote = NQ;
861*e044bafaSDavid van Moolenbroek break;
862*e044bafaSDavid van Moolenbroek
863*e044bafaSDavid van Moolenbroek case ENV_USERVAR:
864*e044bafaSDavid van Moolenbroek output_data("%sUSERVAR ", noquote);
865*e044bafaSDavid van Moolenbroek noquote = NQ;
866*e044bafaSDavid van Moolenbroek break;
867*e044bafaSDavid van Moolenbroek
868*e044bafaSDavid van Moolenbroek default:
869*e044bafaSDavid van Moolenbroek if (isprint(pointer[i]) && pointer[i] != '"') {
870*e044bafaSDavid van Moolenbroek if (*noquote) {
871*e044bafaSDavid van Moolenbroek output_data("\"");
872*e044bafaSDavid van Moolenbroek noquote = "";
873*e044bafaSDavid van Moolenbroek }
874*e044bafaSDavid van Moolenbroek output_data("%c", pointer[i]);
875*e044bafaSDavid van Moolenbroek } else {
876*e044bafaSDavid van Moolenbroek output_data("%s%03o ", noquote, pointer[i]);
877*e044bafaSDavid van Moolenbroek noquote = NQ;
878*e044bafaSDavid van Moolenbroek }
879*e044bafaSDavid van Moolenbroek break;
880*e044bafaSDavid van Moolenbroek }
881*e044bafaSDavid van Moolenbroek }
882*e044bafaSDavid van Moolenbroek if (!noquote)
883*e044bafaSDavid van Moolenbroek output_data("\"");
884*e044bafaSDavid van Moolenbroek break;
885*e044bafaSDavid van Moolenbroek }
886*e044bafaSDavid van Moolenbroek }
887*e044bafaSDavid van Moolenbroek break;
888*e044bafaSDavid van Moolenbroek
889*e044bafaSDavid van Moolenbroek #ifdef AUTHENTICATION
890*e044bafaSDavid van Moolenbroek case TELOPT_AUTHENTICATION:
891*e044bafaSDavid van Moolenbroek output_data("AUTHENTICATION");
892*e044bafaSDavid van Moolenbroek
893*e044bafaSDavid van Moolenbroek if (length < 2) {
894*e044bafaSDavid van Moolenbroek output_data(" (empty suboption??\?)");
895*e044bafaSDavid van Moolenbroek break;
896*e044bafaSDavid van Moolenbroek }
897*e044bafaSDavid van Moolenbroek switch (pointer[1]) {
898*e044bafaSDavid van Moolenbroek case TELQUAL_REPLY:
899*e044bafaSDavid van Moolenbroek case TELQUAL_IS:
900*e044bafaSDavid van Moolenbroek output_data(" %s ", (pointer[1] == TELQUAL_IS) ?
901*e044bafaSDavid van Moolenbroek "IS" : "REPLY");
902*e044bafaSDavid van Moolenbroek if (AUTHTYPE_NAME_OK(pointer[2]))
903*e044bafaSDavid van Moolenbroek output_data("%s ", AUTHTYPE_NAME(pointer[2]));
904*e044bafaSDavid van Moolenbroek else
905*e044bafaSDavid van Moolenbroek output_data("%d ", pointer[2]);
906*e044bafaSDavid van Moolenbroek if (length < 3) {
907*e044bafaSDavid van Moolenbroek output_data("(partial suboption??\?)");
908*e044bafaSDavid van Moolenbroek break;
909*e044bafaSDavid van Moolenbroek }
910*e044bafaSDavid van Moolenbroek output_data("%s|%s",
911*e044bafaSDavid van Moolenbroek ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
912*e044bafaSDavid van Moolenbroek "CLIENT" : "SERVER",
913*e044bafaSDavid van Moolenbroek ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
914*e044bafaSDavid van Moolenbroek "MUTUAL" : "ONE-WAY");
915*e044bafaSDavid van Moolenbroek
916*e044bafaSDavid van Moolenbroek auth_printsub(&pointer[1], length - 1, buf, sizeof(buf));
917*e044bafaSDavid van Moolenbroek output_data("%s", buf);
918*e044bafaSDavid van Moolenbroek break;
919*e044bafaSDavid van Moolenbroek
920*e044bafaSDavid van Moolenbroek case TELQUAL_SEND:
921*e044bafaSDavid van Moolenbroek i = 2;
922*e044bafaSDavid van Moolenbroek output_data(" SEND ");
923*e044bafaSDavid van Moolenbroek while (i < length) {
924*e044bafaSDavid van Moolenbroek if (AUTHTYPE_NAME_OK(pointer[i]))
925*e044bafaSDavid van Moolenbroek output_data("%s ", AUTHTYPE_NAME(pointer[i]));
926*e044bafaSDavid van Moolenbroek else
927*e044bafaSDavid van Moolenbroek output_data("%d ", pointer[i]);
928*e044bafaSDavid van Moolenbroek if (++i >= length) {
929*e044bafaSDavid van Moolenbroek output_data("(partial suboption??\?)");
930*e044bafaSDavid van Moolenbroek break;
931*e044bafaSDavid van Moolenbroek }
932*e044bafaSDavid van Moolenbroek output_data("%s|%s ",
933*e044bafaSDavid van Moolenbroek ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ?
934*e044bafaSDavid van Moolenbroek "CLIENT" : "SERVER",
935*e044bafaSDavid van Moolenbroek ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ?
936*e044bafaSDavid van Moolenbroek "MUTUAL" : "ONE-WAY");
937*e044bafaSDavid van Moolenbroek ++i;
938*e044bafaSDavid van Moolenbroek }
939*e044bafaSDavid van Moolenbroek break;
940*e044bafaSDavid van Moolenbroek
941*e044bafaSDavid van Moolenbroek case TELQUAL_NAME:
942*e044bafaSDavid van Moolenbroek i = 2;
943*e044bafaSDavid van Moolenbroek output_data(" NAME \"");
944*e044bafaSDavid van Moolenbroek while (i < length) {
945*e044bafaSDavid van Moolenbroek if (isprint(pointer[i]))
946*e044bafaSDavid van Moolenbroek output_data("%c", pointer[i++]);
947*e044bafaSDavid van Moolenbroek else
948*e044bafaSDavid van Moolenbroek output_data("\"%03o\"",pointer[i++]);
949*e044bafaSDavid van Moolenbroek }
950*e044bafaSDavid van Moolenbroek output_data("\"");
951*e044bafaSDavid van Moolenbroek break;
952*e044bafaSDavid van Moolenbroek
953*e044bafaSDavid van Moolenbroek default:
954*e044bafaSDavid van Moolenbroek for (i = 2; i < length; i++)
955*e044bafaSDavid van Moolenbroek output_data(" ?%d?", pointer[i]);
956*e044bafaSDavid van Moolenbroek break;
957*e044bafaSDavid van Moolenbroek }
958*e044bafaSDavid van Moolenbroek break;
959*e044bafaSDavid van Moolenbroek #endif
960*e044bafaSDavid van Moolenbroek
961*e044bafaSDavid van Moolenbroek #ifdef ENCRYPTION
962*e044bafaSDavid van Moolenbroek case TELOPT_ENCRYPT:
963*e044bafaSDavid van Moolenbroek output_data("ENCRYPT");
964*e044bafaSDavid van Moolenbroek if (length < 2) {
965*e044bafaSDavid van Moolenbroek output_data(" (empty suboption??\?)");
966*e044bafaSDavid van Moolenbroek break;
967*e044bafaSDavid van Moolenbroek }
968*e044bafaSDavid van Moolenbroek switch (pointer[1]) {
969*e044bafaSDavid van Moolenbroek case ENCRYPT_START:
970*e044bafaSDavid van Moolenbroek output_data(" START");
971*e044bafaSDavid van Moolenbroek break;
972*e044bafaSDavid van Moolenbroek
973*e044bafaSDavid van Moolenbroek case ENCRYPT_END:
974*e044bafaSDavid van Moolenbroek output_data(" END");
975*e044bafaSDavid van Moolenbroek break;
976*e044bafaSDavid van Moolenbroek
977*e044bafaSDavid van Moolenbroek case ENCRYPT_REQSTART:
978*e044bafaSDavid van Moolenbroek output_data(" REQUEST-START");
979*e044bafaSDavid van Moolenbroek break;
980*e044bafaSDavid van Moolenbroek
981*e044bafaSDavid van Moolenbroek case ENCRYPT_REQEND:
982*e044bafaSDavid van Moolenbroek output_data(" REQUEST-END");
983*e044bafaSDavid van Moolenbroek break;
984*e044bafaSDavid van Moolenbroek
985*e044bafaSDavid van Moolenbroek case ENCRYPT_IS:
986*e044bafaSDavid van Moolenbroek case ENCRYPT_REPLY:
987*e044bafaSDavid van Moolenbroek output_data(" %s ", (pointer[1] == ENCRYPT_IS) ?
988*e044bafaSDavid van Moolenbroek "IS" : "REPLY");
989*e044bafaSDavid van Moolenbroek if (length < 3) {
990*e044bafaSDavid van Moolenbroek output_data(" (partial suboption??\?)");
991*e044bafaSDavid van Moolenbroek break;
992*e044bafaSDavid van Moolenbroek }
993*e044bafaSDavid van Moolenbroek if (ENCTYPE_NAME_OK(pointer[2]))
994*e044bafaSDavid van Moolenbroek output_data("%s ", ENCTYPE_NAME(pointer[2]));
995*e044bafaSDavid van Moolenbroek else
996*e044bafaSDavid van Moolenbroek output_data(" %d (unknown)", pointer[2]);
997*e044bafaSDavid van Moolenbroek
998*e044bafaSDavid van Moolenbroek encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf));
999*e044bafaSDavid van Moolenbroek output_data("%s", buf);
1000*e044bafaSDavid van Moolenbroek break;
1001*e044bafaSDavid van Moolenbroek
1002*e044bafaSDavid van Moolenbroek case ENCRYPT_SUPPORT:
1003*e044bafaSDavid van Moolenbroek i = 2;
1004*e044bafaSDavid van Moolenbroek output_data(" SUPPORT ");
1005*e044bafaSDavid van Moolenbroek while (i < length) {
1006*e044bafaSDavid van Moolenbroek if (ENCTYPE_NAME_OK(pointer[i]))
1007*e044bafaSDavid van Moolenbroek output_data("%s ", ENCTYPE_NAME(pointer[i]));
1008*e044bafaSDavid van Moolenbroek else
1009*e044bafaSDavid van Moolenbroek output_data("%d ", pointer[i]);
1010*e044bafaSDavid van Moolenbroek i++;
1011*e044bafaSDavid van Moolenbroek }
1012*e044bafaSDavid van Moolenbroek break;
1013*e044bafaSDavid van Moolenbroek
1014*e044bafaSDavid van Moolenbroek case ENCRYPT_ENC_KEYID:
1015*e044bafaSDavid van Moolenbroek output_data(" ENC_KEYID");
1016*e044bafaSDavid van Moolenbroek goto encommon;
1017*e044bafaSDavid van Moolenbroek
1018*e044bafaSDavid van Moolenbroek case ENCRYPT_DEC_KEYID:
1019*e044bafaSDavid van Moolenbroek output_data(" DEC_KEYID");
1020*e044bafaSDavid van Moolenbroek goto encommon;
1021*e044bafaSDavid van Moolenbroek
1022*e044bafaSDavid van Moolenbroek default:
1023*e044bafaSDavid van Moolenbroek output_data(" %d (unknown)", pointer[1]);
1024*e044bafaSDavid van Moolenbroek encommon:
1025*e044bafaSDavid van Moolenbroek for (i = 2; i < length; i++)
1026*e044bafaSDavid van Moolenbroek output_data(" %d", pointer[i]);
1027*e044bafaSDavid van Moolenbroek break;
1028*e044bafaSDavid van Moolenbroek }
1029*e044bafaSDavid van Moolenbroek break;
1030*e044bafaSDavid van Moolenbroek #endif /* ENCRYPTION */
1031*e044bafaSDavid van Moolenbroek
1032*e044bafaSDavid van Moolenbroek default:
1033*e044bafaSDavid van Moolenbroek if (TELOPT_OK(pointer[0]))
1034*e044bafaSDavid van Moolenbroek output_data("%s (unknown)", TELOPT(pointer[0]));
1035*e044bafaSDavid van Moolenbroek else
1036*e044bafaSDavid van Moolenbroek output_data("%d (unknown)", pointer[i]);
1037*e044bafaSDavid van Moolenbroek for (i = 1; i < length; i++)
1038*e044bafaSDavid van Moolenbroek output_data(" %d", pointer[i]);
1039*e044bafaSDavid van Moolenbroek break;
1040*e044bafaSDavid van Moolenbroek }
1041*e044bafaSDavid van Moolenbroek output_data("\r\n");
1042*e044bafaSDavid van Moolenbroek }
1043*e044bafaSDavid van Moolenbroek
1044*e044bafaSDavid van Moolenbroek /*
1045*e044bafaSDavid van Moolenbroek * Dump a data buffer in hex and ascii to the output data stream.
1046*e044bafaSDavid van Moolenbroek */
1047*e044bafaSDavid van Moolenbroek void
printdata(const char * tag,char * ptr,int cnt)1048*e044bafaSDavid van Moolenbroek printdata(const char *tag, char *ptr, int cnt)
1049*e044bafaSDavid van Moolenbroek {
1050*e044bafaSDavid van Moolenbroek int i;
1051*e044bafaSDavid van Moolenbroek char xbuf[30];
1052*e044bafaSDavid van Moolenbroek
1053*e044bafaSDavid van Moolenbroek while (cnt) {
1054*e044bafaSDavid van Moolenbroek /* flush net output buffer if no room for new data) */
1055*e044bafaSDavid van Moolenbroek if ((&netobuf[BUFSIZ] - nfrontp) < 80) {
1056*e044bafaSDavid van Moolenbroek netflush();
1057*e044bafaSDavid van Moolenbroek }
1058*e044bafaSDavid van Moolenbroek
1059*e044bafaSDavid van Moolenbroek /* add a line of output */
1060*e044bafaSDavid van Moolenbroek output_data("%s: ", tag);
1061*e044bafaSDavid van Moolenbroek for (i = 0; i < 20 && cnt; i++) {
1062*e044bafaSDavid van Moolenbroek output_data("%02x", *ptr);
1063*e044bafaSDavid van Moolenbroek if (isprint((unsigned char)*ptr)) {
1064*e044bafaSDavid van Moolenbroek xbuf[i] = *ptr;
1065*e044bafaSDavid van Moolenbroek } else {
1066*e044bafaSDavid van Moolenbroek xbuf[i] = '.';
1067*e044bafaSDavid van Moolenbroek }
1068*e044bafaSDavid van Moolenbroek if (i % 2)
1069*e044bafaSDavid van Moolenbroek output_data(" ");
1070*e044bafaSDavid van Moolenbroek cnt--;
1071*e044bafaSDavid van Moolenbroek ptr++;
1072*e044bafaSDavid van Moolenbroek }
1073*e044bafaSDavid van Moolenbroek xbuf[i] = '\0';
1074*e044bafaSDavid van Moolenbroek output_data(" %s\r\n", xbuf);
1075*e044bafaSDavid van Moolenbroek }
1076*e044bafaSDavid van Moolenbroek }
1077*e044bafaSDavid van Moolenbroek #endif /* DIAGNOSTICS */
1078