111b3aaa1Schristos /* NetBSD: print-telnet.c,v 1.2 1999/10/11 12:40:12 sjg Exp */ 20f74e101Schristos 30f74e101Schristos /*- 40f74e101Schristos * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 50f74e101Schristos * All rights reserved. 60f74e101Schristos * 70f74e101Schristos * This code is derived from software contributed to The NetBSD Foundation 80f74e101Schristos * by Simon J. Gerraty. 90f74e101Schristos * 100f74e101Schristos * Redistribution and use in source and binary forms, with or without 110f74e101Schristos * modification, are permitted provided that the following conditions 120f74e101Schristos * are met: 130f74e101Schristos * 1. Redistributions of source code must retain the above copyright 140f74e101Schristos * notice, this list of conditions and the following disclaimer. 150f74e101Schristos * 2. Redistributions in binary form must reproduce the above copyright 160f74e101Schristos * notice, this list of conditions and the following disclaimer in the 170f74e101Schristos * documentation and/or other materials provided with the distribution. 180f74e101Schristos * 190f74e101Schristos * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 200f74e101Schristos * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 210f74e101Schristos * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 220f74e101Schristos * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 230f74e101Schristos * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 240f74e101Schristos * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 250f74e101Schristos * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 260f74e101Schristos * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 270f74e101Schristos * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 280f74e101Schristos * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 290f74e101Schristos * POSSIBILITY OF SUCH DAMAGE. 300f74e101Schristos */ 310f74e101Schristos /* 320f74e101Schristos * @(#)Copyright (c) 1994, Simon J. Gerraty. 330f74e101Schristos * 340f74e101Schristos * This is free software. It comes with NO WARRANTY. 350f74e101Schristos * Permission to use, modify and distribute this source code 360f74e101Schristos * is granted subject to the following conditions. 370f74e101Schristos * 1/ that the above copyright notice and this notice 380f74e101Schristos * are preserved in all copies. 390f74e101Schristos */ 400f74e101Schristos 4111b3aaa1Schristos #include <sys/cdefs.h> 420f74e101Schristos #ifndef lint 43*26ba0b50Schristos __RCSID("$NetBSD: print-telnet.c,v 1.10 2024/09/02 16:15:33 christos Exp $"); 4411b3aaa1Schristos #endif 45b3a00663Schristos 46dc860a36Sspz /* \summary: Telnet option printer */ 47dc860a36Sspz 48c74ad251Schristos #include <config.h> 490f74e101Schristos 50c74ad251Schristos #include "netdissect-stdinc.h" 510f74e101Schristos 520f74e101Schristos #include <stdio.h> 530f74e101Schristos 54fdccd7e4Schristos #include "netdissect.h" 55c74ad251Schristos #include "extract.h" 560f74e101Schristos 57b3a00663Schristos 58b3a00663Schristos /* NetBSD: telnet.h,v 1.9 2001/06/11 01:50:50 wiz Exp */ 59b3a00663Schristos 60b3a00663Schristos /* 61b3a00663Schristos * Definitions for the TELNET protocol. 62b3a00663Schristos */ 63b3a00663Schristos #define IAC 255 /* interpret as command: */ 64b3a00663Schristos #define DONT 254 /* you are not to use option */ 65b3a00663Schristos #define DO 253 /* please, you use option */ 66b3a00663Schristos #define WONT 252 /* I won't use option */ 67b3a00663Schristos #define WILL 251 /* I will use option */ 68b3a00663Schristos #define SB 250 /* interpret as subnegotiation */ 69b3a00663Schristos #define GA 249 /* you may reverse the line */ 70b3a00663Schristos #define EL 248 /* erase the current line */ 71b3a00663Schristos #define EC 247 /* erase the current character */ 72b3a00663Schristos #define AYT 246 /* are you there */ 73b3a00663Schristos #define AO 245 /* abort output--but let prog finish */ 74b3a00663Schristos #define IP 244 /* interrupt process--permanently */ 75b3a00663Schristos #define BREAK 243 /* break */ 76b3a00663Schristos #define DM 242 /* data mark--for connect. cleaning */ 77b3a00663Schristos #define NOP 241 /* nop */ 78b3a00663Schristos #define SE 240 /* end sub negotiation */ 79b3a00663Schristos #define EOR 239 /* end of record (transparent mode) */ 80b3a00663Schristos #define ABORT 238 /* Abort process */ 81b3a00663Schristos #define SUSP 237 /* Suspend process */ 82b3a00663Schristos #define xEOF 236 /* End of file: EOF is already used... */ 83b3a00663Schristos 84b3a00663Schristos #define SYNCH 242 /* for telfunc calls */ 85b3a00663Schristos 86dc860a36Sspz static const char *telcmds[] = { 87b3a00663Schristos "EOF", "SUSP", "ABORT", "EOR", 88b3a00663Schristos "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC", 89b3a00663Schristos "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0, 90b3a00663Schristos }; 91b3a00663Schristos 92b3a00663Schristos #define TELCMD_FIRST xEOF 93b3a00663Schristos #define TELCMD_LAST IAC 94b3a00663Schristos #define TELCMD_OK(x) ((unsigned int)(x) <= TELCMD_LAST && \ 95b3a00663Schristos (unsigned int)(x) >= TELCMD_FIRST) 96b3a00663Schristos #define TELCMD(x) telcmds[(x)-TELCMD_FIRST] 97b3a00663Schristos 98b3a00663Schristos /* telnet options */ 99b3a00663Schristos #define TELOPT_BINARY 0 /* 8-bit data path */ 100b3a00663Schristos #define TELOPT_ECHO 1 /* echo */ 101b3a00663Schristos #define TELOPT_RCP 2 /* prepare to reconnect */ 102b3a00663Schristos #define TELOPT_SGA 3 /* suppress go ahead */ 103b3a00663Schristos #define TELOPT_NAMS 4 /* approximate message size */ 104b3a00663Schristos #define TELOPT_STATUS 5 /* give status */ 105b3a00663Schristos #define TELOPT_TM 6 /* timing mark */ 106b3a00663Schristos #define TELOPT_RCTE 7 /* remote controlled transmission and echo */ 107b3a00663Schristos #define TELOPT_NAOL 8 /* negotiate about output line width */ 108b3a00663Schristos #define TELOPT_NAOP 9 /* negotiate about output page size */ 109b3a00663Schristos #define TELOPT_NAOCRD 10 /* negotiate about CR disposition */ 110b3a00663Schristos #define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */ 111b3a00663Schristos #define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */ 112b3a00663Schristos #define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */ 113b3a00663Schristos #define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */ 114b3a00663Schristos #define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */ 115b3a00663Schristos #define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */ 116*26ba0b50Schristos #define TELOPT_XASCII 17 /* extended ascii character set */ 117b3a00663Schristos #define TELOPT_LOGOUT 18 /* force logout */ 118b3a00663Schristos #define TELOPT_BM 19 /* byte macro */ 119b3a00663Schristos #define TELOPT_DET 20 /* data entry terminal */ 120b3a00663Schristos #define TELOPT_SUPDUP 21 /* supdup protocol */ 121b3a00663Schristos #define TELOPT_SUPDUPOUTPUT 22 /* supdup output */ 122b3a00663Schristos #define TELOPT_SNDLOC 23 /* send location */ 123b3a00663Schristos #define TELOPT_TTYPE 24 /* terminal type */ 124b3a00663Schristos #define TELOPT_EOR 25 /* end or record */ 125b3a00663Schristos #define TELOPT_TUID 26 /* TACACS user identification */ 126b3a00663Schristos #define TELOPT_OUTMRK 27 /* output marking */ 127b3a00663Schristos #define TELOPT_TTYLOC 28 /* terminal location number */ 128b3a00663Schristos #define TELOPT_3270REGIME 29 /* 3270 regime */ 129b3a00663Schristos #define TELOPT_X3PAD 30 /* X.3 PAD */ 130b3a00663Schristos #define TELOPT_NAWS 31 /* window size */ 131b3a00663Schristos #define TELOPT_TSPEED 32 /* terminal speed */ 132b3a00663Schristos #define TELOPT_LFLOW 33 /* remote flow control */ 133b3a00663Schristos #define TELOPT_LINEMODE 34 /* Linemode option */ 134b3a00663Schristos #define TELOPT_XDISPLOC 35 /* X Display Location */ 135b3a00663Schristos #define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */ 136b3a00663Schristos #define TELOPT_AUTHENTICATION 37/* Authenticate */ 137b3a00663Schristos #define TELOPT_ENCRYPT 38 /* Encryption option */ 138b3a00663Schristos #define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */ 139b3a00663Schristos #define TELOPT_EXOPL 255 /* extended-options-list */ 140b3a00663Schristos 141b3a00663Schristos 142b3a00663Schristos #define NTELOPTS (1+TELOPT_NEW_ENVIRON) 143dc860a36Sspz static const char *telopts[NTELOPTS+1] = { 144b3a00663Schristos "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", 145b3a00663Schristos "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP", 146b3a00663Schristos "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS", 147b3a00663Schristos "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", 148b3a00663Schristos "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT", 149b3a00663Schristos "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", 150b3a00663Schristos "TACACS UID", "OUTPUT MARKING", "TTYLOC", 151b3a00663Schristos "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW", 152b3a00663Schristos "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION", 153b3a00663Schristos "ENCRYPT", "NEW-ENVIRON", 154b3a00663Schristos 0, 155b3a00663Schristos }; 156b3a00663Schristos #define TELOPT_FIRST TELOPT_BINARY 157b3a00663Schristos #define TELOPT_LAST TELOPT_NEW_ENVIRON 158b3a00663Schristos #define TELOPT_OK(x) ((unsigned int)(x) <= TELOPT_LAST) 159b3a00663Schristos #define TELOPT(x) telopts[(x)-TELOPT_FIRST] 160b3a00663Schristos 161b3a00663Schristos /* sub-option qualifiers */ 162b3a00663Schristos #define TELQUAL_IS 0 /* option is... */ 163b3a00663Schristos #define TELQUAL_SEND 1 /* send option */ 164b3a00663Schristos #define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */ 165b3a00663Schristos #define TELQUAL_REPLY 2 /* AUTHENTICATION: client version of IS */ 166b3a00663Schristos #define TELQUAL_NAME 3 /* AUTHENTICATION: client version of IS */ 167b3a00663Schristos 168b3a00663Schristos #define LFLOW_OFF 0 /* Disable remote flow control */ 169b3a00663Schristos #define LFLOW_ON 1 /* Enable remote flow control */ 170b3a00663Schristos #define LFLOW_RESTART_ANY 2 /* Restart output on any char */ 171b3a00663Schristos #define LFLOW_RESTART_XON 3 /* Restart output only on XON */ 172b3a00663Schristos 173b3a00663Schristos /* 174b3a00663Schristos * LINEMODE suboptions 175b3a00663Schristos */ 176b3a00663Schristos 177b3a00663Schristos #define LM_MODE 1 178b3a00663Schristos #define LM_FORWARDMASK 2 179b3a00663Schristos #define LM_SLC 3 180b3a00663Schristos 181b3a00663Schristos #define MODE_EDIT 0x01 182b3a00663Schristos #define MODE_TRAPSIG 0x02 183b3a00663Schristos #define MODE_ACK 0x04 184b3a00663Schristos #define MODE_SOFT_TAB 0x08 185b3a00663Schristos #define MODE_LIT_ECHO 0x10 186b3a00663Schristos 187b3a00663Schristos #define MODE_MASK 0x1f 188b3a00663Schristos 189b3a00663Schristos #define SLC_SYNCH 1 190b3a00663Schristos #define SLC_BRK 2 191b3a00663Schristos #define SLC_IP 3 192b3a00663Schristos #define SLC_AO 4 193b3a00663Schristos #define SLC_AYT 5 194b3a00663Schristos #define SLC_EOR 6 195b3a00663Schristos #define SLC_ABORT 7 196b3a00663Schristos #define SLC_EOF 8 197b3a00663Schristos #define SLC_SUSP 9 198b3a00663Schristos #define SLC_EC 10 199b3a00663Schristos #define SLC_EL 11 200b3a00663Schristos #define SLC_EW 12 201b3a00663Schristos #define SLC_RP 13 202b3a00663Schristos #define SLC_LNEXT 14 203b3a00663Schristos #define SLC_XON 15 204b3a00663Schristos #define SLC_XOFF 16 205b3a00663Schristos #define SLC_FORW1 17 206b3a00663Schristos #define SLC_FORW2 18 207b3a00663Schristos #define SLC_MCL 19 208b3a00663Schristos #define SLC_MCR 20 209b3a00663Schristos #define SLC_MCWL 21 210b3a00663Schristos #define SLC_MCWR 22 211b3a00663Schristos #define SLC_MCBOL 23 212b3a00663Schristos #define SLC_MCEOL 24 213b3a00663Schristos #define SLC_INSRT 25 214b3a00663Schristos #define SLC_OVER 26 215b3a00663Schristos #define SLC_ECR 27 216b3a00663Schristos #define SLC_EWR 28 217b3a00663Schristos #define SLC_EBOL 29 218b3a00663Schristos #define SLC_EEOL 30 219b3a00663Schristos 220b3a00663Schristos #define NSLC 30 221b3a00663Schristos 222b3a00663Schristos /* 223b3a00663Schristos * For backwards compatibility, we define SLC_NAMES to be the 224b3a00663Schristos * list of names if SLC_NAMES is not defined. 225b3a00663Schristos */ 226b3a00663Schristos #define SLC_NAMELIST "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \ 227b3a00663Schristos "ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \ 228b3a00663Schristos "LNEXT", "XON", "XOFF", "FORW1", "FORW2", \ 229b3a00663Schristos "MCL", "MCR", "MCWL", "MCWR", "MCBOL", \ 230b3a00663Schristos "MCEOL", "INSRT", "OVER", "ECR", "EWR", \ 231b3a00663Schristos "EBOL", "EEOL", \ 232b3a00663Schristos 0, 233b3a00663Schristos 234b3a00663Schristos #ifdef SLC_NAMES 235b3a00663Schristos const char *slc_names[] = { 236b3a00663Schristos SLC_NAMELIST 237b3a00663Schristos }; 238b3a00663Schristos #else 239b3a00663Schristos extern char *slc_names[]; 240b3a00663Schristos #define SLC_NAMES SLC_NAMELIST 241b3a00663Schristos #endif 242b3a00663Schristos 243b3a00663Schristos #define SLC_NAME_OK(x) ((unsigned int)(x) <= NSLC) 244b3a00663Schristos #define SLC_NAME(x) slc_names[x] 245b3a00663Schristos 246b3a00663Schristos #define SLC_NOSUPPORT 0 247b3a00663Schristos #define SLC_CANTCHANGE 1 248b3a00663Schristos #define SLC_VARIABLE 2 249b3a00663Schristos #define SLC_DEFAULT 3 250b3a00663Schristos #define SLC_LEVELBITS 0x03 251b3a00663Schristos 252b3a00663Schristos #define SLC_FUNC 0 253b3a00663Schristos #define SLC_FLAGS 1 254b3a00663Schristos #define SLC_VALUE 2 255b3a00663Schristos 256b3a00663Schristos #define SLC_ACK 0x80 257b3a00663Schristos #define SLC_FLUSHIN 0x40 258b3a00663Schristos #define SLC_FLUSHOUT 0x20 259b3a00663Schristos 260b3a00663Schristos #define OLD_ENV_VAR 1 261b3a00663Schristos #define OLD_ENV_VALUE 0 262b3a00663Schristos #define NEW_ENV_VAR 0 263b3a00663Schristos #define NEW_ENV_VALUE 1 264b3a00663Schristos #define ENV_ESC 2 265b3a00663Schristos #define ENV_USERVAR 3 266b3a00663Schristos 267b3a00663Schristos /* 268b3a00663Schristos * AUTHENTICATION suboptions 269b3a00663Schristos */ 270b3a00663Schristos 271b3a00663Schristos /* 272b3a00663Schristos * Who is authenticating who ... 273b3a00663Schristos */ 274b3a00663Schristos #define AUTH_WHO_CLIENT 0 /* Client authenticating server */ 275b3a00663Schristos #define AUTH_WHO_SERVER 1 /* Server authenticating client */ 276b3a00663Schristos #define AUTH_WHO_MASK 1 277b3a00663Schristos 278b3a00663Schristos #define AUTHTYPE_NULL 0 279b3a00663Schristos #define AUTHTYPE_KERBEROS_V4 1 280b3a00663Schristos #define AUTHTYPE_KERBEROS_V5 2 281b3a00663Schristos #define AUTHTYPE_SPX 3 282b3a00663Schristos #define AUTHTYPE_MINK 4 283b3a00663Schristos #define AUTHTYPE_CNT 5 284b3a00663Schristos 285b3a00663Schristos #define AUTHTYPE_TEST 99 286b3a00663Schristos 287b3a00663Schristos #ifdef AUTH_NAMES 288b3a00663Schristos const char *authtype_names[] = { 289b3a00663Schristos "NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0, 290b3a00663Schristos }; 291b3a00663Schristos #else 292b3a00663Schristos extern char *authtype_names[]; 293b3a00663Schristos #endif 294b3a00663Schristos 295b3a00663Schristos #define AUTHTYPE_NAME_OK(x) ((unsigned int)(x) < AUTHTYPE_CNT) 296b3a00663Schristos #define AUTHTYPE_NAME(x) authtype_names[x] 297b3a00663Schristos 298b3a00663Schristos /* 299b3a00663Schristos * ENCRYPTion suboptions 300b3a00663Schristos */ 301b3a00663Schristos #define ENCRYPT_IS 0 /* I pick encryption type ... */ 302b3a00663Schristos #define ENCRYPT_SUPPORT 1 /* I support encryption types ... */ 303b3a00663Schristos #define ENCRYPT_REPLY 2 /* Initial setup response */ 304b3a00663Schristos #define ENCRYPT_START 3 /* Am starting to send encrypted */ 305b3a00663Schristos #define ENCRYPT_END 4 /* Am ending encrypted */ 306b3a00663Schristos #define ENCRYPT_REQSTART 5 /* Request you start encrypting */ 307b3a00663Schristos #define ENCRYPT_REQEND 6 /* Request you send encrypting */ 308b3a00663Schristos #define ENCRYPT_ENC_KEYID 7 309b3a00663Schristos #define ENCRYPT_DEC_KEYID 8 310b3a00663Schristos #define ENCRYPT_CNT 9 311b3a00663Schristos 312b3a00663Schristos #define ENCTYPE_ANY 0 313b3a00663Schristos #define ENCTYPE_DES_CFB64 1 314b3a00663Schristos #define ENCTYPE_DES_OFB64 2 315b3a00663Schristos #define ENCTYPE_CNT 3 316b3a00663Schristos 317b3a00663Schristos #ifdef ENCRYPT_NAMES 318b3a00663Schristos const char *encrypt_names[] = { 319b3a00663Schristos "IS", "SUPPORT", "REPLY", "START", "END", 320b3a00663Schristos "REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID", 321b3a00663Schristos 0, 322b3a00663Schristos }; 323b3a00663Schristos const char *enctype_names[] = { 324b3a00663Schristos "ANY", "DES_CFB64", "DES_OFB64", 0, 325b3a00663Schristos }; 326b3a00663Schristos #else 327b3a00663Schristos extern char *encrypt_names[]; 328b3a00663Schristos extern char *enctype_names[]; 329b3a00663Schristos #endif 330b3a00663Schristos 331b3a00663Schristos #define ENCRYPT_NAME_OK(x) ((unsigned int)(x) < ENCRYPT_CNT) 332b3a00663Schristos #define ENCRYPT_NAME(x) encrypt_names[x] 333b3a00663Schristos 334b3a00663Schristos #define ENCTYPE_NAME_OK(x) ((unsigned int)(x) < ENCTYPE_CNT) 335b3a00663Schristos #define ENCTYPE_NAME(x) enctype_names[x] 3360f74e101Schristos 3370f74e101Schristos /* normal */ 3380f74e101Schristos static const char *cmds[] = { 3390f74e101Schristos "IS", "SEND", "INFO", 3400f74e101Schristos }; 3410f74e101Schristos 3420f74e101Schristos /* 37: Authentication */ 3430f74e101Schristos static const char *authcmd[] = { 3440f74e101Schristos "IS", "SEND", "REPLY", "NAME", 3450f74e101Schristos }; 3460f74e101Schristos static const char *authtype[] = { 3470f74e101Schristos "NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 3480f74e101Schristos "SRP", "RSA", "SSL", NULL, NULL, 3490f74e101Schristos "LOKI", "SSA", "KEA_SJ", "KEA_SJ_INTEG", "DSS", 3500f74e101Schristos "NTLM", 3510f74e101Schristos }; 3520f74e101Schristos 3530f74e101Schristos /* 38: Encryption */ 3540f74e101Schristos static const char *enccmd[] = { 3550f74e101Schristos "IS", "SUPPORT", "REPLY", "START", "END", 3560f74e101Schristos "REQUEST-START", "REQUEST-END", "END_KEYID", "DEC_KEYID", 3570f74e101Schristos }; 3580f74e101Schristos static const char *enctype[] = { 3590f74e101Schristos "NULL", "DES_CFB64", "DES_OFB64", "DES3_CFB64", "DES3_OFB64", 3600f74e101Schristos NULL, "CAST5_40_CFB64", "CAST5_40_OFB64", "CAST128_CFB64", "CAST128_OFB64", 3610f74e101Schristos }; 3620f74e101Schristos 3630f74e101Schristos #define STR_OR_ID(x, tab) \ 3640f74e101Schristos (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x)) 3650f74e101Schristos 3660f74e101Schristos static char * 3670f74e101Schristos numstr(int x) 3680f74e101Schristos { 3690f74e101Schristos static char buf[20]; 3700f74e101Schristos 3710f74e101Schristos snprintf(buf, sizeof(buf), "%#x", x); 3720f74e101Schristos return buf; 3730f74e101Schristos } 3740f74e101Schristos 3750f74e101Schristos /* sp points to IAC byte */ 3760f74e101Schristos static int 377b3a00663Schristos telnet_parse(netdissect_options *ndo, const u_char *sp, u_int length, int print) 3780f74e101Schristos { 3790f74e101Schristos int i, x; 3800f74e101Schristos u_int c; 3810f74e101Schristos const u_char *osp, *p; 3820f74e101Schristos #define FETCH(c, sp, length) \ 3830f74e101Schristos do { \ 3840f74e101Schristos if (length < 1) \ 3850f74e101Schristos goto pktend; \ 386c74ad251Schristos c = GET_U_1(sp); \ 387c74ad251Schristos sp++; \ 3880f74e101Schristos length--; \ 3890f74e101Schristos } while (0) 3900f74e101Schristos 3910f74e101Schristos osp = sp; 3920f74e101Schristos 3930f74e101Schristos FETCH(c, sp, length); 3940f74e101Schristos if (c != IAC) 3950f74e101Schristos goto pktend; 3960f74e101Schristos FETCH(c, sp, length); 3970f74e101Schristos if (c == IAC) { /* <IAC><IAC>! */ 3980f74e101Schristos if (print) 399c74ad251Schristos ND_PRINT("IAC IAC"); 4000f74e101Schristos goto done; 4010f74e101Schristos } 4020f74e101Schristos 4030f74e101Schristos i = c - TELCMD_FIRST; 4040f74e101Schristos if (i < 0 || i > IAC - TELCMD_FIRST) 4050f74e101Schristos goto pktend; 4060f74e101Schristos 4070f74e101Schristos switch (c) { 4080f74e101Schristos case DONT: 4090f74e101Schristos case DO: 4100f74e101Schristos case WONT: 4110f74e101Schristos case WILL: 4120f74e101Schristos case SB: 4130f74e101Schristos /* DONT/DO/WONT/WILL x */ 4140f74e101Schristos FETCH(x, sp, length); 4150f74e101Schristos if (x >= 0 && x < NTELOPTS) { 4160f74e101Schristos if (print) 417c74ad251Schristos ND_PRINT("%s %s", telcmds[i], telopts[x]); 4180f74e101Schristos } else { 4190f74e101Schristos if (print) 420c74ad251Schristos ND_PRINT("%s %#x", telcmds[i], x); 4210f74e101Schristos } 4220f74e101Schristos if (c != SB) 4230f74e101Schristos break; 4240f74e101Schristos /* IAC SB .... IAC SE */ 4250f74e101Schristos p = sp; 4260f74e101Schristos while (length > (u_int)(p + 1 - sp)) { 427c74ad251Schristos if (GET_U_1(p) == IAC && GET_U_1(p + 1) == SE) 4280f74e101Schristos break; 4290f74e101Schristos p++; 4300f74e101Schristos } 431c74ad251Schristos if (GET_U_1(p) != IAC) 4320f74e101Schristos goto pktend; 4330f74e101Schristos 4340f74e101Schristos switch (x) { 4350f74e101Schristos case TELOPT_AUTHENTICATION: 4360f74e101Schristos if (p <= sp) 4370f74e101Schristos break; 4380f74e101Schristos FETCH(c, sp, length); 4390f74e101Schristos if (print) 440c74ad251Schristos ND_PRINT(" %s", STR_OR_ID(c, authcmd)); 4410f74e101Schristos if (p <= sp) 4420f74e101Schristos break; 4430f74e101Schristos FETCH(c, sp, length); 4440f74e101Schristos if (print) 445c74ad251Schristos ND_PRINT(" %s", STR_OR_ID(c, authtype)); 4460f74e101Schristos break; 4470f74e101Schristos case TELOPT_ENCRYPT: 4480f74e101Schristos if (p <= sp) 4490f74e101Schristos break; 4500f74e101Schristos FETCH(c, sp, length); 4510f74e101Schristos if (print) 452c74ad251Schristos ND_PRINT(" %s", STR_OR_ID(c, enccmd)); 4530f74e101Schristos if (p <= sp) 4540f74e101Schristos break; 4550f74e101Schristos FETCH(c, sp, length); 4560f74e101Schristos if (print) 457c74ad251Schristos ND_PRINT(" %s", STR_OR_ID(c, enctype)); 4580f74e101Schristos break; 4590f74e101Schristos default: 4600f74e101Schristos if (p <= sp) 4610f74e101Schristos break; 4620f74e101Schristos FETCH(c, sp, length); 4630f74e101Schristos if (print) 464c74ad251Schristos ND_PRINT(" %s", STR_OR_ID(c, cmds)); 4650f74e101Schristos break; 4660f74e101Schristos } 4670f74e101Schristos while (p > sp) { 4680f74e101Schristos FETCH(x, sp, length); 4690f74e101Schristos if (print) 470c74ad251Schristos ND_PRINT(" %#x", x); 4710f74e101Schristos } 4720f74e101Schristos /* terminating IAC SE */ 4730f74e101Schristos if (print) 474c74ad251Schristos ND_PRINT(" SE"); 4750f74e101Schristos sp += 2; 4760f74e101Schristos break; 4770f74e101Schristos default: 4780f74e101Schristos if (print) 479c74ad251Schristos ND_PRINT("%s", telcmds[i]); 4800f74e101Schristos goto done; 4810f74e101Schristos } 4820f74e101Schristos 4830f74e101Schristos done: 484c74ad251Schristos return (int)(sp - osp); 4850f74e101Schristos 4860f74e101Schristos pktend: 4870f74e101Schristos return -1; 4880f74e101Schristos #undef FETCH 4890f74e101Schristos } 4900f74e101Schristos 4910f74e101Schristos void 492b3a00663Schristos telnet_print(netdissect_options *ndo, const u_char *sp, u_int length) 4930f74e101Schristos { 4940f74e101Schristos int first = 1; 4950f74e101Schristos const u_char *osp; 4960f74e101Schristos int l; 4970f74e101Schristos 498c74ad251Schristos ndo->ndo_protocol = "telnet"; 4990f74e101Schristos osp = sp; 5000f74e101Schristos 501c74ad251Schristos while (length > 0 && GET_U_1(sp) == IAC) { 502ba2ff121Schristos /* 503ba2ff121Schristos * Parse the Telnet command without printing it, 504ba2ff121Schristos * to determine its length. 505ba2ff121Schristos */ 506b3a00663Schristos l = telnet_parse(ndo, sp, length, 0); 5070f74e101Schristos if (l < 0) 5080f74e101Schristos break; 5090f74e101Schristos 5100f74e101Schristos /* 5110f74e101Schristos * now print it 5120f74e101Schristos */ 513b3a00663Schristos if (ndo->ndo_Xflag && 2 < ndo->ndo_vflag) { 5140f74e101Schristos if (first) 515c74ad251Schristos ND_PRINT("\nTelnet:"); 516c74ad251Schristos hex_print_with_offset(ndo, "\n", sp, l, (u_int)(sp - osp)); 5170f74e101Schristos if (l > 8) 518c74ad251Schristos ND_PRINT("\n\t\t\t\t"); 5190f74e101Schristos else 520c74ad251Schristos ND_PRINT("%*s\t", (8 - l) * 3, ""); 5210f74e101Schristos } else 522c74ad251Schristos ND_PRINT("%s", (first) ? " [telnet " : ", "); 5230f74e101Schristos 524b3a00663Schristos (void)telnet_parse(ndo, sp, length, 1); 5250f74e101Schristos first = 0; 5260f74e101Schristos 5270f74e101Schristos sp += l; 5280f74e101Schristos length -= l; 5290f74e101Schristos } 5300f74e101Schristos if (!first) { 531b3a00663Schristos if (ndo->ndo_Xflag && 2 < ndo->ndo_vflag) 532c74ad251Schristos ND_PRINT("\n"); 5330f74e101Schristos else 534c74ad251Schristos ND_PRINT("]"); 5350f74e101Schristos } 5360f74e101Schristos } 537