/* packet-smtp.c * Routines for SMTP packet disassembly * * $Id: packet-smtp.c,v 1.3 2000/08/20 15:25:17 deniel Exp $ * * Copyright (c) 2000 by Richard Sharpe * * Ethereal - Network traffic analyzer * By Gerald Combs * Copyright 1999 Gerald Combs * 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. * * 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. * * 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 #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_NETINET_IN_H #include #endif #include #include #include #include #include #include #include "packet.h" #include "resolv.h" #include "prefs.h" #define TCP_PORT_SMTP 25 void proto_reg_handoff_smtp(void); static int proto_smtp = -1; static int hf_smtp_req = -1; static int hf_smtp_rsp = -1; static int ett_smtp = -1; static int global_smtp_tcp_port = TCP_PORT_SMTP; static int find_smtp_resp_end(const u_char *pd, int offset) { int cntr = 0; /* Look for the CRLF ... but keep in mind the END_OF_FRAME */ while (END_OF_FRAME >= cntr) { if (pd[offset + cntr] == 0x0A) { /* Found it */ if (END_OF_FRAME >= cntr + 1) cntr++; return cntr; } cntr++; } return cntr; } #if 0 static void dissect_smtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { #else static void dissect_smtp(const u_char *pd, int offset, frame_data *fd, proto_tree *tree) { /* tvbuff_t *tvb = tvb_create_from_top(offset);*/ packet_info *pinfo = π #endif void *frame_data; proto_tree *smtp_tree, *ti; int request = 0; const u_char *cmd = NULL, *data = NULL; #if 0 CHECK_DISPLAY_AS_DATA(proto_smtp, tvb, pinfo, tree); #else OLD_CHECK_DISPLAY_AS_DATA(proto_smtp, pd, offset, fd, tree); #endif /* Let's figure out this packet ... First check if we have done it all before ... */ frame_data = p_get_proto_data(pinfo->fd, proto_smtp); /* SMTP messages have a simple format ... */ if (!frame_data) { /* We parse the frame and create the data */ request = pinfo -> destport == TCP_PORT_SMTP; cmd = pd + offset; /* FIXME: What about tvb */ data = strchr(cmd, ' '); /* Find the space */ if (data) data++; /* Skip the space if there */ } else { } if (check_col(fd, COL_PROTOCOL)) col_add_str(fd, COL_PROTOCOL, "SMTP"); if (check_col(fd, COL_INFO)) { /* Add the appropriate type here */ col_add_fstr(fd, COL_INFO, "%s", format_text(cmd, END_OF_FRAME)); } if (tree) { /* Build the tree info ... */ ti = proto_tree_add_item(tree, proto_smtp, NullTVB, offset, END_OF_FRAME, FALSE); smtp_tree = proto_item_add_subtree(ti, ett_smtp); proto_tree_add_boolean_hidden(smtp_tree, (request ? hf_smtp_req : hf_smtp_rsp), NullTVB, offset, 4, TRUE); if (request) { proto_tree_add_protocol_format(smtp_tree, proto_smtp, NullTVB, offset, 4, "Command: %s", format_text(cmd, 4)); proto_tree_add_protocol_format(smtp_tree, proto_smtp, NullTVB, offset + 5, END_OF_FRAME, "Parameter: %s", format_text(cmd + 5, END_OF_FRAME - 5)); } else { /* Must consider a multi-line response here ... */ while (END_OF_FRAME >= 4 && pd[offset + 3] == '-') { int resp_len = find_smtp_resp_end(pd, offset); proto_tree_add_protocol_format(smtp_tree, proto_smtp, NullTVB, offset, 3, "Response: %s", format_text(pd + offset, 3)); proto_tree_add_protocol_format(smtp_tree, proto_smtp, NullTVB, offset + 4, resp_len, "Parameter: %s", format_text(pd + offset + 4, resp_len - 4)); offset += resp_len; } proto_tree_add_protocol_format(smtp_tree, proto_smtp, NullTVB, offset, 3, "Response: %s", format_text(pd + offset, 3)); proto_tree_add_protocol_format(smtp_tree, proto_smtp, NullTVB, offset + 4, END_OF_FRAME, "Parameter: %s", format_text(pd + offset + 4, END_OF_FRAME - 4)); } } } /* Register all the bits needed by the filtering engine */ void proto_register_smtp(void) { static hf_register_info hf[] = { { &hf_smtp_req, { "Request", "smtp.req", FT_BOOLEAN, BASE_NONE, NULL, 0x0, ""}}, { &hf_smtp_rsp, { "Response", "smtp.rsp", FT_BOOLEAN, BASE_NONE, NULL, 0x0, ""}}, }; static gint *ett[] = { &ett_smtp }; /*module_t *smtp_module = NULL; */ /* Not yet used */ /* No Configuration options to register? */ proto_smtp = proto_register_protocol("Simple Mail Transfer Protocol", "smtp"); proto_register_field_array(proto_smtp, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); } /* The registration hand-off routine */ void proto_reg_handoff_smtp(void) { static int smtp_prefs_initialized = FALSE; static int tcp_port = 0; if (smtp_prefs_initialized) { old_dissector_delete("tcp.port", tcp_port, dissect_smtp); } else { smtp_prefs_initialized = TRUE; } tcp_port = global_smtp_tcp_port; old_dissector_add("tcp.port", global_smtp_tcp_port, dissect_smtp); }