xref: /dragonfly/contrib/tcpdump/print-telnet.c (revision ed775ee7)
141c99275SPeter Avalos /*	$NetBSD: print-telnet.c,v 1.2 1999/10/11 12:40:12 sjg Exp $ 	*/
241c99275SPeter Avalos 
341c99275SPeter Avalos /*-
441c99275SPeter Avalos  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
541c99275SPeter Avalos  * All rights reserved.
641c99275SPeter Avalos  *
741c99275SPeter Avalos  * This code is derived from software contributed to The NetBSD Foundation
841c99275SPeter Avalos  * by Simon J. Gerraty.
941c99275SPeter Avalos  *
1041c99275SPeter Avalos  * Redistribution and use in source and binary forms, with or without
1141c99275SPeter Avalos  * modification, are permitted provided that the following conditions
1241c99275SPeter Avalos  * are met:
1341c99275SPeter Avalos  * 1. Redistributions of source code must retain the above copyright
1441c99275SPeter Avalos  *    notice, this list of conditions and the following disclaimer.
1541c99275SPeter Avalos  * 2. Redistributions in binary form must reproduce the above copyright
1641c99275SPeter Avalos  *    notice, this list of conditions and the following disclaimer in the
1741c99275SPeter Avalos  *    documentation and/or other materials provided with the distribution.
1841c99275SPeter Avalos  * 3. All advertising materials mentioning features or use of this software
1941c99275SPeter Avalos  *    must display the following acknowledgement:
2041c99275SPeter Avalos  *        This product includes software developed by the NetBSD
2141c99275SPeter Avalos  *        Foundation, Inc. and its contributors.
2241c99275SPeter Avalos  * 4. Neither the name of The NetBSD Foundation nor the names of its
2341c99275SPeter Avalos  *    contributors may be used to endorse or promote products derived
2441c99275SPeter Avalos  *    from this software without specific prior written permission.
2541c99275SPeter Avalos  *
2641c99275SPeter Avalos  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2741c99275SPeter Avalos  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2841c99275SPeter Avalos  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2941c99275SPeter Avalos  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
3041c99275SPeter Avalos  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3141c99275SPeter Avalos  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3241c99275SPeter Avalos  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
3341c99275SPeter Avalos  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
3441c99275SPeter Avalos  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3541c99275SPeter Avalos  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3641c99275SPeter Avalos  * POSSIBILITY OF SUCH DAMAGE.
3741c99275SPeter Avalos  */
3841c99275SPeter Avalos /*
3941c99275SPeter Avalos  *      @(#)Copyright (c) 1994, Simon J. Gerraty.
4041c99275SPeter Avalos  *
4141c99275SPeter Avalos  *      This is free software.  It comes with NO WARRANTY.
4241c99275SPeter Avalos  *      Permission to use, modify and distribute this source code
4341c99275SPeter Avalos  *      is granted subject to the following conditions.
4441c99275SPeter Avalos  *      1/ that the above copyright notice and this notice
4541c99275SPeter Avalos  *      are preserved in all copies.
4641c99275SPeter Avalos  */
4741c99275SPeter Avalos 
48411677aeSAaron LI /* \summary: Telnet option printer */
49411677aeSAaron LI 
5041c99275SPeter Avalos #ifdef HAVE_CONFIG_H
51*ed775ee7SAntonio Huete Jimenez #include <config.h>
5241c99275SPeter Avalos #endif
5341c99275SPeter Avalos 
54*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
5541c99275SPeter Avalos 
5641c99275SPeter Avalos #include <stdio.h>
5741c99275SPeter Avalos 
58411677aeSAaron LI #include "netdissect.h"
59*ed775ee7SAntonio Huete Jimenez #include "extract.h"
60411677aeSAaron LI 
61411677aeSAaron LI 
62411677aeSAaron LI /*	NetBSD: telnet.h,v 1.9 2001/06/11 01:50:50 wiz Exp 	*/
63411677aeSAaron LI 
64411677aeSAaron LI /*
65411677aeSAaron LI  * Definitions for the TELNET protocol.
66411677aeSAaron LI  */
67411677aeSAaron LI #define	IAC	255		/* interpret as command: */
68411677aeSAaron LI #define	DONT	254		/* you are not to use option */
69411677aeSAaron LI #define	DO	253		/* please, you use option */
70411677aeSAaron LI #define	WONT	252		/* I won't use option */
71411677aeSAaron LI #define	WILL	251		/* I will use option */
72411677aeSAaron LI #define	SB	250		/* interpret as subnegotiation */
73411677aeSAaron LI #define	GA	249		/* you may reverse the line */
74411677aeSAaron LI #define	EL	248		/* erase the current line */
75411677aeSAaron LI #define	EC	247		/* erase the current character */
76411677aeSAaron LI #define	AYT	246		/* are you there */
77411677aeSAaron LI #define	AO	245		/* abort output--but let prog finish */
78411677aeSAaron LI #define	IP	244		/* interrupt process--permanently */
79411677aeSAaron LI #define	BREAK	243		/* break */
80411677aeSAaron LI #define	DM	242		/* data mark--for connect. cleaning */
81411677aeSAaron LI #define	NOP	241		/* nop */
82411677aeSAaron LI #define	SE	240		/* end sub negotiation */
83411677aeSAaron LI #define EOR     239             /* end of record (transparent mode) */
84411677aeSAaron LI #define	ABORT	238		/* Abort process */
85411677aeSAaron LI #define	SUSP	237		/* Suspend process */
86411677aeSAaron LI #define	xEOF	236		/* End of file: EOF is already used... */
87411677aeSAaron LI 
88411677aeSAaron LI #define SYNCH	242		/* for telfunc calls */
89411677aeSAaron LI 
90411677aeSAaron LI static const char *telcmds[] = {
91411677aeSAaron LI 	"EOF", "SUSP", "ABORT", "EOR",
92411677aeSAaron LI 	"SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC",
93411677aeSAaron LI 	"EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0,
94411677aeSAaron LI };
95411677aeSAaron LI 
96411677aeSAaron LI #define	TELCMD_FIRST	xEOF
97411677aeSAaron LI #define	TELCMD_LAST	IAC
98411677aeSAaron LI #define	TELCMD_OK(x)	((unsigned int)(x) <= TELCMD_LAST && \
99411677aeSAaron LI 			 (unsigned int)(x) >= TELCMD_FIRST)
100411677aeSAaron LI #define	TELCMD(x)	telcmds[(x)-TELCMD_FIRST]
101411677aeSAaron LI 
102411677aeSAaron LI /* telnet options */
103411677aeSAaron LI #define TELOPT_BINARY	0	/* 8-bit data path */
104411677aeSAaron LI #define TELOPT_ECHO	1	/* echo */
105411677aeSAaron LI #define	TELOPT_RCP	2	/* prepare to reconnect */
106411677aeSAaron LI #define	TELOPT_SGA	3	/* suppress go ahead */
107411677aeSAaron LI #define	TELOPT_NAMS	4	/* approximate message size */
108411677aeSAaron LI #define	TELOPT_STATUS	5	/* give status */
109411677aeSAaron LI #define	TELOPT_TM	6	/* timing mark */
110411677aeSAaron LI #define	TELOPT_RCTE	7	/* remote controlled transmission and echo */
111411677aeSAaron LI #define TELOPT_NAOL 	8	/* negotiate about output line width */
112411677aeSAaron LI #define TELOPT_NAOP 	9	/* negotiate about output page size */
113411677aeSAaron LI #define TELOPT_NAOCRD	10	/* negotiate about CR disposition */
114411677aeSAaron LI #define TELOPT_NAOHTS	11	/* negotiate about horizontal tabstops */
115411677aeSAaron LI #define TELOPT_NAOHTD	12	/* negotiate about horizontal tab disposition */
116411677aeSAaron LI #define TELOPT_NAOFFD	13	/* negotiate about formfeed disposition */
117411677aeSAaron LI #define TELOPT_NAOVTS	14	/* negotiate about vertical tab stops */
118411677aeSAaron LI #define TELOPT_NAOVTD	15	/* negotiate about vertical tab disposition */
119411677aeSAaron LI #define TELOPT_NAOLFD	16	/* negotiate about output LF disposition */
120411677aeSAaron LI #define TELOPT_XASCII	17	/* extended ascic character set */
121411677aeSAaron LI #define	TELOPT_LOGOUT	18	/* force logout */
122411677aeSAaron LI #define	TELOPT_BM	19	/* byte macro */
123411677aeSAaron LI #define	TELOPT_DET	20	/* data entry terminal */
124411677aeSAaron LI #define	TELOPT_SUPDUP	21	/* supdup protocol */
125411677aeSAaron LI #define	TELOPT_SUPDUPOUTPUT 22	/* supdup output */
126411677aeSAaron LI #define	TELOPT_SNDLOC	23	/* send location */
127411677aeSAaron LI #define	TELOPT_TTYPE	24	/* terminal type */
128411677aeSAaron LI #define	TELOPT_EOR	25	/* end or record */
129411677aeSAaron LI #define	TELOPT_TUID	26	/* TACACS user identification */
130411677aeSAaron LI #define	TELOPT_OUTMRK	27	/* output marking */
131411677aeSAaron LI #define	TELOPT_TTYLOC	28	/* terminal location number */
132411677aeSAaron LI #define	TELOPT_3270REGIME 29	/* 3270 regime */
133411677aeSAaron LI #define	TELOPT_X3PAD	30	/* X.3 PAD */
134411677aeSAaron LI #define	TELOPT_NAWS	31	/* window size */
135411677aeSAaron LI #define	TELOPT_TSPEED	32	/* terminal speed */
136411677aeSAaron LI #define	TELOPT_LFLOW	33	/* remote flow control */
137411677aeSAaron LI #define TELOPT_LINEMODE	34	/* Linemode option */
138411677aeSAaron LI #define TELOPT_XDISPLOC	35	/* X Display Location */
139411677aeSAaron LI #define TELOPT_OLD_ENVIRON 36	/* Old - Environment variables */
140411677aeSAaron LI #define	TELOPT_AUTHENTICATION 37/* Authenticate */
141411677aeSAaron LI #define	TELOPT_ENCRYPT	38	/* Encryption option */
142411677aeSAaron LI #define TELOPT_NEW_ENVIRON 39	/* New - Environment variables */
143411677aeSAaron LI #define	TELOPT_EXOPL	255	/* extended-options-list */
144411677aeSAaron LI 
145411677aeSAaron LI 
146411677aeSAaron LI #define	NTELOPTS	(1+TELOPT_NEW_ENVIRON)
147411677aeSAaron LI static const char *telopts[NTELOPTS+1] = {
148411677aeSAaron LI 	"BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
149411677aeSAaron LI 	"STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
150411677aeSAaron LI 	"NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
151411677aeSAaron LI 	"NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
152411677aeSAaron LI 	"DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
153411677aeSAaron LI 	"SEND LOCATION", "TERMINAL TYPE", "END OF RECORD",
154411677aeSAaron LI 	"TACACS UID", "OUTPUT MARKING", "TTYLOC",
155411677aeSAaron LI 	"3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW",
156411677aeSAaron LI 	"LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION",
157411677aeSAaron LI 	"ENCRYPT", "NEW-ENVIRON",
158411677aeSAaron LI 	0,
159411677aeSAaron LI };
160411677aeSAaron LI #define	TELOPT_FIRST	TELOPT_BINARY
161411677aeSAaron LI #define	TELOPT_LAST	TELOPT_NEW_ENVIRON
162411677aeSAaron LI #define	TELOPT_OK(x)	((unsigned int)(x) <= TELOPT_LAST)
163411677aeSAaron LI #define	TELOPT(x)	telopts[(x)-TELOPT_FIRST]
164411677aeSAaron LI 
165411677aeSAaron LI /* sub-option qualifiers */
166411677aeSAaron LI #define	TELQUAL_IS	0	/* option is... */
167411677aeSAaron LI #define	TELQUAL_SEND	1	/* send option */
168411677aeSAaron LI #define	TELQUAL_INFO	2	/* ENVIRON: informational version of IS */
169411677aeSAaron LI #define	TELQUAL_REPLY	2	/* AUTHENTICATION: client version of IS */
170411677aeSAaron LI #define	TELQUAL_NAME	3	/* AUTHENTICATION: client version of IS */
171411677aeSAaron LI 
172411677aeSAaron LI #define	LFLOW_OFF		0	/* Disable remote flow control */
173411677aeSAaron LI #define	LFLOW_ON		1	/* Enable remote flow control */
174411677aeSAaron LI #define	LFLOW_RESTART_ANY	2	/* Restart output on any char */
175411677aeSAaron LI #define	LFLOW_RESTART_XON	3	/* Restart output only on XON */
176411677aeSAaron LI 
177411677aeSAaron LI /*
178411677aeSAaron LI  * LINEMODE suboptions
179411677aeSAaron LI  */
180411677aeSAaron LI 
181411677aeSAaron LI #define	LM_MODE		1
182411677aeSAaron LI #define	LM_FORWARDMASK	2
183411677aeSAaron LI #define	LM_SLC		3
184411677aeSAaron LI 
185411677aeSAaron LI #define	MODE_EDIT	0x01
186411677aeSAaron LI #define	MODE_TRAPSIG	0x02
187411677aeSAaron LI #define	MODE_ACK	0x04
188411677aeSAaron LI #define MODE_SOFT_TAB	0x08
189411677aeSAaron LI #define MODE_LIT_ECHO	0x10
190411677aeSAaron LI 
191411677aeSAaron LI #define	MODE_MASK	0x1f
192411677aeSAaron LI 
193411677aeSAaron LI #define	SLC_SYNCH	1
194411677aeSAaron LI #define	SLC_BRK		2
195411677aeSAaron LI #define	SLC_IP		3
196411677aeSAaron LI #define	SLC_AO		4
197411677aeSAaron LI #define	SLC_AYT		5
198411677aeSAaron LI #define	SLC_EOR		6
199411677aeSAaron LI #define	SLC_ABORT	7
200411677aeSAaron LI #define	SLC_EOF		8
201411677aeSAaron LI #define	SLC_SUSP	9
202411677aeSAaron LI #define	SLC_EC		10
203411677aeSAaron LI #define	SLC_EL		11
204411677aeSAaron LI #define	SLC_EW		12
205411677aeSAaron LI #define	SLC_RP		13
206411677aeSAaron LI #define	SLC_LNEXT	14
207411677aeSAaron LI #define	SLC_XON		15
208411677aeSAaron LI #define	SLC_XOFF	16
209411677aeSAaron LI #define	SLC_FORW1	17
210411677aeSAaron LI #define	SLC_FORW2	18
211411677aeSAaron LI #define	SLC_MCL         19
212411677aeSAaron LI #define	SLC_MCR         20
213411677aeSAaron LI #define	SLC_MCWL        21
214411677aeSAaron LI #define	SLC_MCWR        22
215411677aeSAaron LI #define	SLC_MCBOL       23
216411677aeSAaron LI #define	SLC_MCEOL       24
217411677aeSAaron LI #define	SLC_INSRT       25
218411677aeSAaron LI #define	SLC_OVER        26
219411677aeSAaron LI #define	SLC_ECR         27
220411677aeSAaron LI #define	SLC_EWR         28
221411677aeSAaron LI #define	SLC_EBOL        29
222411677aeSAaron LI #define	SLC_EEOL        30
223411677aeSAaron LI 
224411677aeSAaron LI #define	NSLC		30
225411677aeSAaron LI 
226411677aeSAaron LI /*
227411677aeSAaron LI  * For backwards compatibility, we define SLC_NAMES to be the
228411677aeSAaron LI  * list of names if SLC_NAMES is not defined.
229411677aeSAaron LI  */
230411677aeSAaron LI #define	SLC_NAMELIST	"0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR",	\
231411677aeSAaron LI 			"ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP",	\
232411677aeSAaron LI 			"LNEXT", "XON", "XOFF", "FORW1", "FORW2",	\
233411677aeSAaron LI 			"MCL", "MCR", "MCWL", "MCWR", "MCBOL",		\
234411677aeSAaron LI 			"MCEOL", "INSRT", "OVER", "ECR", "EWR",		\
235411677aeSAaron LI 			"EBOL", "EEOL",					\
236411677aeSAaron LI 			0,
237411677aeSAaron LI 
238411677aeSAaron LI #ifdef	SLC_NAMES
239411677aeSAaron LI const char *slc_names[] = {
240411677aeSAaron LI 	SLC_NAMELIST
241411677aeSAaron LI };
242411677aeSAaron LI #else
243411677aeSAaron LI extern char *slc_names[];
244411677aeSAaron LI #define	SLC_NAMES SLC_NAMELIST
245411677aeSAaron LI #endif
246411677aeSAaron LI 
247411677aeSAaron LI #define	SLC_NAME_OK(x)	((unsigned int)(x) <= NSLC)
248411677aeSAaron LI #define SLC_NAME(x)	slc_names[x]
249411677aeSAaron LI 
250411677aeSAaron LI #define	SLC_NOSUPPORT	0
251411677aeSAaron LI #define	SLC_CANTCHANGE	1
252411677aeSAaron LI #define	SLC_VARIABLE	2
253411677aeSAaron LI #define	SLC_DEFAULT	3
254411677aeSAaron LI #define	SLC_LEVELBITS	0x03
255411677aeSAaron LI 
256411677aeSAaron LI #define	SLC_FUNC	0
257411677aeSAaron LI #define	SLC_FLAGS	1
258411677aeSAaron LI #define	SLC_VALUE	2
259411677aeSAaron LI 
260411677aeSAaron LI #define	SLC_ACK		0x80
261411677aeSAaron LI #define	SLC_FLUSHIN	0x40
262411677aeSAaron LI #define	SLC_FLUSHOUT	0x20
263411677aeSAaron LI 
264411677aeSAaron LI #define	OLD_ENV_VAR	1
265411677aeSAaron LI #define	OLD_ENV_VALUE	0
266411677aeSAaron LI #define	NEW_ENV_VAR	0
267411677aeSAaron LI #define	NEW_ENV_VALUE	1
268411677aeSAaron LI #define	ENV_ESC		2
269411677aeSAaron LI #define ENV_USERVAR	3
270411677aeSAaron LI 
271411677aeSAaron LI /*
272411677aeSAaron LI  * AUTHENTICATION suboptions
273411677aeSAaron LI  */
274411677aeSAaron LI 
275411677aeSAaron LI /*
276411677aeSAaron LI  * Who is authenticating who ...
277411677aeSAaron LI  */
278411677aeSAaron LI #define	AUTH_WHO_CLIENT		0	/* Client authenticating server */
279411677aeSAaron LI #define	AUTH_WHO_SERVER		1	/* Server authenticating client */
280411677aeSAaron LI #define	AUTH_WHO_MASK		1
281411677aeSAaron LI 
282411677aeSAaron LI #define	AUTHTYPE_NULL		0
283411677aeSAaron LI #define	AUTHTYPE_KERBEROS_V4	1
284411677aeSAaron LI #define	AUTHTYPE_KERBEROS_V5	2
285411677aeSAaron LI #define	AUTHTYPE_SPX		3
286411677aeSAaron LI #define	AUTHTYPE_MINK		4
287411677aeSAaron LI #define	AUTHTYPE_CNT		5
288411677aeSAaron LI 
289411677aeSAaron LI #define	AUTHTYPE_TEST		99
290411677aeSAaron LI 
291411677aeSAaron LI #ifdef	AUTH_NAMES
292411677aeSAaron LI const char *authtype_names[] = {
293411677aeSAaron LI 	"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0,
294411677aeSAaron LI };
295411677aeSAaron LI #else
296411677aeSAaron LI extern char *authtype_names[];
297411677aeSAaron LI #endif
298411677aeSAaron LI 
299411677aeSAaron LI #define	AUTHTYPE_NAME_OK(x)	((unsigned int)(x) < AUTHTYPE_CNT)
300411677aeSAaron LI #define	AUTHTYPE_NAME(x)	authtype_names[x]
301411677aeSAaron LI 
302411677aeSAaron LI /*
303411677aeSAaron LI  * ENCRYPTion suboptions
304411677aeSAaron LI  */
305411677aeSAaron LI #define	ENCRYPT_IS		0	/* I pick encryption type ... */
306411677aeSAaron LI #define	ENCRYPT_SUPPORT		1	/* I support encryption types ... */
307411677aeSAaron LI #define	ENCRYPT_REPLY		2	/* Initial setup response */
308411677aeSAaron LI #define	ENCRYPT_START		3	/* Am starting to send encrypted */
309411677aeSAaron LI #define	ENCRYPT_END		4	/* Am ending encrypted */
310411677aeSAaron LI #define	ENCRYPT_REQSTART	5	/* Request you start encrypting */
311411677aeSAaron LI #define	ENCRYPT_REQEND		6	/* Request you send encrypting */
312411677aeSAaron LI #define	ENCRYPT_ENC_KEYID	7
313411677aeSAaron LI #define	ENCRYPT_DEC_KEYID	8
314411677aeSAaron LI #define	ENCRYPT_CNT		9
315411677aeSAaron LI 
316411677aeSAaron LI #define	ENCTYPE_ANY		0
317411677aeSAaron LI #define	ENCTYPE_DES_CFB64	1
318411677aeSAaron LI #define	ENCTYPE_DES_OFB64	2
319411677aeSAaron LI #define	ENCTYPE_CNT		3
320411677aeSAaron LI 
321411677aeSAaron LI #ifdef	ENCRYPT_NAMES
322411677aeSAaron LI const char *encrypt_names[] = {
323411677aeSAaron LI 	"IS", "SUPPORT", "REPLY", "START", "END",
324411677aeSAaron LI 	"REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID",
325411677aeSAaron LI 	0,
326411677aeSAaron LI };
327411677aeSAaron LI const char *enctype_names[] = {
328411677aeSAaron LI 	"ANY", "DES_CFB64",  "DES_OFB64",  0,
329411677aeSAaron LI };
330411677aeSAaron LI #else
331411677aeSAaron LI extern char *encrypt_names[];
332411677aeSAaron LI extern char *enctype_names[];
333411677aeSAaron LI #endif
334411677aeSAaron LI 
335411677aeSAaron LI #define	ENCRYPT_NAME_OK(x)	((unsigned int)(x) < ENCRYPT_CNT)
336411677aeSAaron LI #define	ENCRYPT_NAME(x)		encrypt_names[x]
337411677aeSAaron LI 
338411677aeSAaron LI #define	ENCTYPE_NAME_OK(x)	((unsigned int)(x) < ENCTYPE_CNT)
339411677aeSAaron LI #define	ENCTYPE_NAME(x)		enctype_names[x]
34041c99275SPeter Avalos 
34141c99275SPeter Avalos /* normal */
34241c99275SPeter Avalos static const char *cmds[] = {
34341c99275SPeter Avalos 	"IS", "SEND", "INFO",
34441c99275SPeter Avalos };
34541c99275SPeter Avalos 
34641c99275SPeter Avalos /* 37: Authentication */
34741c99275SPeter Avalos static const char *authcmd[] = {
34841c99275SPeter Avalos 	"IS", "SEND", "REPLY", "NAME",
34941c99275SPeter Avalos };
35041c99275SPeter Avalos static const char *authtype[] = {
35141c99275SPeter Avalos 	"NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK",
35241c99275SPeter Avalos 	"SRP", "RSA", "SSL", NULL, NULL,
35341c99275SPeter Avalos 	"LOKI", "SSA", "KEA_SJ", "KEA_SJ_INTEG", "DSS",
35441c99275SPeter Avalos 	"NTLM",
35541c99275SPeter Avalos };
35641c99275SPeter Avalos 
35741c99275SPeter Avalos /* 38: Encryption */
35841c99275SPeter Avalos static const char *enccmd[] = {
35941c99275SPeter Avalos 	"IS", "SUPPORT", "REPLY", "START", "END",
36041c99275SPeter Avalos 	"REQUEST-START", "REQUEST-END", "END_KEYID", "DEC_KEYID",
36141c99275SPeter Avalos };
36241c99275SPeter Avalos static const char *enctype[] = {
36341c99275SPeter Avalos 	"NULL", "DES_CFB64", "DES_OFB64", "DES3_CFB64", "DES3_OFB64",
36441c99275SPeter Avalos 	NULL, "CAST5_40_CFB64", "CAST5_40_OFB64", "CAST128_CFB64", "CAST128_OFB64",
36541c99275SPeter Avalos };
36641c99275SPeter Avalos 
36741c99275SPeter Avalos #define STR_OR_ID(x, tab) \
36841c99275SPeter Avalos 	(((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x))
36941c99275SPeter Avalos 
37041c99275SPeter Avalos static char *
numstr(int x)37141c99275SPeter Avalos numstr(int x)
37241c99275SPeter Avalos {
37341c99275SPeter Avalos 	static char buf[20];
37441c99275SPeter Avalos 
37541c99275SPeter Avalos 	snprintf(buf, sizeof(buf), "%#x", x);
37641c99275SPeter Avalos 	return buf;
37741c99275SPeter Avalos }
37841c99275SPeter Avalos 
37941c99275SPeter Avalos /* sp points to IAC byte */
38041c99275SPeter Avalos static int
telnet_parse(netdissect_options * ndo,const u_char * sp,u_int length,int print)381411677aeSAaron LI telnet_parse(netdissect_options *ndo, const u_char *sp, u_int length, int print)
38241c99275SPeter Avalos {
38341c99275SPeter Avalos 	int i, x;
38441c99275SPeter Avalos 	u_int c;
38541c99275SPeter Avalos 	const u_char *osp, *p;
38641c99275SPeter Avalos #define FETCH(c, sp, length) \
38741c99275SPeter Avalos 	do { \
38841c99275SPeter Avalos 		if (length < 1) \
38941c99275SPeter Avalos 			goto pktend; \
390*ed775ee7SAntonio Huete Jimenez 		c = GET_U_1(sp); \
391*ed775ee7SAntonio Huete Jimenez 		sp++; \
39241c99275SPeter Avalos 		length--; \
39341c99275SPeter Avalos 	} while (0)
39441c99275SPeter Avalos 
39541c99275SPeter Avalos 	osp = sp;
39641c99275SPeter Avalos 
39741c99275SPeter Avalos 	FETCH(c, sp, length);
39841c99275SPeter Avalos 	if (c != IAC)
39941c99275SPeter Avalos 		goto pktend;
40041c99275SPeter Avalos 	FETCH(c, sp, length);
40141c99275SPeter Avalos 	if (c == IAC) {		/* <IAC><IAC>! */
40241c99275SPeter Avalos 		if (print)
403*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("IAC IAC");
40441c99275SPeter Avalos 		goto done;
40541c99275SPeter Avalos 	}
40641c99275SPeter Avalos 
40741c99275SPeter Avalos 	i = c - TELCMD_FIRST;
40841c99275SPeter Avalos 	if (i < 0 || i > IAC - TELCMD_FIRST)
40941c99275SPeter Avalos 		goto pktend;
41041c99275SPeter Avalos 
41141c99275SPeter Avalos 	switch (c) {
41241c99275SPeter Avalos 	case DONT:
41341c99275SPeter Avalos 	case DO:
41441c99275SPeter Avalos 	case WONT:
41541c99275SPeter Avalos 	case WILL:
41641c99275SPeter Avalos 	case SB:
41741c99275SPeter Avalos 		/* DONT/DO/WONT/WILL x */
41841c99275SPeter Avalos 		FETCH(x, sp, length);
41941c99275SPeter Avalos 		if (x >= 0 && x < NTELOPTS) {
42041c99275SPeter Avalos 			if (print)
421*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("%s %s", telcmds[i], telopts[x]);
42241c99275SPeter Avalos 		} else {
42341c99275SPeter Avalos 			if (print)
424*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("%s %#x", telcmds[i], x);
42541c99275SPeter Avalos 		}
42641c99275SPeter Avalos 		if (c != SB)
42741c99275SPeter Avalos 			break;
42841c99275SPeter Avalos 		/* IAC SB .... IAC SE */
42941c99275SPeter Avalos 		p = sp;
43041c99275SPeter Avalos 		while (length > (u_int)(p + 1 - sp)) {
431*ed775ee7SAntonio Huete Jimenez 			if (GET_U_1(p) == IAC && GET_U_1(p + 1) == SE)
43241c99275SPeter Avalos 				break;
43341c99275SPeter Avalos 			p++;
43441c99275SPeter Avalos 		}
435*ed775ee7SAntonio Huete Jimenez 		if (GET_U_1(p) != IAC)
43641c99275SPeter Avalos 			goto pktend;
43741c99275SPeter Avalos 
43841c99275SPeter Avalos 		switch (x) {
43941c99275SPeter Avalos 		case TELOPT_AUTHENTICATION:
44041c99275SPeter Avalos 			if (p <= sp)
44141c99275SPeter Avalos 				break;
44241c99275SPeter Avalos 			FETCH(c, sp, length);
44341c99275SPeter Avalos 			if (print)
444*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" %s", STR_OR_ID(c, authcmd));
44541c99275SPeter Avalos 			if (p <= sp)
44641c99275SPeter Avalos 				break;
44741c99275SPeter Avalos 			FETCH(c, sp, length);
44841c99275SPeter Avalos 			if (print)
449*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" %s", STR_OR_ID(c, authtype));
45041c99275SPeter Avalos 			break;
45141c99275SPeter Avalos 		case TELOPT_ENCRYPT:
45241c99275SPeter Avalos 			if (p <= sp)
45341c99275SPeter Avalos 				break;
45441c99275SPeter Avalos 			FETCH(c, sp, length);
45541c99275SPeter Avalos 			if (print)
456*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" %s", STR_OR_ID(c, enccmd));
45741c99275SPeter Avalos 			if (p <= sp)
45841c99275SPeter Avalos 				break;
45941c99275SPeter Avalos 			FETCH(c, sp, length);
46041c99275SPeter Avalos 			if (print)
461*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" %s", STR_OR_ID(c, enctype));
46241c99275SPeter Avalos 			break;
46341c99275SPeter Avalos 		default:
46441c99275SPeter Avalos 			if (p <= sp)
46541c99275SPeter Avalos 				break;
46641c99275SPeter Avalos 			FETCH(c, sp, length);
46741c99275SPeter Avalos 			if (print)
468*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" %s", STR_OR_ID(c, cmds));
46941c99275SPeter Avalos 			break;
47041c99275SPeter Avalos 		}
47141c99275SPeter Avalos 		while (p > sp) {
47241c99275SPeter Avalos 			FETCH(x, sp, length);
47341c99275SPeter Avalos 			if (print)
474*ed775ee7SAntonio Huete Jimenez 				ND_PRINT(" %#x", x);
47541c99275SPeter Avalos 		}
47641c99275SPeter Avalos 		/* terminating IAC SE */
47741c99275SPeter Avalos 		if (print)
478*ed775ee7SAntonio Huete Jimenez 			ND_PRINT(" SE");
47941c99275SPeter Avalos 		sp += 2;
48041c99275SPeter Avalos 		break;
48141c99275SPeter Avalos 	default:
48241c99275SPeter Avalos 		if (print)
483*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s", telcmds[i]);
48441c99275SPeter Avalos 		goto done;
48541c99275SPeter Avalos 	}
48641c99275SPeter Avalos 
48741c99275SPeter Avalos done:
488*ed775ee7SAntonio Huete Jimenez 	return (int)(sp - osp);
48941c99275SPeter Avalos 
49041c99275SPeter Avalos pktend:
49141c99275SPeter Avalos 	return -1;
49241c99275SPeter Avalos #undef FETCH
49341c99275SPeter Avalos }
49441c99275SPeter Avalos 
49541c99275SPeter Avalos void
telnet_print(netdissect_options * ndo,const u_char * sp,u_int length)496411677aeSAaron LI telnet_print(netdissect_options *ndo, const u_char *sp, u_int length)
49741c99275SPeter Avalos {
49841c99275SPeter Avalos 	int first = 1;
49941c99275SPeter Avalos 	const u_char *osp;
50041c99275SPeter Avalos 	int l;
50141c99275SPeter Avalos 
502*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "telnet";
50341c99275SPeter Avalos 	osp = sp;
50441c99275SPeter Avalos 
505*ed775ee7SAntonio Huete Jimenez 	while (length > 0 && GET_U_1(sp) == IAC) {
506411677aeSAaron LI 		/*
507411677aeSAaron LI 		 * Parse the Telnet command without printing it,
508411677aeSAaron LI 		 * to determine its length.
509411677aeSAaron LI 		 */
510411677aeSAaron LI 		l = telnet_parse(ndo, sp, length, 0);
51141c99275SPeter Avalos 		if (l < 0)
51241c99275SPeter Avalos 			break;
51341c99275SPeter Avalos 
51441c99275SPeter Avalos 		/*
51541c99275SPeter Avalos 		 * now print it
51641c99275SPeter Avalos 		 */
517411677aeSAaron LI 		if (ndo->ndo_Xflag && 2 < ndo->ndo_vflag) {
51841c99275SPeter Avalos 			if (first)
519*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("\nTelnet:");
520*ed775ee7SAntonio Huete Jimenez 			hex_print_with_offset(ndo, "\n", sp, l, (u_int)(sp - osp));
52141c99275SPeter Avalos 			if (l > 8)
522*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("\n\t\t\t\t");
52341c99275SPeter Avalos 			else
524*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("%*s\t", (8 - l) * 3, "");
52541c99275SPeter Avalos 		} else
526*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s", (first) ? " [telnet " : ", ");
52741c99275SPeter Avalos 
528411677aeSAaron LI 		(void)telnet_parse(ndo, sp, length, 1);
52941c99275SPeter Avalos 		first = 0;
53041c99275SPeter Avalos 
53141c99275SPeter Avalos 		sp += l;
53241c99275SPeter Avalos 		length -= l;
53341c99275SPeter Avalos 	}
53441c99275SPeter Avalos 	if (!first) {
535411677aeSAaron LI 		if (ndo->ndo_Xflag && 2 < ndo->ndo_vflag)
536*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("\n");
53741c99275SPeter Avalos 		else
538*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("]");
53941c99275SPeter Avalos 	}
54041c99275SPeter Avalos }
541