xref: /freebsd/contrib/tcpdump/print-telnet.c (revision 8bdc5a6251ddffc81a013f36b4384c8ace9c4bec)
1b0453382SBill Fenner /*	$NetBSD: print-telnet.c,v 1.2 1999/10/11 12:40:12 sjg Exp $ 	*/
2b0453382SBill Fenner 
3b0453382SBill Fenner /*-
4b0453382SBill Fenner  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5b0453382SBill Fenner  * All rights reserved.
6b0453382SBill Fenner  *
7b0453382SBill Fenner  * This code is derived from software contributed to The NetBSD Foundation
8b0453382SBill Fenner  * by Simon J. Gerraty.
9b0453382SBill Fenner  *
10b0453382SBill Fenner  * Redistribution and use in source and binary forms, with or without
11b0453382SBill Fenner  * modification, are permitted provided that the following conditions
12b0453382SBill Fenner  * are met:
13b0453382SBill Fenner  * 1. Redistributions of source code must retain the above copyright
14b0453382SBill Fenner  *    notice, this list of conditions and the following disclaimer.
15b0453382SBill Fenner  * 2. Redistributions in binary form must reproduce the above copyright
16b0453382SBill Fenner  *    notice, this list of conditions and the following disclaimer in the
17b0453382SBill Fenner  *    documentation and/or other materials provided with the distribution.
18b0453382SBill Fenner  * 3. All advertising materials mentioning features or use of this software
19b0453382SBill Fenner  *    must display the following acknowledgement:
20b0453382SBill Fenner  *        This product includes software developed by the NetBSD
21b0453382SBill Fenner  *        Foundation, Inc. and its contributors.
22b0453382SBill Fenner  * 4. Neither the name of The NetBSD Foundation nor the names of its
23b0453382SBill Fenner  *    contributors may be used to endorse or promote products derived
24b0453382SBill Fenner  *    from this software without specific prior written permission.
25b0453382SBill Fenner  *
26b0453382SBill Fenner  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27b0453382SBill Fenner  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28b0453382SBill Fenner  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29b0453382SBill Fenner  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30b0453382SBill Fenner  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31b0453382SBill Fenner  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32b0453382SBill Fenner  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33b0453382SBill Fenner  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34b0453382SBill Fenner  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35b0453382SBill Fenner  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36b0453382SBill Fenner  * POSSIBILITY OF SUCH DAMAGE.
37b0453382SBill Fenner  */
38b0453382SBill Fenner /*
39b0453382SBill Fenner  *      @(#)Copyright (c) 1994, Simon J. Gerraty.
40b0453382SBill Fenner  *
41b0453382SBill Fenner  *      This is free software.  It comes with NO WARRANTY.
42b0453382SBill Fenner  *      Permission to use, modify and distribute this source code
43b0453382SBill Fenner  *      is granted subject to the following conditions.
44b0453382SBill Fenner  *      1/ that the above copyright notice and this notice
45b0453382SBill Fenner  *      are preserved in all copies.
46b0453382SBill Fenner  */
47b0453382SBill Fenner 
483c602fabSXin LI #define NETDISSECT_REWORKED
49b0453382SBill Fenner #ifdef HAVE_CONFIG_H
50b0453382SBill Fenner #include "config.h"
51b0453382SBill Fenner #endif
52b0453382SBill Fenner 
535b0fe478SBruce M Simpson #include <tcpdump-stdinc.h>
54b0453382SBill Fenner 
55b0453382SBill Fenner #include <stdio.h>
56b0453382SBill Fenner 
57b0453382SBill Fenner #include "interface.h"
58b0453382SBill Fenner 
59a90e161bSBill Fenner #define TELCMDS
60a90e161bSBill Fenner #define TELOPTS
613c602fabSXin LI 
623c602fabSXin LI /*	NetBSD: telnet.h,v 1.9 2001/06/11 01:50:50 wiz Exp 	*/
633c602fabSXin LI 
643c602fabSXin LI /*
653c602fabSXin LI  * Definitions for the TELNET protocol.
663c602fabSXin LI  */
673c602fabSXin LI #define	IAC	255		/* interpret as command: */
683c602fabSXin LI #define	DONT	254		/* you are not to use option */
693c602fabSXin LI #define	DO	253		/* please, you use option */
703c602fabSXin LI #define	WONT	252		/* I won't use option */
713c602fabSXin LI #define	WILL	251		/* I will use option */
723c602fabSXin LI #define	SB	250		/* interpret as subnegotiation */
733c602fabSXin LI #define	GA	249		/* you may reverse the line */
743c602fabSXin LI #define	EL	248		/* erase the current line */
753c602fabSXin LI #define	EC	247		/* erase the current character */
763c602fabSXin LI #define	AYT	246		/* are you there */
773c602fabSXin LI #define	AO	245		/* abort output--but let prog finish */
783c602fabSXin LI #define	IP	244		/* interrupt process--permanently */
793c602fabSXin LI #define	BREAK	243		/* break */
803c602fabSXin LI #define	DM	242		/* data mark--for connect. cleaning */
813c602fabSXin LI #define	NOP	241		/* nop */
823c602fabSXin LI #define	SE	240		/* end sub negotiation */
833c602fabSXin LI #define EOR     239             /* end of record (transparent mode) */
843c602fabSXin LI #define	ABORT	238		/* Abort process */
853c602fabSXin LI #define	SUSP	237		/* Suspend process */
863c602fabSXin LI #define	xEOF	236		/* End of file: EOF is already used... */
873c602fabSXin LI 
883c602fabSXin LI #define SYNCH	242		/* for telfunc calls */
893c602fabSXin LI 
903c602fabSXin LI #ifdef TELCMDS
913c602fabSXin LI const char *telcmds[] = {
923c602fabSXin LI 	"EOF", "SUSP", "ABORT", "EOR",
933c602fabSXin LI 	"SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",
943c602fabSXin LI 	"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0,
953c602fabSXin LI };
963c602fabSXin LI #else
973c602fabSXin LI extern char *telcmds[];
983c602fabSXin LI #endif
993c602fabSXin LI 
1003c602fabSXin LI #define	TELCMD_FIRST	xEOF
1013c602fabSXin LI #define	TELCMD_LAST	IAC
1023c602fabSXin LI #define	TELCMD_OK(x)	((unsigned int)(x) <= TELCMD_LAST && \
1033c602fabSXin LI 			 (unsigned int)(x) >= TELCMD_FIRST)
1043c602fabSXin LI #define	TELCMD(x)	telcmds[(x)-TELCMD_FIRST]
1053c602fabSXin LI 
1063c602fabSXin LI /* telnet options */
1073c602fabSXin LI #define TELOPT_BINARY	0	/* 8-bit data path */
1083c602fabSXin LI #define TELOPT_ECHO	1	/* echo */
1093c602fabSXin LI #define	TELOPT_RCP	2	/* prepare to reconnect */
1103c602fabSXin LI #define	TELOPT_SGA	3	/* suppress go ahead */
1113c602fabSXin LI #define	TELOPT_NAMS	4	/* approximate message size */
1123c602fabSXin LI #define	TELOPT_STATUS	5	/* give status */
1133c602fabSXin LI #define	TELOPT_TM	6	/* timing mark */
1143c602fabSXin LI #define	TELOPT_RCTE	7	/* remote controlled transmission and echo */
1153c602fabSXin LI #define TELOPT_NAOL 	8	/* negotiate about output line width */
1163c602fabSXin LI #define TELOPT_NAOP 	9	/* negotiate about output page size */
1173c602fabSXin LI #define TELOPT_NAOCRD	10	/* negotiate about CR disposition */
1183c602fabSXin LI #define TELOPT_NAOHTS	11	/* negotiate about horizontal tabstops */
1193c602fabSXin LI #define TELOPT_NAOHTD	12	/* negotiate about horizontal tab disposition */
1203c602fabSXin LI #define TELOPT_NAOFFD	13	/* negotiate about formfeed disposition */
1213c602fabSXin LI #define TELOPT_NAOVTS	14	/* negotiate about vertical tab stops */
1223c602fabSXin LI #define TELOPT_NAOVTD	15	/* negotiate about vertical tab disposition */
1233c602fabSXin LI #define TELOPT_NAOLFD	16	/* negotiate about output LF disposition */
1243c602fabSXin LI #define TELOPT_XASCII	17	/* extended ascic character set */
1253c602fabSXin LI #define	TELOPT_LOGOUT	18	/* force logout */
1263c602fabSXin LI #define	TELOPT_BM	19	/* byte macro */
1273c602fabSXin LI #define	TELOPT_DET	20	/* data entry terminal */
1283c602fabSXin LI #define	TELOPT_SUPDUP	21	/* supdup protocol */
1293c602fabSXin LI #define	TELOPT_SUPDUPOUTPUT 22	/* supdup output */
1303c602fabSXin LI #define	TELOPT_SNDLOC	23	/* send location */
1313c602fabSXin LI #define	TELOPT_TTYPE	24	/* terminal type */
1323c602fabSXin LI #define	TELOPT_EOR	25	/* end or record */
1333c602fabSXin LI #define	TELOPT_TUID	26	/* TACACS user identification */
1343c602fabSXin LI #define	TELOPT_OUTMRK	27	/* output marking */
1353c602fabSXin LI #define	TELOPT_TTYLOC	28	/* terminal location number */
1363c602fabSXin LI #define	TELOPT_3270REGIME 29	/* 3270 regime */
1373c602fabSXin LI #define	TELOPT_X3PAD	30	/* X.3 PAD */
1383c602fabSXin LI #define	TELOPT_NAWS	31	/* window size */
1393c602fabSXin LI #define	TELOPT_TSPEED	32	/* terminal speed */
1403c602fabSXin LI #define	TELOPT_LFLOW	33	/* remote flow control */
1413c602fabSXin LI #define TELOPT_LINEMODE	34	/* Linemode option */
1423c602fabSXin LI #define TELOPT_XDISPLOC	35	/* X Display Location */
1433c602fabSXin LI #define TELOPT_OLD_ENVIRON 36	/* Old - Environment variables */
1443c602fabSXin LI #define	TELOPT_AUTHENTICATION 37/* Authenticate */
1453c602fabSXin LI #define	TELOPT_ENCRYPT	38	/* Encryption option */
1463c602fabSXin LI #define TELOPT_NEW_ENVIRON 39	/* New - Environment variables */
1473c602fabSXin LI #define	TELOPT_EXOPL	255	/* extended-options-list */
1483c602fabSXin LI 
1493c602fabSXin LI 
1503c602fabSXin LI #define	NTELOPTS	(1+TELOPT_NEW_ENVIRON)
1513c602fabSXin LI #ifdef TELOPTS
1523c602fabSXin LI const char *telopts[NTELOPTS+1] = {
1533c602fabSXin LI 	"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
1543c602fabSXin LI 	"STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
1553c602fabSXin LI 	"NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
1563c602fabSXin LI 	"NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
1573c602fabSXin LI 	"DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
1583c602fabSXin LI 	"SEND LOCATION", "TERMINAL TYPE", "END OF RECORD",
1593c602fabSXin LI 	"TACACS UID", "OUTPUT MARKING", "TTYLOC",
1603c602fabSXin LI 	"3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW",
1613c602fabSXin LI 	"LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
1623c602fabSXin LI 	"ENCRYPT", "NEW-ENVIRON",
1633c602fabSXin LI 	0,
1643c602fabSXin LI };
1653c602fabSXin LI #define	TELOPT_FIRST	TELOPT_BINARY
1663c602fabSXin LI #define	TELOPT_LAST	TELOPT_NEW_ENVIRON
1673c602fabSXin LI #define	TELOPT_OK(x)	((unsigned int)(x) <= TELOPT_LAST)
1683c602fabSXin LI #define	TELOPT(x)	telopts[(x)-TELOPT_FIRST]
1693c602fabSXin LI #endif
1703c602fabSXin LI 
1713c602fabSXin LI /* sub-option qualifiers */
1723c602fabSXin LI #define	TELQUAL_IS	0	/* option is... */
1733c602fabSXin LI #define	TELQUAL_SEND	1	/* send option */
1743c602fabSXin LI #define	TELQUAL_INFO	2	/* ENVIRON: informational version of IS */
1753c602fabSXin LI #define	TELQUAL_REPLY	2	/* AUTHENTICATION: client version of IS */
1763c602fabSXin LI #define	TELQUAL_NAME	3	/* AUTHENTICATION: client version of IS */
1773c602fabSXin LI 
1783c602fabSXin LI #define	LFLOW_OFF		0	/* Disable remote flow control */
1793c602fabSXin LI #define	LFLOW_ON		1	/* Enable remote flow control */
1803c602fabSXin LI #define	LFLOW_RESTART_ANY	2	/* Restart output on any char */
1813c602fabSXin LI #define	LFLOW_RESTART_XON	3	/* Restart output only on XON */
1823c602fabSXin LI 
1833c602fabSXin LI /*
1843c602fabSXin LI  * LINEMODE suboptions
1853c602fabSXin LI  */
1863c602fabSXin LI 
1873c602fabSXin LI #define	LM_MODE		1
1883c602fabSXin LI #define	LM_FORWARDMASK	2
1893c602fabSXin LI #define	LM_SLC		3
1903c602fabSXin LI 
1913c602fabSXin LI #define	MODE_EDIT	0x01
1923c602fabSXin LI #define	MODE_TRAPSIG	0x02
1933c602fabSXin LI #define	MODE_ACK	0x04
1943c602fabSXin LI #define MODE_SOFT_TAB	0x08
1953c602fabSXin LI #define MODE_LIT_ECHO	0x10
1963c602fabSXin LI 
1973c602fabSXin LI #define	MODE_MASK	0x1f
1983c602fabSXin LI 
1993c602fabSXin LI #define	SLC_SYNCH	1
2003c602fabSXin LI #define	SLC_BRK		2
2013c602fabSXin LI #define	SLC_IP		3
2023c602fabSXin LI #define	SLC_AO		4
2033c602fabSXin LI #define	SLC_AYT		5
2043c602fabSXin LI #define	SLC_EOR		6
2053c602fabSXin LI #define	SLC_ABORT	7
2063c602fabSXin LI #define	SLC_EOF		8
2073c602fabSXin LI #define	SLC_SUSP	9
2083c602fabSXin LI #define	SLC_EC		10
2093c602fabSXin LI #define	SLC_EL		11
2103c602fabSXin LI #define	SLC_EW		12
2113c602fabSXin LI #define	SLC_RP		13
2123c602fabSXin LI #define	SLC_LNEXT	14
2133c602fabSXin LI #define	SLC_XON		15
2143c602fabSXin LI #define	SLC_XOFF	16
2153c602fabSXin LI #define	SLC_FORW1	17
2163c602fabSXin LI #define	SLC_FORW2	18
2173c602fabSXin LI #define	SLC_MCL         19
2183c602fabSXin LI #define	SLC_MCR         20
2193c602fabSXin LI #define	SLC_MCWL        21
2203c602fabSXin LI #define	SLC_MCWR        22
2213c602fabSXin LI #define	SLC_MCBOL       23
2223c602fabSXin LI #define	SLC_MCEOL       24
2233c602fabSXin LI #define	SLC_INSRT       25
2243c602fabSXin LI #define	SLC_OVER        26
2253c602fabSXin LI #define	SLC_ECR         27
2263c602fabSXin LI #define	SLC_EWR         28
2273c602fabSXin LI #define	SLC_EBOL        29
2283c602fabSXin LI #define	SLC_EEOL        30
2293c602fabSXin LI 
2303c602fabSXin LI #define	NSLC		30
2313c602fabSXin LI 
2323c602fabSXin LI /*
2333c602fabSXin LI  * For backwards compatibility, we define SLC_NAMES to be the
2343c602fabSXin LI  * list of names if SLC_NAMES is not defined.
2353c602fabSXin LI  */
2363c602fabSXin LI #define	SLC_NAMELIST	"0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR",	\
2373c602fabSXin LI 			"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP",	\
2383c602fabSXin LI 			"LNEXT", "XON", "XOFF", "FORW1", "FORW2",	\
2393c602fabSXin LI 			"MCL", "MCR", "MCWL", "MCWR", "MCBOL",		\
2403c602fabSXin LI 			"MCEOL", "INSRT", "OVER", "ECR", "EWR",		\
2413c602fabSXin LI 			"EBOL", "EEOL",					\
2423c602fabSXin LI 			0,
2433c602fabSXin LI 
2443c602fabSXin LI #ifdef	SLC_NAMES
2453c602fabSXin LI const char *slc_names[] = {
2463c602fabSXin LI 	SLC_NAMELIST
2473c602fabSXin LI };
2483c602fabSXin LI #else
2493c602fabSXin LI extern char *slc_names[];
2503c602fabSXin LI #define	SLC_NAMES SLC_NAMELIST
2513c602fabSXin LI #endif
2523c602fabSXin LI 
2533c602fabSXin LI #define	SLC_NAME_OK(x)	((unsigned int)(x) <= NSLC)
2543c602fabSXin LI #define SLC_NAME(x)	slc_names[x]
2553c602fabSXin LI 
2563c602fabSXin LI #define	SLC_NOSUPPORT	0
2573c602fabSXin LI #define	SLC_CANTCHANGE	1
2583c602fabSXin LI #define	SLC_VARIABLE	2
2593c602fabSXin LI #define	SLC_DEFAULT	3
2603c602fabSXin LI #define	SLC_LEVELBITS	0x03
2613c602fabSXin LI 
2623c602fabSXin LI #define	SLC_FUNC	0
2633c602fabSXin LI #define	SLC_FLAGS	1
2643c602fabSXin LI #define	SLC_VALUE	2
2653c602fabSXin LI 
2663c602fabSXin LI #define	SLC_ACK		0x80
2673c602fabSXin LI #define	SLC_FLUSHIN	0x40
2683c602fabSXin LI #define	SLC_FLUSHOUT	0x20
2693c602fabSXin LI 
2703c602fabSXin LI #define	OLD_ENV_VAR	1
2713c602fabSXin LI #define	OLD_ENV_VALUE	0
2723c602fabSXin LI #define	NEW_ENV_VAR	0
2733c602fabSXin LI #define	NEW_ENV_VALUE	1
2743c602fabSXin LI #define	ENV_ESC		2
2753c602fabSXin LI #define ENV_USERVAR	3
2763c602fabSXin LI 
2773c602fabSXin LI /*
2783c602fabSXin LI  * AUTHENTICATION suboptions
2793c602fabSXin LI  */
2803c602fabSXin LI 
2813c602fabSXin LI /*
2823c602fabSXin LI  * Who is authenticating who ...
2833c602fabSXin LI  */
2843c602fabSXin LI #define	AUTH_WHO_CLIENT		0	/* Client authenticating server */
2853c602fabSXin LI #define	AUTH_WHO_SERVER		1	/* Server authenticating client */
2863c602fabSXin LI #define	AUTH_WHO_MASK		1
2873c602fabSXin LI 
2883c602fabSXin LI #define	AUTHTYPE_NULL		0
2893c602fabSXin LI #define	AUTHTYPE_KERBEROS_V4	1
2903c602fabSXin LI #define	AUTHTYPE_KERBEROS_V5	2
2913c602fabSXin LI #define	AUTHTYPE_SPX		3
2923c602fabSXin LI #define	AUTHTYPE_MINK		4
2933c602fabSXin LI #define	AUTHTYPE_CNT		5
2943c602fabSXin LI 
2953c602fabSXin LI #define	AUTHTYPE_TEST		99
2963c602fabSXin LI 
2973c602fabSXin LI #ifdef	AUTH_NAMES
2983c602fabSXin LI const char *authtype_names[] = {
2993c602fabSXin LI 	"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0,
3003c602fabSXin LI };
3013c602fabSXin LI #else
3023c602fabSXin LI extern char *authtype_names[];
3033c602fabSXin LI #endif
3043c602fabSXin LI 
3053c602fabSXin LI #define	AUTHTYPE_NAME_OK(x)	((unsigned int)(x) < AUTHTYPE_CNT)
3063c602fabSXin LI #define	AUTHTYPE_NAME(x)	authtype_names[x]
3073c602fabSXin LI 
3083c602fabSXin LI /*
3093c602fabSXin LI  * ENCRYPTion suboptions
3103c602fabSXin LI  */
3113c602fabSXin LI #define	ENCRYPT_IS		0	/* I pick encryption type ... */
3123c602fabSXin LI #define	ENCRYPT_SUPPORT		1	/* I support encryption types ... */
3133c602fabSXin LI #define	ENCRYPT_REPLY		2	/* Initial setup response */
3143c602fabSXin LI #define	ENCRYPT_START		3	/* Am starting to send encrypted */
3153c602fabSXin LI #define	ENCRYPT_END		4	/* Am ending encrypted */
3163c602fabSXin LI #define	ENCRYPT_REQSTART	5	/* Request you start encrypting */
3173c602fabSXin LI #define	ENCRYPT_REQEND		6	/* Request you send encrypting */
3183c602fabSXin LI #define	ENCRYPT_ENC_KEYID	7
3193c602fabSXin LI #define	ENCRYPT_DEC_KEYID	8
3203c602fabSXin LI #define	ENCRYPT_CNT		9
3213c602fabSXin LI 
3223c602fabSXin LI #define	ENCTYPE_ANY		0
3233c602fabSXin LI #define	ENCTYPE_DES_CFB64	1
3243c602fabSXin LI #define	ENCTYPE_DES_OFB64	2
3253c602fabSXin LI #define	ENCTYPE_CNT		3
3263c602fabSXin LI 
3273c602fabSXin LI #ifdef	ENCRYPT_NAMES
3283c602fabSXin LI const char *encrypt_names[] = {
3293c602fabSXin LI 	"IS", "SUPPORT", "REPLY", "START", "END",
3303c602fabSXin LI 	"REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID",
3313c602fabSXin LI 	0,
3323c602fabSXin LI };
3333c602fabSXin LI const char *enctype_names[] = {
3343c602fabSXin LI 	"ANY", "DES_CFB64",  "DES_OFB64",  0,
3353c602fabSXin LI };
3363c602fabSXin LI #else
3373c602fabSXin LI extern char *encrypt_names[];
3383c602fabSXin LI extern char *enctype_names[];
3393c602fabSXin LI #endif
3403c602fabSXin LI 
3413c602fabSXin LI #define	ENCRYPT_NAME_OK(x)	((unsigned int)(x) < ENCRYPT_CNT)
3423c602fabSXin LI #define	ENCRYPT_NAME(x)		encrypt_names[x]
3433c602fabSXin LI 
3443c602fabSXin LI #define	ENCTYPE_NAME_OK(x)	((unsigned int)(x) < ENCTYPE_CNT)
3453c602fabSXin LI #define	ENCTYPE_NAME(x)		enctype_names[x]
346b0453382SBill Fenner 
347a90e161bSBill Fenner /* normal */
348a90e161bSBill Fenner static const char *cmds[] = {
349a90e161bSBill Fenner 	"IS", "SEND", "INFO",
350a90e161bSBill Fenner };
351a90e161bSBill Fenner 
352a90e161bSBill Fenner /* 37: Authentication */
353a90e161bSBill Fenner static const char *authcmd[] = {
354a90e161bSBill Fenner 	"IS", "SEND", "REPLY", "NAME",
355a90e161bSBill Fenner };
356a90e161bSBill Fenner static const char *authtype[] = {
357a90e161bSBill Fenner 	"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK",
358a90e161bSBill Fenner 	"SRP", "RSA", "SSL", NULL, NULL,
359a90e161bSBill Fenner 	"LOKI", "SSA", "KEA_SJ", "KEA_SJ_INTEG", "DSS",
360a90e161bSBill Fenner 	"NTLM",
361a90e161bSBill Fenner };
362a90e161bSBill Fenner 
363a90e161bSBill Fenner /* 38: Encryption */
364a90e161bSBill Fenner static const char *enccmd[] = {
365a90e161bSBill Fenner 	"IS", "SUPPORT", "REPLY", "START", "END",
366a90e161bSBill Fenner 	"REQUEST-START", "REQUEST-END", "END_KEYID", "DEC_KEYID",
367a90e161bSBill Fenner };
368a90e161bSBill Fenner static const char *enctype[] = {
369a90e161bSBill Fenner 	"NULL", "DES_CFB64", "DES_OFB64", "DES3_CFB64", "DES3_OFB64",
370a90e161bSBill Fenner 	NULL, "CAST5_40_CFB64", "CAST5_40_OFB64", "CAST128_CFB64", "CAST128_OFB64",
371a90e161bSBill Fenner };
372a90e161bSBill Fenner 
373a90e161bSBill Fenner #define STR_OR_ID(x, tab) \
374a90e161bSBill Fenner 	(((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
375a90e161bSBill Fenner 
376a90e161bSBill Fenner static char *
377a90e161bSBill Fenner numstr(int x)
378b0453382SBill Fenner {
379a90e161bSBill Fenner 	static char buf[20];
380b0453382SBill Fenner 
381a90e161bSBill Fenner 	snprintf(buf, sizeof(buf), "%#x", x);
382a90e161bSBill Fenner 	return buf;
383b0453382SBill Fenner }
384a90e161bSBill Fenner 
385a90e161bSBill Fenner /* sp points to IAC byte */
386a90e161bSBill Fenner static int
3873c602fabSXin LI telnet_parse(netdissect_options *ndo, const u_char *sp, u_int length, int print)
388a90e161bSBill Fenner {
3895b0fe478SBruce M Simpson 	int i, x;
3905b0fe478SBruce M Simpson 	u_int c;
391a90e161bSBill Fenner 	const u_char *osp, *p;
392a90e161bSBill Fenner #define FETCH(c, sp, length) \
393a90e161bSBill Fenner 	do { \
394a90e161bSBill Fenner 		if (length < 1) \
395a90e161bSBill Fenner 			goto pktend; \
3963c602fabSXin LI 		ND_TCHECK(*sp); \
397a90e161bSBill Fenner 		c = *sp++; \
398a90e161bSBill Fenner 		length--; \
399a90e161bSBill Fenner 	} while (0)
400a90e161bSBill Fenner 
401a90e161bSBill Fenner 	osp = sp;
402a90e161bSBill Fenner 
403a90e161bSBill Fenner 	FETCH(c, sp, length);
404a90e161bSBill Fenner 	if (c != IAC)
405a90e161bSBill Fenner 		goto pktend;
406a90e161bSBill Fenner 	FETCH(c, sp, length);
407a90e161bSBill Fenner 	if (c == IAC) {		/* <IAC><IAC>! */
408a90e161bSBill Fenner 		if (print)
4093c602fabSXin LI 			ND_PRINT((ndo, "IAC IAC"));
410a90e161bSBill Fenner 		goto done;
411b0453382SBill Fenner 	}
412a90e161bSBill Fenner 
413a90e161bSBill Fenner 	i = c - TELCMD_FIRST;
414a90e161bSBill Fenner 	if (i < 0 || i > IAC - TELCMD_FIRST)
415a90e161bSBill Fenner 		goto pktend;
416a90e161bSBill Fenner 
417b0453382SBill Fenner 	switch (c) {
418b0453382SBill Fenner 	case DONT:
419b0453382SBill Fenner 	case DO:
420b0453382SBill Fenner 	case WONT:
421b0453382SBill Fenner 	case WILL:
422b0453382SBill Fenner 	case SB:
423a90e161bSBill Fenner 		/* DONT/DO/WONT/WILL x */
424a90e161bSBill Fenner 		FETCH(x, sp, length);
425b0453382SBill Fenner 		if (x >= 0 && x < NTELOPTS) {
426a90e161bSBill Fenner 			if (print)
4273c602fabSXin LI 				ND_PRINT((ndo, "%s %s", telcmds[i], telopts[x]));
428b0453382SBill Fenner 		} else {
429a90e161bSBill Fenner 			if (print)
4303c602fabSXin LI 				ND_PRINT((ndo, "%s %#x", telcmds[i], x));
431b0453382SBill Fenner 		}
432a90e161bSBill Fenner 		if (c != SB)
433a90e161bSBill Fenner 			break;
434a90e161bSBill Fenner 		/* IAC SB .... IAC SE */
435a90e161bSBill Fenner 		p = sp;
4365b0fe478SBruce M Simpson 		while (length > (u_int)(p + 1 - sp)) {
437a90e161bSBill Fenner 			if (p[0] == IAC && p[1] == SE)
438a90e161bSBill Fenner 				break;
439a90e161bSBill Fenner 			p++;
440a90e161bSBill Fenner 		}
441a90e161bSBill Fenner 		if (*p != IAC)
442a90e161bSBill Fenner 			goto pktend;
443a90e161bSBill Fenner 
444a90e161bSBill Fenner 		switch (x) {
445a90e161bSBill Fenner 		case TELOPT_AUTHENTICATION:
446a90e161bSBill Fenner 			if (p <= sp)
447a90e161bSBill Fenner 				break;
448a90e161bSBill Fenner 			FETCH(c, sp, length);
449a90e161bSBill Fenner 			if (print)
4503c602fabSXin LI 				ND_PRINT((ndo, " %s", STR_OR_ID(c, authcmd)));
451a90e161bSBill Fenner 			if (p <= sp)
452a90e161bSBill Fenner 				break;
453a90e161bSBill Fenner 			FETCH(c, sp, length);
454a90e161bSBill Fenner 			if (print)
4553c602fabSXin LI 				ND_PRINT((ndo, " %s", STR_OR_ID(c, authtype)));
456a90e161bSBill Fenner 			break;
457a90e161bSBill Fenner 		case TELOPT_ENCRYPT:
458a90e161bSBill Fenner 			if (p <= sp)
459a90e161bSBill Fenner 				break;
460a90e161bSBill Fenner 			FETCH(c, sp, length);
461a90e161bSBill Fenner 			if (print)
4623c602fabSXin LI 				ND_PRINT((ndo, " %s", STR_OR_ID(c, enccmd)));
463a90e161bSBill Fenner 			if (p <= sp)
464a90e161bSBill Fenner 				break;
465a90e161bSBill Fenner 			FETCH(c, sp, length);
466a90e161bSBill Fenner 			if (print)
4673c602fabSXin LI 				ND_PRINT((ndo, " %s", STR_OR_ID(c, enctype)));
468b0453382SBill Fenner 			break;
469b0453382SBill Fenner 		default:
470a90e161bSBill Fenner 			if (p <= sp)
471a90e161bSBill Fenner 				break;
472a90e161bSBill Fenner 			FETCH(c, sp, length);
473a90e161bSBill Fenner 			if (print)
4743c602fabSXin LI 				ND_PRINT((ndo, " %s", STR_OR_ID(c, cmds)));
475b0453382SBill Fenner 			break;
476b0453382SBill Fenner 		}
477a90e161bSBill Fenner 		while (p > sp) {
478a90e161bSBill Fenner 			FETCH(x, sp, length);
479a90e161bSBill Fenner 			if (print)
4803c602fabSXin LI 				ND_PRINT((ndo, " %#x", x));
481a90e161bSBill Fenner 		}
482a90e161bSBill Fenner 		/* terminating IAC SE */
483a90e161bSBill Fenner 		if (print)
4843c602fabSXin LI 			ND_PRINT((ndo, " SE"));
485a90e161bSBill Fenner 		sp += 2;
486a90e161bSBill Fenner 		break;
487a90e161bSBill Fenner 	default:
488a90e161bSBill Fenner 		if (print)
4893c602fabSXin LI 			ND_PRINT((ndo, "%s", telcmds[i]));
490a90e161bSBill Fenner 		goto done;
491a90e161bSBill Fenner 	}
492a90e161bSBill Fenner 
493a90e161bSBill Fenner done:
494a90e161bSBill Fenner 	return sp - osp;
495a90e161bSBill Fenner 
496a90e161bSBill Fenner trunc:
4973c602fabSXin LI 	ND_PRINT((ndo, "[|telnet]"));
498a90e161bSBill Fenner pktend:
499a90e161bSBill Fenner 	return -1;
500a90e161bSBill Fenner #undef FETCH
501a90e161bSBill Fenner }
502a90e161bSBill Fenner 
503a90e161bSBill Fenner void
5043c602fabSXin LI telnet_print(netdissect_options *ndo, const u_char *sp, u_int length)
505a90e161bSBill Fenner {
506a90e161bSBill Fenner 	int first = 1;
507a90e161bSBill Fenner 	const u_char *osp;
508a90e161bSBill Fenner 	int l;
509a90e161bSBill Fenner 
510a90e161bSBill Fenner 	osp = sp;
511a90e161bSBill Fenner 
512a90e161bSBill Fenner 	while (length > 0 && *sp == IAC) {
513*8bdc5a62SPatrick Kelsey 		/*
514*8bdc5a62SPatrick Kelsey 		 * Parse the Telnet command without printing it,
515*8bdc5a62SPatrick Kelsey 		 * to determine its length.
516*8bdc5a62SPatrick Kelsey 		 */
5173c602fabSXin LI 		l = telnet_parse(ndo, sp, length, 0);
518a90e161bSBill Fenner 		if (l < 0)
519a90e161bSBill Fenner 			break;
520a90e161bSBill Fenner 
521b0453382SBill Fenner 		/*
522b0453382SBill Fenner 		 * now print it
523b0453382SBill Fenner 		 */
5243c602fabSXin LI 		if (ndo->ndo_Xflag && 2 < ndo->ndo_vflag) {
525b0453382SBill Fenner 			if (first)
5263c602fabSXin LI 				ND_PRINT((ndo, "\nTelnet:"));
5273c602fabSXin LI 			hex_print_with_offset(ndo, "\n", sp, l, sp - osp);
528a90e161bSBill Fenner 			if (l > 8)
5293c602fabSXin LI 				ND_PRINT((ndo, "\n\t\t\t\t"));
530b0453382SBill Fenner 			else
5313c602fabSXin LI 				ND_PRINT((ndo, "%*s\t", (8 - l) * 3, ""));
532a90e161bSBill Fenner 		} else
5333c602fabSXin LI 			ND_PRINT((ndo, "%s", (first) ? " [telnet " : ", "));
534a90e161bSBill Fenner 
5353c602fabSXin LI 		(void)telnet_parse(ndo, sp, length, 1);
536b0453382SBill Fenner 		first = 0;
537a90e161bSBill Fenner 
538a90e161bSBill Fenner 		sp += l;
539a90e161bSBill Fenner 		length -= l;
540b0453382SBill Fenner 	}
541b0453382SBill Fenner 	if (!first) {
5423c602fabSXin LI 		if (ndo->ndo_Xflag && 2 < ndo->ndo_vflag)
5433c602fabSXin LI 			ND_PRINT((ndo, "\n"));
544b0453382SBill Fenner 		else
5453c602fabSXin LI 			ND_PRINT((ndo, "]"));
546b0453382SBill Fenner 	}
547b0453382SBill Fenner }
548