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