2 * Routines for telnet packet dissection
3 * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
5 * $Id: packet-telnet.c,v 1.9 2000/03/23 10:25:38 guy Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@zing.org>
9 * Copyright 1998 Gerald Combs
11 * Copied from packet-pop.c
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
34 #ifdef HAVE_SYS_TYPES_H
35 # include <sys/types.h>
38 #ifdef HAVE_NETINET_IN_H
39 # include <netinet/in.h>
46 static int proto_telnet = -1;
48 static gint ett_telnet = -1;
49 static gint ett_telnet_subopt = -1;
51 /* Some defines for Telnet */
74 static const char *options[] = {
75 "Binary Transmission",
79 "Approx Message Size Negotiation",
82 "Remote Controlled Trans and Echo",
85 "Output Carriage-Return Disposition",
86 "Output Horizontal Tab Stops",
87 "Output Horizontal Tab Disposition",
88 "Output Formfeed Disposition",
89 "Output Vertical Tabstops",
90 "Output Vertical Tab Disposition",
91 "Output Linefeed Disposition",
95 "Data Entry Terminal",
101 "TACACS User Identification",
103 "Terminal Location Number",
104 "Telnet 3270 Regime",
106 "Negotiate About Window Size",
108 "Remote Flow Control",
110 "X Display Location",
111 "Environment Option",
112 "Authentication Option",
114 "New Environment Option",
118 #define NOPTIONS (sizeof options / sizeof options[0])
121 telnet_sub_option(proto_tree *telnet_tree, const u_char *pd,
124 proto_tree *ti, *option_tree;
125 int offset = start_offset;
127 gboolean not_found = TRUE;
130 offset += 2; /* skip IAC and SB */
132 /* Figure out the option and type */
133 if (pd[offset] > NOPTIONS)
134 opt = "<unknown option>";
136 opt = options[pd[offset]];
141 while (offset < pi.captured_len && not_found) {
142 if (pd[offset] == TN_IAC)
148 subneg_len = offset - start_offset;
150 ti = proto_tree_add_text(telnet_tree, start_offset, subneg_len,
151 "Suboption Begin: %s", opt);
153 option_tree = proto_item_add_subtree(ti, ett_telnet_subopt);
155 proto_tree_add_text(option_tree, start_offset + 2, 2,
156 "%s %s", (req ? "Send your" : "Here's my"), opt);
158 if (req == 0) { /* Add the value */
159 proto_tree_add_text(option_tree, start_offset + 4, subneg_len - 4,
160 "Value: %s", format_text(&pd[start_offset + 4], subneg_len - 4));
166 telnet_will_wont_do_dont(proto_tree *telnet_tree, const u_char *pd,
167 int start_offset, char *type)
169 int offset = start_offset;
172 offset += 2; /* skip IAC and WILL,WONT,DO,DONT} */
173 if (pd[offset] > NOPTIONS)
174 opt = "<unknown option>";
176 opt = options[pd[offset]];
179 proto_tree_add_text(telnet_tree, start_offset, 3,
180 "Command: %s %s", type, opt);
185 telnet_command(proto_tree *telnet_tree, const u_char *pd,
186 int start_offset, int max_data)
188 int offset = start_offset;
191 offset += 1; /* skip IAC */
192 optcode = pd[offset];
197 proto_tree_add_text(telnet_tree, start_offset, 2,
198 "Command: End of File");
202 proto_tree_add_text(telnet_tree, start_offset, 2,
203 "Command: Suspend Current Process");
207 proto_tree_add_text(telnet_tree, start_offset, 2,
208 "Command: Abort Process");
212 proto_tree_add_text(telnet_tree, start_offset, 2,
213 "Command: End of Record");
217 proto_tree_add_text(telnet_tree, start_offset, 2,
218 "Command: Suboption End");
222 proto_tree_add_text(telnet_tree, start_offset, 2,
223 "Command: No Operation");
227 proto_tree_add_text(telnet_tree, start_offset, 2,
228 "Command: Data Mark");
232 proto_tree_add_text(telnet_tree, start_offset, 2,
237 proto_tree_add_text(telnet_tree, start_offset, 2,
238 "Command: Interrupt Process");
242 proto_tree_add_text(telnet_tree, start_offset, 2,
243 "Command: Abort Output");
247 proto_tree_add_text(telnet_tree, start_offset, 2,
248 "Command: Are You There?");
252 proto_tree_add_text(telnet_tree, start_offset, 2,
253 "Command: Escape Character");
257 proto_tree_add_text(telnet_tree, start_offset, 2,
258 "Command: Erase Line");
262 proto_tree_add_text(telnet_tree, start_offset, 2,
263 "Command: Go Ahead");
267 offset = telnet_sub_option(telnet_tree, pd, start_offset);
271 offset = telnet_will_wont_do_dont(telnet_tree, pd, start_offset,
276 offset = telnet_will_wont_do_dont(telnet_tree, pd, start_offset,
281 offset = telnet_will_wont_do_dont(telnet_tree, pd, start_offset,
286 offset = telnet_will_wont_do_dont(telnet_tree, pd, start_offset,
295 dissect_telnet(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
297 proto_tree *telnet_tree, *ti;
298 int max_data = pi.captured_len - offset;
300 if (check_col(fd, COL_PROTOCOL))
301 col_add_str(fd, COL_PROTOCOL, "TELNET");
303 if (check_col(fd, COL_INFO)) {
305 col_add_fstr(fd, COL_INFO, "Telnet Data ...");
313 ti = proto_tree_add_item(tree, proto_telnet, offset, END_OF_FRAME, NULL);
314 telnet_tree = proto_item_add_subtree(ti, ett_telnet);
316 data_offset = offset;
320 * Scan through the buffer looking for an IAC byte.
322 while (offset < pi.captured_len) {
323 if (pd[offset] == TN_IAC) {
325 * We found an IAC byte.
326 * If there's any data before it, add that data to the
330 proto_tree_add_text(telnet_tree, data_offset, data_len,
331 "Data: %s", format_text(&pd[data_offset], data_len));
333 data_offset = offset;
337 * Now interpret the command.
339 offset = telnet_command(telnet_tree, pd, offset, max_data);
340 data_offset = offset;
349 * We've reached the end of the buffer.
350 * If there's any data left, add it to the tree.
353 proto_tree_add_text(telnet_tree, data_offset, data_len, "Data: %s",
354 format_text(&pd[data_offset], data_len));
360 proto_register_telnet(void)
362 /* static hf_register_info hf[] = {
364 { "Name", "telnet.abbreviation", TYPE, VALS_POINTER }},
366 static gint *ett[] = {
371 proto_telnet = proto_register_protocol("Telnet", "telnet");
372 /* proto_register_field_array(proto_telnet, hf, array_length(hf));*/
373 proto_register_subtree_array(ett, array_length(ett));