157416Smarkm/* 257416Smarkm * Copyright (c) 1988, 1993 357416Smarkm * The Regents of the University of California. All rights reserved. 457416Smarkm * 557416Smarkm * Redistribution and use in source and binary forms, with or without 657416Smarkm * modification, are permitted provided that the following conditions 757416Smarkm * are met: 857416Smarkm * 1. Redistributions of source code must retain the above copyright 957416Smarkm * notice, this list of conditions and the following disclaimer. 1057416Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1157416Smarkm * notice, this list of conditions and the following disclaimer in the 1257416Smarkm * documentation and/or other materials provided with the distribution. 1357416Smarkm * 3. All advertising materials mentioning features or use of this software 1457416Smarkm * must display the following acknowledgement: 1557416Smarkm * This product includes software developed by the University of 1657416Smarkm * California, Berkeley and its contributors. 1757416Smarkm * 4. Neither the name of the University nor the names of its contributors 1857416Smarkm * may be used to endorse or promote products derived from this software 1957416Smarkm * without specific prior written permission. 2057416Smarkm * 2157416Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2257416Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2357416Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2457416Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2557416Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2657416Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2757416Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2857416Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2957416Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3057416Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3157416Smarkm * SUCH DAMAGE. 3257416Smarkm */ 3357416Smarkm 3457416Smarkm#define TELOPTS 3557416Smarkm#define TELCMDS 3657416Smarkm#define SLC_NAMES 3757416Smarkm 3857416Smarkm#include "telnet_locl.h" 3957416Smarkm 40233294SstasRCSID("$Id$"); 4157416Smarkm 4257416SmarkmFILE *NetTrace = 0; /* Not in bss, since needs to stay */ 4357416Smarkmint prettydump; 4457416Smarkm 4557416Smarkm/* 4657416Smarkm * SetSockOpt() 4757416Smarkm * 4857416Smarkm * Compensate for differences in 4.2 and 4.3 systems. 4957416Smarkm */ 5057416Smarkm 5157416Smarkmint 5257416SmarkmSetSockOpt(int fd, int level, int option, int yesno) 5357416Smarkm{ 5457416Smarkm#ifdef HAVE_SETSOCKOPT 5557416Smarkm#ifndef NOT43 5657416Smarkm return setsockopt(fd, level, option, 5757416Smarkm (void *)&yesno, sizeof yesno); 5857416Smarkm#else /* NOT43 */ 5957416Smarkm if (yesno == 0) { /* Can't do that in 4.2! */ 6057416Smarkm fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n", 6157416Smarkm option); 6257416Smarkm return -1; 6357416Smarkm } 6457416Smarkm return setsockopt(fd, level, option, 0, 0); 6557416Smarkm#endif /* NOT43 */ 6657416Smarkm#else 6757416Smarkm return -1; 6857416Smarkm#endif 6957416Smarkm} 7057416Smarkm 7157416Smarkm/* 7257416Smarkm * The following are routines used to print out debugging information. 7357416Smarkm */ 7457416Smarkm 7557416Smarkmchar NetTraceFile[256] = "(standard output)"; 7657416Smarkm 7757416Smarkmvoid 7857416SmarkmSetNetTrace(char *file) 7957416Smarkm{ 8057416Smarkm if (NetTrace && NetTrace != stdout) 8157416Smarkm fclose(NetTrace); 8257416Smarkm if (file && (strcmp(file, "-") != 0)) { 8357416Smarkm NetTrace = fopen(file, "w"); 8457416Smarkm if (NetTrace) { 8557416Smarkm strlcpy(NetTraceFile, file, sizeof(NetTraceFile)); 8657416Smarkm return; 8757416Smarkm } 8857416Smarkm fprintf(stderr, "Cannot open %s.\n", file); 8957416Smarkm } 9057416Smarkm NetTrace = stdout; 9157416Smarkm strlcpy(NetTraceFile, "(standard output)", sizeof(NetTraceFile)); 9257416Smarkm} 9357416Smarkm 9457416Smarkmvoid 9557416SmarkmDump(char direction, unsigned char *buffer, int length) 9657416Smarkm{ 9757416Smarkm# define BYTES_PER_LINE 32 9857416Smarkm unsigned char *pThis; 9957416Smarkm int offset; 10057416Smarkm 10157416Smarkm offset = 0; 10257416Smarkm 10357416Smarkm while (length) { 10457416Smarkm /* print one line */ 10557416Smarkm fprintf(NetTrace, "%c 0x%x\t", direction, offset); 10657416Smarkm pThis = buffer; 10757416Smarkm if (prettydump) { 10857416Smarkm buffer = buffer + min(length, BYTES_PER_LINE/2); 10957416Smarkm while (pThis < buffer) { 11057416Smarkm fprintf(NetTrace, "%c%.2x", 11157416Smarkm (((*pThis)&0xff) == 0xff) ? '*' : ' ', 11257416Smarkm (*pThis)&0xff); 11357416Smarkm pThis++; 11457416Smarkm } 11557416Smarkm length -= BYTES_PER_LINE/2; 11657416Smarkm offset += BYTES_PER_LINE/2; 11757416Smarkm } else { 11857416Smarkm buffer = buffer + min(length, BYTES_PER_LINE); 11957416Smarkm while (pThis < buffer) { 12057416Smarkm fprintf(NetTrace, "%.2x", (*pThis)&0xff); 12157416Smarkm pThis++; 12257416Smarkm } 12357416Smarkm length -= BYTES_PER_LINE; 12457416Smarkm offset += BYTES_PER_LINE; 12557416Smarkm } 12657416Smarkm if (NetTrace == stdout) { 12757416Smarkm fprintf(NetTrace, "\r\n"); 12857416Smarkm } else { 12957416Smarkm fprintf(NetTrace, "\n"); 13057416Smarkm } 13157416Smarkm if (length < 0) { 13257416Smarkm fflush(NetTrace); 13357416Smarkm return; 13457416Smarkm } 13557416Smarkm /* find next unique line */ 13657416Smarkm } 13757416Smarkm fflush(NetTrace); 13857416Smarkm} 13957416Smarkm 14057416Smarkm 14157416Smarkmvoid 14257416Smarkmprintoption(char *direction, int cmd, int option) 14357416Smarkm{ 14457416Smarkm if (!showoptions) 14557416Smarkm return; 14657416Smarkm if (cmd == IAC) { 14757416Smarkm if (TELCMD_OK(option)) 14857416Smarkm fprintf(NetTrace, "%s IAC %s", direction, TELCMD(option)); 14957416Smarkm else 15057416Smarkm fprintf(NetTrace, "%s IAC %d", direction, option); 15157416Smarkm } else { 15257416Smarkm char *fmt; 15357416Smarkm fmt = (cmd == WILL) ? "WILL" : (cmd == WONT) ? "WONT" : 15457416Smarkm (cmd == DO) ? "DO" : (cmd == DONT) ? "DONT" : 0; 15557416Smarkm if (fmt) { 15657416Smarkm fprintf(NetTrace, "%s %s ", direction, fmt); 15757416Smarkm if (TELOPT_OK(option)) 15857416Smarkm fprintf(NetTrace, "%s", TELOPT(option)); 15957416Smarkm else if (option == TELOPT_EXOPL) 16057416Smarkm fprintf(NetTrace, "EXOPL"); 16157416Smarkm else 16257416Smarkm fprintf(NetTrace, "%d", option); 16357416Smarkm } else 16457416Smarkm fprintf(NetTrace, "%s %d %d", direction, cmd, option); 16557416Smarkm } 16657416Smarkm if (NetTrace == stdout) { 16757416Smarkm fprintf(NetTrace, "\r\n"); 16857416Smarkm fflush(NetTrace); 16957416Smarkm } else { 17057416Smarkm fprintf(NetTrace, "\n"); 17157416Smarkm } 17257416Smarkm return; 17357416Smarkm} 17457416Smarkm 17557416Smarkmvoid 17657416Smarkmoptionstatus(void) 17757416Smarkm{ 17857416Smarkm int i; 17957416Smarkm 18057416Smarkm for (i = 0; i < 256; i++) { 18157416Smarkm if (do_dont_resp[i]) { 18257416Smarkm if (TELOPT_OK(i)) 18357416Smarkm printf("resp DO_DONT %s: %d\n", TELOPT(i), do_dont_resp[i]); 18457416Smarkm else if (TELCMD_OK(i)) 18557416Smarkm printf("resp DO_DONT %s: %d\n", TELCMD(i), do_dont_resp[i]); 18657416Smarkm else 18757416Smarkm printf("resp DO_DONT %d: %d\n", i, 18857416Smarkm do_dont_resp[i]); 18957416Smarkm if (my_want_state_is_do(i)) { 19057416Smarkm if (TELOPT_OK(i)) 19157416Smarkm printf("want DO %s\n", TELOPT(i)); 19257416Smarkm else if (TELCMD_OK(i)) 19357416Smarkm printf("want DO %s\n", TELCMD(i)); 19457416Smarkm else 19557416Smarkm printf("want DO %d\n", i); 19657416Smarkm } else { 19757416Smarkm if (TELOPT_OK(i)) 19857416Smarkm printf("want DONT %s\n", TELOPT(i)); 19957416Smarkm else if (TELCMD_OK(i)) 20057416Smarkm printf("want DONT %s\n", TELCMD(i)); 20157416Smarkm else 20257416Smarkm printf("want DONT %d\n", i); 20357416Smarkm } 20457416Smarkm } else { 20557416Smarkm if (my_state_is_do(i)) { 20657416Smarkm if (TELOPT_OK(i)) 20757416Smarkm printf(" DO %s\n", TELOPT(i)); 20857416Smarkm else if (TELCMD_OK(i)) 20957416Smarkm printf(" DO %s\n", TELCMD(i)); 21057416Smarkm else 21157416Smarkm printf(" DO %d\n", i); 21257416Smarkm } 21357416Smarkm } 21457416Smarkm if (will_wont_resp[i]) { 21557416Smarkm if (TELOPT_OK(i)) 21657416Smarkm printf("resp WILL_WONT %s: %d\n", TELOPT(i), will_wont_resp[i]); 21757416Smarkm else if (TELCMD_OK(i)) 21857416Smarkm printf("resp WILL_WONT %s: %d\n", TELCMD(i), will_wont_resp[i]); 21957416Smarkm else 22057416Smarkm printf("resp WILL_WONT %d: %d\n", 22157416Smarkm i, will_wont_resp[i]); 22257416Smarkm if (my_want_state_is_will(i)) { 22357416Smarkm if (TELOPT_OK(i)) 22457416Smarkm printf("want WILL %s\n", TELOPT(i)); 22557416Smarkm else if (TELCMD_OK(i)) 22657416Smarkm printf("want WILL %s\n", TELCMD(i)); 22757416Smarkm else 22857416Smarkm printf("want WILL %d\n", i); 22957416Smarkm } else { 23057416Smarkm if (TELOPT_OK(i)) 23157416Smarkm printf("want WONT %s\n", TELOPT(i)); 23257416Smarkm else if (TELCMD_OK(i)) 23357416Smarkm printf("want WONT %s\n", TELCMD(i)); 23457416Smarkm else 23557416Smarkm printf("want WONT %d\n", i); 23657416Smarkm } 23757416Smarkm } else { 23857416Smarkm if (my_state_is_will(i)) { 23957416Smarkm if (TELOPT_OK(i)) 24057416Smarkm printf(" WILL %s\n", TELOPT(i)); 24157416Smarkm else if (TELCMD_OK(i)) 24257416Smarkm printf(" WILL %s\n", TELCMD(i)); 24357416Smarkm else 24457416Smarkm printf(" WILL %d\n", i); 24557416Smarkm } 24657416Smarkm } 24757416Smarkm } 24857416Smarkm 24957416Smarkm} 25057416Smarkm 251233294Sstasstatic void __attribute__((format (printf, 3, 4))) 252233294Sstasqprintf(int quote, FILE *f, const char *fmt, ...) 253233294Sstas 254233294Sstas{ 255233294Sstas va_list va; 256233294Sstas if (quote) 257233294Sstas fprintf(f, "\" "); 258233294Sstas va_start(va, fmt); 259233294Sstas vfprintf(f, fmt, va); 260233294Sstas va_end(va); 261233294Sstas} 262233294Sstas 26357416Smarkmvoid 264233294Sstasprintsub(int direction, unsigned char *pointer, size_t length) 26557416Smarkm{ 26657416Smarkm int i; 26757416Smarkm unsigned char buf[512]; 26857416Smarkm 26957416Smarkm if (showoptions || direction == 0 || 27057416Smarkm (want_status_response && (pointer[0] == TELOPT_STATUS))) { 27157416Smarkm if (direction) { 27257416Smarkm fprintf(NetTrace, "%s IAC SB ", 27357416Smarkm (direction == '<')? "RCVD":"SENT"); 27457416Smarkm if (length >= 3) { 27557416Smarkm int j; 27657416Smarkm 27757416Smarkm i = pointer[length-2]; 27857416Smarkm j = pointer[length-1]; 27957416Smarkm 28057416Smarkm if (i != IAC || j != SE) { 28157416Smarkm fprintf(NetTrace, "(terminated by "); 28257416Smarkm if (TELOPT_OK(i)) 28357416Smarkm fprintf(NetTrace, "%s ", TELOPT(i)); 28457416Smarkm else if (TELCMD_OK(i)) 28557416Smarkm fprintf(NetTrace, "%s ", TELCMD(i)); 28657416Smarkm else 28757416Smarkm fprintf(NetTrace, "%d ", i); 28857416Smarkm if (TELOPT_OK(j)) 28957416Smarkm fprintf(NetTrace, "%s", TELOPT(j)); 29057416Smarkm else if (TELCMD_OK(j)) 29157416Smarkm fprintf(NetTrace, "%s", TELCMD(j)); 29257416Smarkm else 29357416Smarkm fprintf(NetTrace, "%d", j); 29457416Smarkm fprintf(NetTrace, ", not IAC SE!) "); 29557416Smarkm } 29657416Smarkm } 29757416Smarkm length -= 2; 29857416Smarkm } 29957416Smarkm if (length < 1) { 30057416Smarkm fprintf(NetTrace, "(Empty suboption??\?)"); 30157416Smarkm if (NetTrace == stdout) 30257416Smarkm fflush(NetTrace); 30357416Smarkm return; 30457416Smarkm } 30557416Smarkm switch (pointer[0]) { 30657416Smarkm case TELOPT_TTYPE: 30757416Smarkm fprintf(NetTrace, "TERMINAL-TYPE "); 30857416Smarkm switch (pointer[1]) { 30957416Smarkm case TELQUAL_IS: 310233294Sstas fprintf(NetTrace, "IS \"%.*s\"", 311233294Sstas (int)(length-2), 312233294Sstas (char *)pointer+2); 31357416Smarkm break; 31457416Smarkm case TELQUAL_SEND: 31557416Smarkm fprintf(NetTrace, "SEND"); 31657416Smarkm break; 31757416Smarkm default: 31857416Smarkm fprintf(NetTrace, 31957416Smarkm "- unknown qualifier %d (0x%x).", 32057416Smarkm pointer[1], pointer[1]); 32157416Smarkm } 32257416Smarkm break; 32357416Smarkm case TELOPT_TSPEED: 32457416Smarkm fprintf(NetTrace, "TERMINAL-SPEED"); 32557416Smarkm if (length < 2) { 32657416Smarkm fprintf(NetTrace, " (empty suboption??\?)"); 32757416Smarkm break; 32857416Smarkm } 32957416Smarkm switch (pointer[1]) { 33057416Smarkm case TELQUAL_IS: 33157416Smarkm fprintf(NetTrace, " IS "); 332233294Sstas fprintf(NetTrace, "%.*s", (int)(length-2), (char *)pointer+2); 33357416Smarkm break; 33457416Smarkm default: 33557416Smarkm if (pointer[1] == 1) 33657416Smarkm fprintf(NetTrace, " SEND"); 33757416Smarkm else 33857416Smarkm fprintf(NetTrace, " %d (unknown)", pointer[1]); 33957416Smarkm for (i = 2; i < length; i++) 34057416Smarkm fprintf(NetTrace, " ?%d?", pointer[i]); 34157416Smarkm break; 34257416Smarkm } 34357416Smarkm break; 34457416Smarkm 34557416Smarkm case TELOPT_LFLOW: 34657416Smarkm fprintf(NetTrace, "TOGGLE-FLOW-CONTROL"); 34757416Smarkm if (length < 2) { 34857416Smarkm fprintf(NetTrace, " (empty suboption??\?)"); 34957416Smarkm break; 35057416Smarkm } 35157416Smarkm switch (pointer[1]) { 35257416Smarkm case LFLOW_OFF: 35357416Smarkm fprintf(NetTrace, " OFF"); break; 35457416Smarkm case LFLOW_ON: 35557416Smarkm fprintf(NetTrace, " ON"); break; 35657416Smarkm case LFLOW_RESTART_ANY: 35757416Smarkm fprintf(NetTrace, " RESTART-ANY"); break; 35857416Smarkm case LFLOW_RESTART_XON: 35957416Smarkm fprintf(NetTrace, " RESTART-XON"); break; 36057416Smarkm default: 36157416Smarkm fprintf(NetTrace, " %d (unknown)", pointer[1]); 36257416Smarkm } 36357416Smarkm for (i = 2; i < length; i++) 36457416Smarkm fprintf(NetTrace, " ?%d?", pointer[i]); 36557416Smarkm break; 36657416Smarkm 36757416Smarkm case TELOPT_NAWS: 36857416Smarkm fprintf(NetTrace, "NAWS"); 36957416Smarkm if (length < 2) { 37057416Smarkm fprintf(NetTrace, " (empty suboption??\?)"); 37157416Smarkm break; 37257416Smarkm } 37357416Smarkm if (length == 2) { 37457416Smarkm fprintf(NetTrace, " ?%d?", pointer[1]); 37557416Smarkm break; 37657416Smarkm } 37757416Smarkm fprintf(NetTrace, " %d %d (%d)", 37857416Smarkm pointer[1], pointer[2], 37957416Smarkm (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); 38057416Smarkm if (length == 4) { 38157416Smarkm fprintf(NetTrace, " ?%d?", pointer[3]); 38257416Smarkm break; 38357416Smarkm } 38457416Smarkm fprintf(NetTrace, " %d %d (%d)", 38557416Smarkm pointer[3], pointer[4], 38657416Smarkm (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); 38757416Smarkm for (i = 5; i < length; i++) 38857416Smarkm fprintf(NetTrace, " ?%d?", pointer[i]); 38957416Smarkm break; 39057416Smarkm 39157416Smarkm#if defined(AUTHENTICATION) 39257416Smarkm case TELOPT_AUTHENTICATION: 39357416Smarkm fprintf(NetTrace, "AUTHENTICATION"); 39457416Smarkm if (length < 2) { 39557416Smarkm fprintf(NetTrace, " (empty suboption??\?)"); 39657416Smarkm break; 39757416Smarkm } 39857416Smarkm switch (pointer[1]) { 39957416Smarkm case TELQUAL_REPLY: 40057416Smarkm case TELQUAL_IS: 40157416Smarkm fprintf(NetTrace, " %s ", (pointer[1] == TELQUAL_IS) ? 40257416Smarkm "IS" : "REPLY"); 40357416Smarkm if (AUTHTYPE_NAME_OK(pointer[2])) 40457416Smarkm fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[2])); 40557416Smarkm else 40657416Smarkm fprintf(NetTrace, "%d ", pointer[2]); 40757416Smarkm if (length < 3) { 40857416Smarkm fprintf(NetTrace, "(partial suboption??\?)"); 40957416Smarkm break; 41057416Smarkm } 41157416Smarkm fprintf(NetTrace, "%s|%s", 41257416Smarkm ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? 41357416Smarkm "CLIENT" : "SERVER", 41457416Smarkm ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? 41557416Smarkm "MUTUAL" : "ONE-WAY"); 41657416Smarkm 41757416Smarkm auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); 41857416Smarkm fprintf(NetTrace, "%s", buf); 41957416Smarkm break; 42057416Smarkm 42157416Smarkm case TELQUAL_SEND: 42257416Smarkm i = 2; 42357416Smarkm fprintf(NetTrace, " SEND "); 42457416Smarkm while (i < length) { 42557416Smarkm if (AUTHTYPE_NAME_OK(pointer[i])) 42657416Smarkm fprintf(NetTrace, "%s ", AUTHTYPE_NAME(pointer[i])); 42757416Smarkm else 42857416Smarkm fprintf(NetTrace, "%d ", pointer[i]); 42957416Smarkm if (++i >= length) { 43057416Smarkm fprintf(NetTrace, "(partial suboption??\?)"); 43157416Smarkm break; 43257416Smarkm } 43357416Smarkm fprintf(NetTrace, "%s|%s ", 43457416Smarkm ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? 43557416Smarkm "CLIENT" : "SERVER", 43657416Smarkm ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? 43757416Smarkm "MUTUAL" : "ONE-WAY"); 43857416Smarkm ++i; 43957416Smarkm } 44057416Smarkm break; 44157416Smarkm 44257416Smarkm case TELQUAL_NAME: 44357416Smarkm i = 2; 44457416Smarkm fprintf(NetTrace, " NAME \""); 44557416Smarkm while (i < length) 44657416Smarkm putc(pointer[i++], NetTrace); 44757416Smarkm putc('"', NetTrace); 44857416Smarkm break; 44957416Smarkm 45057416Smarkm default: 45157416Smarkm for (i = 2; i < length; i++) 45257416Smarkm fprintf(NetTrace, " ?%d?", pointer[i]); 45357416Smarkm break; 45457416Smarkm } 45557416Smarkm break; 45657416Smarkm#endif 45757416Smarkm 45857416Smarkm#if defined(ENCRYPTION) 45957416Smarkm case TELOPT_ENCRYPT: 46057416Smarkm fprintf(NetTrace, "ENCRYPT"); 46157416Smarkm if (length < 2) { 46257416Smarkm fprintf(NetTrace, " (empty suboption?)"); 46357416Smarkm break; 46457416Smarkm } 46557416Smarkm switch (pointer[1]) { 46657416Smarkm case ENCRYPT_START: 46757416Smarkm fprintf(NetTrace, " START"); 46857416Smarkm break; 46957416Smarkm 47057416Smarkm case ENCRYPT_END: 47157416Smarkm fprintf(NetTrace, " END"); 47257416Smarkm break; 47357416Smarkm 47457416Smarkm case ENCRYPT_REQSTART: 47557416Smarkm fprintf(NetTrace, " REQUEST-START"); 47657416Smarkm break; 47757416Smarkm 47857416Smarkm case ENCRYPT_REQEND: 47957416Smarkm fprintf(NetTrace, " REQUEST-END"); 48057416Smarkm break; 48157416Smarkm 48257416Smarkm case ENCRYPT_IS: 48357416Smarkm case ENCRYPT_REPLY: 48457416Smarkm fprintf(NetTrace, " %s ", (pointer[1] == ENCRYPT_IS) ? 48557416Smarkm "IS" : "REPLY"); 48657416Smarkm if (length < 3) { 48757416Smarkm fprintf(NetTrace, " (partial suboption?)"); 48857416Smarkm break; 48957416Smarkm } 49057416Smarkm if (ENCTYPE_NAME_OK(pointer[2])) 49157416Smarkm fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[2])); 49257416Smarkm else 49357416Smarkm fprintf(NetTrace, " %d (unknown)", pointer[2]); 49457416Smarkm 49557416Smarkm encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); 49657416Smarkm fprintf(NetTrace, "%s", buf); 49757416Smarkm break; 49857416Smarkm 49957416Smarkm case ENCRYPT_SUPPORT: 50057416Smarkm i = 2; 50157416Smarkm fprintf(NetTrace, " SUPPORT "); 50257416Smarkm while (i < length) { 50357416Smarkm if (ENCTYPE_NAME_OK(pointer[i])) 50457416Smarkm fprintf(NetTrace, "%s ", ENCTYPE_NAME(pointer[i])); 50557416Smarkm else 50657416Smarkm fprintf(NetTrace, "%d ", pointer[i]); 50757416Smarkm i++; 50857416Smarkm } 50957416Smarkm break; 51057416Smarkm 51157416Smarkm case ENCRYPT_ENC_KEYID: 51257416Smarkm fprintf(NetTrace, " ENC_KEYID "); 51357416Smarkm goto encommon; 51457416Smarkm 51557416Smarkm case ENCRYPT_DEC_KEYID: 51657416Smarkm fprintf(NetTrace, " DEC_KEYID "); 51757416Smarkm goto encommon; 51857416Smarkm 51957416Smarkm default: 52057416Smarkm fprintf(NetTrace, " %d (unknown)", pointer[1]); 52157416Smarkm encommon: 52257416Smarkm for (i = 2; i < length; i++) 52357416Smarkm fprintf(NetTrace, " %d", pointer[i]); 52457416Smarkm break; 52557416Smarkm } 52657416Smarkm break; 52757416Smarkm#endif 52857416Smarkm 52957416Smarkm case TELOPT_LINEMODE: 53057416Smarkm fprintf(NetTrace, "LINEMODE "); 53157416Smarkm if (length < 2) { 53257416Smarkm fprintf(NetTrace, " (empty suboption??\?)"); 53357416Smarkm break; 53457416Smarkm } 53557416Smarkm switch (pointer[1]) { 53657416Smarkm case WILL: 53757416Smarkm fprintf(NetTrace, "WILL "); 53857416Smarkm goto common; 53957416Smarkm case WONT: 54057416Smarkm fprintf(NetTrace, "WONT "); 54157416Smarkm goto common; 54257416Smarkm case DO: 54357416Smarkm fprintf(NetTrace, "DO "); 54457416Smarkm goto common; 54557416Smarkm case DONT: 54657416Smarkm fprintf(NetTrace, "DONT "); 54757416Smarkm common: 54857416Smarkm if (length < 3) { 54957416Smarkm fprintf(NetTrace, "(no option??\?)"); 55057416Smarkm break; 55157416Smarkm } 55257416Smarkm switch (pointer[2]) { 55357416Smarkm case LM_FORWARDMASK: 55457416Smarkm fprintf(NetTrace, "Forward Mask"); 55557416Smarkm for (i = 3; i < length; i++) 55657416Smarkm fprintf(NetTrace, " %x", pointer[i]); 55757416Smarkm break; 55857416Smarkm default: 55957416Smarkm fprintf(NetTrace, "%d (unknown)", pointer[2]); 56057416Smarkm for (i = 3; i < length; i++) 56157416Smarkm fprintf(NetTrace, " %d", pointer[i]); 56257416Smarkm break; 56357416Smarkm } 56457416Smarkm break; 56557416Smarkm 56657416Smarkm case LM_SLC: 56757416Smarkm fprintf(NetTrace, "SLC"); 56857416Smarkm for (i = 2; i < length - 2; i += 3) { 56957416Smarkm if (SLC_NAME_OK(pointer[i+SLC_FUNC])) 57057416Smarkm fprintf(NetTrace, " %s", SLC_NAME(pointer[i+SLC_FUNC])); 57157416Smarkm else 57257416Smarkm fprintf(NetTrace, " %d", pointer[i+SLC_FUNC]); 57357416Smarkm switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { 57457416Smarkm case SLC_NOSUPPORT: 57557416Smarkm fprintf(NetTrace, " NOSUPPORT"); break; 57657416Smarkm case SLC_CANTCHANGE: 57757416Smarkm fprintf(NetTrace, " CANTCHANGE"); break; 57857416Smarkm case SLC_VARIABLE: 57957416Smarkm fprintf(NetTrace, " VARIABLE"); break; 58057416Smarkm case SLC_DEFAULT: 58157416Smarkm fprintf(NetTrace, " DEFAULT"); break; 58257416Smarkm } 58357416Smarkm fprintf(NetTrace, "%s%s%s", 58457416Smarkm pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", 58557416Smarkm pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", 58657416Smarkm pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); 58757416Smarkm if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| 58857416Smarkm SLC_FLUSHOUT| SLC_LEVELBITS)) 58957416Smarkm fprintf(NetTrace, "(0x%x)", pointer[i+SLC_FLAGS]); 59057416Smarkm fprintf(NetTrace, " %d;", pointer[i+SLC_VALUE]); 59157416Smarkm if ((pointer[i+SLC_VALUE] == IAC) && 59257416Smarkm (pointer[i+SLC_VALUE+1] == IAC)) 59357416Smarkm i++; 59457416Smarkm } 59557416Smarkm for (; i < length; i++) 59657416Smarkm fprintf(NetTrace, " ?%d?", pointer[i]); 59757416Smarkm break; 59857416Smarkm 59957416Smarkm case LM_MODE: 60057416Smarkm fprintf(NetTrace, "MODE "); 60157416Smarkm if (length < 3) { 60257416Smarkm fprintf(NetTrace, "(no mode??\?)"); 60357416Smarkm break; 60457416Smarkm } 60557416Smarkm { 60657416Smarkm char tbuf[64]; 60757416Smarkm snprintf(tbuf, sizeof(tbuf), 60857416Smarkm "%s%s%s%s%s", 60957416Smarkm pointer[2]&MODE_EDIT ? "|EDIT" : "", 61057416Smarkm pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", 61157416Smarkm pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", 61257416Smarkm pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", 61357416Smarkm pointer[2]&MODE_ACK ? "|ACK" : ""); 61457416Smarkm fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0"); 61557416Smarkm } 61657416Smarkm if (pointer[2]&~(MODE_MASK)) 61757416Smarkm fprintf(NetTrace, " (0x%x)", pointer[2]); 61857416Smarkm for (i = 3; i < length; i++) 61957416Smarkm fprintf(NetTrace, " ?0x%x?", pointer[i]); 62057416Smarkm break; 62157416Smarkm default: 62257416Smarkm fprintf(NetTrace, "%d (unknown)", pointer[1]); 62357416Smarkm for (i = 2; i < length; i++) 62457416Smarkm fprintf(NetTrace, " %d", pointer[i]); 62557416Smarkm } 62657416Smarkm break; 62757416Smarkm 62857416Smarkm case TELOPT_STATUS: { 62957416Smarkm char *cp; 63057416Smarkm int j, k; 63157416Smarkm 63257416Smarkm fprintf(NetTrace, "STATUS"); 63357416Smarkm 63457416Smarkm switch (pointer[1]) { 63557416Smarkm default: 63657416Smarkm if (pointer[1] == TELQUAL_SEND) 63757416Smarkm fprintf(NetTrace, " SEND"); 63857416Smarkm else 63957416Smarkm fprintf(NetTrace, " %d (unknown)", pointer[1]); 64057416Smarkm for (i = 2; i < length; i++) 64157416Smarkm fprintf(NetTrace, " ?%d?", pointer[i]); 64257416Smarkm break; 64357416Smarkm case TELQUAL_IS: 64457416Smarkm if (--want_status_response < 0) 64557416Smarkm want_status_response = 0; 64657416Smarkm if (NetTrace == stdout) 64757416Smarkm fprintf(NetTrace, " IS\r\n"); 64857416Smarkm else 64957416Smarkm fprintf(NetTrace, " IS\n"); 65057416Smarkm 65157416Smarkm for (i = 2; i < length; i++) { 65257416Smarkm switch(pointer[i]) { 65357416Smarkm case DO: cp = "DO"; goto common2; 65457416Smarkm case DONT: cp = "DONT"; goto common2; 65557416Smarkm case WILL: cp = "WILL"; goto common2; 65657416Smarkm case WONT: cp = "WONT"; goto common2; 65757416Smarkm common2: 65857416Smarkm i++; 65957416Smarkm if (TELOPT_OK((int)pointer[i])) 66057416Smarkm fprintf(NetTrace, " %s %s", cp, TELOPT(pointer[i])); 66157416Smarkm else 66257416Smarkm fprintf(NetTrace, " %s %d", cp, pointer[i]); 66357416Smarkm 66457416Smarkm if (NetTrace == stdout) 66557416Smarkm fprintf(NetTrace, "\r\n"); 66657416Smarkm else 66757416Smarkm fprintf(NetTrace, "\n"); 66857416Smarkm break; 66957416Smarkm 67057416Smarkm case SB: 67157416Smarkm fprintf(NetTrace, " SB "); 67257416Smarkm i++; 67357416Smarkm j = k = i; 67457416Smarkm while (j < length) { 67557416Smarkm if (pointer[j] == SE) { 67657416Smarkm if (j+1 == length) 67757416Smarkm break; 67857416Smarkm if (pointer[j+1] == SE) 67957416Smarkm j++; 68057416Smarkm else 68157416Smarkm break; 68257416Smarkm } 68357416Smarkm pointer[k++] = pointer[j++]; 68457416Smarkm } 68557416Smarkm printsub(0, &pointer[i], k - i); 68657416Smarkm if (i < length) { 68757416Smarkm fprintf(NetTrace, " SE"); 68857416Smarkm i = j; 68957416Smarkm } else 69057416Smarkm i = j - 1; 69157416Smarkm 69257416Smarkm if (NetTrace == stdout) 69357416Smarkm fprintf(NetTrace, "\r\n"); 69457416Smarkm else 69557416Smarkm fprintf(NetTrace, "\n"); 69657416Smarkm 69757416Smarkm break; 69857416Smarkm 69957416Smarkm default: 70057416Smarkm fprintf(NetTrace, " %d", pointer[i]); 70157416Smarkm break; 70257416Smarkm } 70357416Smarkm } 70457416Smarkm break; 70557416Smarkm } 70657416Smarkm break; 70757416Smarkm } 70857416Smarkm 70957416Smarkm case TELOPT_XDISPLOC: 71057416Smarkm fprintf(NetTrace, "X-DISPLAY-LOCATION "); 71157416Smarkm switch (pointer[1]) { 71257416Smarkm case TELQUAL_IS: 713233294Sstas fprintf(NetTrace, "IS \"%.*s\"", (int)(length-2), (char *)pointer+2); 71457416Smarkm break; 71557416Smarkm case TELQUAL_SEND: 71657416Smarkm fprintf(NetTrace, "SEND"); 71757416Smarkm break; 71857416Smarkm default: 71957416Smarkm fprintf(NetTrace, "- unknown qualifier %d (0x%x).", 72057416Smarkm pointer[1], pointer[1]); 72157416Smarkm } 72257416Smarkm break; 72357416Smarkm 72457416Smarkm case TELOPT_NEW_ENVIRON: 72557416Smarkm fprintf(NetTrace, "NEW-ENVIRON "); 72657416Smarkm#ifdef OLD_ENVIRON 72757416Smarkm goto env_common1; 72857416Smarkm case TELOPT_OLD_ENVIRON: 72957416Smarkm fprintf(NetTrace, "OLD-ENVIRON"); 73057416Smarkm env_common1: 73157416Smarkm#endif 73257416Smarkm switch (pointer[1]) { 73357416Smarkm case TELQUAL_IS: 73457416Smarkm fprintf(NetTrace, "IS "); 73557416Smarkm goto env_common; 73657416Smarkm case TELQUAL_SEND: 73757416Smarkm fprintf(NetTrace, "SEND "); 73857416Smarkm goto env_common; 73957416Smarkm case TELQUAL_INFO: 74057416Smarkm fprintf(NetTrace, "INFO "); 74157416Smarkm env_common: 74257416Smarkm { 743233294Sstas int quote = 0; 74457416Smarkm for (i = 2; i < length; i++ ) { 74557416Smarkm switch (pointer[i]) { 746233294Sstas case NEW_ENV_VAR: 747233294Sstas qprintf(quote, NetTrace, "VAR "); 748233294Sstas quote = 0; 74957416Smarkm break; 75057416Smarkm 751233294Sstas case NEW_ENV_VALUE: 752233294Sstas qprintf(quote, NetTrace, "VALUE"); 753233294Sstas quote = 0; 75457416Smarkm break; 75557416Smarkm 75657416Smarkm case ENV_ESC: 757233294Sstas qprintf(quote, NetTrace, "ESC "); 758233294Sstas quote = 0; 75957416Smarkm break; 76057416Smarkm 76157416Smarkm case ENV_USERVAR: 762233294Sstas qprintf(quote, NetTrace, "USERVAR "); 763233294Sstas quote = 0; 76457416Smarkm break; 76557416Smarkm 76657416Smarkm default: 76757416Smarkm if (isprint(pointer[i]) && pointer[i] != '"') { 768233294Sstas if (!quote) { 76957416Smarkm putc('"', NetTrace); 770233294Sstas quote = 1; 77157416Smarkm } 77257416Smarkm putc(pointer[i], NetTrace); 77357416Smarkm } else { 774233294Sstas qprintf(quote, NetTrace, "%03o ", pointer[i]); 775233294Sstas quote = 0; 77657416Smarkm } 77757416Smarkm break; 77857416Smarkm } 77957416Smarkm } 780233294Sstas if (quote) 78157416Smarkm putc('"', NetTrace); 78257416Smarkm break; 78357416Smarkm } 78457416Smarkm } 78557416Smarkm break; 78657416Smarkm 78757416Smarkm default: 78857416Smarkm if (TELOPT_OK(pointer[0])) 78957416Smarkm fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0])); 79057416Smarkm else 79157416Smarkm fprintf(NetTrace, "%d (unknown)", pointer[0]); 79257416Smarkm for (i = 1; i < length; i++) 79357416Smarkm fprintf(NetTrace, " %d", pointer[i]); 79457416Smarkm break; 79557416Smarkm } 79657416Smarkm if (direction) { 79757416Smarkm if (NetTrace == stdout) 79857416Smarkm fprintf(NetTrace, "\r\n"); 79957416Smarkm else 80057416Smarkm fprintf(NetTrace, "\n"); 80157416Smarkm } 80257416Smarkm if (NetTrace == stdout) 80357416Smarkm fflush(NetTrace); 80457416Smarkm } 80557416Smarkm} 80657416Smarkm 80757416Smarkm/* EmptyTerminal - called to make sure that the terminal buffer is empty. 80857416Smarkm * Note that we consider the buffer to run all the 80957416Smarkm * way to the kernel (thus the select). 81057416Smarkm */ 81157416Smarkm 81257416Smarkmvoid 81357416SmarkmEmptyTerminal(void) 81457416Smarkm{ 81557416Smarkm fd_set outs; 81657416Smarkm 81757416Smarkm FD_ZERO(&outs); 81857416Smarkm 81972445Sassar if (tout >= FD_SETSIZE) 82072445Sassar ExitString("fd too large", 1); 82172445Sassar 82257416Smarkm if (TTYBYTES() == 0) { 82357416Smarkm FD_SET(tout, &outs); 82457416Smarkm select(tout+1, 0, &outs, 0, 82557416Smarkm (struct timeval *) 0); /* wait for TTLOWAT */ 82657416Smarkm } else { 82757416Smarkm while (TTYBYTES()) { 82857416Smarkm ttyflush(0); 82957416Smarkm FD_SET(tout, &outs); 83057416Smarkm select(tout+1, 0, &outs, 0, 83157416Smarkm (struct timeval *) 0); /* wait for TTLOWAT */ 83257416Smarkm } 83357416Smarkm } 83457416Smarkm} 83557416Smarkm 83657416Smarkmvoid 83757416SmarkmSetForExit(void) 83857416Smarkm{ 83957416Smarkm setconnmode(0); 84057416Smarkm do { 84157416Smarkm telrcv(); /* Process any incoming data */ 84257416Smarkm EmptyTerminal(); 84357416Smarkm } while (ring_full_count(&netiring)); /* While there is any */ 84457416Smarkm setcommandmode(); 84557416Smarkm fflush(stdout); 84657416Smarkm fflush(stderr); 84757416Smarkm setconnmode(0); 84857416Smarkm EmptyTerminal(); /* Flush the path to the tty */ 84957416Smarkm setcommandmode(); 85057416Smarkm} 85157416Smarkm 85257416Smarkmvoid 85357416SmarkmExit(int returnCode) 85457416Smarkm{ 85557416Smarkm SetForExit(); 85657416Smarkm exit(returnCode); 85757416Smarkm} 85857416Smarkm 85957416Smarkmvoid 86057416SmarkmExitString(char *string, int returnCode) 86157416Smarkm{ 86257416Smarkm SetForExit(); 86357416Smarkm fwrite(string, 1, strlen(string), stderr); 86457416Smarkm exit(returnCode); 86557416Smarkm} 866