2000-04-08 03:32:10 +00:00
|
|
|
/* packet-rlogin.c
|
|
|
|
* Routines for unix rlogin packet dissection
|
|
|
|
* Copyright 2000, Jeffrey C. Foster <jfoste@woodward.com>
|
|
|
|
*
|
2002-08-28 21:04:11 +00:00
|
|
|
* $Id: packet-rlogin.c,v 1.28 2002/08/28 21:00:29 jmayer Exp $
|
2000-04-08 03:32:10 +00:00
|
|
|
*
|
|
|
|
* Ethereal - Network traffic analyzer
|
2001-06-08 08:41:03 +00:00
|
|
|
* By Gerald Combs <gerald@ethereal.com>
|
2000-04-08 03:32:10 +00:00
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
|
|
|
* Based upon RFC-1282 - BSD Rlogin
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
2000-04-08 03:32:10 +00:00
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
2000-04-08 03:32:10 +00:00
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
2002-08-28 21:04:11 +00:00
|
|
|
*
|
2000-04-08 03:32:10 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <glib.h>
|
2000-08-11 13:37:21 +00:00
|
|
|
|
2002-01-21 07:37:49 +00:00
|
|
|
#include <epan/packet.h>
|
|
|
|
#include <epan/conversation.h>
|
2000-04-08 03:32:10 +00:00
|
|
|
|
|
|
|
#include "packet-tcp.h"
|
|
|
|
|
|
|
|
#define TCP_PORT_RLOGIN 513
|
|
|
|
|
|
|
|
static int proto_rlogin = -1;
|
|
|
|
|
|
|
|
static int ett_rlogin = -1;
|
|
|
|
static int ett_rlogin_window = -1;
|
|
|
|
static int ett_rlogin_user_info = -1;
|
|
|
|
static int ett_rlogin_window_rows = -1;
|
|
|
|
static int ett_rlogin_window_cols = -1;
|
|
|
|
static int ett_rlogin_window_x_pixels = -1;
|
|
|
|
static int ett_rlogin_window_y_pixels = -1;
|
|
|
|
|
|
|
|
static int hf_user_info = -1;
|
|
|
|
static int hf_window_info = -1;
|
|
|
|
static int hf_window_info_rows = -1;
|
|
|
|
static int hf_window_info_cols = -1;
|
|
|
|
static int hf_window_info_x_pixels = -1;
|
|
|
|
static int hf_window_info_y_pixels = -1;
|
|
|
|
|
|
|
|
#define RLOGIN_PORT 513
|
|
|
|
|
|
|
|
#define NAME_LEN 32
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
int state;
|
2001-07-03 00:40:48 +00:00
|
|
|
guint32 info_framenum;
|
2000-04-08 03:32:10 +00:00
|
|
|
char name[ NAME_LEN];
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
} rlogin_hash_entry_t;
|
2000-04-08 03:32:10 +00:00
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
#define NONE 0
|
|
|
|
#define USER_INFO_WAIT 1
|
|
|
|
#define DONE 2
|
|
|
|
#define BAD 2
|
2000-04-08 03:32:10 +00:00
|
|
|
|
|
|
|
static GMemChunk *rlogin_vals = NULL;
|
|
|
|
|
|
|
|
#define rlogin_hash_init_count 20
|
|
|
|
|
|
|
|
static guint32 last_abs_sec = 0;
|
|
|
|
static guint32 last_abs_usec= 0;
|
|
|
|
|
|
|
|
static void
|
2001-07-03 00:40:48 +00:00
|
|
|
rlogin_init(void)
|
|
|
|
{
|
2000-04-08 03:32:10 +00:00
|
|
|
|
|
|
|
/* Routine to initialize rlogin protocol before each capture or filter pass. */
|
|
|
|
/* Release any memory if needed. Then setup the memory chunks. */
|
|
|
|
|
|
|
|
last_abs_sec = 0;
|
|
|
|
last_abs_usec= 0;
|
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
if (rlogin_vals)
|
|
|
|
g_mem_chunk_destroy(rlogin_vals);
|
2000-04-08 03:32:10 +00:00
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
rlogin_vals = g_mem_chunk_new("rlogin_vals",
|
|
|
|
sizeof( rlogin_hash_entry_t),
|
2000-04-08 03:32:10 +00:00
|
|
|
rlogin_hash_init_count * sizeof( rlogin_hash_entry_t),
|
|
|
|
G_ALLOC_AND_FREE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**************** Decoder State Machine ******************/
|
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
static void
|
2001-07-03 00:40:48 +00:00
|
|
|
rlogin_state_machine( rlogin_hash_entry_t *hash_info, tvbuff_t *tvb,
|
|
|
|
packet_info *pinfo)
|
|
|
|
{
|
|
|
|
guint length;
|
|
|
|
gint stringlen;
|
2000-04-08 03:32:10 +00:00
|
|
|
|
|
|
|
/* rlogin stream decoder */
|
|
|
|
/* Just watched for second packet from client with the user name and */
|
|
|
|
/* terminal type information. */
|
|
|
|
|
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
if ( pinfo->destport != RLOGIN_PORT) /* not from client */
|
2000-04-08 03:32:10 +00:00
|
|
|
return;
|
|
|
|
/* exit if not needed */
|
|
|
|
if (( hash_info->state == DONE) || ( hash_info->state == BAD))
|
|
|
|
return;
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2000-04-08 03:32:10 +00:00
|
|
|
/* test timestamp */
|
2002-08-28 21:04:11 +00:00
|
|
|
if (( last_abs_sec > pinfo->fd->abs_secs) ||
|
2001-07-03 00:40:48 +00:00
|
|
|
(( last_abs_sec == pinfo->fd->abs_secs) &&
|
|
|
|
( last_abs_usec >= pinfo->fd->abs_usecs)))
|
2000-04-08 03:32:10 +00:00
|
|
|
return;
|
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
last_abs_sec = pinfo->fd->abs_secs; /* save timestamp */
|
|
|
|
last_abs_usec = pinfo->fd->abs_usecs;
|
2000-04-08 03:32:10 +00:00
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
length = tvb_length(tvb);
|
|
|
|
if ( length == 0) /* exit if no data */
|
2002-08-28 21:04:11 +00:00
|
|
|
return;
|
2000-04-08 03:32:10 +00:00
|
|
|
|
|
|
|
if ( hash_info->state == NONE){ /* new connection*/
|
2001-07-03 00:40:48 +00:00
|
|
|
if (tvb_get_guint8(tvb, 0) != '\0') {
|
|
|
|
/*
|
|
|
|
* We expected a NUL, but didn't get one; quit.
|
|
|
|
*/
|
|
|
|
hash_info->state = DONE;
|
2000-04-08 03:32:10 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
2001-07-03 00:40:48 +00:00
|
|
|
if (length <= 1) /* if no data */
|
2000-04-08 03:32:10 +00:00
|
|
|
hash_info->state = USER_INFO_WAIT;
|
|
|
|
else {
|
2001-07-03 00:40:48 +00:00
|
|
|
hash_info->state = DONE;
|
|
|
|
hash_info->info_framenum = pinfo->fd->num;
|
2002-08-28 21:04:11 +00:00
|
|
|
}
|
2000-04-08 03:32:10 +00:00
|
|
|
}
|
|
|
|
} /* expect user data here */
|
2002-08-28 21:04:11 +00:00
|
|
|
/*$$$ may need to do more checking here */
|
2000-04-08 03:32:10 +00:00
|
|
|
else if ( hash_info->state == USER_INFO_WAIT) {
|
2002-08-28 21:04:11 +00:00
|
|
|
hash_info->state = DONE;
|
2001-07-03 00:40:48 +00:00
|
|
|
hash_info->info_framenum = pinfo->fd->num;
|
2000-04-08 03:32:10 +00:00
|
|
|
/* save name for later*/
|
2001-07-03 00:40:48 +00:00
|
|
|
stringlen = tvb_strnlen(tvb, 0, NAME_LEN);
|
|
|
|
if (stringlen == -1)
|
|
|
|
stringlen = NAME_LEN - 1; /* no '\0' found */
|
|
|
|
else if (stringlen > NAME_LEN - 1)
|
|
|
|
stringlen = NAME_LEN - 1; /* name too long */
|
|
|
|
tvb_memcpy(tvb, (guint8 *)hash_info->name, 0, stringlen);
|
|
|
|
hash_info->name[stringlen] = '\0';
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO)) /* update summary */
|
|
|
|
col_append_str(pinfo->cinfo, COL_INFO,
|
2001-07-03 00:40:48 +00:00
|
|
|
", User information");
|
2002-08-28 21:04:11 +00:00
|
|
|
}
|
2000-04-08 03:32:10 +00:00
|
|
|
}
|
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
static void rlogin_display( rlogin_hash_entry_t *hash_info, tvbuff_t *tvb,
|
2001-09-30 23:14:43 +00:00
|
|
|
packet_info *pinfo, proto_tree *tree, struct tcpinfo *tcpinfo)
|
2001-07-03 00:40:48 +00:00
|
|
|
{
|
2000-04-08 03:32:10 +00:00
|
|
|
/* Display the proto tree */
|
2001-07-03 00:40:48 +00:00
|
|
|
int offset = 0;
|
2000-04-08 03:32:10 +00:00
|
|
|
proto_tree *rlogin_tree, *user_info_tree, *window_tree;
|
|
|
|
proto_item *ti;
|
2001-07-03 00:40:48 +00:00
|
|
|
guint length;
|
|
|
|
int str_len;
|
|
|
|
gint ti_offset;
|
2000-04-08 03:32:10 +00:00
|
|
|
proto_item *user_info_item, *window_info_item;
|
|
|
|
|
2002-01-24 09:20:54 +00:00
|
|
|
ti = proto_tree_add_item( tree, proto_rlogin, tvb, 0, -1, FALSE);
|
2000-04-08 03:32:10 +00:00
|
|
|
|
|
|
|
rlogin_tree = proto_item_add_subtree(ti, ett_rlogin);
|
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
length = tvb_length(tvb);
|
|
|
|
if ( length == 0) /* exit if no captured data */
|
2000-04-08 03:32:10 +00:00
|
|
|
return;
|
|
|
|
|
Have a flag in the "packet_info" structure, which indicates whether the
stuff currently being dissected is part of a packet included in an error
packet (e.g., an ICMP Unreachable packet). Have the TCP dissector not
bother doing reassembly if the TCP segment is part of an error packet,
rather than an actual TCP transmission; other dissectors might want to
treat those packets specially as well.
Add to the "tcpinfo" structure a flag indicating whether the URG flag
was set, rather than having the zero or non-zero value of the urgent
pointer indicate that. (Yes, at least as I read RFC 793, a zero urgent
pointer value isn't useful, as it means "the stuff before this segment
is urgent", but it's certainly possible to put onto the wire a TCP
segment with URG set and a zero urgent pointer.)
Don't dissect the TCP header by grabbing the entire header with
"tvb_memcpy()" and then pulling stuff out of it - extract stuff with
individual tvbuff calls, and put stuff into the protocol tree and the
Info column as we extract it, so that we can dissect a partial header.
This lets us, for example, get the source and destination ports from the
TCP header of the part of a TCP segment included in a minimum-length
ICMPv4 error packet.
svn path=/trunk/; revision=3986
2001-10-01 08:29:37 +00:00
|
|
|
/*
|
|
|
|
* XXX - this works only if the urgent pointer points to something
|
|
|
|
* in this segment; to make it work if the urgent pointer points
|
|
|
|
* to something past this segment, we'd have to remember the urgent
|
|
|
|
* pointer setting for this conversation.
|
|
|
|
*/
|
|
|
|
if ( tcpinfo->urgent && /* if urgent pointer set */
|
2001-09-30 23:14:43 +00:00
|
|
|
length >= tcpinfo->urgent_pointer) { /* and it's in this frame */
|
2000-04-08 03:32:10 +00:00
|
|
|
|
2001-09-30 23:14:43 +00:00
|
|
|
int urgent_offset = tcpinfo->urgent_pointer - 1;
|
2001-07-03 00:40:48 +00:00
|
|
|
guint8 Temp = tvb_get_guint8(tvb, urgent_offset);
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
if (urgent_offset > offset) /* check for data in front */
|
|
|
|
proto_tree_add_text( rlogin_tree, tvb, offset,
|
|
|
|
urgent_offset, "Data");
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
proto_tree_add_text( rlogin_tree, tvb, urgent_offset, 1,
|
|
|
|
"Control byte: %u (%s)",
|
|
|
|
Temp,
|
|
|
|
(Temp == 0x02) ? "Clear buffer" :
|
2000-04-08 03:32:10 +00:00
|
|
|
(Temp == 0x10) ? "Raw mode" :
|
|
|
|
(Temp == 0x20) ? "Cooked mode" :
|
|
|
|
(Temp == 0x80) ? "Window size request" :
|
|
|
|
"Unknown");
|
2001-07-03 00:40:48 +00:00
|
|
|
offset = urgent_offset + 1; /* adjust offset */
|
|
|
|
}
|
|
|
|
else if ( tvb_get_guint8(tvb, offset) == '\0'){ /* startup */
|
|
|
|
if ( pinfo->srcport== RLOGIN_PORT) /* from server */
|
|
|
|
proto_tree_add_text(rlogin_tree, tvb, offset, 1,
|
2000-04-08 03:32:10 +00:00
|
|
|
"Startup info received flag (0x00)");
|
2002-08-28 21:04:11 +00:00
|
|
|
|
|
|
|
else
|
2001-07-03 00:40:48 +00:00
|
|
|
proto_tree_add_text(rlogin_tree, tvb, offset, 1,
|
2000-04-08 03:32:10 +00:00
|
|
|
"Client Startup Flag (0x00)");
|
|
|
|
++offset;
|
|
|
|
}
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
if (!tvb_offset_exists(tvb, offset))
|
|
|
|
return; /* No more data to check */
|
|
|
|
|
|
|
|
if ( hash_info->info_framenum == pinfo->fd->num){
|
|
|
|
/*
|
|
|
|
* First frame of conversation, hence user info?
|
|
|
|
*/
|
|
|
|
user_info_item = proto_tree_add_item( rlogin_tree, hf_user_info, tvb,
|
2002-01-24 09:20:54 +00:00
|
|
|
offset, -1, FALSE);
|
2001-07-03 00:40:48 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Do server user name.
|
|
|
|
*/
|
|
|
|
str_len = tvb_strsize(tvb, offset);
|
2000-04-08 03:32:10 +00:00
|
|
|
user_info_tree = proto_item_add_subtree( user_info_item,
|
|
|
|
ett_rlogin_user_info);
|
2001-07-03 00:40:48 +00:00
|
|
|
proto_tree_add_text(user_info_tree, tvb, offset, str_len,
|
2001-07-03 00:49:57 +00:00
|
|
|
"Server User Name: %.*s", str_len - 1,
|
2001-07-03 00:40:48 +00:00
|
|
|
tvb_get_ptr(tvb, offset, str_len - 1));
|
2000-08-06 08:53:44 +00:00
|
|
|
offset += str_len;
|
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
/*
|
|
|
|
* Do client user name.
|
|
|
|
*/
|
|
|
|
str_len = tvb_strsize(tvb, offset);
|
|
|
|
proto_tree_add_text(user_info_tree, tvb, offset, str_len,
|
2001-07-03 00:49:57 +00:00
|
|
|
"Client User Name: %.*s", str_len - 1,
|
2001-07-03 00:40:48 +00:00
|
|
|
tvb_get_ptr(tvb, offset, str_len - 1));
|
2000-08-06 08:53:44 +00:00
|
|
|
offset += str_len;
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
/*
|
|
|
|
* Do terminal type/speed.
|
|
|
|
*/
|
|
|
|
str_len = tvb_strsize(tvb, offset);
|
|
|
|
proto_tree_add_text(user_info_tree, tvb, offset, str_len,
|
2001-07-03 00:49:57 +00:00
|
|
|
"Terminal Type/Speed: %.*s", str_len - 1,
|
2001-07-03 00:40:48 +00:00
|
|
|
tvb_get_ptr(tvb, offset, str_len - 1));
|
2000-08-06 08:53:44 +00:00
|
|
|
offset += str_len;
|
2001-07-03 00:40:48 +00:00
|
|
|
}
|
2000-08-06 08:53:44 +00:00
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
if (!tvb_offset_exists(tvb, offset))
|
|
|
|
return; /* No more data to check */
|
2000-04-08 03:32:10 +00:00
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
/* test for terminal information, the data will have 2 0xff bytes */
|
2000-04-08 03:32:10 +00:00
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
/* look for first 0xff byte */
|
|
|
|
ti_offset = tvb_find_guint8(tvb, offset, -1, 0xff);
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
if (ti_offset != -1 &&
|
|
|
|
tvb_bytes_exist(tvb, ti_offset + 1, 1) &&
|
|
|
|
tvb_get_guint8(tvb, ti_offset + 1) == 0xff) {
|
|
|
|
/*
|
|
|
|
* Found terminal info.
|
|
|
|
*/
|
|
|
|
if (ti_offset > offset) {
|
|
|
|
/*
|
|
|
|
* There's data before the terminal info.
|
|
|
|
*/
|
|
|
|
proto_tree_add_text( rlogin_tree, tvb, offset,
|
2000-04-08 03:32:10 +00:00
|
|
|
(ti_offset - offset), "Data");
|
|
|
|
offset = ti_offset;
|
|
|
|
}
|
2001-07-03 00:40:48 +00:00
|
|
|
|
|
|
|
window_info_item = proto_tree_add_item(rlogin_tree,
|
|
|
|
hf_window_info, tvb, offset, 12, FALSE );
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
window_tree = proto_item_add_subtree(window_info_item,
|
2000-04-08 03:32:10 +00:00
|
|
|
ett_rlogin_window);
|
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
proto_tree_add_text(window_tree, tvb, offset, 2,
|
2001-07-03 00:49:57 +00:00
|
|
|
"Magic Cookie: (0xff, 0xff)");
|
2000-04-08 03:32:10 +00:00
|
|
|
offset += 2;
|
2002-08-28 21:04:11 +00:00
|
|
|
|
|
|
|
proto_tree_add_text(window_tree, tvb, offset, 2,
|
2001-07-03 00:49:57 +00:00
|
|
|
"Window size marker: 'ss'");
|
2000-04-08 03:32:10 +00:00
|
|
|
offset += 2;
|
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
proto_tree_add_item(window_tree, hf_window_info_rows, tvb,
|
|
|
|
offset, 2, FALSE);
|
2000-04-08 03:32:10 +00:00
|
|
|
offset += 2;
|
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
proto_tree_add_item(window_tree, hf_window_info_cols, tvb,
|
|
|
|
offset, 2, FALSE);
|
2000-04-08 03:32:10 +00:00
|
|
|
offset += 2;
|
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
proto_tree_add_item(window_tree, hf_window_info_x_pixels, tvb,
|
|
|
|
offset, 2, FALSE);
|
2000-04-08 03:32:10 +00:00
|
|
|
offset += 2;
|
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
proto_tree_add_item(window_tree, hf_window_info_y_pixels, tvb,
|
|
|
|
offset, 2, FALSE);
|
2000-04-08 03:32:10 +00:00
|
|
|
offset += 2;
|
|
|
|
}
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
if (tvb_offset_exists(tvb, offset)) {
|
|
|
|
/*
|
|
|
|
* There's more data in the frame.
|
|
|
|
*/
|
2002-01-24 09:20:54 +00:00
|
|
|
proto_tree_add_text(rlogin_tree, tvb, offset, -1, "Data");
|
2001-07-03 00:40:48 +00:00
|
|
|
}
|
2002-08-28 21:04:11 +00:00
|
|
|
}
|
2000-04-08 03:32:10 +00:00
|
|
|
|
|
|
|
static void
|
2001-07-03 00:40:48 +00:00
|
|
|
dissect_rlogin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
|
|
{
|
2001-11-03 00:58:52 +00:00
|
|
|
struct tcpinfo *tcpinfo = pinfo->private_data;
|
2000-04-08 03:32:10 +00:00
|
|
|
conversation_t *conversation;
|
2001-09-03 10:33:12 +00:00
|
|
|
rlogin_hash_entry_t *hash_info;
|
Have a flag in the "packet_info" structure, which indicates whether the
stuff currently being dissected is part of a packet included in an error
packet (e.g., an ICMP Unreachable packet). Have the TCP dissector not
bother doing reassembly if the TCP segment is part of an error packet,
rather than an actual TCP transmission; other dissectors might want to
treat those packets specially as well.
Add to the "tcpinfo" structure a flag indicating whether the URG flag
was set, rather than having the zero or non-zero value of the urgent
pointer indicate that. (Yes, at least as I read RFC 793, a zero urgent
pointer value isn't useful, as it means "the stuff before this segment
is urgent", but it's certainly possible to put onto the wire a TCP
segment with URG set and a zero urgent pointer.)
Don't dissect the TCP header by grabbing the entire header with
"tvb_memcpy()" and then pulling stuff out of it - extract stuff with
individual tvbuff calls, and put stuff into the protocol tree and the
Info column as we extract it, so that we can dissect a partial header.
This lets us, for example, get the source and destination ports from the
TCP header of the part of a TCP segment included in a minimum-length
ICMPv4 error packet.
svn path=/trunk/; revision=3986
2001-10-01 08:29:37 +00:00
|
|
|
guint length;
|
2001-07-03 00:40:48 +00:00
|
|
|
gint ti_offset;
|
2000-04-08 03:32:10 +00:00
|
|
|
|
|
|
|
/* Lookup this connection*/
|
2001-07-03 00:40:48 +00:00
|
|
|
conversation = find_conversation( &pinfo->src, &pinfo->dst,
|
|
|
|
pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
|
2000-04-08 03:32:10 +00:00
|
|
|
|
2001-09-03 10:33:12 +00:00
|
|
|
if ( !conversation) {
|
|
|
|
conversation = conversation_new( &pinfo->src, &pinfo->dst,
|
|
|
|
pinfo->ptype, pinfo->srcport, pinfo->destport, 0);
|
|
|
|
}
|
|
|
|
hash_info = conversation_get_proto_data(conversation, proto_rlogin);
|
|
|
|
if ( !hash_info) {
|
2001-07-03 00:40:48 +00:00
|
|
|
hash_info = g_mem_chunk_alloc(rlogin_vals);
|
|
|
|
hash_info->state = NONE;
|
|
|
|
hash_info->info_framenum = 0; /* no frame has the number 0 */
|
2000-04-08 03:32:10 +00:00
|
|
|
hash_info->name[ 0] = 0;
|
2001-09-03 10:33:12 +00:00
|
|
|
conversation_add_proto_data(conversation, proto_rlogin,
|
|
|
|
hash_info);
|
2000-04-08 03:32:10 +00:00
|
|
|
}
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL)) /* update protocol */
|
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "Rlogin");
|
2000-04-08 03:32:10 +00:00
|
|
|
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO)){ /* display packet info*/
|
2000-04-08 03:32:10 +00:00
|
|
|
|
|
|
|
char temp[1000];
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-12-10 00:26:21 +00:00
|
|
|
col_clear(pinfo->cinfo, COL_INFO);
|
2000-04-08 03:32:10 +00:00
|
|
|
if ( hash_info->name[0]) {
|
|
|
|
strcpy( temp, "User name: ");
|
|
|
|
strcat( temp, hash_info->name);
|
|
|
|
strcat( temp, ", ");
|
|
|
|
}
|
2002-08-28 21:04:11 +00:00
|
|
|
else
|
2000-04-08 03:32:10 +00:00
|
|
|
temp[0] = 0;
|
2001-07-03 00:40:48 +00:00
|
|
|
|
Have a flag in the "packet_info" structure, which indicates whether the
stuff currently being dissected is part of a packet included in an error
packet (e.g., an ICMP Unreachable packet). Have the TCP dissector not
bother doing reassembly if the TCP segment is part of an error packet,
rather than an actual TCP transmission; other dissectors might want to
treat those packets specially as well.
Add to the "tcpinfo" structure a flag indicating whether the URG flag
was set, rather than having the zero or non-zero value of the urgent
pointer indicate that. (Yes, at least as I read RFC 793, a zero urgent
pointer value isn't useful, as it means "the stuff before this segment
is urgent", but it's certainly possible to put onto the wire a TCP
segment with URG set and a zero urgent pointer.)
Don't dissect the TCP header by grabbing the entire header with
"tvb_memcpy()" and then pulling stuff out of it - extract stuff with
individual tvbuff calls, and put stuff into the protocol tree and the
Info column as we extract it, so that we can dissect a partial header.
This lets us, for example, get the source and destination ports from the
TCP header of the part of a TCP segment included in a minimum-length
ICMPv4 error packet.
svn path=/trunk/; revision=3986
2001-10-01 08:29:37 +00:00
|
|
|
length = tvb_length(tvb);
|
|
|
|
if (length != 0) {
|
|
|
|
if ( tvb_get_guint8(tvb, 0) == '\0')
|
2002-08-28 21:04:11 +00:00
|
|
|
strcat( temp, "Start Handshake");
|
Have a flag in the "packet_info" structure, which indicates whether the
stuff currently being dissected is part of a packet included in an error
packet (e.g., an ICMP Unreachable packet). Have the TCP dissector not
bother doing reassembly if the TCP segment is part of an error packet,
rather than an actual TCP transmission; other dissectors might want to
treat those packets specially as well.
Add to the "tcpinfo" structure a flag indicating whether the URG flag
was set, rather than having the zero or non-zero value of the urgent
pointer indicate that. (Yes, at least as I read RFC 793, a zero urgent
pointer value isn't useful, as it means "the stuff before this segment
is urgent", but it's certainly possible to put onto the wire a TCP
segment with URG set and a zero urgent pointer.)
Don't dissect the TCP header by grabbing the entire header with
"tvb_memcpy()" and then pulling stuff out of it - extract stuff with
individual tvbuff calls, and put stuff into the protocol tree and the
Info column as we extract it, so that we can dissect a partial header.
This lets us, for example, get the source and destination ports from the
TCP header of the part of a TCP segment included in a minimum-length
ICMPv4 error packet.
svn path=/trunk/; revision=3986
2001-10-01 08:29:37 +00:00
|
|
|
else if ( tcpinfo->urgent &&
|
|
|
|
length >= tcpinfo->urgent_pointer )
|
2002-08-28 21:04:11 +00:00
|
|
|
strcat( temp, "Control Message");
|
Have a flag in the "packet_info" structure, which indicates whether the
stuff currently being dissected is part of a packet included in an error
packet (e.g., an ICMP Unreachable packet). Have the TCP dissector not
bother doing reassembly if the TCP segment is part of an error packet,
rather than an actual TCP transmission; other dissectors might want to
treat those packets specially as well.
Add to the "tcpinfo" structure a flag indicating whether the URG flag
was set, rather than having the zero or non-zero value of the urgent
pointer indicate that. (Yes, at least as I read RFC 793, a zero urgent
pointer value isn't useful, as it means "the stuff before this segment
is urgent", but it's certainly possible to put onto the wire a TCP
segment with URG set and a zero urgent pointer.)
Don't dissect the TCP header by grabbing the entire header with
"tvb_memcpy()" and then pulling stuff out of it - extract stuff with
individual tvbuff calls, and put stuff into the protocol tree and the
Info column as we extract it, so that we can dissect a partial header.
This lets us, for example, get the source and destination ports from the
TCP header of the part of a TCP segment included in a minimum-length
ICMPv4 error packet.
svn path=/trunk/; revision=3986
2001-10-01 08:29:37 +00:00
|
|
|
|
|
|
|
else { /* check for terminal info */
|
|
|
|
ti_offset = tvb_find_guint8(tvb, 0, -1, 0xff);
|
|
|
|
if (ti_offset != -1 &&
|
|
|
|
tvb_bytes_exist(tvb, ti_offset + 1, 1) &&
|
|
|
|
tvb_get_guint8(tvb, ti_offset + 1) == 0xff)
|
|
|
|
strcat( temp, "Terminal Info");
|
|
|
|
else {
|
|
|
|
int i;
|
|
|
|
int bytes_to_copy;
|
|
|
|
|
|
|
|
strcat( temp, "Data: ");
|
|
|
|
i = strlen( temp);
|
|
|
|
bytes_to_copy = tvb_length(tvb);
|
|
|
|
if (bytes_to_copy > 128)
|
|
|
|
bytes_to_copy = 128;
|
|
|
|
tvb_memcpy(tvb, (guint8 *)&temp[i], 0,
|
|
|
|
bytes_to_copy);
|
|
|
|
temp[i + bytes_to_copy] = '\0';
|
|
|
|
}
|
2000-04-08 03:32:10 +00:00
|
|
|
}
|
2002-08-28 21:04:11 +00:00
|
|
|
}
|
2000-04-08 03:32:10 +00:00
|
|
|
|
2001-12-10 00:26:21 +00:00
|
|
|
col_add_str(pinfo->cinfo, COL_INFO, temp);
|
2000-04-08 03:32:10 +00:00
|
|
|
}
|
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
rlogin_state_machine( hash_info, tvb, pinfo);
|
2000-04-08 03:32:10 +00:00
|
|
|
|
|
|
|
if ( tree) /* if proto tree, decode data */
|
2001-09-30 23:14:43 +00:00
|
|
|
rlogin_display( hash_info, tvb, pinfo, tree, tcpinfo);
|
2000-04-08 03:32:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_register_rlogin( void){
|
|
|
|
|
|
|
|
/* Prep the rlogin protocol, for now, just register it */
|
|
|
|
|
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_rlogin,
|
|
|
|
&ett_rlogin_window,
|
|
|
|
&ett_rlogin_window_rows,
|
|
|
|
&ett_rlogin_window_cols,
|
|
|
|
&ett_rlogin_window_x_pixels,
|
|
|
|
&ett_rlogin_window_y_pixels,
|
|
|
|
&ett_rlogin_user_info
|
|
|
|
};
|
2002-08-28 21:04:11 +00:00
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
static hf_register_info hf[] = {
|
|
|
|
|
|
|
|
{ &hf_user_info,
|
|
|
|
{ "User Info", "rlogin.user_info", FT_NONE, BASE_NONE,
|
|
|
|
NULL, 0x0, "", HFILL
|
|
|
|
}
|
2000-04-08 03:32:10 +00:00
|
|
|
},
|
2001-07-03 00:40:48 +00:00
|
|
|
{ &hf_window_info,
|
|
|
|
{ "Window Info", "rlogin.window_size", FT_NONE, BASE_NONE,
|
|
|
|
NULL, 0x0, "", HFILL
|
|
|
|
}
|
2000-04-08 03:32:10 +00:00
|
|
|
},
|
2001-07-03 00:40:48 +00:00
|
|
|
{ &hf_window_info_rows,
|
|
|
|
{ "Rows", "rlogin.window_size.rows", FT_UINT16, BASE_DEC,
|
|
|
|
NULL, 0x0, "", HFILL
|
|
|
|
}
|
2000-04-08 03:32:10 +00:00
|
|
|
},
|
2001-07-03 00:40:48 +00:00
|
|
|
{ &hf_window_info_cols,
|
|
|
|
{ "Columns", "rlogin.window_size.cols", FT_UINT16, BASE_DEC,
|
|
|
|
NULL, 0x0, "", HFILL
|
|
|
|
}
|
2000-04-08 03:32:10 +00:00
|
|
|
},
|
2001-07-03 00:40:48 +00:00
|
|
|
{ &hf_window_info_x_pixels,
|
|
|
|
{ "X Pixels", "rlogin.window_size.x_pixels", FT_UINT16, BASE_DEC,
|
|
|
|
NULL, 0x0, "", HFILL
|
|
|
|
}
|
2000-04-08 03:32:10 +00:00
|
|
|
},
|
2001-07-03 00:40:48 +00:00
|
|
|
{ &hf_window_info_y_pixels,
|
|
|
|
{ "Y Pixels", "rlogin.window_size.y_pixels", FT_UINT16, BASE_DEC,
|
|
|
|
NULL, 0x0, "", HFILL
|
|
|
|
}
|
2000-04-08 03:32:10 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2001-07-03 00:40:48 +00:00
|
|
|
proto_rlogin = proto_register_protocol (
|
|
|
|
"Rlogin Protocol", "Rlogin", "rlogin");
|
2000-04-08 03:32:10 +00:00
|
|
|
|
|
|
|
proto_register_field_array(proto_rlogin, hf, array_length(hf));
|
2002-08-28 21:04:11 +00:00
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
2000-04-08 03:32:10 +00:00
|
|
|
|
|
|
|
register_init_routine( &rlogin_init); /* register re-init routine */
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
proto_reg_handoff_rlogin(void) {
|
|
|
|
|
2002-08-28 21:04:11 +00:00
|
|
|
/* dissector install routine */
|
|
|
|
|
2001-12-03 04:00:26 +00:00
|
|
|
dissector_handle_t rlogin_handle;
|
|
|
|
|
|
|
|
rlogin_handle = create_dissector_handle(dissect_rlogin, proto_rlogin);
|
|
|
|
dissector_add("tcp.port", TCP_PORT_RLOGIN, rlogin_handle);
|
2000-04-08 03:32:10 +00:00
|
|
|
}
|