xref: /freebsd/contrib/tcpdump/print-telnet.c (revision ee67461e)
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 
483340d773SGleb Smirnoff /* \summary: Telnet option printer */
493340d773SGleb Smirnoff 
50b0453382SBill Fenner #ifdef HAVE_CONFIG_H
51ee67461eSJoseph Mingrone #include <config.h>
52b0453382SBill Fenner #endif
53b0453382SBill Fenner 
54ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
55b0453382SBill Fenner 
56b0453382SBill Fenner #include <stdio.h>
57b0453382SBill Fenner 
583340d773SGleb Smirnoff #include "netdissect.h"
59ee67461eSJoseph Mingrone #include "extract.h"
603340d773SGleb Smirnoff 
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 
903340d773SGleb Smirnoff static const char *telcmds[] = {
913c602fabSXin LI 	"EOF", "SUSP", "ABORT", "EOR",
923c602fabSXin LI 	"SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",
933c602fabSXin LI 	"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0,
943c602fabSXin LI };
953c602fabSXin LI 
963c602fabSXin LI #define	TELCMD_FIRST	xEOF
973c602fabSXin LI #define	TELCMD_LAST	IAC
983c602fabSXin LI #define	TELCMD_OK(x)	((unsigned int)(x) <= TELCMD_LAST && \
993c602fabSXin LI 			 (unsigned int)(x) >= TELCMD_FIRST)
1003c602fabSXin LI #define	TELCMD(x)	telcmds[(x)-TELCMD_FIRST]
1013c602fabSXin LI 
1023c602fabSXin LI /* telnet options */
1033c602fabSXin LI #define TELOPT_BINARY	0	/* 8-bit data path */
1043c602fabSXin LI #define TELOPT_ECHO	1	/* echo */
1053c602fabSXin LI #define	TELOPT_RCP	2	/* prepare to reconnect */
1063c602fabSXin LI #define	TELOPT_SGA	3	/* suppress go ahead */
1073c602fabSXin LI #define	TELOPT_NAMS	4	/* approximate message size */
1083c602fabSXin LI #define	TELOPT_STATUS	5	/* give status */
1093c602fabSXin LI #define	TELOPT_TM	6	/* timing mark */
1103c602fabSXin LI #define	TELOPT_RCTE	7	/* remote controlled transmission and echo */
1113c602fabSXin LI #define TELOPT_NAOL	8	/* negotiate about output line width */
1123c602fabSXin LI #define TELOPT_NAOP	9	/* negotiate about output page size */
1133c602fabSXin LI #define TELOPT_NAOCRD	10	/* negotiate about CR disposition */
1143c602fabSXin LI #define TELOPT_NAOHTS	11	/* negotiate about horizontal tabstops */
1153c602fabSXin LI #define TELOPT_NAOHTD	12	/* negotiate about horizontal tab disposition */
1163c602fabSXin LI #define TELOPT_NAOFFD	13	/* negotiate about formfeed disposition */
1173c602fabSXin LI #define TELOPT_NAOVTS	14	/* negotiate about vertical tab stops */
1183c602fabSXin LI #define TELOPT_NAOVTD	15	/* negotiate about vertical tab disposition */
1193c602fabSXin LI #define TELOPT_NAOLFD	16	/* negotiate about output LF disposition */
1203c602fabSXin LI #define TELOPT_XASCII	17	/* extended ascic character set */
1213c602fabSXin LI #define	TELOPT_LOGOUT	18	/* force logout */
1223c602fabSXin LI #define	TELOPT_BM	19	/* byte macro */
1233c602fabSXin LI #define	TELOPT_DET	20	/* data entry terminal */
1243c602fabSXin LI #define	TELOPT_SUPDUP	21	/* supdup protocol */
1253c602fabSXin LI #define	TELOPT_SUPDUPOUTPUT 22	/* supdup output */
1263c602fabSXin LI #define	TELOPT_SNDLOC	23	/* send location */
1273c602fabSXin LI #define	TELOPT_TTYPE	24	/* terminal type */
1283c602fabSXin LI #define	TELOPT_EOR	25	/* end or record */
1293c602fabSXin LI #define	TELOPT_TUID	26	/* TACACS user identification */
1303c602fabSXin LI #define	TELOPT_OUTMRK	27	/* output marking */
1313c602fabSXin LI #define	TELOPT_TTYLOC	28	/* terminal location number */
1323c602fabSXin LI #define	TELOPT_3270REGIME 29	/* 3270 regime */
1333c602fabSXin LI #define	TELOPT_X3PAD	30	/* X.3 PAD */
1343c602fabSXin LI #define	TELOPT_NAWS	31	/* window size */
1353c602fabSXin LI #define	TELOPT_TSPEED	32	/* terminal speed */
1363c602fabSXin LI #define	TELOPT_LFLOW	33	/* remote flow control */
1373c602fabSXin LI #define TELOPT_LINEMODE	34	/* Linemode option */
1383c602fabSXin LI #define TELOPT_XDISPLOC	35	/* X Display Location */
1393c602fabSXin LI #define TELOPT_OLD_ENVIRON 36	/* Old - Environment variables */
1403c602fabSXin LI #define	TELOPT_AUTHENTICATION 37/* Authenticate */
1413c602fabSXin LI #define	TELOPT_ENCRYPT	38	/* Encryption option */
1423c602fabSXin LI #define TELOPT_NEW_ENVIRON 39	/* New - Environment variables */
1433c602fabSXin LI #define	TELOPT_EXOPL	255	/* extended-options-list */
1443c602fabSXin LI 
1453c602fabSXin LI 
1463c602fabSXin LI #define	NTELOPTS	(1+TELOPT_NEW_ENVIRON)
1473340d773SGleb Smirnoff static const char *telopts[NTELOPTS+1] = {
1483c602fabSXin LI 	"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
1493c602fabSXin LI 	"STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
1503c602fabSXin LI 	"NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
1513c602fabSXin LI 	"NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
1523c602fabSXin LI 	"DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
1533c602fabSXin LI 	"SEND LOCATION", "TERMINAL TYPE", "END OF RECORD",
1543c602fabSXin LI 	"TACACS UID", "OUTPUT MARKING", "TTYLOC",
1553c602fabSXin LI 	"3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW",
1563c602fabSXin LI 	"LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
1573c602fabSXin LI 	"ENCRYPT", "NEW-ENVIRON",
1583c602fabSXin LI 	0,
1593c602fabSXin LI };
1603c602fabSXin LI #define	TELOPT_FIRST	TELOPT_BINARY
1613c602fabSXin LI #define	TELOPT_LAST	TELOPT_NEW_ENVIRON
1623c602fabSXin LI #define	TELOPT_OK(x)	((unsigned int)(x) <= TELOPT_LAST)
1633c602fabSXin LI #define	TELOPT(x)	telopts[(x)-TELOPT_FIRST]
1643c602fabSXin LI 
1653c602fabSXin LI /* sub-option qualifiers */
1663c602fabSXin LI #define	TELQUAL_IS	0	/* option is... */
1673c602fabSXin LI #define	TELQUAL_SEND	1	/* send option */
1683c602fabSXin LI #define	TELQUAL_INFO	2	/* ENVIRON: informational version of IS */
1693c602fabSXin LI #define	TELQUAL_REPLY	2	/* AUTHENTICATION: client version of IS */
1703c602fabSXin LI #define	TELQUAL_NAME	3	/* AUTHENTICATION: client version of IS */
1713c602fabSXin LI 
1723c602fabSXin LI #define	LFLOW_OFF		0	/* Disable remote flow control */
1733c602fabSXin LI #define	LFLOW_ON		1	/* Enable remote flow control */
1743c602fabSXin LI #define	LFLOW_RESTART_ANY	2	/* Restart output on any char */
1753c602fabSXin LI #define	LFLOW_RESTART_XON	3	/* Restart output only on XON */
1763c602fabSXin LI 
1773c602fabSXin LI /*
1783c602fabSXin LI  * LINEMODE suboptions
1793c602fabSXin LI  */
1803c602fabSXin LI 
1813c602fabSXin LI #define	LM_MODE		1
1823c602fabSXin LI #define	LM_FORWARDMASK	2
1833c602fabSXin LI #define	LM_SLC		3
1843c602fabSXin LI 
1853c602fabSXin LI #define	MODE_EDIT	0x01
1863c602fabSXin LI #define	MODE_TRAPSIG	0x02
1873c602fabSXin LI #define	MODE_ACK	0x04
1883c602fabSXin LI #define MODE_SOFT_TAB	0x08
1893c602fabSXin LI #define MODE_LIT_ECHO	0x10
1903c602fabSXin LI 
1913c602fabSXin LI #define	MODE_MASK	0x1f
1923c602fabSXin LI 
1933c602fabSXin LI #define	SLC_SYNCH	1
1943c602fabSXin LI #define	SLC_BRK		2
1953c602fabSXin LI #define	SLC_IP		3
1963c602fabSXin LI #define	SLC_AO		4
1973c602fabSXin LI #define	SLC_AYT		5
1983c602fabSXin LI #define	SLC_EOR		6
1993c602fabSXin LI #define	SLC_ABORT	7
2003c602fabSXin LI #define	SLC_EOF		8
2013c602fabSXin LI #define	SLC_SUSP	9
2023c602fabSXin LI #define	SLC_EC		10
2033c602fabSXin LI #define	SLC_EL		11
2043c602fabSXin LI #define	SLC_EW		12
2053c602fabSXin LI #define	SLC_RP		13
2063c602fabSXin LI #define	SLC_LNEXT	14
2073c602fabSXin LI #define	SLC_XON		15
2083c602fabSXin LI #define	SLC_XOFF	16
2093c602fabSXin LI #define	SLC_FORW1	17
2103c602fabSXin LI #define	SLC_FORW2	18
2113c602fabSXin LI #define	SLC_MCL         19
2123c602fabSXin LI #define	SLC_MCR         20
2133c602fabSXin LI #define	SLC_MCWL        21
2143c602fabSXin LI #define	SLC_MCWR        22
2153c602fabSXin LI #define	SLC_MCBOL       23
2163c602fabSXin LI #define	SLC_MCEOL       24
2173c602fabSXin LI #define	SLC_INSRT       25
2183c602fabSXin LI #define	SLC_OVER        26
2193c602fabSXin LI #define	SLC_ECR         27
2203c602fabSXin LI #define	SLC_EWR         28
2213c602fabSXin LI #define	SLC_EBOL        29
2223c602fabSXin LI #define	SLC_EEOL        30
2233c602fabSXin LI 
2243c602fabSXin LI #define	NSLC		30
2253c602fabSXin LI 
2263c602fabSXin LI /*
2273c602fabSXin LI  * For backwards compatibility, we define SLC_NAMES to be the
2283c602fabSXin LI  * list of names if SLC_NAMES is not defined.
2293c602fabSXin LI  */
2303c602fabSXin LI #define	SLC_NAMELIST	"0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR",	\
2313c602fabSXin LI 			"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP",	\
2323c602fabSXin LI 			"LNEXT", "XON", "XOFF", "FORW1", "FORW2",	\
2333c602fabSXin LI 			"MCL", "MCR", "MCWL", "MCWR", "MCBOL",		\
2343c602fabSXin LI 			"MCEOL", "INSRT", "OVER", "ECR", "EWR",		\
2353c602fabSXin LI 			"EBOL", "EEOL",					\
2363c602fabSXin LI 			0,
2373c602fabSXin LI 
2383c602fabSXin LI #ifdef	SLC_NAMES
2393c602fabSXin LI const char *slc_names[] = {
2403c602fabSXin LI 	SLC_NAMELIST
2413c602fabSXin LI };
2423c602fabSXin LI #else
2433c602fabSXin LI extern char *slc_names[];
2443c602fabSXin LI #define	SLC_NAMES SLC_NAMELIST
2453c602fabSXin LI #endif
2463c602fabSXin LI 
2473c602fabSXin LI #define	SLC_NAME_OK(x)	((unsigned int)(x) <= NSLC)
2483c602fabSXin LI #define SLC_NAME(x)	slc_names[x]
2493c602fabSXin LI 
2503c602fabSXin LI #define	SLC_NOSUPPORT	0
2513c602fabSXin LI #define	SLC_CANTCHANGE	1
2523c602fabSXin LI #define	SLC_VARIABLE	2
2533c602fabSXin LI #define	SLC_DEFAULT	3
2543c602fabSXin LI #define	SLC_LEVELBITS	0x03
2553c602fabSXin LI 
2563c602fabSXin LI #define	SLC_FUNC	0
2573c602fabSXin LI #define	SLC_FLAGS	1
2583c602fabSXin LI #define	SLC_VALUE	2
2593c602fabSXin LI 
2603c602fabSXin LI #define	SLC_ACK		0x80
2613c602fabSXin LI #define	SLC_FLUSHIN	0x40
2623c602fabSXin LI #define	SLC_FLUSHOUT	0x20
2633c602fabSXin LI 
2643c602fabSXin LI #define	OLD_ENV_VAR	1
2653c602fabSXin LI #define	OLD_ENV_VALUE	0
2663c602fabSXin LI #define	NEW_ENV_VAR	0
2673c602fabSXin LI #define	NEW_ENV_VALUE	1
2683c602fabSXin LI #define	ENV_ESC		2
2693c602fabSXin LI #define ENV_USERVAR	3
2703c602fabSXin LI 
2713c602fabSXin LI /*
2723c602fabSXin LI  * AUTHENTICATION suboptions
2733c602fabSXin LI  */
2743c602fabSXin LI 
2753c602fabSXin LI /*
2763c602fabSXin LI  * Who is authenticating who ...
2773c602fabSXin LI  */
2783c602fabSXin LI #define	AUTH_WHO_CLIENT		0	/* Client authenticating server */
2793c602fabSXin LI #define	AUTH_WHO_SERVER		1	/* Server authenticating client */
2803c602fabSXin LI #define	AUTH_WHO_MASK		1
2813c602fabSXin LI 
2823c602fabSXin LI #define	AUTHTYPE_NULL		0
2833c602fabSXin LI #define	AUTHTYPE_KERBEROS_V4	1
2843c602fabSXin LI #define	AUTHTYPE_KERBEROS_V5	2
2853c602fabSXin LI #define	AUTHTYPE_SPX		3
2863c602fabSXin LI #define	AUTHTYPE_MINK		4
2873c602fabSXin LI #define	AUTHTYPE_CNT		5
2883c602fabSXin LI 
2893c602fabSXin LI #define	AUTHTYPE_TEST		99
2903c602fabSXin LI 
2913c602fabSXin LI #ifdef	AUTH_NAMES
2923c602fabSXin LI const char *authtype_names[] = {
2933c602fabSXin LI 	"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0,
2943c602fabSXin LI };
2953c602fabSXin LI #else
2963c602fabSXin LI extern char *authtype_names[];
2973c602fabSXin LI #endif
2983c602fabSXin LI 
2993c602fabSXin LI #define	AUTHTYPE_NAME_OK(x)	((unsigned int)(x) < AUTHTYPE_CNT)
3003c602fabSXin LI #define	AUTHTYPE_NAME(x)	authtype_names[x]
3013c602fabSXin LI 
3023c602fabSXin LI /*
3033c602fabSXin LI  * ENCRYPTion suboptions
3043c602fabSXin LI  */
3053c602fabSXin LI #define	ENCRYPT_IS		0	/* I pick encryption type ... */
3063c602fabSXin LI #define	ENCRYPT_SUPPORT		1	/* I support encryption types ... */
3073c602fabSXin LI #define	ENCRYPT_REPLY		2	/* Initial setup response */
3083c602fabSXin LI #define	ENCRYPT_START		3	/* Am starting to send encrypted */
3093c602fabSXin LI #define	ENCRYPT_END		4	/* Am ending encrypted */
3103c602fabSXin LI #define	ENCRYPT_REQSTART	5	/* Request you start encrypting */
3113c602fabSXin LI #define	ENCRYPT_REQEND		6	/* Request you send encrypting */
3123c602fabSXin LI #define	ENCRYPT_ENC_KEYID	7
3133c602fabSXin LI #define	ENCRYPT_DEC_KEYID	8
3143c602fabSXin LI #define	ENCRYPT_CNT		9
3153c602fabSXin LI 
3163c602fabSXin LI #define	ENCTYPE_ANY		0
3173c602fabSXin LI #define	ENCTYPE_DES_CFB64	1
3183c602fabSXin LI #define	ENCTYPE_DES_OFB64	2
3193c602fabSXin LI #define	ENCTYPE_CNT		3
3203c602fabSXin LI 
3213c602fabSXin LI #ifdef	ENCRYPT_NAMES
3223c602fabSXin LI const char *encrypt_names[] = {
3233c602fabSXin LI 	"IS", "SUPPORT", "REPLY", "START", "END",
3243c602fabSXin LI 	"REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID",
3253c602fabSXin LI 	0,
3263c602fabSXin LI };
3273c602fabSXin LI const char *enctype_names[] = {
3283c602fabSXin LI 	"ANY", "DES_CFB64",  "DES_OFB64",  0,
3293c602fabSXin LI };
3303c602fabSXin LI #else
3313c602fabSXin LI extern char *encrypt_names[];
3323c602fabSXin LI extern char *enctype_names[];
3333c602fabSXin LI #endif
3343c602fabSXin LI 
3353c602fabSXin LI #define	ENCRYPT_NAME_OK(x)	((unsigned int)(x) < ENCRYPT_CNT)
3363c602fabSXin LI #define	ENCRYPT_NAME(x)		encrypt_names[x]
3373c602fabSXin LI 
3383c602fabSXin LI #define	ENCTYPE_NAME_OK(x)	((unsigned int)(x) < ENCTYPE_CNT)
3393c602fabSXin LI #define	ENCTYPE_NAME(x)		enctype_names[x]
340b0453382SBill Fenner 
341a90e161bSBill Fenner /* normal */
342a90e161bSBill Fenner static const char *cmds[] = {
343a90e161bSBill Fenner 	"IS", "SEND", "INFO",
344a90e161bSBill Fenner };
345a90e161bSBill Fenner 
346a90e161bSBill Fenner /* 37: Authentication */
347a90e161bSBill Fenner static const char *authcmd[] = {
348a90e161bSBill Fenner 	"IS", "SEND", "REPLY", "NAME",
349a90e161bSBill Fenner };
350a90e161bSBill Fenner static const char *authtype[] = {
351a90e161bSBill Fenner 	"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK",
352a90e161bSBill Fenner 	"SRP", "RSA", "SSL", NULL, NULL,
353a90e161bSBill Fenner 	"LOKI", "SSA", "KEA_SJ", "KEA_SJ_INTEG", "DSS",
354a90e161bSBill Fenner 	"NTLM",
355a90e161bSBill Fenner };
356a90e161bSBill Fenner 
357a90e161bSBill Fenner /* 38: Encryption */
358a90e161bSBill Fenner static const char *enccmd[] = {
359a90e161bSBill Fenner 	"IS", "SUPPORT", "REPLY", "START", "END",
360a90e161bSBill Fenner 	"REQUEST-START", "REQUEST-END", "END_KEYID", "DEC_KEYID",
361a90e161bSBill Fenner };
362a90e161bSBill Fenner static const char *enctype[] = {
363a90e161bSBill Fenner 	"NULL", "DES_CFB64", "DES_OFB64", "DES3_CFB64", "DES3_OFB64",
364a90e161bSBill Fenner 	NULL, "CAST5_40_CFB64", "CAST5_40_OFB64", "CAST128_CFB64", "CAST128_OFB64",
365a90e161bSBill Fenner };
366a90e161bSBill Fenner 
367a90e161bSBill Fenner #define STR_OR_ID(x, tab) \
368a90e161bSBill Fenner 	(((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
369a90e161bSBill Fenner 
370a90e161bSBill Fenner static char *
numstr(int x)371a90e161bSBill Fenner numstr(int x)
372b0453382SBill Fenner {
373a90e161bSBill Fenner 	static char buf[20];
374b0453382SBill Fenner 
375a90e161bSBill Fenner 	snprintf(buf, sizeof(buf), "%#x", x);
376a90e161bSBill Fenner 	return buf;
377b0453382SBill Fenner }
378a90e161bSBill Fenner 
379a90e161bSBill Fenner /* sp points to IAC byte */
380a90e161bSBill Fenner static int
telnet_parse(netdissect_options * ndo,const u_char * sp,u_int length,int print)3813c602fabSXin LI telnet_parse(netdissect_options *ndo, const u_char *sp, u_int length, int print)
382a90e161bSBill Fenner {
3835b0fe478SBruce M Simpson 	int i, x;
3845b0fe478SBruce M Simpson 	u_int c;
385a90e161bSBill Fenner 	const u_char *osp, *p;
386a90e161bSBill Fenner #define FETCH(c, sp, length) \
387a90e161bSBill Fenner 	do { \
388a90e161bSBill Fenner 		if (length < 1) \
389a90e161bSBill Fenner 			goto pktend; \
390ee67461eSJoseph Mingrone 		c = GET_U_1(sp); \
391ee67461eSJoseph Mingrone 		sp++; \
392a90e161bSBill Fenner 		length--; \
393a90e161bSBill Fenner 	} while (0)
394a90e161bSBill Fenner 
395a90e161bSBill Fenner 	osp = sp;
396a90e161bSBill Fenner 
397a90e161bSBill Fenner 	FETCH(c, sp, length);
398a90e161bSBill Fenner 	if (c != IAC)
399a90e161bSBill Fenner 		goto pktend;
400a90e161bSBill Fenner 	FETCH(c, sp, length);
401a90e161bSBill Fenner 	if (c == IAC) {		/* <IAC><IAC>! */
402a90e161bSBill Fenner 		if (print)
403ee67461eSJoseph Mingrone 			ND_PRINT("IAC IAC");
404a90e161bSBill Fenner 		goto done;
405b0453382SBill Fenner 	}
406a90e161bSBill Fenner 
407a90e161bSBill Fenner 	i = c - TELCMD_FIRST;
408a90e161bSBill Fenner 	if (i < 0 || i > IAC - TELCMD_FIRST)
409a90e161bSBill Fenner 		goto pktend;
410a90e161bSBill Fenner 
411b0453382SBill Fenner 	switch (c) {
412b0453382SBill Fenner 	case DONT:
413b0453382SBill Fenner 	case DO:
414b0453382SBill Fenner 	case WONT:
415b0453382SBill Fenner 	case WILL:
416b0453382SBill Fenner 	case SB:
417a90e161bSBill Fenner 		/* DONT/DO/WONT/WILL x */
418a90e161bSBill Fenner 		FETCH(x, sp, length);
419b0453382SBill Fenner 		if (x >= 0 && x < NTELOPTS) {
420a90e161bSBill Fenner 			if (print)
421ee67461eSJoseph Mingrone 				ND_PRINT("%s %s", telcmds[i], telopts[x]);
422b0453382SBill Fenner 		} else {
423a90e161bSBill Fenner 			if (print)
424ee67461eSJoseph Mingrone 				ND_PRINT("%s %#x", telcmds[i], x);
425b0453382SBill Fenner 		}
426a90e161bSBill Fenner 		if (c != SB)
427a90e161bSBill Fenner 			break;
428a90e161bSBill Fenner 		/* IAC SB .... IAC SE */
429a90e161bSBill Fenner 		p = sp;
4305b0fe478SBruce M Simpson 		while (length > (u_int)(p + 1 - sp)) {
431ee67461eSJoseph Mingrone 			if (GET_U_1(p) == IAC && GET_U_1(p + 1) == SE)
432a90e161bSBill Fenner 				break;
433a90e161bSBill Fenner 			p++;
434a90e161bSBill Fenner 		}
435ee67461eSJoseph Mingrone 		if (GET_U_1(p) != IAC)
436a90e161bSBill Fenner 			goto pktend;
437a90e161bSBill Fenner 
438a90e161bSBill Fenner 		switch (x) {
439a90e161bSBill Fenner 		case TELOPT_AUTHENTICATION:
440a90e161bSBill Fenner 			if (p <= sp)
441a90e161bSBill Fenner 				break;
442a90e161bSBill Fenner 			FETCH(c, sp, length);
443a90e161bSBill Fenner 			if (print)
444ee67461eSJoseph Mingrone 				ND_PRINT(" %s", STR_OR_ID(c, authcmd));
445a90e161bSBill Fenner 			if (p <= sp)
446a90e161bSBill Fenner 				break;
447a90e161bSBill Fenner 			FETCH(c, sp, length);
448a90e161bSBill Fenner 			if (print)
449ee67461eSJoseph Mingrone 				ND_PRINT(" %s", STR_OR_ID(c, authtype));
450a90e161bSBill Fenner 			break;
451a90e161bSBill Fenner 		case TELOPT_ENCRYPT:
452a90e161bSBill Fenner 			if (p <= sp)
453a90e161bSBill Fenner 				break;
454a90e161bSBill Fenner 			FETCH(c, sp, length);
455a90e161bSBill Fenner 			if (print)
456ee67461eSJoseph Mingrone 				ND_PRINT(" %s", STR_OR_ID(c, enccmd));
457a90e161bSBill Fenner 			if (p <= sp)
458a90e161bSBill Fenner 				break;
459a90e161bSBill Fenner 			FETCH(c, sp, length);
460a90e161bSBill Fenner 			if (print)
461ee67461eSJoseph Mingrone 				ND_PRINT(" %s", STR_OR_ID(c, enctype));
462b0453382SBill Fenner 			break;
463b0453382SBill Fenner 		default:
464a90e161bSBill Fenner 			if (p <= sp)
465a90e161bSBill Fenner 				break;
466a90e161bSBill Fenner 			FETCH(c, sp, length);
467a90e161bSBill Fenner 			if (print)
468ee67461eSJoseph Mingrone 				ND_PRINT(" %s", STR_OR_ID(c, cmds));
469b0453382SBill Fenner 			break;
470b0453382SBill Fenner 		}
471a90e161bSBill Fenner 		while (p > sp) {
472a90e161bSBill Fenner 			FETCH(x, sp, length);
473a90e161bSBill Fenner 			if (print)
474ee67461eSJoseph Mingrone 				ND_PRINT(" %#x", x);
475a90e161bSBill Fenner 		}
476a90e161bSBill Fenner 		/* terminating IAC SE */
477a90e161bSBill Fenner 		if (print)
478ee67461eSJoseph Mingrone 			ND_PRINT(" SE");
479a90e161bSBill Fenner 		sp += 2;
480a90e161bSBill Fenner 		break;
481a90e161bSBill Fenner 	default:
482a90e161bSBill Fenner 		if (print)
483ee67461eSJoseph Mingrone 			ND_PRINT("%s", telcmds[i]);
484a90e161bSBill Fenner 		goto done;
485a90e161bSBill Fenner 	}
486a90e161bSBill Fenner 
487a90e161bSBill Fenner done:
488ee67461eSJoseph Mingrone 	return (int)(sp - osp);
489a90e161bSBill Fenner 
490a90e161bSBill Fenner pktend:
491a90e161bSBill Fenner 	return -1;
492a90e161bSBill Fenner #undef FETCH
493a90e161bSBill Fenner }
494a90e161bSBill Fenner 
495a90e161bSBill Fenner void
telnet_print(netdissect_options * ndo,const u_char * sp,u_int length)4963c602fabSXin LI telnet_print(netdissect_options *ndo, const u_char *sp, u_int length)
497a90e161bSBill Fenner {
498a90e161bSBill Fenner 	int first = 1;
499a90e161bSBill Fenner 	const u_char *osp;
500a90e161bSBill Fenner 	int l;
501a90e161bSBill Fenner 
502ee67461eSJoseph Mingrone 	ndo->ndo_protocol = "telnet";
503a90e161bSBill Fenner 	osp = sp;
504a90e161bSBill Fenner 
505ee67461eSJoseph Mingrone 	while (length > 0 && GET_U_1(sp) == IAC) {
5068bdc5a62SPatrick Kelsey 		/*
5078bdc5a62SPatrick Kelsey 		 * Parse the Telnet command without printing it,
5088bdc5a62SPatrick Kelsey 		 * to determine its length.
5098bdc5a62SPatrick Kelsey 		 */
5103c602fabSXin LI 		l = telnet_parse(ndo, sp, length, 0);
511a90e161bSBill Fenner 		if (l < 0)
512a90e161bSBill Fenner 			break;
513a90e161bSBill Fenner 
514b0453382SBill Fenner 		/*
515b0453382SBill Fenner 		 * now print it
516b0453382SBill Fenner 		 */
5173c602fabSXin LI 		if (ndo->ndo_Xflag && 2 < ndo->ndo_vflag) {
518b0453382SBill Fenner 			if (first)
519ee67461eSJoseph Mingrone 				ND_PRINT("\nTelnet:");
520ee67461eSJoseph Mingrone 			hex_print_with_offset(ndo, "\n", sp, l, (u_int)(sp - osp));
521a90e161bSBill Fenner 			if (l > 8)
522ee67461eSJoseph Mingrone 				ND_PRINT("\n\t\t\t\t");
523b0453382SBill Fenner 			else
524ee67461eSJoseph Mingrone 				ND_PRINT("%*s\t", (8 - l) * 3, "");
525a90e161bSBill Fenner 		} else
526ee67461eSJoseph Mingrone 			ND_PRINT("%s", (first) ? " [telnet " : ", ");
527a90e161bSBill Fenner 
5283c602fabSXin LI 		(void)telnet_parse(ndo, sp, length, 1);
529b0453382SBill Fenner 		first = 0;
530a90e161bSBill Fenner 
531a90e161bSBill Fenner 		sp += l;
532a90e161bSBill Fenner 		length -= l;
533b0453382SBill Fenner 	}
534b0453382SBill Fenner 	if (!first) {
5353c602fabSXin LI 		if (ndo->ndo_Xflag && 2 < ndo->ndo_vflag)
536ee67461eSJoseph Mingrone 			ND_PRINT("\n");
537b0453382SBill Fenner 		else
538ee67461eSJoseph Mingrone 			ND_PRINT("]");
539b0453382SBill Fenner 	}
540b0453382SBill Fenner }
541