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