2000-11-04 07:50:47 +00:00
|
|
|
/* packet-sip.c
|
|
|
|
* Routines for the Session Initiation Protocol (SIP) dissection.
|
|
|
|
* RFC 2543
|
|
|
|
*
|
2000-11-11 19:57:09 +00:00
|
|
|
* TODO: Pay attention to Content-Type: It might not always be SDP.
|
2000-11-04 07:50:47 +00:00
|
|
|
* Add hf_* fields for filtering support.
|
2001-08-23 00:18:57 +00:00
|
|
|
* Add sip msg body dissection based on Content-Type for:
|
|
|
|
* SDP, MIME, and other types
|
|
|
|
* Align SIP methods with recent Internet Drafts or RFC
|
|
|
|
* (SIP INFO, rfc2976 - done)
|
|
|
|
* (SIP SUBSCRIBE-NOTIFY - done)
|
|
|
|
* (SIP REFER - done)
|
|
|
|
* check for other
|
2000-11-04 07:50:47 +00:00
|
|
|
*
|
|
|
|
* Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi>
|
2001-08-23 00:18:57 +00:00
|
|
|
* Copyright 2001, Jean-Francois Mule <jfm@clarent.com>
|
2000-11-04 07:50:47 +00:00
|
|
|
*
|
2002-01-24 09:20:54 +00:00
|
|
|
* $Id: packet-sip.c,v 1.22 2002/01/24 09:20:51 guy Exp $
|
2000-11-04 07:50:47 +00:00
|
|
|
*
|
|
|
|
* Ethereal - Network traffic analyzer
|
2001-08-23 00:18:57 +00:00
|
|
|
* By Gerald Combs <gerald@ethereal.com>
|
2000-11-04 07:50:47 +00:00
|
|
|
* Copyright 1998 Gerald Combs
|
|
|
|
*
|
|
|
|
* Copied from packet-cops.c
|
|
|
|
*
|
|
|
|
* 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
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <glib.h>
|
2002-01-21 07:37:49 +00:00
|
|
|
#include <epan/packet.h>
|
2000-11-04 07:50:47 +00:00
|
|
|
|
|
|
|
#define TCP_PORT_SIP 5060
|
|
|
|
#define UDP_PORT_SIP 5060
|
|
|
|
|
|
|
|
/* Initialize the protocol and registered fields */
|
|
|
|
static gint proto_sip = -1;
|
|
|
|
static gint hf_msg_hdr = -1;
|
|
|
|
|
|
|
|
/* Initialize the subtree pointers */
|
|
|
|
static gint ett_sip = -1;
|
|
|
|
static gint ett_sip_hdr = -1;
|
|
|
|
|
|
|
|
static const char *sip_methods[] = {
|
|
|
|
"<Invalid method>", /* Pad so that the real methods start at index 1 */
|
|
|
|
"INVITE",
|
|
|
|
"ACK",
|
|
|
|
"OPTIONS",
|
|
|
|
"BYE",
|
|
|
|
"CANCEL",
|
2001-08-23 00:18:57 +00:00
|
|
|
"REGISTER",
|
|
|
|
"INFO",
|
|
|
|
"REFER",
|
|
|
|
"SUBSCRIBE",
|
|
|
|
"NOTIFY"
|
2000-11-04 07:50:47 +00:00
|
|
|
};
|
|
|
|
|
2001-08-23 00:18:57 +00:00
|
|
|
static gboolean sip_is_request(tvbuff_t *tvb, guint32 offset);
|
2000-11-04 07:50:47 +00:00
|
|
|
static gint sip_get_msg_offset(tvbuff_t *tvb, guint32 offset);
|
|
|
|
|
Add a mechanism by which a dissector can be registered by name, another
dissector can get a "handle" for that dissector by name and then call
that dissector through the handle.
This allows dissectors that can't be called through a port table or a
heuristic table to be called from other dissectors without directly
referring to the dissector function - dynamically-loaded modules, under
Windows, cannot directly call functions in the main program, and
non-plugin dissectors are in the main program and thus cannot be called
from plugin dissectors unless either
1) a pointer to the dissector is put in the Big Transfer Vector
or
2) some other mechanism for getting a pointer to the dissector
is provided.
This mechanism could also support registering old-style dissectors and
calling them from new-style dissectors without the new-style dissector
having to do the argument translation itself (I didn't add support for
registering old-style dissectors because I'd prefer to have people
tvbuffify their code if they have to register a dissector...).
It could also, in the future, perhaps support
disabling of protocols;
setting "pinfo->current_proto";
inside "call_dissector()" - and inside "{old_}dissector_try_port()" and
"{old_"dissector_try_heuristic()" - allowing a pile of stuff that
currently has to be done in every dissector be done by common code.
(I have some ideas about how to do this, by
having "proto_register_protocol()" take an abbreviation - of the
sort that would be put in, for example, "pinfo->current_proto" -
as an argument;
having the calls to register dissectors take an index returned
by "proto_register_protocol()" as an argument.
The abbreviation could be used elsewhere as well, e.g. in the "Decoding"
tab of the "Edit->Protocols" dialog box, and in a GUI for constructing
protocol filters. Watch this space.)
Make "dissect_sdp()" the first client of this mechanism; it's now static
to "packet-sdp.c", and all dissectors that call it - including the MGCP
plugin - now call it through a dissector handle fetched by
"find_dissector()". (Next step - see if Ethereal can now compile on
Windows as a result of this.)
svn path=/trunk/; revision=2647
2000-11-15 07:07:52 +00:00
|
|
|
static dissector_handle_t sdp_handle;
|
2001-11-25 22:19:25 +00:00
|
|
|
static dissector_handle_t data_handle;
|
Add a mechanism by which a dissector can be registered by name, another
dissector can get a "handle" for that dissector by name and then call
that dissector through the handle.
This allows dissectors that can't be called through a port table or a
heuristic table to be called from other dissectors without directly
referring to the dissector function - dynamically-loaded modules, under
Windows, cannot directly call functions in the main program, and
non-plugin dissectors are in the main program and thus cannot be called
from plugin dissectors unless either
1) a pointer to the dissector is put in the Big Transfer Vector
or
2) some other mechanism for getting a pointer to the dissector
is provided.
This mechanism could also support registering old-style dissectors and
calling them from new-style dissectors without the new-style dissector
having to do the argument translation itself (I didn't add support for
registering old-style dissectors because I'd prefer to have people
tvbuffify their code if they have to register a dissector...).
It could also, in the future, perhaps support
disabling of protocols;
setting "pinfo->current_proto";
inside "call_dissector()" - and inside "{old_}dissector_try_port()" and
"{old_"dissector_try_heuristic()" - allowing a pile of stuff that
currently has to be done in every dissector be done by common code.
(I have some ideas about how to do this, by
having "proto_register_protocol()" take an abbreviation - of the
sort that would be put in, for example, "pinfo->current_proto" -
as an argument;
having the calls to register dissectors take an index returned
by "proto_register_protocol()" as an argument.
The abbreviation could be used elsewhere as well, e.g. in the "Decoding"
tab of the "Edit->Protocols" dialog box, and in a GUI for constructing
protocol filters. Watch this space.)
Make "dissect_sdp()" the first client of this mechanism; it's now static
to "packet-sdp.c", and all dissectors that call it - including the MGCP
plugin - now call it through a dissector handle fetched by
"find_dissector()". (Next step - see if Ethereal can now compile on
Windows as a result of this.)
svn path=/trunk/; revision=2647
2000-11-15 07:07:52 +00:00
|
|
|
|
2001-01-30 02:22:23 +00:00
|
|
|
#define SIP2_HDR "SIP/2.0 "
|
|
|
|
#define SIP2_HDR_LEN (strlen (SIP2_HDR))
|
|
|
|
|
2000-11-04 07:50:47 +00:00
|
|
|
/* Code to actually dissect the packets */
|
|
|
|
static void dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|
|
|
{
|
|
|
|
guint32 offset;
|
2000-11-11 19:57:09 +00:00
|
|
|
gint eol, next_offset, msg_offset;
|
2000-11-04 07:50:47 +00:00
|
|
|
tvbuff_t *next_tvb;
|
2001-01-30 02:38:33 +00:00
|
|
|
gboolean is_request;
|
2000-11-04 07:50:47 +00:00
|
|
|
|
Remove more "CHECK_DISPLAY_AS_DATA()" calls and "pinfo->current_proto ="
statements.
Move the setting of the Protocol column in various dissectors before
anything is fetched from the packet, and also clear the Info column at
that point in those and some other dissectors, so that if an exception
is thrown, the columns don't reflect the previous protocol.
"Tvbuffify" the Mobile IP dissector (it took old-style arguments, and
then converted them into tvbuff arguments, so there wasn't much to do,
other than to fix references to "fd" to refer to "pinfo->fd").
In the SCTP dissector, refer to the port type and source and destination
ports through "pinfo" rather than through the global "pi", as it's a
tvbuffified dissector.
In the SMTP and Time Protocol dissectors, use "pinfo->match_port" rather
than "TCP_PORT_SMTP" when checking whether the packet is a request or
reply, just in case somebody makes a non-standard port be dissected as
SMTP or Time. (Also, remove a bogus comment from the Time dissector; it
was probably cut-and-pasted from the TFTP dissector.)
svn path=/trunk/; revision=2938
2001-01-25 06:14:14 +00:00
|
|
|
/*
|
|
|
|
* Note that "tvb_strneql()" doesn't throw exceptions, so
|
|
|
|
* "sip_is_request()" won't throw an exception.
|
|
|
|
*
|
|
|
|
* Note that "tvb_find_line_end()" will return a value that
|
|
|
|
* is not longer than what's in the buffer, so the
|
|
|
|
* "tvb_get_ptr()" call s below won't throw exceptions.
|
|
|
|
*/
|
2000-11-04 07:50:47 +00:00
|
|
|
offset = 0;
|
2000-11-11 19:57:09 +00:00
|
|
|
eol = tvb_find_line_end(tvb, 0, -1, &next_offset);
|
2001-01-30 02:22:23 +00:00
|
|
|
is_request = sip_is_request(tvb, 0);
|
|
|
|
/* XXX - Is this case-sensitive? RFC 2543 didn't explicitly say. */
|
2001-01-30 02:38:33 +00:00
|
|
|
if (tvb_strneql(tvb, 0, SIP2_HDR, SIP2_HDR_LEN) != 0 && ! is_request)
|
|
|
|
goto bad;
|
2001-01-30 02:22:23 +00:00
|
|
|
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_PROTOCOL))
|
|
|
|
col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIP");
|
2001-01-30 02:22:23 +00:00
|
|
|
|
2000-11-04 07:50:47 +00:00
|
|
|
|
2001-12-10 00:26:21 +00:00
|
|
|
if (check_col(pinfo->cinfo, COL_INFO))
|
|
|
|
col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
|
2000-11-11 19:57:09 +00:00
|
|
|
is_request ? "Request" : "Status",
|
|
|
|
is_request ?
|
2001-01-30 02:22:23 +00:00
|
|
|
tvb_format_text(tvb, 0, eol - SIP2_HDR_LEN) :
|
|
|
|
tvb_format_text(tvb, SIP2_HDR_LEN, eol - SIP2_HDR_LEN));
|
2000-11-04 07:50:47 +00:00
|
|
|
|
2000-11-18 16:56:31 +00:00
|
|
|
msg_offset = sip_get_msg_offset(tvb, offset);
|
|
|
|
if (msg_offset < 0) goto bad;
|
|
|
|
|
2000-11-04 07:50:47 +00:00
|
|
|
if (tree) {
|
|
|
|
proto_item *ti, *th;
|
|
|
|
proto_tree *sip_tree, *hdr_tree;
|
|
|
|
|
2002-01-24 09:20:54 +00:00
|
|
|
ti = proto_tree_add_item(tree, proto_sip, tvb, 0, -1, FALSE);
|
2000-11-04 07:50:47 +00:00
|
|
|
sip_tree = proto_item_add_subtree(ti, ett_sip);
|
|
|
|
|
2000-11-11 19:57:09 +00:00
|
|
|
proto_tree_add_text(sip_tree, tvb, 0, next_offset, "%s-Line: %s",
|
|
|
|
is_request ? "Request" : "Status",
|
|
|
|
tvb_format_text(tvb, 0, eol));
|
2000-11-04 07:50:47 +00:00
|
|
|
|
2000-11-11 19:57:09 +00:00
|
|
|
offset = next_offset;
|
2000-11-04 07:50:47 +00:00
|
|
|
th = proto_tree_add_item(sip_tree, hf_msg_hdr, tvb, offset, msg_offset - offset, FALSE);
|
|
|
|
hdr_tree = proto_item_add_subtree(th, ett_sip_hdr);
|
2000-11-11 19:57:09 +00:00
|
|
|
|
2000-11-04 07:50:47 +00:00
|
|
|
/* - 2 since we have a CRLF separating the message-body */
|
2001-10-26 18:28:17 +00:00
|
|
|
while (msg_offset - 2 > (int) offset) {
|
2000-11-11 19:57:09 +00:00
|
|
|
eol = tvb_find_line_end(tvb, offset, -1, &next_offset);
|
|
|
|
proto_tree_add_text(hdr_tree, tvb, offset, next_offset - offset, "%s",
|
|
|
|
tvb_format_text(tvb, offset, eol));
|
|
|
|
offset = next_offset;
|
2000-11-04 07:50:47 +00:00
|
|
|
}
|
|
|
|
offset += 2; /* Skip the CRLF mentioned above */
|
|
|
|
}
|
|
|
|
|
2000-11-18 16:56:31 +00:00
|
|
|
if (tvb_length_remaining(tvb, msg_offset) > 0) {
|
2000-11-04 07:50:47 +00:00
|
|
|
next_tvb = tvb_new_subset(tvb, offset, -1, -1);
|
Add a mechanism by which a dissector can be registered by name, another
dissector can get a "handle" for that dissector by name and then call
that dissector through the handle.
This allows dissectors that can't be called through a port table or a
heuristic table to be called from other dissectors without directly
referring to the dissector function - dynamically-loaded modules, under
Windows, cannot directly call functions in the main program, and
non-plugin dissectors are in the main program and thus cannot be called
from plugin dissectors unless either
1) a pointer to the dissector is put in the Big Transfer Vector
or
2) some other mechanism for getting a pointer to the dissector
is provided.
This mechanism could also support registering old-style dissectors and
calling them from new-style dissectors without the new-style dissector
having to do the argument translation itself (I didn't add support for
registering old-style dissectors because I'd prefer to have people
tvbuffify their code if they have to register a dissector...).
It could also, in the future, perhaps support
disabling of protocols;
setting "pinfo->current_proto";
inside "call_dissector()" - and inside "{old_}dissector_try_port()" and
"{old_"dissector_try_heuristic()" - allowing a pile of stuff that
currently has to be done in every dissector be done by common code.
(I have some ideas about how to do this, by
having "proto_register_protocol()" take an abbreviation - of the
sort that would be put in, for example, "pinfo->current_proto" -
as an argument;
having the calls to register dissectors take an index returned
by "proto_register_protocol()" as an argument.
The abbreviation could be used elsewhere as well, e.g. in the "Decoding"
tab of the "Edit->Protocols" dialog box, and in a GUI for constructing
protocol filters. Watch this space.)
Make "dissect_sdp()" the first client of this mechanism; it's now static
to "packet-sdp.c", and all dissectors that call it - including the MGCP
plugin - now call it through a dissector handle fetched by
"find_dissector()". (Next step - see if Ethereal can now compile on
Windows as a result of this.)
svn path=/trunk/; revision=2647
2000-11-15 07:07:52 +00:00
|
|
|
call_dissector(sdp_handle, next_tvb, pinfo, tree);
|
2000-11-04 07:50:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
bad:
|
|
|
|
next_tvb = tvb_new_subset(tvb, offset, -1, -1);
|
2001-11-25 22:19:25 +00:00
|
|
|
call_dissector(data_handle,next_tvb, pinfo, tree);
|
2000-11-04 07:50:47 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Returns the offset to the start of the optional message-body, or
|
|
|
|
* -1 for an error.
|
|
|
|
*/
|
|
|
|
static gint sip_get_msg_offset(tvbuff_t *tvb, guint32 offset)
|
|
|
|
{
|
|
|
|
gint eol;
|
|
|
|
|
|
|
|
while ((eol = tvb_find_guint8(tvb, offset, tvb_length_remaining(tvb, offset), '\r')) > 0) {
|
|
|
|
if (tvb_get_guint8(tvb, eol + 1) == '\n' &&
|
|
|
|
tvb_get_guint8(tvb, eol + 2) == '\r' &&
|
|
|
|
tvb_get_guint8(tvb, eol + 3) == '\n')
|
|
|
|
return eol + 4;
|
|
|
|
offset = eol + 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2001-08-23 00:18:57 +00:00
|
|
|
static gboolean sip_is_request(tvbuff_t *tvb, guint32 offset)
|
2000-11-04 07:50:47 +00:00
|
|
|
{
|
2001-08-23 00:18:57 +00:00
|
|
|
u_int i;
|
2000-11-04 07:50:47 +00:00
|
|
|
|
|
|
|
for (i = 1; i < array_length(sip_methods); i++) {
|
2000-11-11 19:57:09 +00:00
|
|
|
if (tvb_strneql(tvb, offset, sip_methods[i], strlen(sip_methods[i])) == 0)
|
2001-08-23 00:18:57 +00:00
|
|
|
return TRUE;
|
2000-11-04 07:50:47 +00:00
|
|
|
}
|
|
|
|
|
2001-08-23 00:18:57 +00:00
|
|
|
return FALSE;
|
2000-11-04 07:50:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Register the protocol with Ethereal */
|
|
|
|
void proto_register_sip(void)
|
|
|
|
{
|
|
|
|
|
|
|
|
/* Setup list of header fields */
|
|
|
|
static hf_register_info hf[] = {
|
|
|
|
|
|
|
|
{ &hf_msg_hdr,
|
|
|
|
{ "Message Header", "sip.msg_hdr",
|
|
|
|
FT_NONE, 0, NULL, 0,
|
2001-06-18 02:18:27 +00:00
|
|
|
"Message Header in SIP message", HFILL }
|
2000-11-04 07:50:47 +00:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Setup protocol subtree array */
|
|
|
|
static gint *ett[] = {
|
|
|
|
&ett_sip,
|
|
|
|
&ett_sip_hdr,
|
|
|
|
};
|
|
|
|
|
|
|
|
/* Register the protocol name and description */
|
2001-01-03 06:56:03 +00:00
|
|
|
proto_sip = proto_register_protocol("Session Initiation Protocol",
|
|
|
|
"SIP", "sip");
|
2000-11-04 07:50:47 +00:00
|
|
|
|
|
|
|
/* Required function calls to register the header fields and subtrees used */
|
|
|
|
proto_register_field_array(proto_sip, hf, array_length(hf));
|
|
|
|
proto_register_subtree_array(ett, array_length(ett));
|
2001-03-09 04:35:25 +00:00
|
|
|
}
|
2000-11-04 07:50:47 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
proto_reg_handoff_sip(void)
|
|
|
|
{
|
2001-12-03 04:00:26 +00:00
|
|
|
dissector_handle_t sip_handle;
|
|
|
|
|
|
|
|
sip_handle = create_dissector_handle(dissect_sip, proto_sip);
|
|
|
|
dissector_add("tcp.port", TCP_PORT_SIP, sip_handle);
|
|
|
|
dissector_add("udp.port", UDP_PORT_SIP, sip_handle);
|
Add a mechanism by which a dissector can be registered by name, another
dissector can get a "handle" for that dissector by name and then call
that dissector through the handle.
This allows dissectors that can't be called through a port table or a
heuristic table to be called from other dissectors without directly
referring to the dissector function - dynamically-loaded modules, under
Windows, cannot directly call functions in the main program, and
non-plugin dissectors are in the main program and thus cannot be called
from plugin dissectors unless either
1) a pointer to the dissector is put in the Big Transfer Vector
or
2) some other mechanism for getting a pointer to the dissector
is provided.
This mechanism could also support registering old-style dissectors and
calling them from new-style dissectors without the new-style dissector
having to do the argument translation itself (I didn't add support for
registering old-style dissectors because I'd prefer to have people
tvbuffify their code if they have to register a dissector...).
It could also, in the future, perhaps support
disabling of protocols;
setting "pinfo->current_proto";
inside "call_dissector()" - and inside "{old_}dissector_try_port()" and
"{old_"dissector_try_heuristic()" - allowing a pile of stuff that
currently has to be done in every dissector be done by common code.
(I have some ideas about how to do this, by
having "proto_register_protocol()" take an abbreviation - of the
sort that would be put in, for example, "pinfo->current_proto" -
as an argument;
having the calls to register dissectors take an index returned
by "proto_register_protocol()" as an argument.
The abbreviation could be used elsewhere as well, e.g. in the "Decoding"
tab of the "Edit->Protocols" dialog box, and in a GUI for constructing
protocol filters. Watch this space.)
Make "dissect_sdp()" the first client of this mechanism; it's now static
to "packet-sdp.c", and all dissectors that call it - including the MGCP
plugin - now call it through a dissector handle fetched by
"find_dissector()". (Next step - see if Ethereal can now compile on
Windows as a result of this.)
svn path=/trunk/; revision=2647
2000-11-15 07:07:52 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Get a handle for the SDP dissector.
|
|
|
|
*/
|
|
|
|
sdp_handle = find_dissector("sdp");
|
2001-11-25 22:19:25 +00:00
|
|
|
data_handle = find_dissector("data");
|
2000-11-04 07:50:47 +00:00
|
|
|
}
|