2 * Routines for telnet packet dissection
3 * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
5 * $Id: packet-telnet.c,v 1.8 2000/01/07 22:05:41 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 */
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 void telnet_sub_option(proto_tree *telnet_tree, char *rr, int *i, int offset, int max_data)
120 proto_tree *ti, *option_tree;
121 int subneg_len, req, si1, not_found = 1;
123 char *opt, sub_opt_data[1500];
125 memset(sub_opt_data, '\0', sizeof(sub_opt_data));
127 /* Figure out the option and type */
129 opt = options[(unsigned int)rr[*i]];
130 req = (unsigned int)rr[*i + 1];
132 i1 = *i + 2; si1 = i1;
133 while ((i1 < max_data) && (not_found)) {
135 if ((unsigned char)rr[i1] == (unsigned char)TN_IAC)
142 subneg_len = i1 - *i + 2;
144 ti = proto_tree_add_text(telnet_tree, offset, subneg_len, "Suboption Begin: %s", opt);
146 option_tree = proto_item_add_subtree(ti, ett_telnet_subopt);
148 proto_tree_add_text(option_tree, offset + 2, subneg_len - 2, "%s %s", (req ? "Send your" : "Here's my"), opt);
150 if (req == 0) { /* Add the value */
152 memcpy(sub_opt_data, rr + *i + 2, subneg_len - 2);
153 proto_tree_add_text(option_tree, offset + 4, subneg_len - 4, "Value: %s", format_text(sub_opt_data, subneg_len - 4));
154 *i += subneg_len - 2;
159 *i += subneg_len - 2;
164 void telnet_command(proto_tree *telnet_tree, char *rr, int *i, int offset, int max_data)
168 switch((unsigned char)rr[*i]) {
172 proto_tree_add_text(telnet_tree, offset, 2, "Command: End of File");
178 proto_tree_add_text(telnet_tree, offset, 2, "Command: Suspend Current Process");
184 proto_tree_add_text(telnet_tree, offset, 2, "Command: Abort Process");
190 proto_tree_add_text(telnet_tree, offset, 2, "Command: End of Record");
196 proto_tree_add_text(telnet_tree, offset, 2, "Command: Suboption End");
202 proto_tree_add_text(telnet_tree, offset, 2, "Command: No Operation");
208 proto_tree_add_text(telnet_tree, offset, 2, "Command: Data Mark");
214 proto_tree_add_text(telnet_tree, offset, 2, "Command: Break");
220 proto_tree_add_text(telnet_tree, offset, 2, "Command: Interrupt Process");
226 proto_tree_add_text(telnet_tree, offset, 2, "Command: Abort Output");
232 proto_tree_add_text(telnet_tree, offset, 2, "Command: Are You There?");
238 proto_tree_add_text(telnet_tree, offset, 2, "Command: Escape Character");
244 proto_tree_add_text(telnet_tree, offset, 2, "Command: Erase Line");
250 proto_tree_add_text(telnet_tree, offset, 2, "Command: Go Ahead");
257 telnet_sub_option(telnet_tree, rr, i, offset, max_data);
262 if (rr[*i + 1] > (sizeof(options)/sizeof(char *)))
263 opt = "<unknown option>";
265 opt = options[(unsigned int)rr[*i + 1]];
267 proto_tree_add_text(telnet_tree, offset, 3, "Command: Will %s", opt);
268 *i += 2; /* skip two chars */
273 if (rr[*i + 1] > (sizeof(options)/sizeof(char *)))
274 opt = "<unknown option>";
276 opt = options[(unsigned int)rr[*i + 1]];
278 proto_tree_add_text(telnet_tree, offset, 3, "Command: Won't %s", opt);
279 *i += 2; /* skip two chars */
284 if (rr[*i + 1] > (sizeof(options)/sizeof(char *)))
285 opt = "<unknown option>";
287 opt = options[(unsigned int)rr[*i + 1]];
289 proto_tree_add_text(telnet_tree, offset, 3, "Command: Do %s", opt);
290 *i += 2; /* skip two chars */
295 if (rr[*i + 1] > (sizeof(options)/sizeof(char *)))
296 opt = "<unknown option>";
298 opt = options[(unsigned int)rr[*i + 1]];
300 proto_tree_add_text(telnet_tree, offset, 3, "Command: Don't %s", opt);
301 *i += 2; /* skip two chars */
309 dissect_telnet(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
311 proto_tree *telnet_tree, *ti;
315 int max_data = pi.captured_len - offset;
317 memset(rr, '\0', sizeof(rr));
319 if (check_col(fd, COL_PROTOCOL))
320 col_add_str(fd, COL_PROTOCOL, "TELNET");
322 if (check_col(fd, COL_INFO)) {
324 col_add_fstr(fd, COL_INFO, "Telnet Data ...");
333 memset(data, '\0', sizeof(data));
335 memcpy(rr, pd + offset, max_data);
337 ti = proto_tree_add_item(tree, proto_telnet, offset, END_OF_FRAME, NULL);
338 telnet_tree = proto_item_add_subtree(ti, ett_telnet);
342 while (i1 < max_data) {
344 if ((unsigned char)rr[i1] == (unsigned char)TN_IAC) {
346 if (strlen(data) > 0) {
348 proto_tree_add_text(telnet_tree, offset + i2, strlen(data), "Data: %s", format_text(data, strlen(data)));
349 memset(data, '\0', sizeof(data));
355 telnet_command(telnet_tree, rr, &i1, offset + i1 - 1, max_data);
369 if (strlen(data) > 0) { /* Still some data to add */
371 proto_tree_add_text(telnet_tree, offset + i2, strlen(data), "Data: %s", format_text(data, strlen(data)));
380 proto_register_telnet(void)
382 /* static hf_register_info hf[] = {
384 { "Name", "telnet.abbreviation", TYPE, VALS_POINTER }},
386 static gint *ett[] = {
391 proto_telnet = proto_register_protocol("Telnet", "telnet");
392 /* proto_register_field_array(proto_telnet, hf, array_length(hf));*/
393 proto_register_subtree_array(ett, array_length(ett));