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