2 * Routines for telnet packet dissection
3 * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
5 * $Id: packet-telnet.c,v 1.13 2000/05/31 05:07:50 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 */
53 #define TCP_PORT_TELNET 23
76 static const char *options[] = {
77 "Binary Transmission",
81 "Approx Message Size Negotiation",
84 "Remote Controlled Trans and Echo",
87 "Output Carriage-Return Disposition",
88 "Output Horizontal Tab Stops",
89 "Output Horizontal Tab Disposition",
90 "Output Formfeed Disposition",
91 "Output Vertical Tabstops",
92 "Output Vertical Tab Disposition",
93 "Output Linefeed Disposition",
97 "Data Entry Terminal",
103 "TACACS User Identification",
105 "Terminal Location Number",
106 "Telnet 3270 Regime",
108 "Negotiate About Window Size",
110 "Remote Flow Control",
112 "X Display Location",
113 "Environment Option",
114 "Authentication Option",
116 "New Environment Option",
120 #define NOPTIONS (sizeof options / sizeof options[0])
123 telnet_sub_option(proto_tree *telnet_tree, const u_char *pd,
126 proto_tree *ti, *option_tree;
127 int offset = start_offset;
129 gboolean not_found = TRUE;
132 offset += 2; /* skip IAC and SB */
134 /* Figure out the option and type */
135 if (pd[offset] > NOPTIONS)
136 opt = "<unknown option>";
138 opt = options[pd[offset]];
143 while (offset < pi.captured_len && not_found) {
144 if (pd[offset] == TN_IAC)
150 subneg_len = offset - start_offset;
152 ti = proto_tree_add_text(telnet_tree, NullTVB, start_offset, subneg_len,
153 "Suboption Begin: %s", opt);
155 option_tree = proto_item_add_subtree(ti, ett_telnet_subopt);
157 proto_tree_add_text(option_tree, NullTVB, start_offset + 2, 2,
158 "%s %s", (req ? "Send your" : "Here's my"), opt);
160 if (req == 0) { /* Add the value */
161 proto_tree_add_text(option_tree, NullTVB, start_offset + 4, subneg_len - 4,
162 "Value: %s", format_text(&pd[start_offset + 4], subneg_len - 4));
168 telnet_will_wont_do_dont(proto_tree *telnet_tree, const u_char *pd,
169 int start_offset, char *type)
171 int offset = start_offset;
174 offset += 2; /* skip IAC and WILL,WONT,DO,DONT} */
175 if (pd[offset] > NOPTIONS)
176 opt = "<unknown option>";
178 opt = options[pd[offset]];
181 proto_tree_add_text(telnet_tree, NullTVB, start_offset, 3,
182 "Command: %s %s", type, opt);
187 telnet_command(proto_tree *telnet_tree, const u_char *pd, int start_offset)
189 int offset = start_offset;
192 offset += 1; /* skip IAC */
193 optcode = pd[offset];
198 proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2,
199 "Command: End of File");
203 proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2,
204 "Command: Suspend Current Process");
208 proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2,
209 "Command: Abort Process");
213 proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2,
214 "Command: End of Record");
218 proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2,
219 "Command: Suboption End");
223 proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2,
224 "Command: No Operation");
228 proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2,
229 "Command: Data Mark");
233 proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2,
238 proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2,
239 "Command: Interrupt Process");
243 proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2,
244 "Command: Abort Output");
248 proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2,
249 "Command: Are You There?");
253 proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2,
254 "Command: Escape Character");
258 proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2,
259 "Command: Erase Line");
263 proto_tree_add_text(telnet_tree, NullTVB, start_offset, 2,
264 "Command: Go Ahead");
268 offset = telnet_sub_option(telnet_tree, pd, start_offset);
272 offset = telnet_will_wont_do_dont(telnet_tree, pd, start_offset,
277 offset = telnet_will_wont_do_dont(telnet_tree, pd, start_offset,
282 offset = telnet_will_wont_do_dont(telnet_tree, pd, start_offset,
287 offset = telnet_will_wont_do_dont(telnet_tree, pd, start_offset,
296 dissect_telnet(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
298 proto_tree *telnet_tree, *ti;
300 if (check_col(fd, COL_PROTOCOL))
301 col_add_str(fd, COL_PROTOCOL, "TELNET");
303 if (check_col(fd, COL_INFO))
304 col_add_fstr(fd, COL_INFO, "Telnet Data ...");
310 ti = proto_tree_add_item(tree, proto_telnet, NullTVB, offset, END_OF_FRAME, FALSE);
311 telnet_tree = proto_item_add_subtree(ti, ett_telnet);
313 data_offset = offset;
317 * Scan through the buffer looking for an IAC byte.
319 while (offset < pi.captured_len) {
320 if (pd[offset] == TN_IAC) {
322 * We found an IAC byte.
323 * If there's any data before it, add that data to the
327 proto_tree_add_text(telnet_tree, NullTVB, data_offset, data_len,
328 "Data: %s", format_text(&pd[data_offset], data_len));
330 data_offset = offset;
334 * Now interpret the command.
336 offset = telnet_command(telnet_tree, pd, offset);
337 data_offset = offset;
346 * We've reached the end of the buffer.
347 * If there's any data left, add it to the tree.
350 proto_tree_add_text(telnet_tree, NullTVB, data_offset, data_len, "Data: %s",
351 format_text(&pd[data_offset], data_len));
357 proto_register_telnet(void)
359 /* static hf_register_info hf[] = {
361 { "Name", "telnet.abbreviation", TYPE, VALS_POINTER }},
363 static gint *ett[] = {
368 proto_telnet = proto_register_protocol("Telnet", "telnet");
369 /* proto_register_field_array(proto_telnet, hf, array_length(hf));*/
370 proto_register_subtree_array(ett, array_length(ett));
374 proto_reg_handoff_telnet(void)
376 dissector_add("tcp.port", TCP_PORT_TELNET, dissect_telnet);