2 * Routines for telnet packet dissection
3 * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
5 * $Id: packet-telnet.c,v 1.6 1999/08/24 17:26:15 gram Exp $
7 * Ethereal - Network traffic analyzer
8 * By Gerald Combs <gerald@unicom.net>
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 /* Some defines for Telnet */
72 "Binary Transmission",
76 "Approx Message Size Negotiation",
79 "Remote Controlled Trans and Echo",
82 "Output Carriage-Return Disposition",
83 "Output Horizontal Tab Stops",
84 "Output Horizontal Tab Disposition",
85 "Output Formfeed Disposition",
86 "Output Vertical Tabstops",
87 "Output Vertical Tab Disposition",
88 "Output Linefeed Disposition",
92 "Data Entry Terminal",
98 "TACACS User Identification",
100 "Terminal Location Number",
101 "Telnet 3270 Regime",
103 "Negotiate About Window Size",
105 "Remote Flow Control",
107 "X Display Location",
108 "Environment Option",
109 "Authentication Option",
111 "New Environment Option",
115 void telnet_sub_option(proto_tree *telnet_tree, char *rr, int *i, int offset, int max_data)
117 proto_tree *ti, *option_tree;
118 int subneg_len, req, si1, not_found = 1;
120 char *opt, sub_opt_data[1500];
122 memset(sub_opt_data, '\0', sizeof(sub_opt_data));
124 /* Figure out the option and type */
126 opt = options[(unsigned int)rr[*i]];
127 req = (unsigned int)rr[*i + 1];
129 i1 = *i + 2; si1 = i1;
130 while ((i1 < max_data) && (not_found)) {
132 if ((unsigned char)rr[i1] == (unsigned char)TN_IAC)
139 subneg_len = i1 - *i + 2;
141 ti = proto_tree_add_text(telnet_tree, offset, subneg_len, "Suboption Begin: %s", opt);
143 option_tree = proto_item_add_subtree(ti, ETT_TELNET_SUBOPT);
145 proto_tree_add_text(option_tree, offset + 2, subneg_len - 2, "%s %s", (req ? "Send your" : "Here's my"), opt);
147 if (req == 0) { /* Add the value */
149 memcpy(sub_opt_data, rr + *i + 2, subneg_len - 2);
150 proto_tree_add_text(option_tree, offset + 4, subneg_len - 4, "Value: %s", format_text(sub_opt_data, subneg_len - 4));
151 *i += subneg_len - 2;
156 *i += subneg_len - 2;
161 void telnet_command(proto_tree *telnet_tree, char *rr, int *i, int offset, int max_data)
165 switch((unsigned char)rr[*i]) {
169 proto_tree_add_text(telnet_tree, offset, 2, "Command: End of File");
175 proto_tree_add_text(telnet_tree, offset, 2, "Command: Suspend Current Process");
181 proto_tree_add_text(telnet_tree, offset, 2, "Command: Abort Process");
187 proto_tree_add_text(telnet_tree, offset, 2, "Command: End of Record");
193 proto_tree_add_text(telnet_tree, offset, 2, "Command: Suboption End");
199 proto_tree_add_text(telnet_tree, offset, 2, "Command: No Operation");
205 proto_tree_add_text(telnet_tree, offset, 2, "Command: Data Mark");
211 proto_tree_add_text(telnet_tree, offset, 2, "Command: Break");
217 proto_tree_add_text(telnet_tree, offset, 2, "Command: Interrupt Process");
223 proto_tree_add_text(telnet_tree, offset, 2, "Command: Abort Output");
229 proto_tree_add_text(telnet_tree, offset, 2, "Command: Are You There?");
235 proto_tree_add_text(telnet_tree, offset, 2, "Command: Escape Character");
241 proto_tree_add_text(telnet_tree, offset, 2, "Command: Erase Line");
247 proto_tree_add_text(telnet_tree, offset, 2, "Command: Go Ahead");
254 telnet_sub_option(telnet_tree, rr, i, offset, max_data);
259 if (rr[*i + 1] > (sizeof(options)/sizeof(char *)))
260 opt = "<unknown option>";
262 opt = options[(unsigned int)rr[*i + 1]];
264 proto_tree_add_text(telnet_tree, offset, 3, "Command: Will %s", opt);
265 *i += 2; /* skip two chars */
270 if (rr[*i + 1] > (sizeof(options)/sizeof(char *)))
271 opt = "<unknown option>";
273 opt = options[(unsigned int)rr[*i + 1]];
275 proto_tree_add_text(telnet_tree, offset, 3, "Command: Won't %s", opt);
276 *i += 2; /* skip two chars */
281 if (rr[*i + 1] > (sizeof(options)/sizeof(char *)))
282 opt = "<unknown option>";
284 opt = options[(unsigned int)rr[*i + 1]];
286 proto_tree_add_text(telnet_tree, offset, 3, "Command: Do %s", opt);
287 *i += 2; /* skip two chars */
292 if (rr[*i + 1] > (sizeof(options)/sizeof(char *)))
293 opt = "<unknown option>";
295 opt = options[(unsigned int)rr[*i + 1]];
297 proto_tree_add_text(telnet_tree, offset, 3, "Command: Don't %s", opt);
298 *i += 2; /* skip two chars */
306 dissect_telnet(const u_char *pd, int offset, frame_data *fd, proto_tree *tree)
308 proto_tree *telnet_tree, *ti;
312 int max_data = pi.captured_len - offset;
314 memset(rr, '\0', sizeof(rr));
316 if (check_col(fd, COL_PROTOCOL))
317 col_add_str(fd, COL_PROTOCOL, "TELNET");
319 if (check_col(fd, COL_INFO)) {
321 col_add_fstr(fd, COL_INFO, "Telnet Data ...");
330 memset(data, '\0', sizeof(data));
332 memcpy(rr, pd + offset, max_data);
334 ti = proto_tree_add_item(tree, proto_telnet, offset, END_OF_FRAME, NULL);
335 telnet_tree = proto_item_add_subtree(ti, ETT_TELNET);
339 while (i1 < max_data) {
341 if ((unsigned char)rr[i1] == (unsigned char)TN_IAC) {
343 if (strlen(data) > 0) {
345 proto_tree_add_text(telnet_tree, offset + i2, strlen(data), "Data: %s", format_text(data, strlen(data)));
346 memset(data, '\0', sizeof(data));
352 telnet_command(telnet_tree, rr, &i1, offset + i1 - 1, max_data);
366 if (strlen(data) > 0) { /* Still some data to add */
368 proto_tree_add_text(telnet_tree, offset + i2, strlen(data), "Data: %s", format_text(data, strlen(data)));
377 proto_register_telnet(void)
379 /* static hf_register_info hf[] = {
381 { "Name", "telnet.abbreviation", TYPE, VALS_POINTER }},
384 proto_telnet = proto_register_protocol("Telnet", "telnet");
385 /* proto_register_field_array(proto_telnet, hf, array_length(hf));*/