2 * Routines for the Session Initiation Protocol (SIP) dissection.
5 * TODO: Pay attention to Content-Type: It might not always be SDP.
6 * hf_ display filters for headers of SIP extension RFCs:
7 * Done for RFC 3265, RFC 3262
8 * Use hash table for list of headers
9 * Add sip msg body dissection based on Content-Type for:
10 * SDP, MIME, and other types
11 * Align SIP methods with recent Internet Drafts or RFC
12 * (SIP INFO, rfc2976 - done)
13 * (SIP SUBSCRIBE-NOTIFY - done)
17 * Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi>
18 * Copyright 2001, Jean-Francois Mule <jfm@cablelabs.com>
20 * $Id: packet-sip.c,v 1.46 2003/10/24 00:50:39 guy Exp $
22 * Ethereal - Network traffic analyzer
23 * By Gerald Combs <gerald@ethereal.com>
24 * Copyright 1998 Gerald Combs
26 * Copied from packet-cops.c
28 * This program is free software; you can redistribute it and/or
29 * modify it under the terms of the GNU General Public License
30 * as published by the Free Software Foundation; either version 2
31 * of the License, or (at your option) any later version.
33 * This program is distributed in the hope that it will be useful,
34 * but WITHOUT ANY WARRANTY; without even the implied warranty of
35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
36 * GNU General Public License for more details.
38 * You should have received a copy of the GNU General Public License
39 * along with this program; if not, write to the Free Software
40 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
55 #include <epan/packet.h>
57 #define TCP_PORT_SIP 5060
58 #define UDP_PORT_SIP 5060
60 /* Initialize the protocol and registered fields */
61 static gint proto_sip = -1;
62 static gint proto_raw_sip = -1;
63 static gint hf_msg_hdr = -1;
64 static gint hf_Method = -1;
65 static gint hf_Status_Code = -1;
66 static gint hf_sip_to_addr = -1;
67 static gint hf_sip_from_addr = -1;
68 static gint hf_sip_tag = -1;
70 /* Initialize the subtree pointers */
71 static gint ett_sip = -1;
72 static gint ett_sip_reqresp = -1;
73 static gint ett_sip_hdr = -1;
74 static gint ett_raw_text = -1;
75 static gint ett_sip_element = -1;
77 static const char *sip_methods[] = {
78 "<Invalid method>", /* Pad so that the real methods start at index 1 */
98 static const char *sip_headers[] = {
99 "Unknown-header", /* Pad so that the real headers start at index 1 */
106 "Authentication-Info",
111 "Content-Disposition",
128 "Proxy-Authenticate",
129 "Proxy-Authorization",
140 "Subscription-State",
153 #define POS_ACCEPT_ENCODING 2
154 #define POS_ACCEPT_LANGUAGE 3
155 #define POS_ALERT_INFO 4
157 #define POS_ALLOW_EVENTS 6
158 #define POS_AUTHENTICATION_INFO 7
159 #define POS_AUTHORIZATION 8
160 #define POS_CALL_ID 9
161 #define POS_CALL_INFO 10
162 #define POS_CONTACT 11
163 #define POS_CONTENT_DISPOSITION 12
164 #define POS_CONTENT_ENCODING 13
165 #define POS_CONTENT_LANGUAGE 14
166 #define POS_CONTENT_LENGTH 15
167 #define POS_CONTENT_TYPE 16
170 #define POS_ERROR_INFO 19
172 #define POS_EXPIRES 21
174 #define POS_IN_REPLY_TO 23
175 #define POS_MAX_FORWARDS 24
176 #define POS_MIME_VERSION 25
177 #define POS_MIN_EXPIRES 26
178 #define POS_ORGANIZATION 27
179 #define POS_PRIORITY 28
180 #define POS_PROXY_AUTHENTICATE 29
181 #define POS_PROXY_AUTHORIZATION 30
182 #define POS_PROXY_REQUIRE 31
185 #define POS_RECORD_ROUTE 34
186 #define POS_REPLY_TO 35
187 #define POS_REQUIRE 36
188 #define POS_RETRY_AFTER 37
190 #define POS_SERVER 39
191 #define POS_SUBJECT 40
192 #define POS_SUBSCRIPTION_STATE 41
193 #define POS_SUPPORTED 42
194 #define POS_TIMESTAMP 43
196 #define POS_UNSUPPORTED 45
197 #define POS_USER_AGENT 46
199 #define POS_WARNING 48
200 #define POS_WWW_AUTHENTICATE 49
202 static gint hf_header_array[] = {
203 -1, /* "Unknown-header" - Pad so that the real headers start at index 1 */
205 -1, /* "Accept-Encoding" */
206 -1, /* "Accept-Language" */
207 -1, /* "Alert-Info" */
209 -1, /* "Allow-Events" - RFC 3265 */
210 -1, /* "Authentication-Info" */
211 -1, /* "Authorization" */
213 -1, /* "Call-Info" */
215 -1, /* "Content-Disposition" */
216 -1, /* "Content-Encoding" */
217 -1, /* "Content-Language" */
218 -1, /* "Content-Length" */
219 -1, /* "Content-Type" */
222 -1, /* "Error-Info" */
224 -1, /* "Event" - RFC 3265 */
226 -1, /* "In-Reply-To" */
227 -1, /* "Max-Forwards" */
228 -1, /* "MIME-Version" */
229 -1, /* "Min-Expires" */
230 -1, /* "Organization" */
232 -1, /* "Proxy-Authenticate" */
233 -1, /* "Proxy-Authorization" */
234 -1, /* "Proxy-Require" */
235 -1, /* "RAck" - RFC 3262 */
236 -1, /* "RSeq" - RFC 3261 */
237 -1, /* "Record-Route" */
240 -1, /* "Retry-After" */
244 -1, /* "Subscription-State" - RFC 3265 */
245 -1, /* "Supported" */
246 -1, /* "Timestamp" */
248 -1, /* "Unsupported" */
249 -1, /* "User-Agent" */
252 -1 /* "WWW-Authenticate" */
256 * Type of line. It's either a SIP Request-Line, a SIP Status-Line, or
257 * another type of line.
265 /* global_sip_raw_text determines whether we are going to display */
266 /* the raw text of the SIP message, much like the MEGACO dissector does. */
267 static gboolean global_sip_raw_text = FALSE;
269 static gboolean dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo,
270 proto_tree *tree, gboolean is_heur);
271 static line_type_t sip_parse_line(tvbuff_t *tvb, gint linelen,
273 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
275 static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset,
277 static void dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree,
279 static void dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree);
280 static void tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree);
282 static dissector_handle_t sdp_handle;
284 #define SIP2_HDR "SIP/2.0"
285 #define SIP2_HDR_LEN (strlen (SIP2_HDR))
287 /* Code to actually dissect the packets */
289 dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
291 if (!dissect_sip_common(tvb, pinfo, tree, FALSE))
293 return tvb_length(tvb);
297 dissect_sip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
299 dissect_sip_common(tvb, pinfo, tree, TRUE);
303 dissect_sip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
305 return dissect_sip_common(tvb, pinfo, tree, FALSE);
309 dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
310 gboolean dissect_other_as_continuation)
313 gint next_offset, linelen;
314 line_type_t line_type;
316 gboolean is_known_request;
319 proto_item *ts = NULL, *ti, *th = NULL, *sip_element_item;
320 proto_tree *sip_tree, *reqresp_tree, *hdr_tree = NULL, *sip_element_tree;
323 * Note that "tvb_find_line_end()" will return a value that
324 * is not longer than what's in the buffer, so the
325 * "tvb_get_ptr()" calls below won't throw exceptions.
327 * Note that "tvb_strneql()" doesn't throw exceptions, so
328 * "sip_parse_line()" won't throw an exception.
331 linelen = tvb_find_line_end(tvb, 0, -1, &next_offset, FALSE);
332 line_type = sip_parse_line(tvb, linelen, &token_1_len);
333 if (line_type == OTHER_LINE) {
335 * This is neither a SIP request nor response.
337 if (!dissect_other_as_continuation) {
339 * We were asked to reject this.
345 * Just dissect it as a continuation.
349 if (check_col(pinfo->cinfo, COL_PROTOCOL))
350 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIP");
355 is_known_request = sip_is_known_request(tvb, 0, token_1_len);
356 descr = is_known_request ? "Request" : "Unknown request";
357 if (check_col(pinfo->cinfo, COL_INFO)) {
358 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
360 tvb_format_text(tvb, 0, linelen - SIP2_HDR_LEN - 1));
366 if (check_col(pinfo->cinfo, COL_INFO)) {
367 col_add_fstr(pinfo->cinfo, COL_INFO, "Status: %s",
368 tvb_format_text(tvb, SIP2_HDR_LEN + 1, linelen - SIP2_HDR_LEN - 1));
373 default: /* Squelch compiler complaints */
374 descr = "Continuation";
375 if (check_col(pinfo->cinfo, COL_INFO))
376 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
381 ts = proto_tree_add_item(tree, proto_sip, tvb, 0, -1, FALSE);
382 sip_tree = proto_item_add_subtree(ts, ett_sip);
384 ti = proto_tree_add_text(sip_tree, tvb, 0, next_offset,
385 "%s line: %s", descr,
386 tvb_format_text(tvb, 0, linelen));
387 reqresp_tree = proto_item_add_subtree(ti, ett_sip_reqresp);
392 dfilter_sip_request_line(tvb, reqresp_tree, token_1_len);
396 dfilter_sip_status_line(tvb, reqresp_tree);
400 proto_tree_add_text(sip_tree, tvb, 0, -1,
401 "Continuation data");
405 offset = next_offset;
406 th = proto_tree_add_item(sip_tree, hf_msg_hdr, tvb, offset, -1,
408 hdr_tree = proto_item_add_subtree(th, ett_sip_hdr);
412 * Process the headers - if we're not building a protocol tree,
413 * we just do this to find the blank line separating the
414 * headers from the message body.
416 next_offset = offset;
417 while (tvb_reported_length_remaining(tvb, offset) > 0) {
418 gint line_end_offset;
422 gint value_offset,tag_offset;
427 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset,
431 * This is a blank line separating the
432 * message header from the message body.
437 line_end_offset = offset + linelen;
438 colon_offset = tvb_find_guint8(tvb, offset, linelen,
440 if (colon_offset == -1) {
442 * Malformed header - no colon after the
445 proto_tree_add_text(hdr_tree, tvb, offset,
446 next_offset - offset, "%s",
447 tvb_format_text(tvb, offset, linelen));
449 header_len = colon_offset - offset;
450 hf_index = sip_is_known_sip_header(tvb,
453 if (hf_index == -1) {
454 proto_tree_add_text(hdr_tree, tvb,
455 offset, next_offset - offset, "%s",
456 tvb_format_text(tvb, offset, linelen));
459 * Skip whitespace after the colon.
461 value_offset = colon_offset + 1;
462 while (value_offset < line_end_offset
463 && ((c = tvb_get_guint8(tvb,
464 value_offset)) == ' '
470 value_len = line_end_offset - value_offset;
471 value = tvb_get_string(tvb, value_offset,
475 * Add it to the protocol tree,
476 * but display the line as is.
479 switch ( hf_index ) {
481 sip_element_item = proto_tree_add_string_format(hdr_tree,
482 hf_header_array[hf_index], tvb,
483 offset, next_offset - offset,
485 tvb_format_text(tvb, offset, linelen));
486 sip_element_tree = proto_item_add_subtree( sip_element_item, ett_sip_element);
487 tag_offset = tvb_find_guint8(tvb, offset,linelen, ';');
488 if ( tag_offset != -1){
489 tag_offset = tag_offset + 1;
490 c = tvb_get_guint8(tvb,tag_offset);
491 if ( c == 't' ){/* tag found */
492 proto_tree_add_string(sip_element_tree,
494 value_offset, (tag_offset - value_offset - 1),
495 tvb_format_text(tvb, value_offset, ( tag_offset - value_offset - 1)));
496 tag_offset = tvb_find_guint8(tvb, tag_offset,linelen, '=') + 1;
497 proto_tree_add_string(sip_element_tree,
499 tag_offset, (line_end_offset - tag_offset),
500 tvb_format_text(tvb, tag_offset, (line_end_offset - tag_offset)));
504 proto_tree_add_string_format(sip_element_tree,
506 offset, line_end_offset - offset,
508 tvb_format_text(tvb, offset, linelen));
510 } /* if tag offset */
513 sip_element_item = proto_tree_add_string_format(hdr_tree,
514 hf_header_array[hf_index], tvb,
515 offset, next_offset - offset,
517 tvb_format_text(tvb, offset, linelen));
518 sip_element_tree = proto_item_add_subtree( sip_element_item, ett_sip_element);
519 tag_offset = tvb_find_guint8(tvb, offset,linelen, ';');
520 if ( tag_offset != -1){
521 tag_offset = tag_offset + 1;
522 c = tvb_get_guint8(tvb,tag_offset);
523 if ( c == 't' ){/* tag found */
524 proto_tree_add_string(sip_element_tree,
525 hf_sip_from_addr, tvb,
526 value_offset, (tag_offset - value_offset - 1),
527 tvb_format_text(tvb, value_offset, ( tag_offset - value_offset - 1)));
528 tag_offset = tvb_find_guint8(tvb, offset,linelen, '=') + 1;
529 proto_tree_add_string(sip_element_tree,
531 tag_offset, (line_end_offset - tag_offset),
532 tvb_format_text(tvb, tag_offset, (line_end_offset - tag_offset)));
536 tag_offset = tvb_find_guint8(tvb, tag_offset,linelen, ';');
537 if ( tag_offset != -1){
538 tag_offset = tag_offset + 1;
539 c = tvb_get_guint8(tvb,tag_offset);
540 if ( c == 't' ){/* tag found */
541 proto_tree_add_string(sip_element_tree,
542 hf_sip_from_addr, tvb,
543 value_offset, (tag_offset - value_offset - 1),
544 tvb_format_text(tvb, value_offset, ( tag_offset - value_offset - 1)));
545 tag_offset = tvb_find_guint8(tvb, tag_offset,linelen, '=') + 1;
546 proto_tree_add_string(sip_element_tree,
548 tag_offset, (line_end_offset - tag_offset),
549 tvb_format_text(tvb, tag_offset, (line_end_offset - tag_offset)));
553 } /* if tag offset */
557 proto_tree_add_string_format(hdr_tree,
558 hf_header_array[hf_index], tvb,
559 offset, next_offset - offset,
561 tvb_format_text(tvb, offset, linelen));
566 }/* if colon_offset */
568 offset = next_offset;
571 if (tvb_offset_exists(tvb, next_offset)) {
573 * There's a message body starting at "next_offset".
574 * Set the length of the SIP portion and of the
577 proto_item_set_end(ts, tvb, next_offset);
578 proto_item_set_end(th, tvb, next_offset);
579 next_tvb = tvb_new_subset(tvb, next_offset, -1, -1);
580 call_dissector(sdp_handle, next_tvb, pinfo, tree);
583 if (global_sip_raw_text)
584 tvb_raw_text_add(tvb, tree);
589 /* Display filter for SIP Request-Line */
591 dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, guint meth_len)
596 * We know we have the entire method; otherwise, "sip_parse_line()"
597 * would have returned OTHER_LINE.
599 string = tvb_get_string(tvb, 0, meth_len);
600 proto_tree_add_string(tree, hf_Method, tvb, 0, meth_len, string);
604 /* Display filter for SIP Status-Line */
606 dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree)
611 * We know we have the entire status code; otherwise,
612 * "sip_parse_line()" would have returned OTHER_LINE.
613 * We also know that we have a version string followed by a
614 * space at the beginning of the line, for the same reason.
616 tvb_memcpy(tvb, (guint8 *)string, SIP2_HDR_LEN + 1, 3);
618 proto_tree_add_string(tree, hf_Status_Code, tvb, SIP2_HDR_LEN + 1,
622 /* From section 4.1 of RFC 2543:
624 * Request-Line = Method SP Request-URI SP SIP-Version CRLF
626 * From section 5.1 of RFC 2543:
628 * Status-Line = SIP-version SP Status-Code SP Reason-Phrase CRLF
631 sip_parse_line(tvbuff_t *tvb, gint linelen, guint *token_1_lenp)
641 space_offset = tvb_find_guint8(tvb, 0, -1, ' ');
642 if (space_offset <= 0) {
644 * Either there's no space in the line (which means
645 * the line is empty or doesn't have a token followed
646 * by a space; neither is valid for a request or status), or
647 * the first character in the line is a space (meaning
648 * the method is empty, which isn't valid for a request,
649 * or the SIP version is empty, which isn't valid for a
654 token_1_len = space_offset;
655 token_2_start = space_offset + 1;
656 space_offset = tvb_find_guint8(tvb, token_2_start, -1, ' ');
657 if (space_offset == -1) {
659 * There's no space after the second token, so we don't
660 * have a third token.
664 token_2_len = space_offset - token_2_start;
665 token_3_start = space_offset + 1;
666 token_3_len = linelen - token_3_start;
668 *token_1_lenp = token_1_len;
671 * Is the first token a version string?
673 if (token_1_len == SIP2_HDR_LEN &&
674 tvb_strneql(tvb, 0, SIP2_HDR, SIP2_HDR_LEN) == 0) {
676 * Yes, so this is either a Status-Line or something
677 * else other than a Request-Line. To be a Status-Line,
678 * the second token must be a 3-digit number.
680 if (token_2_len != 3) {
682 * We don't have 3-character status code.
686 if (!isdigit(tvb_get_guint8(tvb, token_2_start)) ||
687 !isdigit(tvb_get_guint8(tvb, token_2_start + 1)) ||
688 !isdigit(tvb_get_guint8(tvb, token_2_start + 2))) {
690 * 3 characters yes, 3 digits no.
697 * No, so this is either a Request-Line or something
698 * other than a Status-Line. To be a Request-Line, the
699 * second token must be a URI and the third token must
700 * be a version string.
702 if (token_2_len < 3) {
704 * We don't have a URI consisting of at least 3
709 colon_pos = tvb_find_guint8(tvb, token_2_start + 1, -1, ':');
710 if (colon_pos == -1) {
712 * There is no colon after the method, so the URI
713 * doesn't have a colon in it, so it's not valid.
717 if (colon_pos >= token_3_start) {
719 * The colon is in the version string, not the URI.
723 /* XXX - Check for a proper URI prefix? */
724 if (token_3_len != SIP2_HDR_LEN ||
725 tvb_strneql(tvb, token_3_start, SIP2_HDR, SIP2_HDR_LEN) == -1) {
727 * The version string isn't an SIP version 2.0 version
736 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
741 for (i = 1; i < array_length(sip_methods); i++) {
742 if (meth_len == strlen(sip_methods[i]) &&
743 tvb_strneql(tvb, meth_offset, sip_methods[i], meth_len) == 0)
750 /* Returns index of method in sip_headers */
751 static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset, guint header_len)
755 for (i = 1; i < array_length(sip_headers); i++) {
756 if (header_len == strlen(sip_headers[i]) &&
757 tvb_strncaseeql(tvb, offset, sip_headers[i], header_len) == 0)
765 * Display the entire message as raw text.
768 tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree)
770 proto_tree *raw_tree;
772 int offset, next_offset, linelen;
774 ti = proto_tree_add_item(tree, proto_raw_sip, tvb, 0, -1, FALSE);
775 raw_tree = proto_item_add_subtree(ti, ett_raw_text);
779 while (tvb_offset_exists(tvb, offset)) {
780 tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
781 linelen = next_offset - offset;
782 proto_tree_add_text(raw_tree, tvb, offset, linelen,
783 "%s", tvb_format_text(tvb, offset, linelen));
784 offset = next_offset;
788 /* Register the protocol with Ethereal */
789 void proto_register_sip(void)
792 /* Setup list of header fields */
793 static hf_register_info hf[] = {
796 { "Message Header", "sip.msg_hdr",
798 "Message Header in SIP message", HFILL }
801 { "Method", "sip.Method",
802 FT_STRING, BASE_NONE,NULL,0x0,
803 "SIP Method", HFILL }
806 { "Status-Code", "sip.Status-Code",
807 FT_STRING, BASE_NONE,NULL,0x0,
808 "SIP Status Code", HFILL }
811 { "SIP to address", "sip.from_addr",
812 FT_STRING, BASE_NONE,NULL,0x0,
813 "RFC 3261: from addr", HFILL }
816 { "SIP from address", "sip.to_addr",
817 FT_STRING, BASE_NONE,NULL,0x0,
818 "RFC 3261: to addr", HFILL }
821 { "SIP tag", "sip.tag",
822 FT_STRING, BASE_NONE,NULL,0x0,
823 "RFC 3261: tag", HFILL }
825 { &hf_header_array[POS_ACCEPT],
826 { "Accept", "sip.Accept",
827 FT_STRING, BASE_NONE,NULL,0x0,
828 "RFC 3261: Accept Header", HFILL }
830 { &hf_header_array[POS_ACCEPT_ENCODING],
831 { "Accept-Encoding", "sip.Accept-Encoding",
832 FT_STRING, BASE_NONE,NULL,0x0,
833 "RFC 3261: Accept-Encoding Header", HFILL }
835 { &hf_header_array[POS_ACCEPT_LANGUAGE],
836 { "Accept-Language", "sip.Accept-Language",
837 FT_STRING, BASE_NONE,NULL,0x0,
838 "RFC 3261: Accept-Language Header", HFILL }
840 { &hf_header_array[POS_ALERT_INFO],
841 { "Alert-Info", "sip.Alert-Info",
842 FT_STRING, BASE_NONE,NULL,0x0,
843 "RFC 3261: Alert-Info Header", HFILL }
845 { &hf_header_array[POS_ALLOW],
846 { "Allow", "sip.Allow",
847 FT_STRING, BASE_NONE,NULL,0x0,
848 "RFC 3261: Allow Header", HFILL }
850 { &hf_header_array[POS_ALLOW_EVENTS],
851 { "Allow-Events", "sip.Allow-Events",
852 FT_STRING, BASE_NONE,NULL,0x0,
853 "RFC 3265: Allow-Events Header", HFILL }
855 { &hf_header_array[POS_AUTHENTICATION_INFO],
856 { "Authentication-Info", "sip.Authentication-Info",
857 FT_STRING, BASE_NONE,NULL,0x0,
858 "RFC 3261: Authentication-Info Header", HFILL }
860 { &hf_header_array[POS_AUTHORIZATION],
861 { "Authorization", "sip.Authorization",
862 FT_STRING, BASE_NONE,NULL,0x0,
863 "RFC 3261: Authorization Header", HFILL }
865 { &hf_header_array[POS_CALL_ID],
866 { "Call-ID", "sip.Call-ID",
867 FT_STRING, BASE_NONE,NULL,0x0,
868 "RFC 3261: Call-ID Header", HFILL }
870 { &hf_header_array[POS_CALL_INFO],
871 { "Call-Info", "sip.Call-Info",
872 FT_STRING, BASE_NONE,NULL,0x0,
873 "RFC 3261: Call-Info Header", HFILL }
875 { &hf_header_array[POS_CONTACT],
876 { "Contact", "sip.Contact",
877 FT_STRING, BASE_NONE,NULL,0x0,
878 "RFC 3261: Contact Header", HFILL }
880 { &hf_header_array[POS_CONTENT_DISPOSITION],
881 { "Content-Disposition", "sip.Content-Disposition",
882 FT_STRING, BASE_NONE,NULL,0x0,
883 "RFC 3261: Content-Disposition Header", HFILL }
885 { &hf_header_array[POS_CONTENT_ENCODING],
886 { "Content-Encoding", "sip.Content-Encoding",
887 FT_STRING, BASE_NONE,NULL,0x0,
888 "RFC 3261: Content-Encoding Header", HFILL }
890 { &hf_header_array[POS_CONTENT_LANGUAGE],
891 { "Content-Language", "sip.Content-Language",
892 FT_STRING, BASE_NONE,NULL,0x0,
893 "RFC 3261: Content-Language Header", HFILL }
895 { &hf_header_array[POS_CONTENT_LENGTH],
896 { "Content-Length", "sip.Content-Length",
897 FT_STRING, BASE_NONE,NULL,0x0,
898 "RFC 3261: Content-Length Header", HFILL }
900 { &hf_header_array[POS_CONTENT_TYPE],
901 { "Content-Type", "sip.Content-Type",
902 FT_STRING, BASE_NONE,NULL,0x0,
903 "RFC 3261: Content-Type Header", HFILL }
905 { &hf_header_array[POS_CSEQ],
906 { "CSeq", "sip.CSeq",
907 FT_STRING, BASE_NONE,NULL,0x0,
908 "RFC 3261: CSeq Header", HFILL }
910 { &hf_header_array[POS_DATE],
911 { "Date", "sip.Date",
912 FT_STRING, BASE_NONE,NULL,0x0,
913 "RFC 3261: Date Header", HFILL }
915 { &hf_header_array[POS_ERROR_INFO],
916 { "Error-Info", "sip.Error-Info",
917 FT_STRING, BASE_NONE,NULL,0x0,
918 "RFC 3261: Error-Info Header", HFILL }
920 { &hf_header_array[POS_EVENT],
921 { "Event", "sip.Event",
922 FT_STRING, BASE_NONE,NULL,0x0,
923 "RFC 3265: Event Header", HFILL }
925 { &hf_header_array[POS_EXPIRES],
926 { "Expires", "sip.Expires",
927 FT_STRING, BASE_NONE,NULL,0x0,
928 "RFC 3261: Expires Header", HFILL }
930 { &hf_header_array[POS_FROM],
931 { "From", "sip.From",
932 FT_STRING, BASE_NONE,NULL,0x0,
933 "RFC 3261: From Header", HFILL }
935 { &hf_header_array[POS_IN_REPLY_TO],
936 { "In-Reply-To", "sip.In-Reply-To",
937 FT_STRING, BASE_NONE,NULL,0x0,
938 "RFC 3261: In-Reply-To Header", HFILL }
940 { &hf_header_array[POS_MAX_FORWARDS],
941 { "Max-Forwards", "sip.Max-Forwards",
942 FT_STRING, BASE_NONE,NULL,0x0,
943 "RFC 3261: Max-Forwards Header", HFILL }
945 { &hf_header_array[POS_MIME_VERSION],
946 { "MIME-Version", "sip.MIME-Version",
947 FT_STRING, BASE_NONE,NULL,0x0,
948 "RFC 3261: MIME-Version Header", HFILL }
950 { &hf_header_array[POS_MIN_EXPIRES],
951 { "Min-Expires", "sip.Min-Expires",
952 FT_STRING, BASE_NONE,NULL,0x0,
953 "RFC 3261: Min-Expires Header", HFILL }
955 { &hf_header_array[POS_ORGANIZATION],
956 { "Organization", "sip.Organization",
957 FT_STRING, BASE_NONE,NULL,0x0,
958 "RFC 3261: Organization Header", HFILL }
960 { &hf_header_array[POS_PRIORITY],
961 { "Priority", "sip.Priority",
962 FT_STRING, BASE_NONE,NULL,0x0,
963 "RFC 3261: Priority Header", HFILL }
965 { &hf_header_array[POS_PROXY_AUTHENTICATE],
966 { "Proxy-Authenticate", "sip.Proxy-Authenticate",
967 FT_STRING, BASE_NONE,NULL,0x0,
968 "RFC 3261: Proxy-Authenticate Header", HFILL }
970 { &hf_header_array[POS_PROXY_AUTHORIZATION],
971 { "Proxy-Authorization", "sip.Proxy-Authorization",
972 FT_STRING, BASE_NONE,NULL,0x0,
973 "RFC 3261: Proxy-Authorization Header", HFILL }
975 { &hf_header_array[POS_RACK],
976 { "RAck", "sip.RAck",
977 FT_STRING, BASE_NONE,NULL,0x0,
978 "RFC 3262: RAck Header", HFILL }
980 { &hf_header_array[POS_RSEQ],
981 { "RSeq", "sip.RSeq",
982 FT_STRING, BASE_NONE,NULL,0x0,
983 "RFC 3262: RSeq Header", HFILL }
985 { &hf_header_array[POS_PROXY_REQUIRE],
986 { "Proxy-Require", "sip.Proxy-Require",
987 FT_STRING, BASE_NONE,NULL,0x0,
988 "RFC 3261: Proxy-Require Header", HFILL }
990 { &hf_header_array[POS_RECORD_ROUTE],
991 { "Record-Route", "sip.Record-Route",
992 FT_STRING, BASE_NONE,NULL,0x0,
993 "RFC 3261: Record-Route Header", HFILL }
995 { &hf_header_array[POS_REPLY_TO],
996 { "Reply-To", "sip.Reply-To",
997 FT_STRING, BASE_NONE,NULL,0x0,
998 "RFC 3261: Reply-To Header", HFILL }
1000 { &hf_header_array[POS_REQUIRE],
1001 { "Require", "sip.Require",
1002 FT_STRING, BASE_NONE,NULL,0x0,
1003 "RFC 3261: Require Header", HFILL }
1005 { &hf_header_array[POS_RETRY_AFTER],
1006 { "Retry-After", "sip.Retry-After",
1007 FT_STRING, BASE_NONE,NULL,0x0,
1008 "RFC 3261: Retry-After Header", HFILL }
1010 { &hf_header_array[POS_ROUTE],
1011 { "Route", "sip.Route",
1012 FT_STRING, BASE_NONE,NULL,0x0,
1013 "RFC 3261: Route Header", HFILL }
1015 { &hf_header_array[POS_SERVER],
1016 { "Server", "sip.Server",
1017 FT_STRING, BASE_NONE,NULL,0x0,
1018 "RFC 3261: Server Header", HFILL }
1020 { &hf_header_array[POS_SUBJECT],
1021 { "Subject", "sip.Subject",
1022 FT_STRING, BASE_NONE,NULL,0x0,
1023 "RFC 3261: Subject Header", HFILL }
1025 { &hf_header_array[POS_SUBSCRIPTION_STATE],
1026 { "Subscription-State", "sip.Subscription-State",
1027 FT_STRING, BASE_NONE,NULL,0x0,
1028 "RFC 3265: Subscription-State Header", HFILL }
1030 { &hf_header_array[POS_SUPPORTED],
1031 { "Supported", "sip.Supported",
1032 FT_STRING, BASE_NONE,NULL,0x0,
1033 "RFC 3261: Supported Header", HFILL }
1035 { &hf_header_array[POS_TIMESTAMP],
1036 { "Timestamp", "sip.Timestamp",
1037 FT_STRING, BASE_NONE,NULL,0x0,
1038 "RFC 3261: Timestamp Header", HFILL }
1040 { &hf_header_array[POS_TO],
1042 FT_STRING, BASE_NONE,NULL,0x0,
1043 "RFC 3261: To Header", HFILL }
1045 { &hf_header_array[POS_UNSUPPORTED],
1046 { "Unsupported", "sip.Unsupported",
1047 FT_STRING, BASE_NONE,NULL,0x0,
1048 "RFC 3261: Unsupported Header", HFILL }
1050 { &hf_header_array[POS_USER_AGENT],
1051 { "User-Agent", "sip.User-Agent",
1052 FT_STRING, BASE_NONE,NULL,0x0,
1053 "RFC 3261: User-Agent Header", HFILL }
1055 { &hf_header_array[POS_VIA],
1057 FT_STRING, BASE_NONE,NULL,0x0,
1058 "RFC 3261: Via Header", HFILL }
1060 { &hf_header_array[POS_WARNING],
1061 { "Warning", "sip.Warning",
1062 FT_STRING, BASE_NONE,NULL,0x0,
1063 "RFC 3261: Warning Header", HFILL }
1065 { &hf_header_array[POS_WWW_AUTHENTICATE],
1066 { "WWW-Authenticate", "sip.WWW-Authenticate",
1067 FT_STRING, BASE_NONE,NULL,0x0,
1068 "RFC 3261: WWW-Authenticate Header", HFILL }
1072 /* Setup protocol subtree array */
1073 static gint *ett[] = {
1080 static gint *ett_raw[] = {
1084 module_t *sip_module;
1086 /* Register the protocol name and description */
1087 proto_sip = proto_register_protocol("Session Initiation Protocol",
1089 proto_raw_sip = proto_register_protocol("Session Initiation Protocol (SIP as raw text)",
1090 "Raw_SIP", "raw_sip");
1092 /* Required function calls to register the header fields and subtrees used */
1093 proto_register_field_array(proto_sip, hf, array_length(hf));
1094 proto_register_subtree_array(ett, array_length(ett));
1095 proto_register_subtree_array(ett_raw, array_length(ett_raw));
1097 sip_module = prefs_register_protocol(proto_sip, NULL);
1099 prefs_register_bool_preference(sip_module, "display_raw_text",
1100 "Display raw text for SIP message",
1101 "Specifies that the raw text of the "
1102 "SIP message should be displayed "
1103 "in addition to the dissection tree",
1104 &global_sip_raw_text);
1108 proto_reg_handoff_sip(void)
1110 dissector_handle_t sip_handle, sip_tcp_handle;
1112 sip_handle = new_create_dissector_handle(dissect_sip, proto_sip);
1113 dissector_add("udp.port", UDP_PORT_SIP, sip_handle);
1115 sip_tcp_handle = create_dissector_handle(dissect_sip_tcp, proto_sip);
1116 dissector_add("tcp.port", TCP_PORT_SIP, sip_tcp_handle);
1118 heur_dissector_add("udp", dissect_sip_heur, proto_sip);
1119 heur_dissector_add("tcp", dissect_sip_heur, proto_sip);
1120 heur_dissector_add("sctp", dissect_sip_heur, proto_sip);
1123 * Get a handle for the SDP dissector.
1125 sdp_handle = find_dissector("sdp");