2 * Routines for telnet packet dissection
3 * Copyright 1999, Richard Sharpe <rsharpe@ns.aus.com>
5 * $Id: packet-telnet.c,v 1.2 1999/04/05 23:39:51 guy 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>
47 /* Some defines for Telnet */
71 "Binary Transmission",
75 "Approx Message Size Negotiation",
78 "Remote Controlled Trans and Echo",
81 "Output Carriage-Return Disposition",
82 "Output Horizontal Tab Stops",
83 "Output Horizontal Tab Disposition",
84 "Output Formfeed Disposition",
85 "Output Vertical Tabstops",
86 "Output Vertical Tab Disposition",
87 "Output Linefeed Disposition",
91 "Data Entry Terminal",
97 "TACACS User Identification",
99 "Terminal Location Number",
100 "Telnet 3270 Regime",
102 "Negotiate About Window Size",
104 "Remote Flow Control",
106 "X Display Location",
107 "Environment Option",
108 "Authentication Option",
110 "New Environment Option",
114 extern packet_info pi;
116 void telnet_sub_option(proto_tree *telnet_tree, char *rr, int *i, int offset, int max_data)
118 proto_tree *ti, *option_tree;
119 int subneg_len, req, si1, not_found = 1;
121 char *opt, sub_opt_data[1500];
123 memset(sub_opt_data, '\0', sizeof(sub_opt_data));
125 /* Figure out the option and type */
127 opt = options[(unsigned int)rr[*i]];
128 req = (unsigned int)rr[*i + 1];
130 i1 = *i + 2; si1 = i1;
131 while ((i1 < max_data) && (not_found)) {
133 if ((unsigned char)rr[i1] == (unsigned char)TN_IAC)
140 subneg_len = i1 - *i + 2;
142 ti = proto_tree_add_item(telnet_tree, offset, subneg_len, "Suboption Begin: %s", opt);
144 option_tree = proto_tree_new();
146 proto_item_add_subtree(ti, option_tree, ETT_TELNET_SUBOPT);
148 proto_tree_add_item(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_item(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_item(telnet_tree, offset, 2, "Command: End of File");
178 proto_tree_add_item(telnet_tree, offset, 2, "Command: Suspend Current Process");
184 proto_tree_add_item(telnet_tree, offset, 2, "Command: Abort Process");
190 proto_tree_add_item(telnet_tree, offset, 2, "Command: End of Record");
196 proto_tree_add_item(telnet_tree, offset, 2, "Command: Suboption End");
202 proto_tree_add_item(telnet_tree, offset, 2, "Command: No Operation");
208 proto_tree_add_item(telnet_tree, offset, 2, "Command: Data Mark");
214 proto_tree_add_item(telnet_tree, offset, 2, "Command: Break");
220 proto_tree_add_item(telnet_tree, offset, 2, "Command: Interrupt Process");
226 proto_tree_add_item(telnet_tree, offset, 2, "Command: Abort Output");
232 proto_tree_add_item(telnet_tree, offset, 2, "Command: Are You There?");
238 proto_tree_add_item(telnet_tree, offset, 2, "Command: Escape Character");
244 proto_tree_add_item(telnet_tree, offset, 2, "Command: Erase Line");
250 proto_tree_add_item(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_item(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_item(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_item(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_item(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, int max_data)
311 proto_tree *telnet_tree, *ti;
316 memset(rr, '\0', sizeof(rr));
318 if (check_col(fd, COL_PROTOCOL))
319 col_add_str(fd, COL_PROTOCOL, "TELNET");
321 if (check_col(fd, COL_INFO)) {
323 col_add_fstr(fd, COL_INFO, "Telnet Data ...");
332 memset(data, '\0', sizeof(data));
334 memcpy(rr, pd + offset, max_data);
336 ti = proto_tree_add_item(tree, offset, END_OF_FRAME,
338 telnet_tree = proto_tree_new();
339 proto_item_add_subtree(ti, telnet_tree, ETT_TELNET);
343 while (i1 < max_data) {
345 if ((unsigned char)rr[i1] == (unsigned char)TN_IAC) {
347 if (strlen(data) > 0) {
349 proto_tree_add_item(telnet_tree, offset + i2, strlen(data), "Data: %s", format_text(data, strlen(data)));
350 memset(data, '\0', sizeof(data));
356 telnet_command(telnet_tree, rr, &i1, offset + i1 - 1, max_data);
370 if (strlen(data) > 0) { /* Still some data to add */
372 proto_tree_add_item(telnet_tree, offset + i2, strlen(data), "Data: %s", format_text(data, strlen(data)));