129088Smarkm/* 229088Smarkm * Copyright (c) 1988, 1993 329088Smarkm * The Regents of the University of California. All rights reserved. 429088Smarkm * 529088Smarkm * Redistribution and use in source and binary forms, with or without 629088Smarkm * modification, are permitted provided that the following conditions 729088Smarkm * are met: 829088Smarkm * 1. Redistributions of source code must retain the above copyright 929088Smarkm * notice, this list of conditions and the following disclaimer. 1029088Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1129088Smarkm * notice, this list of conditions and the following disclaimer in the 1229088Smarkm * documentation and/or other materials provided with the distribution. 13351432Semaste * 3. Neither the name of the University nor the names of its contributors 1429088Smarkm * may be used to endorse or promote products derived from this software 1529088Smarkm * without specific prior written permission. 1629088Smarkm * 1729088Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1829088Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1929088Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2029088Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2129088Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2229088Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2329088Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2429088Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2529088Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2629088Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2729088Smarkm * SUCH DAMAGE. 2829088Smarkm */ 2929088Smarkm 30114630Sobrien#if 0 3129088Smarkm#ifndef lint 3229181Smarkmstatic const char sccsid[] = "@(#)utilities.c 8.3 (Berkeley) 5/30/95"; 3363248Speter#endif 34114630Sobrien#endif 35114630Sobrien#include <sys/cdefs.h> 36114630Sobrien__FBSDID("$FreeBSD: stable/11/contrib/telnet/telnet/utilities.c 351432 2019-08-23 17:40:47Z emaste $"); 3729088Smarkm 3829088Smarkm#define TELOPTS 3929088Smarkm#define TELCMDS 4029088Smarkm#define SLC_NAMES 4129088Smarkm#include <arpa/telnet.h> 4229088Smarkm#include <sys/types.h> 4329181Smarkm#include <sys/socket.h> 4429088Smarkm#include <sys/time.h> 4581965Smarkm#include <ctype.h> 4696385Salfred#include <stdlib.h> 4729181Smarkm#include <unistd.h> 4829088Smarkm 4929088Smarkm#include "general.h" 5029088Smarkm 5129088Smarkm#include "fdset.h" 5229088Smarkm 5329088Smarkm#include "ring.h" 5429088Smarkm 5529088Smarkm#include "defines.h" 5629088Smarkm 5729088Smarkm#include "externs.h" 5829088Smarkm 5987139Smarkm#ifdef AUTHENTICATION 6029181Smarkm#include <libtelnet/auth.h> 6129181Smarkm#endif 6287139Smarkm#ifdef ENCRYPTION 6329181Smarkm#include <libtelnet/encrypt.h> 6429181Smarkm#endif 6529181Smarkm 6629088SmarkmFILE *NetTrace = 0; /* Not in bss, since needs to stay */ 6729088Smarkmint prettydump; 6829088Smarkm 6929088Smarkm/* 7029088Smarkm * upcase() 7129088Smarkm * 7229088Smarkm * Upcase (in place) the argument. 7329088Smarkm */ 7429088Smarkm 7587139Smarkmvoid 7687139Smarkmupcase(char *argument) 7729088Smarkm{ 7887139Smarkm int c; 7929088Smarkm 8029088Smarkm while ((c = *argument) != 0) { 8129088Smarkm if (islower(c)) { 8229088Smarkm *argument = toupper(c); 8329088Smarkm } 8429088Smarkm argument++; 8529088Smarkm } 8629088Smarkm} 8729088Smarkm 8829088Smarkm/* 8929088Smarkm * SetSockOpt() 9029088Smarkm * 9129088Smarkm * Compensate for differences in 4.2 and 4.3 systems. 9229088Smarkm */ 9329088Smarkm 9487139Smarkmint 9587139SmarkmSetSockOpt(int fd, int level, int option, int yesno) 9629088Smarkm{ 9729088Smarkm return setsockopt(fd, level, option, 9829088Smarkm (char *)&yesno, sizeof yesno); 9929088Smarkm} 10029088Smarkm 10129088Smarkm/* 10229088Smarkm * The following are routines used to print out debugging information. 10329088Smarkm */ 10429088Smarkm 10529088Smarkmunsigned char NetTraceFile[256] = "(standard output)"; 10629088Smarkm 10787139Smarkmvoid 10887139SmarkmSetNetTrace(char *file) 10929088Smarkm{ 11029088Smarkm if (NetTrace && NetTrace != stdout) 11129088Smarkm fclose(NetTrace); 11229088Smarkm if (file && (strcmp(file, "-") != 0)) { 11329088Smarkm NetTrace = fopen(file, "w"); 11429088Smarkm if (NetTrace) { 11529088Smarkm strcpy((char *)NetTraceFile, file); 11629088Smarkm return; 11729088Smarkm } 11829088Smarkm fprintf(stderr, "Cannot open %s.\n", file); 11929088Smarkm } 12029088Smarkm NetTrace = stdout; 12129088Smarkm strcpy((char *)NetTraceFile, "(standard output)"); 12229088Smarkm} 12329088Smarkm 12487139Smarkmvoid 12587139SmarkmDump(char direction, unsigned char *buffer, int length) 12629088Smarkm{ 12729088Smarkm# define BYTES_PER_LINE 32 12829088Smarkm# define min(x,y) ((x<y)? x:y) 12929088Smarkm unsigned char *pThis; 13029088Smarkm int offset; 13129088Smarkm 13229088Smarkm offset = 0; 13329088Smarkm 13429088Smarkm while (length) { 13529088Smarkm /* print one line */ 13629088Smarkm fprintf(NetTrace, "%c 0x%x\t", direction, offset); 13729088Smarkm pThis = buffer; 13829088Smarkm if (prettydump) { 13929088Smarkm buffer = buffer + min(length, BYTES_PER_LINE/2); 14029088Smarkm while (pThis < buffer) { 14129088Smarkm fprintf(NetTrace, "%c%.2x", 14229088Smarkm (((*pThis)&0xff) == 0xff) ? '*' : ' ', 14329088Smarkm (*pThis)&0xff); 14429088Smarkm pThis++; 14529088Smarkm } 14629088Smarkm length -= BYTES_PER_LINE/2; 14729088Smarkm offset += BYTES_PER_LINE/2; 14829088Smarkm } else { 14929088Smarkm buffer = buffer + min(length, BYTES_PER_LINE); 15029088Smarkm while (pThis < buffer) { 15129088Smarkm fprintf(NetTrace, "%.2x", (*pThis)&0xff); 15229088Smarkm pThis++; 15329088Smarkm } 15429088Smarkm length -= BYTES_PER_LINE; 15529088Smarkm offset += BYTES_PER_LINE; 15629088Smarkm } 15729088Smarkm if (NetTrace == stdout) { 15829088Smarkm fprintf(NetTrace, "\r\n"); 15929088Smarkm } else { 16029088Smarkm fprintf(NetTrace, "\n"); 16129088Smarkm } 16229088Smarkm if (length < 0) { 16329088Smarkm fflush(NetTrace); 16429088Smarkm return; 16529088Smarkm } 16629088Smarkm /* find next unique line */ 16729088Smarkm } 16829088Smarkm fflush(NetTrace); 16929088Smarkm} 17029088Smarkm 17129088Smarkm 17287139Smarkmvoid 17387139Smarkmprintoption(const char *direction, int cmd, int option) 17429088Smarkm{ 17529088Smarkm if (!showoptions) 17629088Smarkm return; 17729088Smarkm if (cmd == IAC) { 17829088Smarkm if (TELCMD_OK(option)) 17929088Smarkm fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option)); 18029088Smarkm else 18129088Smarkm fprintf(NetTrace, "%s IAC %d", direction, option); 18229088Smarkm } else { 18387139Smarkm const char *fmt; 18429088Smarkm fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" : 18529088Smarkm (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0; 18629088Smarkm if (fmt) { 18729088Smarkm fprintf(NetTrace, "%s %s ", direction, fmt); 18829088Smarkm if (TELOPT_OK(option)) 18929088Smarkm fprintf(NetTrace, "%s", TELOPT(option)); 19029088Smarkm else if (option == TELOPT_EXOPL) 19129088Smarkm fprintf(NetTrace, "EXOPL"); 19229088Smarkm else 19329088Smarkm fprintf(NetTrace, "%d", option); 19429088Smarkm } else 19529088Smarkm fprintf(NetTrace, "%s %d %d", direction, cmd, option); 19629088Smarkm } 19729088Smarkm if (NetTrace == stdout) { 19829088Smarkm fprintf(NetTrace, "\r\n"); 19929088Smarkm fflush(NetTrace); 20029088Smarkm } else { 20129088Smarkm fprintf(NetTrace, "\n"); 20229088Smarkm } 20329088Smarkm return; 20429088Smarkm} 20529088Smarkm 20687139Smarkmvoid 20787139Smarkmoptionstatus(void) 20829088Smarkm{ 20987139Smarkm int i; 21029088Smarkm extern char will_wont_resp[], do_dont_resp[]; 21129088Smarkm 21229088Smarkm for (i = 0; i < 256; i++) { 21329088Smarkm if (do_dont_resp[i]) { 21429088Smarkm if (TELOPT_OK(i)) 21529088Smarkm printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]); 21629088Smarkm else if (TELCMD_OK(i)) 21729088Smarkm printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]); 21829088Smarkm else 21929088Smarkm printf("resp DO_DONT %d: %d\n", i, 22029088Smarkm do_dont_resp[i]); 22129088Smarkm if (my_want_state_is_do(i)) { 22229088Smarkm if (TELOPT_OK(i)) 22329088Smarkm printf("want DO %s\n", TELOPT(i)); 22429088Smarkm else if (TELCMD_OK(i)) 22529088Smarkm printf("want DO %s\n", TELCMD(i)); 22629088Smarkm else 22729088Smarkm printf("want DO %d\n", i); 22829088Smarkm } else { 22929088Smarkm if (TELOPT_OK(i)) 23029088Smarkm printf("want DONT %s\n", TELOPT(i)); 23129088Smarkm else if (TELCMD_OK(i)) 23229088Smarkm printf("want DONT %s\n", TELCMD(i)); 23329088Smarkm else 23429088Smarkm printf("want DONT %d\n", i); 23529088Smarkm } 23629088Smarkm } else { 23729088Smarkm if (my_state_is_do(i)) { 23829088Smarkm if (TELOPT_OK(i)) 23929088Smarkm printf(" DO %s\n", TELOPT(i)); 24029088Smarkm else if (TELCMD_OK(i)) 24129088Smarkm printf(" DO %s\n", TELCMD(i)); 24229088Smarkm else 24329088Smarkm printf(" DO %d\n", i); 24429088Smarkm } 24529088Smarkm } 24629088Smarkm if (will_wont_resp[i]) { 24729088Smarkm if (TELOPT_OK(i)) 24829088Smarkm printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]); 24929088Smarkm else if (TELCMD_OK(i)) 25029088Smarkm printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]); 25129088Smarkm else 25229088Smarkm printf("resp WILL_WONT %d: %d\n", 25329088Smarkm i, will_wont_resp[i]); 25429088Smarkm if (my_want_state_is_will(i)) { 25529088Smarkm if (TELOPT_OK(i)) 25629088Smarkm printf("want WILL %s\n", TELOPT(i)); 25729088Smarkm else if (TELCMD_OK(i)) 25829088Smarkm printf("want WILL %s\n", TELCMD(i)); 25929088Smarkm else 26029088Smarkm printf("want WILL %d\n", i); 26129088Smarkm } else { 26229088Smarkm if (TELOPT_OK(i)) 26329088Smarkm printf("want WONT %s\n", TELOPT(i)); 26429088Smarkm else if (TELCMD_OK(i)) 26529088Smarkm printf("want WONT %s\n", TELCMD(i)); 26629088Smarkm else 26729088Smarkm printf("want WONT %d\n", i); 26829088Smarkm } 26929088Smarkm } else { 27029088Smarkm if (my_state_is_will(i)) { 27129088Smarkm if (TELOPT_OK(i)) 27229088Smarkm printf(" WILL %s\n", TELOPT(i)); 27329088Smarkm else if (TELCMD_OK(i)) 27429088Smarkm printf(" WILL %s\n", TELCMD(i)); 27529088Smarkm else 27629088Smarkm printf(" WILL %d\n", i); 27729088Smarkm } 27829088Smarkm } 27929088Smarkm } 28029088Smarkm 28129088Smarkm} 28229088Smarkm 28387139Smarkmvoid 28487139Smarkmprintsub(char direction, unsigned char *pointer, int length) 28529088Smarkm{ 28687139Smarkm int i; 28787139Smarkm#ifdef AUTHENTICATION 28829088Smarkm char buf[512]; 28987139Smarkm#endif 29029088Smarkm extern int want_status_response; 29129088Smarkm 29229088Smarkm if (showoptions || direction == 0 || 29329088Smarkm (want_status_response && (pointer[0] == TELOPT_STATUS))) { 29429088Smarkm if (direction) { 29529088Smarkm fprintf(NetTrace, "%s IAC SB ", 29629088Smarkm (direction == '<')? "RCVD":"SENT"); 29729088Smarkm if (length >= 3) { 29887139Smarkm int j; 29929088Smarkm 30029088Smarkm i = pointer[length-2]; 30129088Smarkm j = pointer[length-1]; 30229088Smarkm 30329088Smarkm if (i != IAC || j != SE) { 30429088Smarkm fprintf(NetTrace, "(terminated by "); 30529088Smarkm if (TELOPT_OK(i)) 30629088Smarkm fprintf(NetTrace, "%s ", TELOPT(i)); 30729088Smarkm else if (TELCMD_OK(i)) 30829088Smarkm fprintf(NetTrace, "%s ", TELCMD(i)); 30929088Smarkm else 31029088Smarkm fprintf(NetTrace, "%d ", i); 31129088Smarkm if (TELOPT_OK(j)) 31229088Smarkm fprintf(NetTrace, "%s", TELOPT(j)); 31329088Smarkm else if (TELCMD_OK(j)) 31429088Smarkm fprintf(NetTrace, "%s", TELCMD(j)); 31529088Smarkm else 31629088Smarkm fprintf(NetTrace, "%d", j); 31729088Smarkm fprintf(NetTrace, ", not IAC SE!) "); 31829088Smarkm } 31929088Smarkm } 32029088Smarkm length -= 2; 32129088Smarkm } 32229088Smarkm if (length < 1) { 32329088Smarkm fprintf(NetTrace, "(Empty suboption??\?)"); 32429088Smarkm if (NetTrace == stdout) 32529088Smarkm fflush(NetTrace); 32629088Smarkm return; 32729088Smarkm } 32829088Smarkm switch (pointer[0]) { 32929088Smarkm case TELOPT_TTYPE: 33029088Smarkm fprintf(NetTrace, "TERMINAL-TYPE "); 33129088Smarkm switch (pointer[1]) { 33229088Smarkm case TELQUAL_IS: 33329088Smarkm fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); 33429088Smarkm break; 33529088Smarkm case TELQUAL_SEND: 33629088Smarkm fprintf(NetTrace, "SEND"); 33729088Smarkm break; 33829088Smarkm default: 33929088Smarkm fprintf(NetTrace, 34029088Smarkm "- unknown qualifier %d (0x%x).", 34129088Smarkm pointer[1], pointer[1]); 34229088Smarkm } 34329088Smarkm break; 34429088Smarkm case TELOPT_TSPEED: 34529088Smarkm fprintf(NetTrace, "TERMINAL-SPEED"); 34629088Smarkm if (length < 2) { 34729088Smarkm fprintf(NetTrace, " (empty suboption??\?)"); 34829088Smarkm break; 34929088Smarkm } 35029088Smarkm switch (pointer[1]) { 35129088Smarkm case TELQUAL_IS: 35229088Smarkm fprintf(NetTrace, " IS "); 35329088Smarkm fprintf(NetTrace, "%.*s", length-2, (char *)pointer+2); 35429088Smarkm break; 35529088Smarkm default: 35629088Smarkm if (pointer[1] == 1) 35729088Smarkm fprintf(NetTrace, " SEND"); 35829088Smarkm else 35929088Smarkm fprintf(NetTrace, " %d (unknown)", pointer[1]); 36029088Smarkm for (i = 2; i < length; i++) 36129088Smarkm fprintf(NetTrace, " ?%d?", pointer[i]); 36229088Smarkm break; 36329088Smarkm } 36429088Smarkm break; 36529088Smarkm 36629088Smarkm case TELOPT_LFLOW: 36729088Smarkm fprintf(NetTrace, "TOGGLE-FLOW-CONTROL"); 36829088Smarkm if (length < 2) { 36929088Smarkm fprintf(NetTrace, " (empty suboption??\?)"); 37029088Smarkm break; 37129088Smarkm } 37229088Smarkm switch (pointer[1]) { 37329088Smarkm case LFLOW_OFF: 37429088Smarkm fprintf(NetTrace, " OFF"); break; 37529088Smarkm case LFLOW_ON: 37629088Smarkm fprintf(NetTrace, " ON"); break; 37729088Smarkm case LFLOW_RESTART_ANY: 37829088Smarkm fprintf(NetTrace, " RESTART-ANY"); break; 37929088Smarkm case LFLOW_RESTART_XON: 38029088Smarkm fprintf(NetTrace, " RESTART-XON"); break; 38129088Smarkm default: 38229088Smarkm fprintf(NetTrace, " %d (unknown)", pointer[1]); 38329088Smarkm } 38429088Smarkm for (i = 2; i < length; i++) 38529088Smarkm fprintf(NetTrace, " ?%d?", pointer[i]); 38629088Smarkm break; 38729088Smarkm 38829088Smarkm case TELOPT_NAWS: 38929088Smarkm fprintf(NetTrace, "NAWS"); 39029088Smarkm if (length < 2) { 39129088Smarkm fprintf(NetTrace, " (empty suboption??\?)"); 39229088Smarkm break; 39329088Smarkm } 39429088Smarkm if (length == 2) { 39529088Smarkm fprintf(NetTrace, " ?%d?", pointer[1]); 39629088Smarkm break; 39729088Smarkm } 39829088Smarkm fprintf(NetTrace, " %d %d (%d)", 39929088Smarkm pointer[1], pointer[2], 40029088Smarkm (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); 40129088Smarkm if (length == 4) { 40229088Smarkm fprintf(NetTrace, " ?%d?", pointer[3]); 40329088Smarkm break; 40429088Smarkm } 40529088Smarkm fprintf(NetTrace, " %d %d (%d)", 40629088Smarkm pointer[3], pointer[4], 40729088Smarkm (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); 40829088Smarkm for (i = 5; i < length; i++) 40929088Smarkm fprintf(NetTrace, " ?%d?", pointer[i]); 41029088Smarkm break; 41129088Smarkm 41287139Smarkm#ifdef AUTHENTICATION 41329088Smarkm case TELOPT_AUTHENTICATION: 41429088Smarkm fprintf(NetTrace, "AUTHENTICATION"); 41529088Smarkm if (length < 2) { 41629088Smarkm fprintf(NetTrace, " (empty suboption??\?)"); 41729088Smarkm break; 41829088Smarkm } 41929088Smarkm switch (pointer[1]) { 42029088Smarkm case TELQUAL_REPLY: 42129088Smarkm case TELQUAL_IS: 42229088Smarkm fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ? 42329088Smarkm "IS" : "REPLY"); 42429088Smarkm if (AUTHTYPE_NAME_OK(pointer[2])) 42529088Smarkm fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2])); 42629088Smarkm else 42729088Smarkm fprintf(NetTrace, "%d ", pointer[2]); 42829088Smarkm if (length < 3) { 42929088Smarkm fprintf(NetTrace, "(partial suboption??\?)"); 43029088Smarkm break; 43129088Smarkm } 43229088Smarkm fprintf(NetTrace, "%s|%s", 43329088Smarkm ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? 43429088Smarkm "CLIENT" : "SERVER", 43529088Smarkm ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? 43629088Smarkm "MUTUAL" : "ONE-WAY"); 43729088Smarkm 43829088Smarkm auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); 43929088Smarkm fprintf(NetTrace, "%s", buf); 44029088Smarkm break; 44129088Smarkm 44229088Smarkm case TELQUAL_SEND: 44329088Smarkm i = 2; 44429088Smarkm fprintf(NetTrace, " SEND "); 44529088Smarkm while (i < length) { 44629088Smarkm if (AUTHTYPE_NAME_OK(pointer[i])) 44729088Smarkm fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i])); 44829088Smarkm else 44929088Smarkm fprintf(NetTrace, "%d ", pointer[i]); 45029088Smarkm if (++i >= length) { 45129088Smarkm fprintf(NetTrace, "(partial suboption??\?)"); 45229088Smarkm break; 45329088Smarkm } 45429088Smarkm fprintf(NetTrace, "%s|%s ", 45529088Smarkm ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? 45629088Smarkm "CLIENT" : "SERVER", 45729088Smarkm ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? 45829088Smarkm "MUTUAL" : "ONE-WAY"); 45929088Smarkm ++i; 46029088Smarkm } 46129088Smarkm break; 46229088Smarkm 46329088Smarkm case TELQUAL_NAME: 46429088Smarkm i = 2; 46529088Smarkm fprintf(NetTrace, " NAME \""); 46629088Smarkm while (i < length) 46729088Smarkm putc(pointer[i++], NetTrace); 46829088Smarkm putc('"', NetTrace); 46929088Smarkm break; 47029088Smarkm 47129088Smarkm default: 47229088Smarkm for (i = 2; i < length; i++) 47329088Smarkm fprintf(NetTrace, " ?%d?", pointer[i]); 47429088Smarkm break; 47529088Smarkm } 47629088Smarkm break; 47729088Smarkm#endif 47829088Smarkm 47929088Smarkm#ifdef ENCRYPTION 48029088Smarkm case TELOPT_ENCRYPT: 48129088Smarkm fprintf(NetTrace, "ENCRYPT"); 48229088Smarkm if (length < 2) { 48329088Smarkm fprintf(NetTrace, " (empty suboption??\?)"); 48429088Smarkm break; 48529088Smarkm } 48629088Smarkm switch (pointer[1]) { 48729088Smarkm case ENCRYPT_START: 48829088Smarkm fprintf(NetTrace, " START"); 48929088Smarkm break; 49029088Smarkm 49129088Smarkm case ENCRYPT_END: 49229088Smarkm fprintf(NetTrace, " END"); 49329088Smarkm break; 49429088Smarkm 49529088Smarkm case ENCRYPT_REQSTART: 49629088Smarkm fprintf(NetTrace, " REQUEST-START"); 49729088Smarkm break; 49829088Smarkm 49929088Smarkm case ENCRYPT_REQEND: 50029088Smarkm fprintf(NetTrace, " REQUEST-END"); 50129088Smarkm break; 50229088Smarkm 50329088Smarkm case ENCRYPT_IS: 50429088Smarkm case ENCRYPT_REPLY: 50529088Smarkm fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ? 50629088Smarkm "IS" : "REPLY"); 50729088Smarkm if (length < 3) { 50829088Smarkm fprintf(NetTrace, " (partial suboption??\?)"); 50929088Smarkm break; 51029088Smarkm } 51129088Smarkm if (ENCTYPE_NAME_OK(pointer[2])) 51229088Smarkm fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2])); 51329088Smarkm else 51429088Smarkm fprintf(NetTrace, " %d (unknown)", pointer[2]); 51529088Smarkm 51629088Smarkm encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); 51729088Smarkm fprintf(NetTrace, "%s", buf); 51829088Smarkm break; 51929088Smarkm 52029088Smarkm case ENCRYPT_SUPPORT: 52129088Smarkm i = 2; 52229088Smarkm fprintf(NetTrace, " SUPPORT "); 52329088Smarkm while (i < length) { 52429088Smarkm if (ENCTYPE_NAME_OK(pointer[i])) 52529088Smarkm fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i])); 52629088Smarkm else 52729088Smarkm fprintf(NetTrace, "%d ", pointer[i]); 52829088Smarkm i++; 52929088Smarkm } 53029088Smarkm break; 53129088Smarkm 53229088Smarkm case ENCRYPT_ENC_KEYID: 53329088Smarkm fprintf(NetTrace, " ENC_KEYID "); 53429088Smarkm goto encommon; 53529088Smarkm 53629088Smarkm case ENCRYPT_DEC_KEYID: 53729088Smarkm fprintf(NetTrace, " DEC_KEYID "); 53829088Smarkm goto encommon; 53929088Smarkm 54029088Smarkm default: 54129088Smarkm fprintf(NetTrace, " %d (unknown)", pointer[1]); 54229088Smarkm encommon: 54329088Smarkm for (i = 2; i < length; i++) 54429088Smarkm fprintf(NetTrace, " %d", pointer[i]); 54529088Smarkm break; 54629088Smarkm } 54729088Smarkm break; 54829088Smarkm#endif /* ENCRYPTION */ 54929088Smarkm 55029088Smarkm case TELOPT_LINEMODE: 55129088Smarkm fprintf(NetTrace, "LINEMODE "); 55229088Smarkm if (length < 2) { 55329088Smarkm fprintf(NetTrace, " (empty suboption??\?)"); 55429088Smarkm break; 55529088Smarkm } 55629088Smarkm switch (pointer[1]) { 55729088Smarkm case WILL: 55829088Smarkm fprintf(NetTrace, "WILL "); 55929088Smarkm goto common; 56029088Smarkm case WONT: 56129088Smarkm fprintf(NetTrace, "WONT "); 56229088Smarkm goto common; 56329088Smarkm case DO: 56429088Smarkm fprintf(NetTrace, "DO "); 56529088Smarkm goto common; 56629088Smarkm case DONT: 56729088Smarkm fprintf(NetTrace, "DONT "); 56829088Smarkm common: 56929088Smarkm if (length < 3) { 57029088Smarkm fprintf(NetTrace, "(no option??\?)"); 57129088Smarkm break; 57229088Smarkm } 57329088Smarkm switch (pointer[2]) { 57429088Smarkm case LM_FORWARDMASK: 57529088Smarkm fprintf(NetTrace, "Forward Mask"); 57629088Smarkm for (i = 3; i < length; i++) 57729088Smarkm fprintf(NetTrace, " %x", pointer[i]); 57829088Smarkm break; 57929088Smarkm default: 58029088Smarkm fprintf(NetTrace, "%d (unknown)", pointer[2]); 58129088Smarkm for (i = 3; i < length; i++) 58229088Smarkm fprintf(NetTrace, " %d", pointer[i]); 58329088Smarkm break; 58429088Smarkm } 58529088Smarkm break; 58629088Smarkm 58729088Smarkm case LM_SLC: 58829088Smarkm fprintf(NetTrace, "SLC"); 58929088Smarkm for (i = 2; i < length - 2; i += 3) { 59029088Smarkm if (SLC_NAME_OK(pointer[i+SLC_FUNC])) 59129088Smarkm fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC])); 59229088Smarkm else 59329088Smarkm fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]); 59429088Smarkm switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { 59529088Smarkm case SLC_NOSUPPORT: 59629088Smarkm fprintf(NetTrace, " NOSUPPORT"); break; 59729088Smarkm case SLC_CANTCHANGE: 59829088Smarkm fprintf(NetTrace, " CANTCHANGE"); break; 59929088Smarkm case SLC_VARIABLE: 60029088Smarkm fprintf(NetTrace, " VARIABLE"); break; 60129088Smarkm case SLC_DEFAULT: 60229088Smarkm fprintf(NetTrace, " DEFAULT"); break; 60329088Smarkm } 60429088Smarkm fprintf(NetTrace, "%s%s%s", 60529088Smarkm pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", 60629088Smarkm pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", 60729088Smarkm pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); 60829088Smarkm if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| 60929088Smarkm SLC_FLUSHOUT| SLC_LEVELBITS)) 61029088Smarkm fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]); 61129088Smarkm fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]); 61229088Smarkm if ((pointer[i+SLC_VALUE] == IAC) && 61329088Smarkm (pointer[i+SLC_VALUE+1] == IAC)) 61429088Smarkm i++; 61529088Smarkm } 61629088Smarkm for (; i < length; i++) 61729088Smarkm fprintf(NetTrace, " ?%d?", pointer[i]); 61829088Smarkm break; 61929088Smarkm 62029088Smarkm case LM_MODE: 62129088Smarkm fprintf(NetTrace, "MODE "); 62229088Smarkm if (length < 3) { 62329088Smarkm fprintf(NetTrace, "(no mode??\?)"); 62429088Smarkm break; 62529088Smarkm } 62629088Smarkm { 62729088Smarkm char tbuf[64]; 628350140Sphilip snprintf(tbuf, sizeof(tbuf), "%s%s%s%s%s", 62929088Smarkm pointer[2]&MODE_EDIT ? "|EDIT" : "", 63029088Smarkm pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", 63129088Smarkm pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", 63229088Smarkm pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", 63329088Smarkm pointer[2]&MODE_ACK ? "|ACK" : ""); 63429088Smarkm fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0"); 63529088Smarkm } 63629088Smarkm if (pointer[2]&~(MODE_MASK)) 63729088Smarkm fprintf(NetTrace, " (0x%x)", pointer[2]); 63829088Smarkm for (i = 3; i < length; i++) 63929088Smarkm fprintf(NetTrace, " ?0x%x?", pointer[i]); 64029088Smarkm break; 64129088Smarkm default: 64229088Smarkm fprintf(NetTrace, "%d (unknown)", pointer[1]); 64329088Smarkm for (i = 2; i < length; i++) 64429088Smarkm fprintf(NetTrace, " %d", pointer[i]); 64529088Smarkm } 64629088Smarkm break; 64729088Smarkm 64829088Smarkm case TELOPT_STATUS: { 64987139Smarkm const char *cp; 65087139Smarkm int j, k; 65129088Smarkm 65229088Smarkm fprintf(NetTrace, "STATUS"); 65329088Smarkm 65429088Smarkm switch (pointer[1]) { 65529088Smarkm default: 65629088Smarkm if (pointer[1] == TELQUAL_SEND) 65729088Smarkm fprintf(NetTrace, " SEND"); 65829088Smarkm else 65929088Smarkm fprintf(NetTrace, " %d (unknown)", pointer[1]); 66029088Smarkm for (i = 2; i < length; i++) 66129088Smarkm fprintf(NetTrace, " ?%d?", pointer[i]); 66229088Smarkm break; 66329088Smarkm case TELQUAL_IS: 66429088Smarkm if (--want_status_response < 0) 66529088Smarkm want_status_response = 0; 66629088Smarkm if (NetTrace == stdout) 66729088Smarkm fprintf(NetTrace, " IS\r\n"); 66829088Smarkm else 66929088Smarkm fprintf(NetTrace, " IS\n"); 67029088Smarkm 67129088Smarkm for (i = 2; i < length; i++) { 67229088Smarkm switch(pointer[i]) { 67329088Smarkm case DO: cp = "DO"; goto common2; 67429088Smarkm case DONT: cp = "DONT"; goto common2; 67529088Smarkm case WILL: cp = "WILL"; goto common2; 67629088Smarkm case WONT: cp = "WONT"; goto common2; 67729088Smarkm common2: 67829088Smarkm i++; 67929088Smarkm if (TELOPT_OK((int)pointer[i])) 68029088Smarkm fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i])); 68129088Smarkm else 68229088Smarkm fprintf(NetTrace, " %s %d", cp, pointer[i]); 68329088Smarkm 68429088Smarkm if (NetTrace == stdout) 68529088Smarkm fprintf(NetTrace, "\r\n"); 68629088Smarkm else 68729088Smarkm fprintf(NetTrace, "\n"); 68829088Smarkm break; 68929088Smarkm 69029088Smarkm case SB: 69129088Smarkm fprintf(NetTrace, " SB "); 69229088Smarkm i++; 69329088Smarkm j = k = i; 69429088Smarkm while (j < length) { 69529088Smarkm if (pointer[j] == SE) { 69629088Smarkm if (j+1 == length) 69729088Smarkm break; 69829088Smarkm if (pointer[j+1] == SE) 69929088Smarkm j++; 70029088Smarkm else 70129088Smarkm break; 70229088Smarkm } 70329088Smarkm pointer[k++] = pointer[j++]; 70429088Smarkm } 70529088Smarkm printsub(0, &pointer[i], k - i); 70629088Smarkm if (i < length) { 70729088Smarkm fprintf(NetTrace, " SE"); 70829088Smarkm i = j; 70929088Smarkm } else 71029088Smarkm i = j - 1; 71129088Smarkm 71229088Smarkm if (NetTrace == stdout) 71329088Smarkm fprintf(NetTrace, "\r\n"); 71429088Smarkm else 71529088Smarkm fprintf(NetTrace, "\n"); 71629088Smarkm 71729088Smarkm break; 71829088Smarkm 71929088Smarkm default: 72029088Smarkm fprintf(NetTrace, " %d", pointer[i]); 72129088Smarkm break; 72229088Smarkm } 72329088Smarkm } 72429088Smarkm break; 72529088Smarkm } 72629088Smarkm break; 72729088Smarkm } 72829088Smarkm 72929088Smarkm case TELOPT_XDISPLOC: 73029088Smarkm fprintf(NetTrace, "X-DISPLAY-LOCATION "); 73129088Smarkm switch (pointer[1]) { 73229088Smarkm case TELQUAL_IS: 73329088Smarkm fprintf(NetTrace, "IS \"%.*s\"", length-2, (char *)pointer+2); 73429088Smarkm break; 73529088Smarkm case TELQUAL_SEND: 73629088Smarkm fprintf(NetTrace, "SEND"); 73729088Smarkm break; 73829088Smarkm default: 73929088Smarkm fprintf(NetTrace, "- unknown qualifier %d (0x%x).", 74029088Smarkm pointer[1], pointer[1]); 74129088Smarkm } 74229088Smarkm break; 74329088Smarkm 74429088Smarkm case TELOPT_NEW_ENVIRON: 74529088Smarkm fprintf(NetTrace, "NEW-ENVIRON "); 74629088Smarkm#ifdef OLD_ENVIRON 74729088Smarkm goto env_common1; 74829088Smarkm case TELOPT_OLD_ENVIRON: 74929088Smarkm fprintf(NetTrace, "OLD-ENVIRON"); 75029088Smarkm env_common1: 75129088Smarkm#endif 75229088Smarkm switch (pointer[1]) { 75329088Smarkm case TELQUAL_IS: 75429088Smarkm fprintf(NetTrace, "IS "); 75529088Smarkm goto env_common; 75629088Smarkm case TELQUAL_SEND: 75729088Smarkm fprintf(NetTrace, "SEND "); 75829088Smarkm goto env_common; 75929088Smarkm case TELQUAL_INFO: 76029088Smarkm fprintf(NetTrace, "INFO "); 76129088Smarkm env_common: 76229088Smarkm { 76387139Smarkm int noquote = 2; 76429088Smarkm#if defined(ENV_HACK) && defined(OLD_ENVIRON) 76529088Smarkm extern int old_env_var, old_env_value; 76629088Smarkm#endif 76729088Smarkm for (i = 2; i < length; i++ ) { 76829088Smarkm switch (pointer[i]) { 76929088Smarkm case NEW_ENV_VALUE: 77029088Smarkm#ifdef OLD_ENVIRON 77129088Smarkm /* case NEW_ENV_OVAR: */ 77229088Smarkm if (pointer[0] == TELOPT_OLD_ENVIRON) { 77329088Smarkm# ifdef ENV_HACK 77429088Smarkm if (old_env_var == OLD_ENV_VALUE) 77529088Smarkm fprintf(NetTrace, "\" (VALUE) " + noquote); 77629088Smarkm else 77729088Smarkm# endif 77829088Smarkm fprintf(NetTrace, "\" VAR " + noquote); 77929088Smarkm } else 78029088Smarkm#endif /* OLD_ENVIRON */ 781228651Sdim fprintf(NetTrace, "%s", "\" VALUE " + noquote); 78229088Smarkm noquote = 2; 78329088Smarkm break; 78429088Smarkm 78529088Smarkm case NEW_ENV_VAR: 78629088Smarkm#ifdef OLD_ENVIRON 78729088Smarkm /* case OLD_ENV_VALUE: */ 78829088Smarkm if (pointer[0] == TELOPT_OLD_ENVIRON) { 78929088Smarkm# ifdef ENV_HACK 79029088Smarkm if (old_env_value == OLD_ENV_VAR) 79129088Smarkm fprintf(NetTrace, "\" (VAR) " + noquote); 79229088Smarkm else 79329088Smarkm# endif 79429088Smarkm fprintf(NetTrace, "\" VALUE " + noquote); 79529088Smarkm } else 79629088Smarkm#endif /* OLD_ENVIRON */ 797228651Sdim fprintf(NetTrace, "%s", "\" VAR " + noquote); 79829088Smarkm noquote = 2; 79929088Smarkm break; 80029088Smarkm 80129088Smarkm case ENV_ESC: 802228651Sdim fprintf(NetTrace, "%s", "\" ESC " + noquote); 80329088Smarkm noquote = 2; 80429088Smarkm break; 80529088Smarkm 80629088Smarkm case ENV_USERVAR: 807228651Sdim fprintf(NetTrace, "%s", "\" USERVAR " + noquote); 80829088Smarkm noquote = 2; 80929088Smarkm break; 81029088Smarkm 81129088Smarkm default: 81229088Smarkm if (isprint(pointer[i]) && pointer[i] != '"') { 81329088Smarkm if (noquote) { 81429088Smarkm putc('"', NetTrace); 81529088Smarkm noquote = 0; 81629088Smarkm } 81729088Smarkm putc(pointer[i], NetTrace); 81829088Smarkm } else { 81929088Smarkm fprintf(NetTrace, "\" %03o " + noquote, 82029088Smarkm pointer[i]); 82129088Smarkm noquote = 2; 82229088Smarkm } 82329088Smarkm break; 82429088Smarkm } 82529088Smarkm } 82629088Smarkm if (!noquote) 82729088Smarkm putc('"', NetTrace); 82829088Smarkm break; 82929088Smarkm } 83029088Smarkm } 83129088Smarkm break; 83229088Smarkm 83329088Smarkm default: 83429088Smarkm if (TELOPT_OK(pointer[0])) 83529088Smarkm fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0])); 83629088Smarkm else 83729088Smarkm fprintf(NetTrace, "%d (unknown)", pointer[0]); 83829088Smarkm for (i = 1; i < length; i++) 83929088Smarkm fprintf(NetTrace, " %d", pointer[i]); 84029088Smarkm break; 84129088Smarkm } 84229088Smarkm if (direction) { 84329088Smarkm if (NetTrace == stdout) 84429088Smarkm fprintf(NetTrace, "\r\n"); 84529088Smarkm else 84629088Smarkm fprintf(NetTrace, "\n"); 84729088Smarkm } 84829088Smarkm if (NetTrace == stdout) 84929088Smarkm fflush(NetTrace); 85029088Smarkm } 85129088Smarkm} 85229088Smarkm 85329088Smarkm/* EmptyTerminal - called to make sure that the terminal buffer is empty. 85429088Smarkm * Note that we consider the buffer to run all the 85529088Smarkm * way to the kernel (thus the select). 85629088Smarkm */ 85729088Smarkm 85887139Smarkmstatic void 85987139SmarkmEmptyTerminal(void) 86029088Smarkm{ 86129088Smarkm fd_set o; 86229088Smarkm 86329088Smarkm FD_ZERO(&o); 86429088Smarkm 86529088Smarkm if (TTYBYTES() == 0) { 86629088Smarkm FD_SET(tout, &o); 86729088Smarkm (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, 86829088Smarkm (struct timeval *) 0); /* wait for TTLOWAT */ 86929088Smarkm } else { 87029088Smarkm while (TTYBYTES()) { 87129088Smarkm (void) ttyflush(0); 87229088Smarkm FD_SET(tout, &o); 87329088Smarkm (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0, 87429088Smarkm (struct timeval *) 0); /* wait for TTLOWAT */ 87529088Smarkm } 87629088Smarkm } 87729088Smarkm} 87829088Smarkm 87987139Smarkmstatic void 88087139SmarkmSetForExit(void) 88129088Smarkm{ 88229088Smarkm setconnmode(0); 88329088Smarkm do { 88429088Smarkm (void)telrcv(); /* Process any incoming data */ 88529088Smarkm EmptyTerminal(); 88629088Smarkm } while (ring_full_count(&netiring)); /* While there is any */ 88729088Smarkm setcommandmode(); 88829088Smarkm fflush(stdout); 88929088Smarkm fflush(stderr); 89029088Smarkm setconnmode(0); 89129088Smarkm EmptyTerminal(); /* Flush the path to the tty */ 89229088Smarkm setcommandmode(); 89329088Smarkm} 89429088Smarkm 89587139Smarkmvoid 89687139SmarkmExit(int returnCode) 89729088Smarkm{ 89829088Smarkm SetForExit(); 89929088Smarkm exit(returnCode); 90029088Smarkm} 90129088Smarkm 90287139Smarkmvoid 90387139SmarkmExitString(const char *string, int returnCode) 90429088Smarkm{ 90529088Smarkm SetForExit(); 90629088Smarkm fwrite(string, 1, strlen(string), stderr); 90729088Smarkm exit(returnCode); 90829088Smarkm} 909