xref: /aosp_15_r20/external/tcpdump/print-telnet.c (revision 05b00f6010a2396e3db2409989fc67270046269f)
1*05b00f60SXin Li /*	$NetBSD: print-telnet.c,v 1.2 1999/10/11 12:40:12 sjg Exp $	*/
2*05b00f60SXin Li 
3*05b00f60SXin Li /*-
4*05b00f60SXin Li  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5*05b00f60SXin Li  * All rights reserved.
6*05b00f60SXin Li  *
7*05b00f60SXin Li  * This code is derived from software contributed to The NetBSD Foundation
8*05b00f60SXin Li  * by Simon J. Gerraty.
9*05b00f60SXin Li  *
10*05b00f60SXin Li  * Redistribution and use in source and binary forms, with or without
11*05b00f60SXin Li  * modification, are permitted provided that the following conditions
12*05b00f60SXin Li  * are met:
13*05b00f60SXin Li  * 1. Redistributions of source code must retain the above copyright
14*05b00f60SXin Li  *    notice, this list of conditions and the following disclaimer.
15*05b00f60SXin Li  * 2. Redistributions in binary form must reproduce the above copyright
16*05b00f60SXin Li  *    notice, this list of conditions and the following disclaimer in the
17*05b00f60SXin Li  *    documentation and/or other materials provided with the distribution.
18*05b00f60SXin Li  * 3. All advertising materials mentioning features or use of this software
19*05b00f60SXin Li  *    must display the following acknowledgement:
20*05b00f60SXin Li  *        This product includes software developed by the NetBSD
21*05b00f60SXin Li  *        Foundation, Inc. and its contributors.
22*05b00f60SXin Li  * 4. Neither the name of The NetBSD Foundation nor the names of its
23*05b00f60SXin Li  *    contributors may be used to endorse or promote products derived
24*05b00f60SXin Li  *    from this software without specific prior written permission.
25*05b00f60SXin Li  *
26*05b00f60SXin Li  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27*05b00f60SXin Li  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28*05b00f60SXin Li  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29*05b00f60SXin Li  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30*05b00f60SXin Li  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31*05b00f60SXin Li  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32*05b00f60SXin Li  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33*05b00f60SXin Li  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34*05b00f60SXin Li  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35*05b00f60SXin Li  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36*05b00f60SXin Li  * POSSIBILITY OF SUCH DAMAGE.
37*05b00f60SXin Li  */
38*05b00f60SXin Li /*
39*05b00f60SXin Li  *      @(#)Copyright (c) 1994, Simon J. Gerraty.
40*05b00f60SXin Li  *
41*05b00f60SXin Li  *      This is free software.  It comes with NO WARRANTY.
42*05b00f60SXin Li  *      Permission to use, modify and distribute this source code
43*05b00f60SXin Li  *      is granted subject to the following conditions.
44*05b00f60SXin Li  *      1/ that the above copyright notice and this notice
45*05b00f60SXin Li  *      are preserved in all copies.
46*05b00f60SXin Li  */
47*05b00f60SXin Li 
48*05b00f60SXin Li /* \summary: Telnet option printer */
49*05b00f60SXin Li 
50*05b00f60SXin Li #ifdef HAVE_CONFIG_H
51*05b00f60SXin Li #include <config.h>
52*05b00f60SXin Li #endif
53*05b00f60SXin Li 
54*05b00f60SXin Li #include "netdissect-stdinc.h"
55*05b00f60SXin Li 
56*05b00f60SXin Li #include <stdio.h>
57*05b00f60SXin Li 
58*05b00f60SXin Li #include "netdissect.h"
59*05b00f60SXin Li #include "extract.h"
60*05b00f60SXin Li 
61*05b00f60SXin Li 
62*05b00f60SXin Li /*	NetBSD: telnet.h,v 1.9 2001/06/11 01:50:50 wiz Exp	*/
63*05b00f60SXin Li 
64*05b00f60SXin Li /*
65*05b00f60SXin Li  * Definitions for the TELNET protocol.
66*05b00f60SXin Li  */
67*05b00f60SXin Li #define	IAC	255		/* interpret as command: */
68*05b00f60SXin Li #define	DONT	254		/* you are not to use option */
69*05b00f60SXin Li #define	DO	253		/* please, you use option */
70*05b00f60SXin Li #define	WONT	252		/* I won't use option */
71*05b00f60SXin Li #define	WILL	251		/* I will use option */
72*05b00f60SXin Li #define	SB	250		/* interpret as subnegotiation */
73*05b00f60SXin Li #define	GA	249		/* you may reverse the line */
74*05b00f60SXin Li #define	EL	248		/* erase the current line */
75*05b00f60SXin Li #define	EC	247		/* erase the current character */
76*05b00f60SXin Li #define	AYT	246		/* are you there */
77*05b00f60SXin Li #define	AO	245		/* abort output--but let prog finish */
78*05b00f60SXin Li #define	IP	244		/* interrupt process--permanently */
79*05b00f60SXin Li #define	BREAK	243		/* break */
80*05b00f60SXin Li #define	DM	242		/* data mark--for connect. cleaning */
81*05b00f60SXin Li #define	NOP	241		/* nop */
82*05b00f60SXin Li #define	SE	240		/* end sub negotiation */
83*05b00f60SXin Li #define EOR     239             /* end of record (transparent mode) */
84*05b00f60SXin Li #define	ABORT	238		/* Abort process */
85*05b00f60SXin Li #define	SUSP	237		/* Suspend process */
86*05b00f60SXin Li #define	xEOF	236		/* End of file: EOF is already used... */
87*05b00f60SXin Li 
88*05b00f60SXin Li #define SYNCH	242		/* for telfunc calls */
89*05b00f60SXin Li 
90*05b00f60SXin Li static const char *telcmds[] = {
91*05b00f60SXin Li 	"EOF", "SUSP", "ABORT", "EOR",
92*05b00f60SXin Li 	"SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",
93*05b00f60SXin Li 	"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0,
94*05b00f60SXin Li };
95*05b00f60SXin Li 
96*05b00f60SXin Li #define	TELCMD_FIRST	xEOF
97*05b00f60SXin Li #define	TELCMD_LAST	IAC
98*05b00f60SXin Li #define	TELCMD_OK(x)	((unsigned int)(x) <= TELCMD_LAST && \
99*05b00f60SXin Li 			 (unsigned int)(x) >= TELCMD_FIRST)
100*05b00f60SXin Li #define	TELCMD(x)	telcmds[(x)-TELCMD_FIRST]
101*05b00f60SXin Li 
102*05b00f60SXin Li /* telnet options */
103*05b00f60SXin Li #define TELOPT_BINARY	0	/* 8-bit data path */
104*05b00f60SXin Li #define TELOPT_ECHO	1	/* echo */
105*05b00f60SXin Li #define	TELOPT_RCP	2	/* prepare to reconnect */
106*05b00f60SXin Li #define	TELOPT_SGA	3	/* suppress go ahead */
107*05b00f60SXin Li #define	TELOPT_NAMS	4	/* approximate message size */
108*05b00f60SXin Li #define	TELOPT_STATUS	5	/* give status */
109*05b00f60SXin Li #define	TELOPT_TM	6	/* timing mark */
110*05b00f60SXin Li #define	TELOPT_RCTE	7	/* remote controlled transmission and echo */
111*05b00f60SXin Li #define TELOPT_NAOL	8	/* negotiate about output line width */
112*05b00f60SXin Li #define TELOPT_NAOP	9	/* negotiate about output page size */
113*05b00f60SXin Li #define TELOPT_NAOCRD	10	/* negotiate about CR disposition */
114*05b00f60SXin Li #define TELOPT_NAOHTS	11	/* negotiate about horizontal tabstops */
115*05b00f60SXin Li #define TELOPT_NAOHTD	12	/* negotiate about horizontal tab disposition */
116*05b00f60SXin Li #define TELOPT_NAOFFD	13	/* negotiate about formfeed disposition */
117*05b00f60SXin Li #define TELOPT_NAOVTS	14	/* negotiate about vertical tab stops */
118*05b00f60SXin Li #define TELOPT_NAOVTD	15	/* negotiate about vertical tab disposition */
119*05b00f60SXin Li #define TELOPT_NAOLFD	16	/* negotiate about output LF disposition */
120*05b00f60SXin Li #define TELOPT_XASCII	17	/* extended ascic character set */
121*05b00f60SXin Li #define	TELOPT_LOGOUT	18	/* force logout */
122*05b00f60SXin Li #define	TELOPT_BM	19	/* byte macro */
123*05b00f60SXin Li #define	TELOPT_DET	20	/* data entry terminal */
124*05b00f60SXin Li #define	TELOPT_SUPDUP	21	/* supdup protocol */
125*05b00f60SXin Li #define	TELOPT_SUPDUPOUTPUT 22	/* supdup output */
126*05b00f60SXin Li #define	TELOPT_SNDLOC	23	/* send location */
127*05b00f60SXin Li #define	TELOPT_TTYPE	24	/* terminal type */
128*05b00f60SXin Li #define	TELOPT_EOR	25	/* end or record */
129*05b00f60SXin Li #define	TELOPT_TUID	26	/* TACACS user identification */
130*05b00f60SXin Li #define	TELOPT_OUTMRK	27	/* output marking */
131*05b00f60SXin Li #define	TELOPT_TTYLOC	28	/* terminal location number */
132*05b00f60SXin Li #define	TELOPT_3270REGIME 29	/* 3270 regime */
133*05b00f60SXin Li #define	TELOPT_X3PAD	30	/* X.3 PAD */
134*05b00f60SXin Li #define	TELOPT_NAWS	31	/* window size */
135*05b00f60SXin Li #define	TELOPT_TSPEED	32	/* terminal speed */
136*05b00f60SXin Li #define	TELOPT_LFLOW	33	/* remote flow control */
137*05b00f60SXin Li #define TELOPT_LINEMODE	34	/* Linemode option */
138*05b00f60SXin Li #define TELOPT_XDISPLOC	35	/* X Display Location */
139*05b00f60SXin Li #define TELOPT_OLD_ENVIRON 36	/* Old - Environment variables */
140*05b00f60SXin Li #define	TELOPT_AUTHENTICATION 37/* Authenticate */
141*05b00f60SXin Li #define	TELOPT_ENCRYPT	38	/* Encryption option */
142*05b00f60SXin Li #define TELOPT_NEW_ENVIRON 39	/* New - Environment variables */
143*05b00f60SXin Li #define	TELOPT_EXOPL	255	/* extended-options-list */
144*05b00f60SXin Li 
145*05b00f60SXin Li 
146*05b00f60SXin Li #define	NTELOPTS	(1+TELOPT_NEW_ENVIRON)
147*05b00f60SXin Li static const char *telopts[NTELOPTS+1] = {
148*05b00f60SXin Li 	"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
149*05b00f60SXin Li 	"STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
150*05b00f60SXin Li 	"NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
151*05b00f60SXin Li 	"NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
152*05b00f60SXin Li 	"DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
153*05b00f60SXin Li 	"SEND LOCATION", "TERMINAL TYPE", "END OF RECORD",
154*05b00f60SXin Li 	"TACACS UID", "OUTPUT MARKING", "TTYLOC",
155*05b00f60SXin Li 	"3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW",
156*05b00f60SXin Li 	"LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
157*05b00f60SXin Li 	"ENCRYPT", "NEW-ENVIRON",
158*05b00f60SXin Li 	0,
159*05b00f60SXin Li };
160*05b00f60SXin Li #define	TELOPT_FIRST	TELOPT_BINARY
161*05b00f60SXin Li #define	TELOPT_LAST	TELOPT_NEW_ENVIRON
162*05b00f60SXin Li #define	TELOPT_OK(x)	((unsigned int)(x) <= TELOPT_LAST)
163*05b00f60SXin Li #define	TELOPT(x)	telopts[(x)-TELOPT_FIRST]
164*05b00f60SXin Li 
165*05b00f60SXin Li /* sub-option qualifiers */
166*05b00f60SXin Li #define	TELQUAL_IS	0	/* option is... */
167*05b00f60SXin Li #define	TELQUAL_SEND	1	/* send option */
168*05b00f60SXin Li #define	TELQUAL_INFO	2	/* ENVIRON: informational version of IS */
169*05b00f60SXin Li #define	TELQUAL_REPLY	2	/* AUTHENTICATION: client version of IS */
170*05b00f60SXin Li #define	TELQUAL_NAME	3	/* AUTHENTICATION: client version of IS */
171*05b00f60SXin Li 
172*05b00f60SXin Li #define	LFLOW_OFF		0	/* Disable remote flow control */
173*05b00f60SXin Li #define	LFLOW_ON		1	/* Enable remote flow control */
174*05b00f60SXin Li #define	LFLOW_RESTART_ANY	2	/* Restart output on any char */
175*05b00f60SXin Li #define	LFLOW_RESTART_XON	3	/* Restart output only on XON */
176*05b00f60SXin Li 
177*05b00f60SXin Li /*
178*05b00f60SXin Li  * LINEMODE suboptions
179*05b00f60SXin Li  */
180*05b00f60SXin Li 
181*05b00f60SXin Li #define	LM_MODE		1
182*05b00f60SXin Li #define	LM_FORWARDMASK	2
183*05b00f60SXin Li #define	LM_SLC		3
184*05b00f60SXin Li 
185*05b00f60SXin Li #define	MODE_EDIT	0x01
186*05b00f60SXin Li #define	MODE_TRAPSIG	0x02
187*05b00f60SXin Li #define	MODE_ACK	0x04
188*05b00f60SXin Li #define MODE_SOFT_TAB	0x08
189*05b00f60SXin Li #define MODE_LIT_ECHO	0x10
190*05b00f60SXin Li 
191*05b00f60SXin Li #define	MODE_MASK	0x1f
192*05b00f60SXin Li 
193*05b00f60SXin Li #define	SLC_SYNCH	1
194*05b00f60SXin Li #define	SLC_BRK		2
195*05b00f60SXin Li #define	SLC_IP		3
196*05b00f60SXin Li #define	SLC_AO		4
197*05b00f60SXin Li #define	SLC_AYT		5
198*05b00f60SXin Li #define	SLC_EOR		6
199*05b00f60SXin Li #define	SLC_ABORT	7
200*05b00f60SXin Li #define	SLC_EOF		8
201*05b00f60SXin Li #define	SLC_SUSP	9
202*05b00f60SXin Li #define	SLC_EC		10
203*05b00f60SXin Li #define	SLC_EL		11
204*05b00f60SXin Li #define	SLC_EW		12
205*05b00f60SXin Li #define	SLC_RP		13
206*05b00f60SXin Li #define	SLC_LNEXT	14
207*05b00f60SXin Li #define	SLC_XON		15
208*05b00f60SXin Li #define	SLC_XOFF	16
209*05b00f60SXin Li #define	SLC_FORW1	17
210*05b00f60SXin Li #define	SLC_FORW2	18
211*05b00f60SXin Li #define	SLC_MCL         19
212*05b00f60SXin Li #define	SLC_MCR         20
213*05b00f60SXin Li #define	SLC_MCWL        21
214*05b00f60SXin Li #define	SLC_MCWR        22
215*05b00f60SXin Li #define	SLC_MCBOL       23
216*05b00f60SXin Li #define	SLC_MCEOL       24
217*05b00f60SXin Li #define	SLC_INSRT       25
218*05b00f60SXin Li #define	SLC_OVER        26
219*05b00f60SXin Li #define	SLC_ECR         27
220*05b00f60SXin Li #define	SLC_EWR         28
221*05b00f60SXin Li #define	SLC_EBOL        29
222*05b00f60SXin Li #define	SLC_EEOL        30
223*05b00f60SXin Li 
224*05b00f60SXin Li #define	NSLC		30
225*05b00f60SXin Li 
226*05b00f60SXin Li /*
227*05b00f60SXin Li  * For backwards compatibility, we define SLC_NAMES to be the
228*05b00f60SXin Li  * list of names if SLC_NAMES is not defined.
229*05b00f60SXin Li  */
230*05b00f60SXin Li #define	SLC_NAMELIST	"0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR",	\
231*05b00f60SXin Li 			"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP",	\
232*05b00f60SXin Li 			"LNEXT", "XON", "XOFF", "FORW1", "FORW2",	\
233*05b00f60SXin Li 			"MCL", "MCR", "MCWL", "MCWR", "MCBOL",		\
234*05b00f60SXin Li 			"MCEOL", "INSRT", "OVER", "ECR", "EWR",		\
235*05b00f60SXin Li 			"EBOL", "EEOL",					\
236*05b00f60SXin Li 			0,
237*05b00f60SXin Li 
238*05b00f60SXin Li #ifdef	SLC_NAMES
239*05b00f60SXin Li const char *slc_names[] = {
240*05b00f60SXin Li 	SLC_NAMELIST
241*05b00f60SXin Li };
242*05b00f60SXin Li #else
243*05b00f60SXin Li extern char *slc_names[];
244*05b00f60SXin Li #define	SLC_NAMES SLC_NAMELIST
245*05b00f60SXin Li #endif
246*05b00f60SXin Li 
247*05b00f60SXin Li #define	SLC_NAME_OK(x)	((unsigned int)(x) <= NSLC)
248*05b00f60SXin Li #define SLC_NAME(x)	slc_names[x]
249*05b00f60SXin Li 
250*05b00f60SXin Li #define	SLC_NOSUPPORT	0
251*05b00f60SXin Li #define	SLC_CANTCHANGE	1
252*05b00f60SXin Li #define	SLC_VARIABLE	2
253*05b00f60SXin Li #define	SLC_DEFAULT	3
254*05b00f60SXin Li #define	SLC_LEVELBITS	0x03
255*05b00f60SXin Li 
256*05b00f60SXin Li #define	SLC_FUNC	0
257*05b00f60SXin Li #define	SLC_FLAGS	1
258*05b00f60SXin Li #define	SLC_VALUE	2
259*05b00f60SXin Li 
260*05b00f60SXin Li #define	SLC_ACK		0x80
261*05b00f60SXin Li #define	SLC_FLUSHIN	0x40
262*05b00f60SXin Li #define	SLC_FLUSHOUT	0x20
263*05b00f60SXin Li 
264*05b00f60SXin Li #define	OLD_ENV_VAR	1
265*05b00f60SXin Li #define	OLD_ENV_VALUE	0
266*05b00f60SXin Li #define	NEW_ENV_VAR	0
267*05b00f60SXin Li #define	NEW_ENV_VALUE	1
268*05b00f60SXin Li #define	ENV_ESC		2
269*05b00f60SXin Li #define ENV_USERVAR	3
270*05b00f60SXin Li 
271*05b00f60SXin Li /*
272*05b00f60SXin Li  * AUTHENTICATION suboptions
273*05b00f60SXin Li  */
274*05b00f60SXin Li 
275*05b00f60SXin Li /*
276*05b00f60SXin Li  * Who is authenticating who ...
277*05b00f60SXin Li  */
278*05b00f60SXin Li #define	AUTH_WHO_CLIENT		0	/* Client authenticating server */
279*05b00f60SXin Li #define	AUTH_WHO_SERVER		1	/* Server authenticating client */
280*05b00f60SXin Li #define	AUTH_WHO_MASK		1
281*05b00f60SXin Li 
282*05b00f60SXin Li #define	AUTHTYPE_NULL		0
283*05b00f60SXin Li #define	AUTHTYPE_KERBEROS_V4	1
284*05b00f60SXin Li #define	AUTHTYPE_KERBEROS_V5	2
285*05b00f60SXin Li #define	AUTHTYPE_SPX		3
286*05b00f60SXin Li #define	AUTHTYPE_MINK		4
287*05b00f60SXin Li #define	AUTHTYPE_CNT		5
288*05b00f60SXin Li 
289*05b00f60SXin Li #define	AUTHTYPE_TEST		99
290*05b00f60SXin Li 
291*05b00f60SXin Li #ifdef	AUTH_NAMES
292*05b00f60SXin Li const char *authtype_names[] = {
293*05b00f60SXin Li 	"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0,
294*05b00f60SXin Li };
295*05b00f60SXin Li #else
296*05b00f60SXin Li extern char *authtype_names[];
297*05b00f60SXin Li #endif
298*05b00f60SXin Li 
299*05b00f60SXin Li #define	AUTHTYPE_NAME_OK(x)	((unsigned int)(x) < AUTHTYPE_CNT)
300*05b00f60SXin Li #define	AUTHTYPE_NAME(x)	authtype_names[x]
301*05b00f60SXin Li 
302*05b00f60SXin Li /*
303*05b00f60SXin Li  * ENCRYPTion suboptions
304*05b00f60SXin Li  */
305*05b00f60SXin Li #define	ENCRYPT_IS		0	/* I pick encryption type ... */
306*05b00f60SXin Li #define	ENCRYPT_SUPPORT		1	/* I support encryption types ... */
307*05b00f60SXin Li #define	ENCRYPT_REPLY		2	/* Initial setup response */
308*05b00f60SXin Li #define	ENCRYPT_START		3	/* Am starting to send encrypted */
309*05b00f60SXin Li #define	ENCRYPT_END		4	/* Am ending encrypted */
310*05b00f60SXin Li #define	ENCRYPT_REQSTART	5	/* Request you start encrypting */
311*05b00f60SXin Li #define	ENCRYPT_REQEND		6	/* Request you send encrypting */
312*05b00f60SXin Li #define	ENCRYPT_ENC_KEYID	7
313*05b00f60SXin Li #define	ENCRYPT_DEC_KEYID	8
314*05b00f60SXin Li #define	ENCRYPT_CNT		9
315*05b00f60SXin Li 
316*05b00f60SXin Li #define	ENCTYPE_ANY		0
317*05b00f60SXin Li #define	ENCTYPE_DES_CFB64	1
318*05b00f60SXin Li #define	ENCTYPE_DES_OFB64	2
319*05b00f60SXin Li #define	ENCTYPE_CNT		3
320*05b00f60SXin Li 
321*05b00f60SXin Li #ifdef	ENCRYPT_NAMES
322*05b00f60SXin Li const char *encrypt_names[] = {
323*05b00f60SXin Li 	"IS", "SUPPORT", "REPLY", "START", "END",
324*05b00f60SXin Li 	"REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID",
325*05b00f60SXin Li 	0,
326*05b00f60SXin Li };
327*05b00f60SXin Li const char *enctype_names[] = {
328*05b00f60SXin Li 	"ANY", "DES_CFB64",  "DES_OFB64",  0,
329*05b00f60SXin Li };
330*05b00f60SXin Li #else
331*05b00f60SXin Li extern char *encrypt_names[];
332*05b00f60SXin Li extern char *enctype_names[];
333*05b00f60SXin Li #endif
334*05b00f60SXin Li 
335*05b00f60SXin Li #define	ENCRYPT_NAME_OK(x)	((unsigned int)(x) < ENCRYPT_CNT)
336*05b00f60SXin Li #define	ENCRYPT_NAME(x)		encrypt_names[x]
337*05b00f60SXin Li 
338*05b00f60SXin Li #define	ENCTYPE_NAME_OK(x)	((unsigned int)(x) < ENCTYPE_CNT)
339*05b00f60SXin Li #define	ENCTYPE_NAME(x)		enctype_names[x]
340*05b00f60SXin Li 
341*05b00f60SXin Li /* normal */
342*05b00f60SXin Li static const char *cmds[] = {
343*05b00f60SXin Li 	"IS", "SEND", "INFO",
344*05b00f60SXin Li };
345*05b00f60SXin Li 
346*05b00f60SXin Li /* 37: Authentication */
347*05b00f60SXin Li static const char *authcmd[] = {
348*05b00f60SXin Li 	"IS", "SEND", "REPLY", "NAME",
349*05b00f60SXin Li };
350*05b00f60SXin Li static const char *authtype[] = {
351*05b00f60SXin Li 	"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK",
352*05b00f60SXin Li 	"SRP", "RSA", "SSL", NULL, NULL,
353*05b00f60SXin Li 	"LOKI", "SSA", "KEA_SJ", "KEA_SJ_INTEG", "DSS",
354*05b00f60SXin Li 	"NTLM",
355*05b00f60SXin Li };
356*05b00f60SXin Li 
357*05b00f60SXin Li /* 38: Encryption */
358*05b00f60SXin Li static const char *enccmd[] = {
359*05b00f60SXin Li 	"IS", "SUPPORT", "REPLY", "START", "END",
360*05b00f60SXin Li 	"REQUEST-START", "REQUEST-END", "END_KEYID", "DEC_KEYID",
361*05b00f60SXin Li };
362*05b00f60SXin Li static const char *enctype[] = {
363*05b00f60SXin Li 	"NULL", "DES_CFB64", "DES_OFB64", "DES3_CFB64", "DES3_OFB64",
364*05b00f60SXin Li 	NULL, "CAST5_40_CFB64", "CAST5_40_OFB64", "CAST128_CFB64", "CAST128_OFB64",
365*05b00f60SXin Li };
366*05b00f60SXin Li 
367*05b00f60SXin Li #define STR_OR_ID(x, tab) \
368*05b00f60SXin Li 	(((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
369*05b00f60SXin Li 
370*05b00f60SXin Li static char *
numstr(int x)371*05b00f60SXin Li numstr(int x)
372*05b00f60SXin Li {
373*05b00f60SXin Li 	static char buf[20];
374*05b00f60SXin Li 
375*05b00f60SXin Li 	snprintf(buf, sizeof(buf), "%#x", x);
376*05b00f60SXin Li 	return buf;
377*05b00f60SXin Li }
378*05b00f60SXin Li 
379*05b00f60SXin Li /* sp points to IAC byte */
380*05b00f60SXin Li static int
telnet_parse(netdissect_options * ndo,const u_char * sp,u_int length,int print)381*05b00f60SXin Li telnet_parse(netdissect_options *ndo, const u_char *sp, u_int length, int print)
382*05b00f60SXin Li {
383*05b00f60SXin Li 	int i, x;
384*05b00f60SXin Li 	u_int c;
385*05b00f60SXin Li 	const u_char *osp, *p;
386*05b00f60SXin Li #define FETCH(c, sp, length) \
387*05b00f60SXin Li 	do { \
388*05b00f60SXin Li 		if (length < 1) \
389*05b00f60SXin Li 			goto pktend; \
390*05b00f60SXin Li 		c = GET_U_1(sp); \
391*05b00f60SXin Li 		sp++; \
392*05b00f60SXin Li 		length--; \
393*05b00f60SXin Li 	} while (0)
394*05b00f60SXin Li 
395*05b00f60SXin Li 	osp = sp;
396*05b00f60SXin Li 
397*05b00f60SXin Li 	FETCH(c, sp, length);
398*05b00f60SXin Li 	if (c != IAC)
399*05b00f60SXin Li 		goto pktend;
400*05b00f60SXin Li 	FETCH(c, sp, length);
401*05b00f60SXin Li 	if (c == IAC) {		/* <IAC><IAC>! */
402*05b00f60SXin Li 		if (print)
403*05b00f60SXin Li 			ND_PRINT("IAC IAC");
404*05b00f60SXin Li 		goto done;
405*05b00f60SXin Li 	}
406*05b00f60SXin Li 
407*05b00f60SXin Li 	i = c - TELCMD_FIRST;
408*05b00f60SXin Li 	if (i < 0 || i > IAC - TELCMD_FIRST)
409*05b00f60SXin Li 		goto pktend;
410*05b00f60SXin Li 
411*05b00f60SXin Li 	switch (c) {
412*05b00f60SXin Li 	case DONT:
413*05b00f60SXin Li 	case DO:
414*05b00f60SXin Li 	case WONT:
415*05b00f60SXin Li 	case WILL:
416*05b00f60SXin Li 	case SB:
417*05b00f60SXin Li 		/* DONT/DO/WONT/WILL x */
418*05b00f60SXin Li 		FETCH(x, sp, length);
419*05b00f60SXin Li 		if (x >= 0 && x < NTELOPTS) {
420*05b00f60SXin Li 			if (print)
421*05b00f60SXin Li 				ND_PRINT("%s %s", telcmds[i], telopts[x]);
422*05b00f60SXin Li 		} else {
423*05b00f60SXin Li 			if (print)
424*05b00f60SXin Li 				ND_PRINT("%s %#x", telcmds[i], x);
425*05b00f60SXin Li 		}
426*05b00f60SXin Li 		if (c != SB)
427*05b00f60SXin Li 			break;
428*05b00f60SXin Li 		/* IAC SB .... IAC SE */
429*05b00f60SXin Li 		p = sp;
430*05b00f60SXin Li 		while (length > (u_int)(p + 1 - sp)) {
431*05b00f60SXin Li 			if (GET_U_1(p) == IAC && GET_U_1(p + 1) == SE)
432*05b00f60SXin Li 				break;
433*05b00f60SXin Li 			p++;
434*05b00f60SXin Li 		}
435*05b00f60SXin Li 		if (GET_U_1(p) != IAC)
436*05b00f60SXin Li 			goto pktend;
437*05b00f60SXin Li 
438*05b00f60SXin Li 		switch (x) {
439*05b00f60SXin Li 		case TELOPT_AUTHENTICATION:
440*05b00f60SXin Li 			if (p <= sp)
441*05b00f60SXin Li 				break;
442*05b00f60SXin Li 			FETCH(c, sp, length);
443*05b00f60SXin Li 			if (print)
444*05b00f60SXin Li 				ND_PRINT(" %s", STR_OR_ID(c, authcmd));
445*05b00f60SXin Li 			if (p <= sp)
446*05b00f60SXin Li 				break;
447*05b00f60SXin Li 			FETCH(c, sp, length);
448*05b00f60SXin Li 			if (print)
449*05b00f60SXin Li 				ND_PRINT(" %s", STR_OR_ID(c, authtype));
450*05b00f60SXin Li 			break;
451*05b00f60SXin Li 		case TELOPT_ENCRYPT:
452*05b00f60SXin Li 			if (p <= sp)
453*05b00f60SXin Li 				break;
454*05b00f60SXin Li 			FETCH(c, sp, length);
455*05b00f60SXin Li 			if (print)
456*05b00f60SXin Li 				ND_PRINT(" %s", STR_OR_ID(c, enccmd));
457*05b00f60SXin Li 			if (p <= sp)
458*05b00f60SXin Li 				break;
459*05b00f60SXin Li 			FETCH(c, sp, length);
460*05b00f60SXin Li 			if (print)
461*05b00f60SXin Li 				ND_PRINT(" %s", STR_OR_ID(c, enctype));
462*05b00f60SXin Li 			break;
463*05b00f60SXin Li 		default:
464*05b00f60SXin Li 			if (p <= sp)
465*05b00f60SXin Li 				break;
466*05b00f60SXin Li 			FETCH(c, sp, length);
467*05b00f60SXin Li 			if (print)
468*05b00f60SXin Li 				ND_PRINT(" %s", STR_OR_ID(c, cmds));
469*05b00f60SXin Li 			break;
470*05b00f60SXin Li 		}
471*05b00f60SXin Li 		while (p > sp) {
472*05b00f60SXin Li 			FETCH(x, sp, length);
473*05b00f60SXin Li 			if (print)
474*05b00f60SXin Li 				ND_PRINT(" %#x", x);
475*05b00f60SXin Li 		}
476*05b00f60SXin Li 		/* terminating IAC SE */
477*05b00f60SXin Li 		if (print)
478*05b00f60SXin Li 			ND_PRINT(" SE");
479*05b00f60SXin Li 		sp += 2;
480*05b00f60SXin Li 		break;
481*05b00f60SXin Li 	default:
482*05b00f60SXin Li 		if (print)
483*05b00f60SXin Li 			ND_PRINT("%s", telcmds[i]);
484*05b00f60SXin Li 		goto done;
485*05b00f60SXin Li 	}
486*05b00f60SXin Li 
487*05b00f60SXin Li done:
488*05b00f60SXin Li 	return (int)(sp - osp);
489*05b00f60SXin Li 
490*05b00f60SXin Li pktend:
491*05b00f60SXin Li 	return -1;
492*05b00f60SXin Li #undef FETCH
493*05b00f60SXin Li }
494*05b00f60SXin Li 
495*05b00f60SXin Li void
telnet_print(netdissect_options * ndo,const u_char * sp,u_int length)496*05b00f60SXin Li telnet_print(netdissect_options *ndo, const u_char *sp, u_int length)
497*05b00f60SXin Li {
498*05b00f60SXin Li 	int first = 1;
499*05b00f60SXin Li 	const u_char *osp;
500*05b00f60SXin Li 	int l;
501*05b00f60SXin Li 
502*05b00f60SXin Li 	ndo->ndo_protocol = "telnet";
503*05b00f60SXin Li 	osp = sp;
504*05b00f60SXin Li 
505*05b00f60SXin Li 	while (length > 0 && GET_U_1(sp) == IAC) {
506*05b00f60SXin Li 		/*
507*05b00f60SXin Li 		 * Parse the Telnet command without printing it,
508*05b00f60SXin Li 		 * to determine its length.
509*05b00f60SXin Li 		 */
510*05b00f60SXin Li 		l = telnet_parse(ndo, sp, length, 0);
511*05b00f60SXin Li 		if (l < 0)
512*05b00f60SXin Li 			break;
513*05b00f60SXin Li 
514*05b00f60SXin Li 		/*
515*05b00f60SXin Li 		 * now print it
516*05b00f60SXin Li 		 */
517*05b00f60SXin Li 		if (ndo->ndo_Xflag && 2 < ndo->ndo_vflag) {
518*05b00f60SXin Li 			if (first)
519*05b00f60SXin Li 				ND_PRINT("\nTelnet:");
520*05b00f60SXin Li 			hex_print_with_offset(ndo, "\n", sp, l, (u_int)(sp - osp));
521*05b00f60SXin Li 			if (l > 8)
522*05b00f60SXin Li 				ND_PRINT("\n\t\t\t\t");
523*05b00f60SXin Li 			else
524*05b00f60SXin Li 				ND_PRINT("%*s\t", (8 - l) * 3, "");
525*05b00f60SXin Li 		} else
526*05b00f60SXin Li 			ND_PRINT("%s", (first) ? " [telnet " : ", ");
527*05b00f60SXin Li 
528*05b00f60SXin Li 		(void)telnet_parse(ndo, sp, length, 1);
529*05b00f60SXin Li 		first = 0;
530*05b00f60SXin Li 
531*05b00f60SXin Li 		sp += l;
532*05b00f60SXin Li 		length -= l;
533*05b00f60SXin Li 	}
534*05b00f60SXin Li 	if (!first) {
535*05b00f60SXin Li 		if (ndo->ndo_Xflag && 2 < ndo->ndo_vflag)
536*05b00f60SXin Li 			ND_PRINT("\n");
537*05b00f60SXin Li 		else
538*05b00f60SXin Li 			ND_PRINT("]");
539*05b00f60SXin Li 	}
540*05b00f60SXin Li }
541