2 * Routines for the Session Initiation Protocol (SIP) dissection.
5 * TODO: Pay attention to Content-Type: It might not always be SDP.
6 * Content-Type is fixed, mixed/mode is not handled though.
7 * hf_ display filters for headers of SIP extension RFCs:
8 * Done for RFC 3265, RFC 3262
9 * Use hash table for list of headers
10 * Add sip msg body dissection based on Content-Type for:
11 * SDP, MIME, and other types
12 * Align SIP methods with recent Internet Drafts or RFC
13 * (SIP INFO, rfc2976 - done)
14 * (SIP SUBSCRIBE-NOTIFY - done)
18 * Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi>
19 * Copyright 2001, Jean-Francois Mule <jfm@cablelabs.com>
21 * $Id: packet-sip.c,v 1.52 2003/12/17 20:52:38 guy Exp $
23 * Ethereal - Network traffic analyzer
24 * By Gerald Combs <gerald@ethereal.com>
25 * Copyright 1998 Gerald Combs
27 * Copied from packet-cops.c
29 * This program is free software; you can redistribute it and/or
30 * modify it under the terms of the GNU General Public License
31 * as published by the Free Software Foundation; either version 2
32 * of the License, or (at your option) any later version.
34 * This program is distributed in the hope that it will be useful,
35 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 * GNU General Public License for more details.
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
56 #include <epan/packet.h>
58 #define TCP_PORT_SIP 5060
59 #define UDP_PORT_SIP 5060
61 /* Initialize the protocol and registered fields */
62 static gint proto_sip = -1;
63 static gint proto_raw_sip = -1;
64 static gint hf_msg_hdr = -1;
65 static gint hf_Method = -1;
66 static gint hf_Status_Code = -1;
67 static gint hf_sip_to_addr = -1;
68 static gint hf_sip_from_addr = -1;
69 static gint hf_sip_tag = -1;
71 /* Initialize the subtree pointers */
72 static gint ett_sip = -1;
73 static gint ett_sip_reqresp = -1;
74 static gint ett_sip_hdr = -1;
75 static gint ett_raw_text = -1;
76 static gint ett_sip_element = -1;
77 static gint ett_sip_message_body = -1;
79 /* PUBLISH method added as per http://www.ietf.org/internet-drafts/draft-ietf-sip-publish-01.txt */
80 static const char *sip_methods[] = {
81 "<Invalid method>", /* Pad so that the real methods start at index 1 */
102 /* Updated with info from http://www.iana.org/assignments/sip-parameters */
103 /* (last updated 2003-10-31) */
104 /* Added two headsers ( Etag and If-Match )from http://www.ietf.org/internet-drafts/draft-ietf-sip-publish-01.txt */
109 static const sip_header_t sip_headers[] = {
110 { "Unknown-header", NULL }, /* Pad so that the real headers start at index 1 */
112 { "Accept-Encoding", NULL },
113 { "Accept-Language", NULL },
114 { "Alert-Info", NULL },
116 { "Allow-Events", NULL },
117 { "Authentication-Info", NULL },
118 { "Authorization", NULL },
120 { "Call-Info", NULL },
122 { "Content-Disposition", NULL },
123 { "Content-Encoding", "e" },
124 { "Content-Language", NULL },
125 { "Content-Length", "l" },
126 { "Content-Type", "c" },
129 { "Error-Info", NULL },
133 { "In-Reply-To", NULL },
134 { "Max-Forwards", NULL },
135 { "MIME-Version", NULL },
136 { "Min-Expires", NULL },
137 { "Organization", NULL },
138 { "Priority", NULL },
139 { "Proxy-Authenticate", NULL },
140 { "Proxy-Authorization", NULL },
141 { "Proxy-Require", NULL },
144 { "Record-Route", NULL },
145 { "Reply-To", NULL },
147 { "Retry-After", NULL },
151 { "Subscription-State", NULL },
152 { "Supported", "k" },
153 { "Timestamp", NULL },
155 { "Unsupported", NULL },
156 { "User-Agent", NULL },
159 { "WWW-Authenticate", NULL },
160 { "P-Access-Network-Info", NULL }, /* RFC3455 */
161 { "P-Asserted-Identity", NULL }, /* RFC3325 */
162 { "P-Associated-URI", NULL }, /* RFC3455 */
163 { "P-Called-Party-ID", NULL }, /* RFC3455 */
164 { "P-Charging-Function-Addresses",NULL }, /* RFC3455 */
165 { "P-Charging-Vector", NULL }, /* RFC3455 */
166 { "P-DCS-Trace-Party-ID", NULL }, /* RFC3603 */
167 { "P-DCS-OSPS", NULL }, /* RFC3603 */
168 { "P-DCS-Billing-Info", NULL }, /* RFC3603 */
169 { "P-DCS-LAES", NULL }, /* RFC3603 */
170 { "P-DCS-Redirect", NULL }, /* RFC3603 */
171 { "P-Media-Authorization", NULL }, /* RFC3313 */
172 { "P-Preferred-Identity", NULL }, /* RFC3325 */
173 { "P-Visited-Network-ID", NULL }, /* RFC3455 */
174 { "Path", NULL }, /* RFC3327 */
175 { "Privacy", NULL }, /* RFC3323 */
176 { "Reason", NULL }, /* RFC3326 */
177 { "Refer-To", "r" }, /* RFC3515 */
178 { "Service-Route", NULL }, /* RFC3608 */
179 { "ETag", NULL }, /* draft-ietf-sip-publish-01 */
180 { "If-Match", NULL }, /* draft-ietf-sip-publish-01 */
186 #define POS_ACCEPT_ENCODING 2
187 #define POS_ACCEPT_LANGUAGE 3
188 #define POS_ALERT_INFO 4
190 #define POS_ALLOW_EVENTS 6
191 #define POS_AUTHENTICATION_INFO 7
192 #define POS_AUTHORIZATION 8
193 #define POS_CALL_ID 9
194 #define POS_CALL_INFO 10
195 #define POS_CONTACT 11
196 #define POS_CONTENT_DISPOSITION 12
197 #define POS_CONTENT_ENCODING 13
198 #define POS_CONTENT_LANGUAGE 14
199 #define POS_CONTENT_LENGTH 15
200 #define POS_CONTENT_TYPE 16
203 #define POS_ERROR_INFO 19
205 #define POS_EXPIRES 21
207 #define POS_IN_REPLY_TO 23
208 #define POS_MAX_FORWARDS 24
209 #define POS_MIME_VERSION 25
210 #define POS_MIN_EXPIRES 26
211 #define POS_ORGANIZATION 27
212 #define POS_PRIORITY 28
213 #define POS_PROXY_AUTHENTICATE 29
214 #define POS_PROXY_AUTHORIZATION 30
215 #define POS_PROXY_REQUIRE 31
218 #define POS_RECORD_ROUTE 34
219 #define POS_REPLY_TO 35
220 #define POS_REQUIRE 36
221 #define POS_RETRY_AFTER 37
223 #define POS_SERVER 39
224 #define POS_SUBJECT 40
225 #define POS_SUBSCRIPTION_STATE 41
226 #define POS_SUPPORTED 42
227 #define POS_TIMESTAMP 43
229 #define POS_UNSUPPORTED 45
230 #define POS_USER_AGENT 46
232 #define POS_WARNING 48
233 #define POS_WWW_AUTHENTICATE 49
235 #define POS_P_ACCESS_NETWORK_INFO 50
236 #define POS_P_ASSERTED_IDENTITY 51
237 #define POS_P_ASSOCIATED_URI 52
238 #define POS_P_CALLED_PARTY_ID 53
239 #define POS_P_CHARGING_FUNCTION_ADDRESSES 54
240 #define POS_P_CHARGING_VECTOR 55
241 #define POS_P_DCS_TRACE_PARTY_ID 56
242 #define POS_P_DCS_OSPS 57
243 #define POS_P_DCS_BILLING_INFO 58
244 #define POS_P_DCS_LAES 59
245 #define POS_P_DCS_REDIRECT 60
246 #define POS_P_MEDIA_AUTHORIZATION 61
247 #define POS_P_PREFERRED_IDENTITY 62
248 #define POS_P_VISITED_NETWORK_ID 63
250 #define POS_PRIVACY 65
251 #define POS_REASON 66
252 #define POS_REFER_TO 67
253 #define POS_SERVICE_ROUTE 68
255 #define POS_IF_MATCH 70
257 static gint hf_header_array[] = {
258 -1, /* "Unknown-header" - Pad so that the real headers start at index 1 */
260 -1, /* "Accept-Encoding" */
261 -1, /* "Accept-Language" */
262 -1, /* "Alert-Info" */
264 -1, /* "Allow-Events" - RFC 3265 */
265 -1, /* "Authentication-Info" */
266 -1, /* "Authorization" */
268 -1, /* "Call-Info" */
270 -1, /* "Content-Disposition" */
271 -1, /* "Content-Encoding" */
272 -1, /* "Content-Language" */
273 -1, /* "Content-Length" */
274 -1, /* "Content-Type" */
277 -1, /* "Error-Info" */
279 -1, /* "Event" - RFC 3265 */
281 -1, /* "In-Reply-To" */
282 -1, /* "Max-Forwards" */
283 -1, /* "MIME-Version" */
284 -1, /* "Min-Expires" */
285 -1, /* "Organization" */
287 -1, /* "Proxy-Authenticate" */
288 -1, /* "Proxy-Authorization" */
289 -1, /* "Proxy-Require" */
290 -1, /* "RAck" - RFC 3262 */
291 -1, /* "RSeq" - RFC 3261 */
292 -1, /* "Record-Route" */
295 -1, /* "Retry-After" */
299 -1, /* "Subscription-State" - RFC 3265 */
300 -1, /* "Supported" */
301 -1, /* "Timestamp" */
303 -1, /* "Unsupported" */
304 -1, /* "User-Agent" */
307 -1, /* "WWW-Authenticate" */
308 -1, /* "P-Access-Network-Info" - RFC3455 */
309 -1, /* "P-Asserted-Identity" - RFC3325 */
310 -1, /* "P-Associated-URI" - RFC3455 */
311 -1, /* "P-Called-Party-ID" - RFC3455 */
312 -1, /* "P-Charging-Function-Addresses" - RFC3455 */
313 -1, /* "P-Charging-Vector" - RFC3455 */
314 -1, /* "P-DCS-Trace-Party-ID" - RFC3603 */
315 -1, /* "P-DCS-OSPS" - RFC3603 */
316 -1, /* "P-DCS-Billing-Info" - RFC3603 */
317 -1, /* "P-DCS-LAES" - RFC3603 */
318 -1, /* "P-DCS-Redirect" - RFC3603 */
319 -1, /* "P-Media-Authorization" - RFC3313 */
320 -1, /* "P-Preferred-Identity" - RFC3325 */
321 -1, /* "P-Visited-Network-ID" - RFC3455 */
322 -1, /* "Path" - RFC3327 */
323 -1, /* "Privacy" - RFC3323 */
324 -1, /* "Reason" - RFC3326 */
325 -1, /* "Refer-To" - RFC3515 */
326 -1, /* "Service-Route" - RFC3608 */
327 -1, /* "ETag" draft-ietf-sip-publish-01 */
328 -1, /* "If-Match draft-ietf-sip-publish-01 */
333 * Type of line. It's either a SIP Request-Line, a SIP Status-Line, or
334 * another type of line.
342 /* global_sip_raw_text determines whether we are going to display */
343 /* the raw text of the SIP message, much like the MEGACO dissector does. */
344 static gboolean global_sip_raw_text = FALSE;
346 static gboolean dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo,
347 proto_tree *tree, gboolean is_heur);
348 static line_type_t sip_parse_line(tvbuff_t *tvb, gint linelen,
350 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
351 guint meth_len, guint *meth_idx);
352 static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset,
354 static void dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree,
356 static void dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree);
357 static void tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree);
359 /* SIP content type and internet media type used by other dissectors are the same */
360 /* List of nmediatypes from IANA at: http://www.iana.org/assignments/media-types/index.html */
361 static dissector_table_t media_type_dissector_table;
363 #define SIP2_HDR "SIP/2.0"
364 #define SIP2_HDR_LEN (strlen (SIP2_HDR))
366 /* Code to actually dissect the packets */
368 dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
370 if (!dissect_sip_common(tvb, pinfo, tree, FALSE))
372 return tvb_length(tvb);
376 dissect_sip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
378 dissect_sip_common(tvb, pinfo, tree, TRUE);
382 dissect_sip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
384 return dissect_sip_common(tvb, pinfo, tree, FALSE);
388 dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
389 gboolean dissect_other_as_continuation)
392 gint next_offset, linelen;
393 line_type_t line_type;
395 gboolean is_known_request;
396 gboolean found_match = FALSE;
399 guint current_method_idx = 0;
400 proto_item *ts = NULL, *ti, *th = NULL, *sip_element_item;
401 proto_tree *sip_tree = NULL, *reqresp_tree, *hdr_tree = NULL, *sip_element_tree, *message_body_tree;
402 guchar contacts = 0, contact_is_star = 0, expires_is_0 = 0;
403 char csec_method[16] = "";
404 char *media_type_str = NULL;
405 char *content_type_parameter_str = NULL;
408 * Note that "tvb_find_line_end()" will return a value that
409 * is not longer than what's in the buffer, so the
410 * "tvb_get_ptr()" calls below won't throw exceptions.
412 * Note that "tvb_strneql()" doesn't throw exceptions, so
413 * "sip_parse_line()" won't throw an exception.
416 linelen = tvb_find_line_end(tvb, 0, -1, &next_offset, FALSE);
417 line_type = sip_parse_line(tvb, linelen, &token_1_len);
418 if (line_type == OTHER_LINE) {
420 * This is neither a SIP request nor response.
422 if (!dissect_other_as_continuation) {
424 * We were asked to reject this.
430 * Just dissect it as a continuation.
434 if (check_col(pinfo->cinfo, COL_PROTOCOL))
435 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIP");
440 is_known_request = sip_is_known_request(tvb, 0, token_1_len, ¤t_method_idx);
441 descr = is_known_request ? "Request" : "Unknown request";
442 if (check_col(pinfo->cinfo, COL_INFO)) {
443 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
445 tvb_format_text(tvb, 0, linelen - SIP2_HDR_LEN - 1));
451 if (check_col(pinfo->cinfo, COL_INFO)) {
452 col_add_fstr(pinfo->cinfo, COL_INFO, "Status: %s",
453 tvb_format_text(tvb, SIP2_HDR_LEN + 1, linelen - SIP2_HDR_LEN - 1));
458 default: /* Squelch compiler complaints */
459 descr = "Continuation";
460 if (check_col(pinfo->cinfo, COL_INFO))
461 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
465 ts = proto_tree_add_item(tree, proto_sip, tvb, 0, -1, FALSE);
466 sip_tree = proto_item_add_subtree(ts, ett_sip);
468 ti = proto_tree_add_text(sip_tree, tvb, 0, next_offset,
469 "%s line: %s", descr,
470 tvb_format_text(tvb, 0, linelen));
471 reqresp_tree = proto_item_add_subtree(ti, ett_sip_reqresp);
476 dfilter_sip_request_line(tvb, reqresp_tree, token_1_len);
480 dfilter_sip_status_line(tvb, reqresp_tree);
484 proto_tree_add_text(sip_tree, tvb, 0, -1,
485 "Continuation data");
489 offset = next_offset;
490 th = proto_tree_add_item(sip_tree, hf_msg_hdr, tvb, offset, -1,
492 hdr_tree = proto_item_add_subtree(th, ett_sip_hdr);
496 * Process the headers - if we're not building a protocol tree,
497 * we just do this to find the blank line separating the
498 * headers from the message body.
500 next_offset = offset;
501 while (tvb_reported_length_remaining(tvb, offset) > 0) {
502 gint line_end_offset;
504 gint semicolon_offset;
505 gint content_type_len, content_type_parameter_str_len;
508 gint value_offset,tag_offset;
513 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset,
517 * This is a blank line separating the
518 * message header from the message body.
522 line_end_offset = offset + linelen;
523 colon_offset = tvb_find_guint8(tvb, offset, linelen, ':');
524 if (colon_offset == -1) {
526 * Malformed header - no colon after the name.
528 proto_tree_add_text(hdr_tree, tvb, offset,
529 next_offset - offset, "%s",
530 tvb_format_text(tvb, offset, linelen));
532 header_len = colon_offset - offset;
533 hf_index = sip_is_known_sip_header(tvb,
536 if (hf_index == -1) {
537 proto_tree_add_text(hdr_tree, tvb,
538 offset, next_offset - offset, "%s",
539 tvb_format_text(tvb, offset, linelen));
542 * Skip whitespace after the colon.
544 value_offset = colon_offset + 1;
545 while (value_offset < line_end_offset
546 && ((c = tvb_get_guint8(tvb,
547 value_offset)) == ' '
553 value_len = line_end_offset - value_offset;
554 value = tvb_get_string(tvb, value_offset,
558 * Add it to the protocol tree,
559 * but display the line as is.
561 switch ( hf_index ) {
564 sip_element_item = proto_tree_add_string_format(hdr_tree,
565 hf_header_array[hf_index], tvb,
566 offset, next_offset - offset,
568 tvb_format_text(tvb, offset, linelen));
569 sip_element_tree = proto_item_add_subtree( sip_element_item,
571 tag_offset = tvb_find_guint8(tvb, offset,linelen, ';');
572 if ( tag_offset != -1){
573 tag_offset = tag_offset + 1;
574 c = tvb_get_guint8(tvb,tag_offset);
575 if ( c == 't' ){/* tag found */
576 proto_tree_add_string(sip_element_tree,
578 value_offset, (tag_offset - value_offset - 1),
579 tvb_format_text(tvb, value_offset,
580 ( tag_offset - value_offset - 1)));
581 tag_offset = tvb_find_guint8(tvb, tag_offset,linelen, '=') + 1;
582 proto_tree_add_string(sip_element_tree,
584 tag_offset, (line_end_offset - tag_offset),
585 tvb_format_text(tvb, tag_offset, (line_end_offset - tag_offset)));
589 proto_tree_add_string_format(sip_element_tree,
591 offset, line_end_offset - offset,
593 tvb_format_text(tvb, offset, linelen));
595 } /* if tag offset */
599 sip_element_item = proto_tree_add_string_format(hdr_tree,
600 hf_header_array[hf_index], tvb,
601 offset, next_offset - offset,
603 tvb_format_text(tvb, offset, linelen));
604 sip_element_tree = proto_item_add_subtree( sip_element_item, ett_sip_element);
605 tag_offset = tvb_find_guint8(tvb, offset,linelen, ';');
606 if ( tag_offset != -1){
607 tag_offset = tag_offset + 1;
608 c = tvb_get_guint8(tvb,tag_offset);
609 if ( c == 't' ){/* tag found */
610 proto_tree_add_string(sip_element_tree,
611 hf_sip_from_addr, tvb,
612 value_offset, (tag_offset - value_offset - 1),
613 tvb_format_text(tvb, value_offset, ( tag_offset - value_offset - 1)));
614 tag_offset = tvb_find_guint8(tvb, offset,linelen, '=') + 1;
615 proto_tree_add_string(sip_element_tree,
617 tag_offset, (line_end_offset - tag_offset),
618 tvb_format_text(tvb, tag_offset, (line_end_offset - tag_offset)));
621 tag_offset = tvb_find_guint8(tvb, tag_offset,linelen, ';');
622 if ( tag_offset != -1){
623 tag_offset = tag_offset + 1;
624 c = tvb_get_guint8(tvb,tag_offset);
625 if ( c == 't' ){/* tag found */
626 proto_tree_add_string(sip_element_tree,
627 hf_sip_from_addr, tvb,
628 value_offset, (tag_offset - value_offset - 1),
629 tvb_format_text(tvb, value_offset, ( tag_offset - value_offset - 1)));
630 tag_offset = tvb_find_guint8(tvb, tag_offset,linelen, '=') + 1;
631 proto_tree_add_string(sip_element_tree,
633 tag_offset, (line_end_offset - tag_offset),
634 tvb_format_text(tvb, tag_offset, (line_end_offset - tag_offset)));
638 } /* if tag offset */
642 /* Extract method name from value */
643 for (value_offset = 0; value_offset < (gint)strlen(value); value_offset++)
645 if (isalpha(value[value_offset]))
647 strcpy(csec_method,value+value_offset);
651 /* Add 'CSeq' string item to tree */
652 proto_tree_add_string_format(hdr_tree,
653 hf_header_array[hf_index], tvb,
654 offset, next_offset - offset,
656 tvb_format_text(tvb, offset, linelen));
660 if (strcmp(value, "0") == 0)
664 /* Add 'Expires' string item to tree */
665 proto_tree_add_string_format(hdr_tree,
666 hf_header_array[hf_index], tvb,
667 offset, next_offset - offset,
669 tvb_format_text(tvb, offset, linelen));
673 * Content-Type is the same as Internet
674 * media type used by other dissectors,
675 * appropriate dissector found by
676 * lookup in "media_type" dissector table.
678 case POS_CONTENT_TYPE :
679 proto_tree_add_string_format(hdr_tree,
680 hf_header_array[hf_index], tvb,
681 offset, next_offset - offset,
683 tvb_format_text(tvb, offset, linelen));
684 content_type_len = value_len;
685 semicolon_offset = tvb_find_guint8(tvb, value_offset,linelen, ';');
686 if ( semicolon_offset != -1) {
687 content_type_len = semicolon_offset - value_offset;
688 content_type_parameter_str_len = linelen - semicolon_offset;
689 content_type_parameter_str = tvb_get_string(tvb, semicolon_offset + 1, content_type_parameter_str_len);
691 media_type_str = tvb_get_string(tvb, value_offset, content_type_len);
696 if (strcmp(value, "*") == 0)
700 /* Fall through to default case to add string to tree */
703 proto_tree_add_string_format(hdr_tree,
704 hf_header_array[hf_index], tvb,
705 offset, next_offset - offset,
707 tvb_format_text(tvb, offset, linelen));
712 }/* if colon_offset */
713 offset = next_offset;
716 if (tvb_offset_exists(tvb, next_offset)) {
719 * There's a message body starting at "next_offset".
720 * Set the length of the SIP portion and of the
723 proto_item_set_end(ts, tvb, next_offset);
724 proto_item_set_end(th, tvb, next_offset);
725 next_tvb = tvb_new_subset(tvb, next_offset, -1, -1);
726 ti = proto_tree_add_text(sip_tree, next_tvb, 0, -1,
728 message_body_tree = proto_item_add_subtree(ti, ett_sip_message_body);
730 /* give the content type parameters to sub dissectors */
732 if ( media_type_str != NULL ) {
733 pinfo->private_data = content_type_parameter_str;
734 found_match = dissector_try_string(media_type_dissector_table,
738 g_free(media_type_str);
739 g_free(content_type_parameter_str);
740 /* If no match dump as text */
742 if ( found_match != TRUE )
745 while (tvb_offset_exists(next_tvb, offset)) {
746 tvb_find_line_end(next_tvb, offset, -1, &next_offset, FALSE);
747 linelen = next_offset - offset;
748 proto_tree_add_text(message_body_tree, next_tvb, offset, linelen,
749 "%s", tvb_format_text(next_tvb, offset, linelen));
750 offset = next_offset;
756 /* Add to info column interesting things learned from header fields. */
757 if (check_col(pinfo->cinfo, COL_INFO))
759 /* Registration requests */
760 if (strcmp(sip_methods[current_method_idx], "REGISTER") == 0)
762 if (contact_is_star && expires_is_0)
764 col_append_str(pinfo->cinfo, COL_INFO, " (remove all bindings)");
769 col_append_str(pinfo->cinfo, COL_INFO, " (fetch bindings)");
773 /* Registration responses */
774 if (line_type == STATUS_LINE && (strcmp(csec_method, "REGISTER") == 0))
776 col_append_fstr(pinfo->cinfo, COL_INFO, " (%d bindings)", contacts);
780 if (global_sip_raw_text)
781 tvb_raw_text_add(tvb, tree);
786 /* Display filter for SIP Request-Line */
788 dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, guint meth_len)
793 * We know we have the entire method; otherwise, "sip_parse_line()"
794 * would have returned OTHER_LINE.
796 string = tvb_get_string(tvb, 0, meth_len);
797 proto_tree_add_string(tree, hf_Method, tvb, 0, meth_len, string);
801 /* Display filter for SIP Status-Line */
803 dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree)
808 * We know we have the entire status code; otherwise,
809 * "sip_parse_line()" would have returned OTHER_LINE.
810 * We also know that we have a version string followed by a
811 * space at the beginning of the line, for the same reason.
813 tvb_memcpy(tvb, (guint8 *)string, SIP2_HDR_LEN + 1, 3);
815 proto_tree_add_string(tree, hf_Status_Code, tvb, SIP2_HDR_LEN + 1,
819 /* From section 4.1 of RFC 2543:
821 * Request-Line = Method SP Request-URI SP SIP-Version CRLF
823 * From section 5.1 of RFC 2543:
825 * Status-Line = SIP-version SP Status-Code SP Reason-Phrase CRLF
828 sip_parse_line(tvbuff_t *tvb, gint linelen, guint *token_1_lenp)
838 space_offset = tvb_find_guint8(tvb, 0, -1, ' ');
839 if (space_offset <= 0) {
841 * Either there's no space in the line (which means
842 * the line is empty or doesn't have a token followed
843 * by a space; neither is valid for a request or status), or
844 * the first character in the line is a space (meaning
845 * the method is empty, which isn't valid for a request,
846 * or the SIP version is empty, which isn't valid for a
851 token_1_len = space_offset;
852 token_2_start = space_offset + 1;
853 space_offset = tvb_find_guint8(tvb, token_2_start, -1, ' ');
854 if (space_offset == -1) {
856 * There's no space after the second token, so we don't
857 * have a third token.
861 token_2_len = space_offset - token_2_start;
862 token_3_start = space_offset + 1;
863 token_3_len = linelen - token_3_start;
865 *token_1_lenp = token_1_len;
868 * Is the first token a version string?
870 if (token_1_len == SIP2_HDR_LEN &&
871 tvb_strneql(tvb, 0, SIP2_HDR, SIP2_HDR_LEN) == 0) {
873 * Yes, so this is either a Status-Line or something
874 * else other than a Request-Line. To be a Status-Line,
875 * the second token must be a 3-digit number.
877 if (token_2_len != 3) {
879 * We don't have 3-character status code.
883 if (!isdigit(tvb_get_guint8(tvb, token_2_start)) ||
884 !isdigit(tvb_get_guint8(tvb, token_2_start + 1)) ||
885 !isdigit(tvb_get_guint8(tvb, token_2_start + 2))) {
887 * 3 characters yes, 3 digits no.
894 * No, so this is either a Request-Line or something
895 * other than a Status-Line. To be a Request-Line, the
896 * second token must be a URI and the third token must
897 * be a version string.
899 if (token_2_len < 3) {
901 * We don't have a URI consisting of at least 3
906 colon_pos = tvb_find_guint8(tvb, token_2_start + 1, -1, ':');
907 if (colon_pos == -1) {
909 * There is no colon after the method, so the URI
910 * doesn't have a colon in it, so it's not valid.
914 if (colon_pos >= token_3_start) {
916 * The colon is in the version string, not the URI.
920 /* XXX - Check for a proper URI prefix? */
921 if (token_3_len != SIP2_HDR_LEN ||
922 tvb_strneql(tvb, token_3_start, SIP2_HDR, SIP2_HDR_LEN) == -1) {
924 * The version string isn't an SIP version 2.0 version
933 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
934 guint meth_len, guint *meth_idx)
938 for (i = 1; i < array_length(sip_methods); i++) {
939 if (meth_len == strlen(sip_methods[i]) &&
940 tvb_strneql(tvb, meth_offset, sip_methods[i], meth_len) == 0)
950 /* Returns index of method in sip_headers */
951 static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset, guint header_len)
955 for (i = 1; i < array_length(sip_headers); i++) {
956 if (header_len == strlen(sip_headers[i].name) &&
957 tvb_strncaseeql(tvb, offset, sip_headers[i].name, header_len) == 0)
959 if (sip_headers[i].compact_name != NULL &&
960 header_len == strlen(sip_headers[i].compact_name) &&
961 tvb_strncaseeql(tvb, offset, sip_headers[i].compact_name, header_len) == 0)
969 * Display the entire message as raw text.
972 tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree)
974 proto_tree *raw_tree;
976 int offset, next_offset, linelen;
978 ti = proto_tree_add_item(tree, proto_raw_sip, tvb, 0, -1, FALSE);
979 raw_tree = proto_item_add_subtree(ti, ett_raw_text);
983 while (tvb_offset_exists(tvb, offset)) {
984 tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
985 linelen = next_offset - offset;
986 proto_tree_add_text(raw_tree, tvb, offset, linelen,
987 "%s", tvb_format_text(tvb, offset, linelen));
988 offset = next_offset;
992 /* Register the protocol with Ethereal */
993 void proto_register_sip(void)
996 /* Setup list of header fields */
997 static hf_register_info hf[] = {
1000 { "Message Header", "sip.msg_hdr",
1001 FT_NONE, 0, NULL, 0,
1002 "Message Header in SIP message", HFILL }
1005 { "Method", "sip.Method",
1006 FT_STRING, BASE_NONE,NULL,0x0,
1007 "SIP Method", HFILL }
1010 { "Status-Code", "sip.Status-Code",
1011 FT_STRING, BASE_NONE,NULL,0x0,
1012 "SIP Status Code", HFILL }
1015 { "SIP to address", "sip.from_addr",
1016 FT_STRING, BASE_NONE,NULL,0x0,
1017 "RFC 3261: from addr", HFILL }
1019 { &hf_sip_from_addr,
1020 { "SIP from address", "sip.to_addr",
1021 FT_STRING, BASE_NONE,NULL,0x0,
1022 "RFC 3261: to addr", HFILL }
1025 { "SIP tag", "sip.tag",
1026 FT_STRING, BASE_NONE,NULL,0x0,
1027 "RFC 3261: tag", HFILL }
1029 { &hf_header_array[POS_ACCEPT],
1030 { "Accept", "sip.Accept",
1031 FT_STRING, BASE_NONE,NULL,0x0,
1032 "RFC 3261: Accept Header", HFILL }
1034 { &hf_header_array[POS_ACCEPT_ENCODING],
1035 { "Accept-Encoding", "sip.Accept-Encoding",
1036 FT_STRING, BASE_NONE,NULL,0x0,
1037 "RFC 3261: Accept-Encoding Header", HFILL }
1039 { &hf_header_array[POS_ACCEPT_LANGUAGE],
1040 { "Accept-Language", "sip.Accept-Language",
1041 FT_STRING, BASE_NONE,NULL,0x0,
1042 "RFC 3261: Accept-Language Header", HFILL }
1044 { &hf_header_array[POS_ALERT_INFO],
1045 { "Alert-Info", "sip.Alert-Info",
1046 FT_STRING, BASE_NONE,NULL,0x0,
1047 "RFC 3261: Alert-Info Header", HFILL }
1049 { &hf_header_array[POS_ALLOW],
1050 { "Allow", "sip.Allow",
1051 FT_STRING, BASE_NONE,NULL,0x0,
1052 "RFC 3261: Allow Header", HFILL }
1054 { &hf_header_array[POS_ALLOW_EVENTS],
1055 { "Allow-Events", "sip.Allow-Events",
1056 FT_STRING, BASE_NONE,NULL,0x0,
1057 "RFC 3265: Allow-Events Header", HFILL }
1059 { &hf_header_array[POS_AUTHENTICATION_INFO],
1060 { "Authentication-Info", "sip.Authentication-Info",
1061 FT_STRING, BASE_NONE,NULL,0x0,
1062 "RFC 3261: Authentication-Info Header", HFILL }
1064 { &hf_header_array[POS_AUTHORIZATION],
1065 { "Authorization", "sip.Authorization",
1066 FT_STRING, BASE_NONE,NULL,0x0,
1067 "RFC 3261: Authorization Header", HFILL }
1069 { &hf_header_array[POS_CALL_ID],
1070 { "Call-ID", "sip.Call-ID",
1071 FT_STRING, BASE_NONE,NULL,0x0,
1072 "RFC 3261: Call-ID Header", HFILL }
1074 { &hf_header_array[POS_CALL_INFO],
1075 { "Call-Info", "sip.Call-Info",
1076 FT_STRING, BASE_NONE,NULL,0x0,
1077 "RFC 3261: Call-Info Header", HFILL }
1079 { &hf_header_array[POS_CONTACT],
1080 { "Contact", "sip.Contact",
1081 FT_STRING, BASE_NONE,NULL,0x0,
1082 "RFC 3261: Contact Header", HFILL }
1084 { &hf_header_array[POS_CONTENT_DISPOSITION],
1085 { "Content-Disposition", "sip.Content-Disposition",
1086 FT_STRING, BASE_NONE,NULL,0x0,
1087 "RFC 3261: Content-Disposition Header", HFILL }
1089 { &hf_header_array[POS_CONTENT_ENCODING],
1090 { "Content-Encoding", "sip.Content-Encoding",
1091 FT_STRING, BASE_NONE,NULL,0x0,
1092 "RFC 3261: Content-Encoding Header", HFILL }
1094 { &hf_header_array[POS_CONTENT_LANGUAGE],
1095 { "Content-Language", "sip.Content-Language",
1096 FT_STRING, BASE_NONE,NULL,0x0,
1097 "RFC 3261: Content-Language Header", HFILL }
1099 { &hf_header_array[POS_CONTENT_LENGTH],
1100 { "Content-Length", "sip.Content-Length",
1101 FT_STRING, BASE_NONE,NULL,0x0,
1102 "RFC 3261: Content-Length Header", HFILL }
1104 { &hf_header_array[POS_CONTENT_TYPE],
1105 { "Content-Type", "sip.Content-Type",
1106 FT_STRING, BASE_NONE,NULL,0x0,
1107 "RFC 3261: Content-Type Header", HFILL }
1109 { &hf_header_array[POS_CSEQ],
1110 { "CSeq", "sip.CSeq",
1111 FT_STRING, BASE_NONE,NULL,0x0,
1112 "RFC 3261: CSeq Header", HFILL }
1114 { &hf_header_array[POS_DATE],
1115 { "Date", "sip.Date",
1116 FT_STRING, BASE_NONE,NULL,0x0,
1117 "RFC 3261: Date Header", HFILL }
1119 { &hf_header_array[POS_ERROR_INFO],
1120 { "Error-Info", "sip.Error-Info",
1121 FT_STRING, BASE_NONE,NULL,0x0,
1122 "RFC 3261: Error-Info Header", HFILL }
1124 { &hf_header_array[POS_EVENT],
1125 { "Event", "sip.Event",
1126 FT_STRING, BASE_NONE,NULL,0x0,
1127 "RFC 3265: Event Header", HFILL }
1129 { &hf_header_array[POS_EXPIRES],
1130 { "Expires", "sip.Expires",
1131 FT_STRING, BASE_NONE,NULL,0x0,
1132 "RFC 3261: Expires Header", HFILL }
1134 { &hf_header_array[POS_FROM],
1135 { "From", "sip.From",
1136 FT_STRING, BASE_NONE,NULL,0x0,
1137 "RFC 3261: From Header", HFILL }
1139 { &hf_header_array[POS_IN_REPLY_TO],
1140 { "In-Reply-To", "sip.In-Reply-To",
1141 FT_STRING, BASE_NONE,NULL,0x0,
1142 "RFC 3261: In-Reply-To Header", HFILL }
1144 { &hf_header_array[POS_MAX_FORWARDS],
1145 { "Max-Forwards", "sip.Max-Forwards",
1146 FT_STRING, BASE_NONE,NULL,0x0,
1147 "RFC 3261: Max-Forwards Header", HFILL }
1149 { &hf_header_array[POS_MIME_VERSION],
1150 { "MIME-Version", "sip.MIME-Version",
1151 FT_STRING, BASE_NONE,NULL,0x0,
1152 "RFC 3261: MIME-Version Header", HFILL }
1154 { &hf_header_array[POS_MIN_EXPIRES],
1155 { "Min-Expires", "sip.Min-Expires",
1156 FT_STRING, BASE_NONE,NULL,0x0,
1157 "RFC 3261: Min-Expires Header", HFILL }
1159 { &hf_header_array[POS_ORGANIZATION],
1160 { "Organization", "sip.Organization",
1161 FT_STRING, BASE_NONE,NULL,0x0,
1162 "RFC 3261: Organization Header", HFILL }
1164 { &hf_header_array[POS_PRIORITY],
1165 { "Priority", "sip.Priority",
1166 FT_STRING, BASE_NONE,NULL,0x0,
1167 "RFC 3261: Priority Header", HFILL }
1169 { &hf_header_array[POS_PROXY_AUTHENTICATE],
1170 { "Proxy-Authenticate", "sip.Proxy-Authenticate",
1171 FT_STRING, BASE_NONE,NULL,0x0,
1172 "RFC 3261: Proxy-Authenticate Header", HFILL }
1174 { &hf_header_array[POS_PROXY_AUTHORIZATION],
1175 { "Proxy-Authorization", "sip.Proxy-Authorization",
1176 FT_STRING, BASE_NONE,NULL,0x0,
1177 "RFC 3261: Proxy-Authorization Header", HFILL }
1179 { &hf_header_array[POS_RACK],
1180 { "RAck", "sip.RAck",
1181 FT_STRING, BASE_NONE,NULL,0x0,
1182 "RFC 3262: RAck Header", HFILL }
1184 { &hf_header_array[POS_RSEQ],
1185 { "RSeq", "sip.RSeq",
1186 FT_STRING, BASE_NONE,NULL,0x0,
1187 "RFC 3262: RSeq Header", HFILL }
1189 { &hf_header_array[POS_PROXY_REQUIRE],
1190 { "Proxy-Require", "sip.Proxy-Require",
1191 FT_STRING, BASE_NONE,NULL,0x0,
1192 "RFC 3261: Proxy-Require Header", HFILL }
1194 { &hf_header_array[POS_RECORD_ROUTE],
1195 { "Record-Route", "sip.Record-Route",
1196 FT_STRING, BASE_NONE,NULL,0x0,
1197 "RFC 3261: Record-Route Header", HFILL }
1199 { &hf_header_array[POS_REPLY_TO],
1200 { "Reply-To", "sip.Reply-To",
1201 FT_STRING, BASE_NONE,NULL,0x0,
1202 "RFC 3261: Reply-To Header", HFILL }
1204 { &hf_header_array[POS_REQUIRE],
1205 { "Require", "sip.Require",
1206 FT_STRING, BASE_NONE,NULL,0x0,
1207 "RFC 3261: Require Header", HFILL }
1209 { &hf_header_array[POS_RETRY_AFTER],
1210 { "Retry-After", "sip.Retry-After",
1211 FT_STRING, BASE_NONE,NULL,0x0,
1212 "RFC 3261: Retry-After Header", HFILL }
1214 { &hf_header_array[POS_ROUTE],
1215 { "Route", "sip.Route",
1216 FT_STRING, BASE_NONE,NULL,0x0,
1217 "RFC 3261: Route Header", HFILL }
1219 { &hf_header_array[POS_SERVER],
1220 { "Server", "sip.Server",
1221 FT_STRING, BASE_NONE,NULL,0x0,
1222 "RFC 3261: Server Header", HFILL }
1224 { &hf_header_array[POS_SUBJECT],
1225 { "Subject", "sip.Subject",
1226 FT_STRING, BASE_NONE,NULL,0x0,
1227 "RFC 3261: Subject Header", HFILL }
1229 { &hf_header_array[POS_SUBSCRIPTION_STATE],
1230 { "Subscription-State", "sip.Subscription-State",
1231 FT_STRING, BASE_NONE,NULL,0x0,
1232 "RFC 3265: Subscription-State Header", HFILL }
1234 { &hf_header_array[POS_SUPPORTED],
1235 { "Supported", "sip.Supported",
1236 FT_STRING, BASE_NONE,NULL,0x0,
1237 "RFC 3261: Supported Header", HFILL }
1239 { &hf_header_array[POS_TIMESTAMP],
1240 { "Timestamp", "sip.Timestamp",
1241 FT_STRING, BASE_NONE,NULL,0x0,
1242 "RFC 3261: Timestamp Header", HFILL }
1244 { &hf_header_array[POS_TO],
1246 FT_STRING, BASE_NONE,NULL,0x0,
1247 "RFC 3261: To Header", HFILL }
1249 { &hf_header_array[POS_UNSUPPORTED],
1250 { "Unsupported", "sip.Unsupported",
1251 FT_STRING, BASE_NONE,NULL,0x0,
1252 "RFC 3261: Unsupported Header", HFILL }
1254 { &hf_header_array[POS_USER_AGENT],
1255 { "User-Agent", "sip.User-Agent",
1256 FT_STRING, BASE_NONE,NULL,0x0,
1257 "RFC 3261: User-Agent Header", HFILL }
1259 { &hf_header_array[POS_VIA],
1261 FT_STRING, BASE_NONE,NULL,0x0,
1262 "RFC 3261: Via Header", HFILL }
1264 { &hf_header_array[POS_WARNING],
1265 { "Warning", "sip.Warning",
1266 FT_STRING, BASE_NONE,NULL,0x0,
1267 "RFC 3261: Warning Header", HFILL }
1269 { &hf_header_array[POS_WWW_AUTHENTICATE],
1270 { "WWW-Authenticate", "sip.WWW-Authenticate",
1271 FT_STRING, BASE_NONE,NULL,0x0,
1272 "RFC 3261: WWW-Authenticate Header", HFILL }
1274 { &hf_header_array[POS_P_ACCESS_NETWORK_INFO],
1275 { "P-Access-Network-Info", "sip.P-Access-Network-Info",
1276 FT_STRING, BASE_NONE,NULL,0x0,
1277 "P-Access-Network-Info Header", HFILL }
1280 { &hf_header_array[POS_P_ASSERTED_IDENTITY],
1281 { "P-Asserted-Identity", "sip.P-Asserted-Identity",
1282 FT_STRING, BASE_NONE,NULL,0x0,
1283 "P-Asserted-Identity Header", HFILL }
1286 { &hf_header_array[POS_P_ASSOCIATED_URI],
1287 { "P-Associated-URI", "sip.P-Associated-URI",
1288 FT_STRING, BASE_NONE,NULL,0x0,
1289 "P-Associated-URI Header", HFILL }
1292 { &hf_header_array[POS_P_CALLED_PARTY_ID],
1293 { "P-Called-Party-ID", "sip.P-Called-Party-ID",
1294 FT_STRING, BASE_NONE,NULL,0x0,
1295 "P-Called-Party-ID Header", HFILL }
1298 { &hf_header_array[POS_P_CHARGING_FUNCTION_ADDRESSES],
1299 { "P-Charging-Function-Addresses","sip.P-Charging-Function-Addresses",
1300 FT_STRING, BASE_NONE,NULL,0x0,
1301 "P-Charging-Function-Addresses", HFILL }
1304 { &hf_header_array[POS_P_CHARGING_VECTOR],
1305 { "P-Charging-Vector", "sip.P-Charging-Vector",
1306 FT_STRING, BASE_NONE,NULL,0x0,
1307 "P-Charging-Vector Header", HFILL }
1310 { &hf_header_array[POS_P_DCS_TRACE_PARTY_ID],
1311 { "P-DCS-Trace-Party-ID", "sip.P-DCS-Trace-Party-ID",
1312 FT_STRING, BASE_NONE,NULL,0x0,
1313 "P-DCS-Trace-Party-ID Header", HFILL }
1316 { &hf_header_array[POS_P_DCS_OSPS],
1317 { "P-DCS-OSPS", "sip.P-DCS-OSPS",
1318 FT_STRING, BASE_NONE,NULL,0x0,
1319 "P-DCS-OSPS Header", HFILL }
1322 { &hf_header_array[POS_P_DCS_BILLING_INFO],
1323 { "P-DCS-Billing-Info", "sip.P-DCS-Billing-Info",
1324 FT_STRING, BASE_NONE,NULL,0x0,
1325 "P-DCS-Billing-Info Header", HFILL }
1328 { &hf_header_array[POS_P_DCS_LAES],
1329 { "P-DCS-LAES", "sip.P-DCS-LAES",
1330 FT_STRING, BASE_NONE,NULL,0x0,
1331 "P-DCS-LAES Header", HFILL }
1334 { &hf_header_array[POS_P_DCS_REDIRECT],
1335 { "P-DCS-Redirect", "sip.P-DCS-Redirect",
1336 FT_STRING, BASE_NONE,NULL,0x0,
1337 "P-DCS-Redirect Header", HFILL }
1340 { &hf_header_array[POS_P_MEDIA_AUTHORIZATION],
1341 { "P-Media-Authorization", "sip.P-Media-Authorization",
1342 FT_STRING, BASE_NONE,NULL,0x0,
1343 "P-Media-Authorization Header", HFILL }
1346 { &hf_header_array[POS_P_PREFERRED_IDENTITY],
1347 { "P-Preferred-Identity", "sip.P-Preferred-Identity",
1348 FT_STRING, BASE_NONE,NULL,0x0,
1349 "P-Preferred-Identity Header", HFILL }
1352 { &hf_header_array[POS_P_VISITED_NETWORK_ID],
1353 { "P-Visited-Network-ID", "sip.P-Visited-Network-ID",
1354 FT_STRING, BASE_NONE,NULL,0x0,
1355 "P-Visited-Network-ID Header", HFILL }
1358 { &hf_header_array[POS_PATH],
1359 { "Path", "sip.Path",
1360 FT_STRING, BASE_NONE,NULL,0x0,
1361 "Path Header", HFILL }
1364 { &hf_header_array[POS_PRIVACY],
1365 { "Privacy", "sip.Privacy",
1366 FT_STRING, BASE_NONE,NULL,0x0,
1367 "Privacy Header", HFILL }
1370 { &hf_header_array[POS_REASON],
1371 { "Reason", "sip.Reason",
1372 FT_STRING, BASE_NONE,NULL,0x0,
1373 "Reason Header", HFILL }
1376 { &hf_header_array[POS_REFER_TO],
1377 { "Refer-To", "sip.Refer-To",
1378 FT_STRING, BASE_NONE,NULL,0x0,
1379 "Refer-To Header", HFILL }
1382 { &hf_header_array[POS_SERVICE_ROUTE],
1383 { "Service-Route", "sip.Service-Route",
1384 FT_STRING, BASE_NONE,NULL,0x0,
1385 "Service-Route Header", HFILL }
1388 { &hf_header_array[POS_ETAG],
1389 { "ETag", "sip.ETag",
1390 FT_STRING, BASE_NONE,NULL,0x0,
1391 "ETag Header", HFILL }
1393 { &hf_header_array[POS_IF_MATCH],
1394 { "If_Match", "sip.If_Match",
1395 FT_STRING, BASE_NONE,NULL,0x0,
1396 "If-Match Header", HFILL }
1400 /* Setup protocol subtree array */
1401 static gint *ett[] = {
1406 &ett_sip_message_body,
1408 static gint *ett_raw[] = {
1412 module_t *sip_module;
1414 /* Register the protocol name and description */
1415 proto_sip = proto_register_protocol("Session Initiation Protocol",
1417 proto_raw_sip = proto_register_protocol("Session Initiation Protocol (SIP as raw text)",
1418 "Raw_SIP", "raw_sip");
1420 /* Required function calls to register the header fields and subtrees used */
1421 proto_register_field_array(proto_sip, hf, array_length(hf));
1422 proto_register_subtree_array(ett, array_length(ett));
1423 proto_register_subtree_array(ett_raw, array_length(ett_raw));
1425 /* SIP content type and internet media type used by other dissectors are the same */
1427 media_type_dissector_table = find_dissector_table("media_type");
1430 sip_module = prefs_register_protocol(proto_sip, NULL);
1432 prefs_register_bool_preference(sip_module, "display_raw_text",
1433 "Display raw text for SIP message",
1434 "Specifies that the raw text of the "
1435 "SIP message should be displayed "
1436 "in addition to the dissection tree",
1437 &global_sip_raw_text);
1441 proto_reg_handoff_sip(void)
1443 dissector_handle_t sip_handle, sip_tcp_handle;
1445 sip_handle = new_create_dissector_handle(dissect_sip, proto_sip);
1446 dissector_add("udp.port", UDP_PORT_SIP, sip_handle);
1448 sip_tcp_handle = create_dissector_handle(dissect_sip_tcp, proto_sip);
1449 dissector_add("tcp.port", TCP_PORT_SIP, sip_tcp_handle);
1451 heur_dissector_add("udp", dissect_sip_heur, proto_sip);
1452 heur_dissector_add("tcp", dissect_sip_heur, proto_sip);
1453 heur_dissector_add("sctp", dissect_sip_heur, proto_sip);