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