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.60 2004/02/18 20:55:57 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_Request_Line = -1;
67 static gint hf_Status_Code = -1;
68 static gint hf_Status_Line = -1;
69 static gint hf_sip_to_addr = -1;
70 static gint hf_sip_from_addr = -1;
71 static gint hf_sip_tag = -1;
73 /* Initialize the subtree pointers */
74 static gint ett_sip = -1;
75 static gint ett_sip_reqresp = -1;
76 static gint ett_sip_hdr = -1;
77 static gint ett_raw_text = -1;
78 static gint ett_sip_element = -1;
79 static gint ett_sip_message_body = -1;
81 /* PUBLISH method added as per http://www.ietf.org/internet-drafts/draft-ietf-sip-publish-01.txt */
82 static const char *sip_methods[] = {
83 "<Invalid method>", /* Pad so that the real methods start at index 1 */
104 /* Updated with info from http://www.iana.org/assignments/sip-parameters */
105 /* (last updated 2003-10-31) */
106 /* Added two headsers ( Etag and If-Match )from http://www.ietf.org/internet-drafts/draft-ietf-sip-publish-01.txt */
111 static const sip_header_t sip_headers[] = {
112 { "Unknown-header", NULL }, /* Pad so that the real headers start at index 1 */
114 { "Accept-Encoding", NULL },
115 { "Accept-Language", NULL },
116 { "Alert-Info", NULL },
118 { "Allow-Events", NULL },
119 { "Authentication-Info", NULL },
120 { "Authorization", NULL },
122 { "Call-Info", NULL },
124 { "Content-Disposition", NULL },
125 { "Content-Encoding", "e" },
126 { "Content-Language", NULL },
127 { "Content-Length", "l" },
128 { "Content-Type", "c" },
131 { "Error-Info", NULL },
135 { "In-Reply-To", NULL },
136 { "Max-Forwards", NULL },
137 { "MIME-Version", NULL },
138 { "Min-Expires", NULL },
139 { "Organization", NULL },
140 { "Priority", NULL },
141 { "Proxy-Authenticate", NULL },
142 { "Proxy-Authorization", NULL },
143 { "Proxy-Require", NULL },
146 { "Record-Route", NULL },
147 { "Reply-To", NULL },
149 { "Retry-After", NULL },
153 { "Subscription-State", NULL },
154 { "Supported", "k" },
155 { "Timestamp", NULL },
157 { "Unsupported", NULL },
158 { "User-Agent", NULL },
161 { "WWW-Authenticate", NULL },
162 { "P-Access-Network-Info", NULL }, /* RFC3455 */
163 { "P-Asserted-Identity", NULL }, /* RFC3325 */
164 { "P-Associated-URI", NULL }, /* RFC3455 */
165 { "P-Called-Party-ID", NULL }, /* RFC3455 */
166 { "P-Charging-Function-Addresses",NULL }, /* RFC3455 */
167 { "P-Charging-Vector", NULL }, /* RFC3455 */
168 { "P-DCS-Trace-Party-ID", NULL }, /* RFC3603 */
169 { "P-DCS-OSPS", NULL }, /* RFC3603 */
170 { "P-DCS-Billing-Info", NULL }, /* RFC3603 */
171 { "P-DCS-LAES", NULL }, /* RFC3603 */
172 { "P-DCS-Redirect", NULL }, /* RFC3603 */
173 { "P-Media-Authorization", NULL }, /* RFC3313 */
174 { "P-Preferred-Identity", NULL }, /* RFC3325 */
175 { "P-Visited-Network-ID", NULL }, /* RFC3455 */
176 { "Path", NULL }, /* RFC3327 */
177 { "Privacy", NULL }, /* RFC3323 */
178 { "Reason", NULL }, /* RFC3326 */
179 { "Refer-To", "r" }, /* RFC3515 */
180 { "Service-Route", NULL }, /* RFC3608 */
181 { "ETag", NULL }, /* draft-ietf-sip-publish-01 */
182 { "If-Match", NULL }, /* draft-ietf-sip-publish-01 */
188 #define POS_ACCEPT_ENCODING 2
189 #define POS_ACCEPT_LANGUAGE 3
190 #define POS_ALERT_INFO 4
192 #define POS_ALLOW_EVENTS 6
193 #define POS_AUTHENTICATION_INFO 7
194 #define POS_AUTHORIZATION 8
195 #define POS_CALL_ID 9
196 #define POS_CALL_INFO 10
197 #define POS_CONTACT 11
198 #define POS_CONTENT_DISPOSITION 12
199 #define POS_CONTENT_ENCODING 13
200 #define POS_CONTENT_LANGUAGE 14
201 #define POS_CONTENT_LENGTH 15
202 #define POS_CONTENT_TYPE 16
205 #define POS_ERROR_INFO 19
207 #define POS_EXPIRES 21
209 #define POS_IN_REPLY_TO 23
210 #define POS_MAX_FORWARDS 24
211 #define POS_MIME_VERSION 25
212 #define POS_MIN_EXPIRES 26
213 #define POS_ORGANIZATION 27
214 #define POS_PRIORITY 28
215 #define POS_PROXY_AUTHENTICATE 29
216 #define POS_PROXY_AUTHORIZATION 30
217 #define POS_PROXY_REQUIRE 31
220 #define POS_RECORD_ROUTE 34
221 #define POS_REPLY_TO 35
222 #define POS_REQUIRE 36
223 #define POS_RETRY_AFTER 37
225 #define POS_SERVER 39
226 #define POS_SUBJECT 40
227 #define POS_SUBSCRIPTION_STATE 41
228 #define POS_SUPPORTED 42
229 #define POS_TIMESTAMP 43
231 #define POS_UNSUPPORTED 45
232 #define POS_USER_AGENT 46
234 #define POS_WARNING 48
235 #define POS_WWW_AUTHENTICATE 49
237 #define POS_P_ACCESS_NETWORK_INFO 50
238 #define POS_P_ASSERTED_IDENTITY 51
239 #define POS_P_ASSOCIATED_URI 52
240 #define POS_P_CALLED_PARTY_ID 53
241 #define POS_P_CHARGING_FUNCTION_ADDRESSES 54
242 #define POS_P_CHARGING_VECTOR 55
243 #define POS_P_DCS_TRACE_PARTY_ID 56
244 #define POS_P_DCS_OSPS 57
245 #define POS_P_DCS_BILLING_INFO 58
246 #define POS_P_DCS_LAES 59
247 #define POS_P_DCS_REDIRECT 60
248 #define POS_P_MEDIA_AUTHORIZATION 61
249 #define POS_P_PREFERRED_IDENTITY 62
250 #define POS_P_VISITED_NETWORK_ID 63
252 #define POS_PRIVACY 65
253 #define POS_REASON 66
254 #define POS_REFER_TO 67
255 #define POS_SERVICE_ROUTE 68
257 #define POS_IF_MATCH 70
259 static gint hf_header_array[] = {
260 -1, /* "Unknown-header" - Pad so that the real headers start at index 1 */
262 -1, /* "Accept-Encoding" */
263 -1, /* "Accept-Language" */
264 -1, /* "Alert-Info" */
266 -1, /* "Allow-Events" - RFC 3265 */
267 -1, /* "Authentication-Info" */
268 -1, /* "Authorization" */
270 -1, /* "Call-Info" */
272 -1, /* "Content-Disposition" */
273 -1, /* "Content-Encoding" */
274 -1, /* "Content-Language" */
275 -1, /* "Content-Length" */
276 -1, /* "Content-Type" */
279 -1, /* "Error-Info" */
281 -1, /* "Event" - RFC 3265 */
283 -1, /* "In-Reply-To" */
284 -1, /* "Max-Forwards" */
285 -1, /* "MIME-Version" */
286 -1, /* "Min-Expires" */
287 -1, /* "Organization" */
289 -1, /* "Proxy-Authenticate" */
290 -1, /* "Proxy-Authorization" */
291 -1, /* "Proxy-Require" */
292 -1, /* "RAck" - RFC 3262 */
293 -1, /* "RSeq" - RFC 3261 */
294 -1, /* "Record-Route" */
297 -1, /* "Retry-After" */
301 -1, /* "Subscription-State" - RFC 3265 */
302 -1, /* "Supported" */
303 -1, /* "Timestamp" */
305 -1, /* "Unsupported" */
306 -1, /* "User-Agent" */
309 -1, /* "WWW-Authenticate" */
310 -1, /* "P-Access-Network-Info" - RFC3455 */
311 -1, /* "P-Asserted-Identity" - RFC3325 */
312 -1, /* "P-Associated-URI" - RFC3455 */
313 -1, /* "P-Called-Party-ID" - RFC3455 */
314 -1, /* "P-Charging-Function-Addresses" - RFC3455 */
315 -1, /* "P-Charging-Vector" - RFC3455 */
316 -1, /* "P-DCS-Trace-Party-ID" - RFC3603 */
317 -1, /* "P-DCS-OSPS" - RFC3603 */
318 -1, /* "P-DCS-Billing-Info" - RFC3603 */
319 -1, /* "P-DCS-LAES" - RFC3603 */
320 -1, /* "P-DCS-Redirect" - RFC3603 */
321 -1, /* "P-Media-Authorization" - RFC3313 */
322 -1, /* "P-Preferred-Identity" - RFC3325 */
323 -1, /* "P-Visited-Network-ID" - RFC3455 */
324 -1, /* "Path" - RFC3327 */
325 -1, /* "Privacy" - RFC3323 */
326 -1, /* "Reason" - RFC3326 */
327 -1, /* "Refer-To" - RFC3515 */
328 -1, /* "Service-Route" - RFC3608 */
329 -1, /* "ETag" draft-ietf-sip-publish-01 */
330 -1, /* "If-Match draft-ietf-sip-publish-01 */
335 * Type of line. It's either a SIP Request-Line, a SIP Status-Line, or
336 * another type of line.
344 /* global_sip_raw_text determines whether we are going to display */
345 /* the raw text of the SIP message, much like the MEGACO dissector does. */
346 static gboolean global_sip_raw_text = FALSE;
347 /* strict_sip_version determines whether the SIP dissector enforces
348 * the SIP version to be "SIP/2.0". */
349 static gboolean strict_sip_version = TRUE;
351 static gboolean dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo,
352 proto_tree *tree, gboolean is_heur);
353 static line_type_t sip_parse_line(tvbuff_t *tvb, gint linelen,
355 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
356 guint meth_len, guint *meth_idx);
357 static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset,
359 static void dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree,
361 static void dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree);
362 static void tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree);
364 /* SIP content type and internet media type used by other dissectors
365 * are the same. List of media types from IANA at:
366 * http://www.iana.org/assignments/media-types/index.html */
367 static dissector_table_t media_type_dissector_table;
369 #define SIP2_HDR "SIP/2.0"
370 #define SIP2_HDR_LEN (strlen (SIP2_HDR))
372 /* Code to actually dissect the packets */
374 dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
376 if (!dissect_sip_common(tvb, pinfo, tree, FALSE))
378 return tvb_length(tvb);
382 dissect_sip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
384 dissect_sip_common(tvb, pinfo, tree, TRUE);
388 dissect_sip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
390 return dissect_sip_common(tvb, pinfo, tree, FALSE);
394 dissect_sip_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
395 gboolean dissect_other_as_continuation)
398 gint next_offset, linelen;
399 line_type_t line_type;
401 gboolean is_known_request;
402 gboolean found_match = FALSE;
405 guint current_method_idx = 0;
406 proto_item *ts = NULL, *ti, *th = NULL, *sip_element_item;
407 proto_tree *sip_tree = NULL, *reqresp_tree, *hdr_tree = NULL, *sip_element_tree, *message_body_tree;
408 guchar contacts = 0, contact_is_star = 0, expires_is_0 = 0;
409 char csec_method[16] = "";
410 char *media_type_str = NULL;
411 char *media_type_str_lower_case = NULL;
412 char *content_type_parameter_str = NULL;
415 * Note that "tvb_find_line_end()" will return a value that
416 * is not longer than what's in the buffer, so the
417 * "tvb_get_ptr()" calls below won't throw exceptions.
419 * Note that "tvb_strneql()" doesn't throw exceptions, so
420 * "sip_parse_line()" won't throw an exception.
423 linelen = tvb_find_line_end(tvb, 0, -1, &next_offset, FALSE);
424 line_type = sip_parse_line(tvb, linelen, &token_1_len);
425 if (line_type == OTHER_LINE) {
427 * This is neither a SIP request nor response.
429 if (!dissect_other_as_continuation) {
431 * We were asked to reject this.
437 * Just dissect it as a continuation.
441 if (check_col(pinfo->cinfo, COL_PROTOCOL))
442 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIP");
447 is_known_request = sip_is_known_request(tvb, 0, token_1_len, ¤t_method_idx);
448 descr = is_known_request ? "Request" : "Unknown request";
449 if (check_col(pinfo->cinfo, COL_INFO)) {
450 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
452 tvb_format_text(tvb, 0, linelen - SIP2_HDR_LEN - 1));
458 if (check_col(pinfo->cinfo, COL_INFO)) {
459 col_add_fstr(pinfo->cinfo, COL_INFO, "Status: %s",
460 tvb_format_text(tvb, SIP2_HDR_LEN + 1, linelen - SIP2_HDR_LEN - 1));
465 default: /* Squelch compiler complaints */
466 descr = "Continuation";
467 if (check_col(pinfo->cinfo, COL_INFO))
468 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
472 ts = proto_tree_add_item(tree, proto_sip, tvb, 0, -1, FALSE);
473 sip_tree = proto_item_add_subtree(ts, ett_sip);
478 ti = proto_tree_add_string(sip_tree, hf_Request_Line, tvb, 0, linelen,
479 tvb_format_text(tvb, 0, linelen));
480 reqresp_tree = proto_item_add_subtree(ti, ett_sip_reqresp);
481 dfilter_sip_request_line(tvb, reqresp_tree, token_1_len);
485 ti = proto_tree_add_string(sip_tree, hf_Status_Line, tvb, 0, linelen,
486 tvb_format_text(tvb, 0, linelen));
487 reqresp_tree = proto_item_add_subtree(ti, ett_sip_reqresp);
488 dfilter_sip_status_line(tvb, reqresp_tree);
492 ti = proto_tree_add_text(sip_tree, tvb, 0, next_offset,
493 "%s line: %s", descr,
494 tvb_format_text(tvb, 0, linelen));
495 reqresp_tree = proto_item_add_subtree(ti, ett_sip_reqresp);
496 proto_tree_add_text(sip_tree, tvb, 0, -1,
497 "Continuation data");
501 offset = next_offset;
502 th = proto_tree_add_item(sip_tree, hf_msg_hdr, tvb, offset, -1,
504 hdr_tree = proto_item_add_subtree(th, ett_sip_hdr);
508 * Process the headers - if we're not building a protocol tree,
509 * we just do this to find the blank line separating the
510 * headers from the message body.
512 next_offset = offset;
513 while (tvb_reported_length_remaining(tvb, offset) > 0) {
514 gint line_end_offset;
516 gint semicolon_offset;
517 gint content_type_len, content_type_parameter_str_len;
520 gint value_offset,tag_offset;
525 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset,
529 * This is a blank line separating the
530 * message header from the message body.
534 line_end_offset = offset + linelen;
535 colon_offset = tvb_find_guint8(tvb, offset, linelen, ':');
536 if (colon_offset == -1) {
538 * Malformed header - no colon after the name.
540 proto_tree_add_text(hdr_tree, tvb, offset,
541 next_offset - offset, "%s",
542 tvb_format_text(tvb, offset, linelen));
544 header_len = colon_offset - offset;
545 hf_index = sip_is_known_sip_header(tvb,
548 if (hf_index == -1) {
549 proto_tree_add_text(hdr_tree, tvb,
550 offset, next_offset - offset, "%s",
551 tvb_format_text(tvb, offset, linelen));
554 * Skip whitespace after the colon.
556 value_offset = colon_offset + 1;
557 while (value_offset < line_end_offset
558 && ((c = tvb_get_guint8(tvb,
559 value_offset)) == ' '
565 value_len = line_end_offset - value_offset;
566 value = tvb_get_string(tvb, value_offset,
570 * Add it to the protocol tree,
571 * but display the line as is.
573 switch ( hf_index ) {
576 sip_element_item = proto_tree_add_string_format(hdr_tree,
577 hf_header_array[hf_index], tvb,
578 offset, next_offset - offset,
580 tvb_format_text(tvb, offset, linelen));
581 sip_element_tree = proto_item_add_subtree( sip_element_item,
583 tag_offset = tvb_find_guint8(tvb, offset,linelen, ';');
584 if ( tag_offset != -1){
585 tag_offset = tag_offset + 1;
586 c = tvb_get_guint8(tvb,tag_offset);
587 if ( c == 't' ){/* tag found */
588 proto_tree_add_string(sip_element_tree,
590 value_offset, (tag_offset - value_offset - 1),
591 tvb_format_text(tvb, value_offset,
592 ( tag_offset - value_offset - 1)));
593 tag_offset = tvb_find_guint8(tvb, tag_offset,linelen, '=') + 1;
594 proto_tree_add_string(sip_element_tree,
596 tag_offset, (line_end_offset - tag_offset),
597 tvb_format_text(tvb, tag_offset, (line_end_offset - tag_offset)));
601 proto_tree_add_string_format(sip_element_tree,
603 offset, line_end_offset - offset,
605 tvb_format_text(tvb, offset, linelen));
607 } /* if tag offset */
611 sip_element_item = proto_tree_add_string_format(hdr_tree,
612 hf_header_array[hf_index], tvb,
613 offset, next_offset - offset,
615 tvb_format_text(tvb, offset, linelen));
616 sip_element_tree = proto_item_add_subtree( sip_element_item, ett_sip_element);
617 tag_offset = tvb_find_guint8(tvb, offset,linelen, ';');
618 if ( tag_offset != -1){
619 tag_offset = tag_offset + 1;
620 c = tvb_get_guint8(tvb,tag_offset);
621 if ( c == 't' ){/* tag found */
622 proto_tree_add_string(sip_element_tree,
623 hf_sip_from_addr, tvb,
624 value_offset, (tag_offset - value_offset - 1),
625 tvb_format_text(tvb, value_offset, ( tag_offset - value_offset - 1)));
626 tag_offset = tvb_find_guint8(tvb, offset,linelen, '=') + 1;
627 proto_tree_add_string(sip_element_tree,
629 tag_offset, (line_end_offset - tag_offset),
630 tvb_format_text(tvb, tag_offset, (line_end_offset - tag_offset)));
633 tag_offset = tvb_find_guint8(tvb, tag_offset,linelen, ';');
634 if ( tag_offset != -1){
635 tag_offset = tag_offset + 1;
636 c = tvb_get_guint8(tvb,tag_offset);
637 if ( c == 't' ){/* tag found */
638 proto_tree_add_string(sip_element_tree,
639 hf_sip_from_addr, tvb,
640 value_offset, (tag_offset - value_offset - 1),
641 tvb_format_text(tvb, value_offset, ( tag_offset - value_offset - 1)));
642 tag_offset = tvb_find_guint8(tvb, tag_offset,linelen, '=') + 1;
643 proto_tree_add_string(sip_element_tree,
645 tag_offset, (line_end_offset - tag_offset),
646 tvb_format_text(tvb, tag_offset, (line_end_offset - tag_offset)));
650 } /* if tag offset */
654 /* Extract method name from value */
655 for (value_offset = 0; value_offset < (gint)strlen(value); value_offset++)
657 if (isalpha((guchar)value[value_offset]))
659 strcpy(csec_method,value+value_offset);
663 /* Add 'CSeq' string item to tree */
664 proto_tree_add_string_format(hdr_tree,
665 hf_header_array[hf_index], tvb,
666 offset, next_offset - offset,
668 tvb_format_text(tvb, offset, linelen));
672 if (strcmp(value, "0") == 0)
676 /* Add 'Expires' string item to tree */
677 proto_tree_add_string_format(hdr_tree,
678 hf_header_array[hf_index], tvb,
679 offset, next_offset - offset,
681 tvb_format_text(tvb, offset, linelen));
685 * Content-Type is the same as Internet
686 * media type used by other dissectors,
687 * appropriate dissector found by
688 * lookup in "media_type" dissector table.
690 case POS_CONTENT_TYPE :
691 proto_tree_add_string_format(hdr_tree,
692 hf_header_array[hf_index], tvb,
693 offset, next_offset - offset,
695 tvb_format_text(tvb, offset, linelen));
696 content_type_len = value_len;
697 semicolon_offset = tvb_find_guint8(tvb, value_offset,linelen, ';');
698 if ( semicolon_offset != -1) {
699 content_type_len = semicolon_offset - value_offset;
700 content_type_parameter_str_len = line_end_offset - (semicolon_offset + 1);
701 content_type_parameter_str = tvb_get_string(tvb, semicolon_offset + 1,
702 content_type_parameter_str_len);
704 media_type_str = tvb_get_string(tvb, value_offset, content_type_len);
705 #if GLIB_MAJOR_VERSION < 2
706 media_type_str_lower_case = g_strdup(media_type_str);
707 g_strdown(media_type_str_lower_case);
709 media_type_str_lower_case = g_ascii_strdown(media_type_str, -1);
711 g_free(media_type_str);
716 if (strcmp(value, "*") == 0)
720 /* Fall through to default case to add string to tree */
723 proto_tree_add_string_format(hdr_tree,
724 hf_header_array[hf_index], tvb,
725 offset, next_offset - offset,
727 tvb_format_text(tvb, offset, linelen));
732 }/* if colon_offset */
733 offset = next_offset;
736 if (tvb_offset_exists(tvb, next_offset)) {
739 * There's a message body starting at "next_offset".
740 * Set the length of the header item.
742 proto_item_set_end(th, tvb, next_offset);
743 next_tvb = tvb_new_subset(tvb, next_offset, -1, -1);
744 ti = proto_tree_add_text(sip_tree, next_tvb, 0, -1,
746 message_body_tree = proto_item_add_subtree(ti, ett_sip_message_body);
748 /* give the content type parameters to sub dissectors */
750 if ( media_type_str_lower_case != NULL ) {
751 void *save_private_data = pinfo->private_data;
752 pinfo->private_data = content_type_parameter_str;
753 found_match = dissector_try_string(media_type_dissector_table,
754 media_type_str_lower_case,
757 g_free(media_type_str_lower_case);
758 g_free(content_type_parameter_str);
759 pinfo->private_data = save_private_data;
760 /* If no match dump as text */
762 if ( found_match != TRUE )
765 while (tvb_offset_exists(next_tvb, offset)) {
766 tvb_find_line_end(next_tvb, offset, -1, &next_offset, FALSE);
767 linelen = next_offset - offset;
768 proto_tree_add_text(message_body_tree, next_tvb, offset, linelen,
769 "%s", tvb_format_text(next_tvb, offset, linelen));
770 offset = next_offset;
776 /* Add to info column interesting things learned from header fields. */
777 if (check_col(pinfo->cinfo, COL_INFO))
779 /* Registration requests */
780 if (strcmp(sip_methods[current_method_idx], "REGISTER") == 0)
782 if (contact_is_star && expires_is_0)
784 col_append_str(pinfo->cinfo, COL_INFO, " (remove all bindings)");
789 col_append_str(pinfo->cinfo, COL_INFO, " (fetch bindings)");
793 /* Registration responses */
794 if (line_type == STATUS_LINE && (strcmp(csec_method, "REGISTER") == 0))
796 col_append_fstr(pinfo->cinfo, COL_INFO, " (%d bindings)", contacts);
800 if (global_sip_raw_text)
801 tvb_raw_text_add(tvb, tree);
806 /* Display filter for SIP Request-Line */
808 dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, guint meth_len)
813 * We know we have the entire method; otherwise, "sip_parse_line()"
814 * would have returned OTHER_LINE.
816 string = tvb_get_string(tvb, 0, meth_len);
817 proto_tree_add_string(tree, hf_Method, tvb, 0, meth_len, string);
821 /* Display filter for SIP Status-Line */
823 dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree)
828 * We know we have the entire status code; otherwise,
829 * "sip_parse_line()" would have returned OTHER_LINE.
830 * We also know that we have a version string followed by a
831 * space at the beginning of the line, for the same reason.
833 tvb_memcpy(tvb, (guint8 *)string, SIP2_HDR_LEN + 1, 3);
835 proto_tree_add_string(tree, hf_Status_Code, tvb, SIP2_HDR_LEN + 1,
839 /* From section 4.1 of RFC 2543:
841 * Request-Line = Method SP Request-URI SP SIP-Version CRLF
843 * From section 5.1 of RFC 2543:
845 * Status-Line = SIP-version SP Status-Code SP Reason-Phrase CRLF
847 * From section 7.1 of RFC 3261:
849 * Unlike HTTP, SIP treats the version number as a literal string.
850 * In practice, this should make no difference.
853 sip_parse_line(tvbuff_t *tvb, gint linelen, guint *token_1_lenp)
863 space_offset = tvb_find_guint8(tvb, 0, -1, ' ');
864 if (space_offset <= 0) {
866 * Either there's no space in the line (which means
867 * the line is empty or doesn't have a token followed
868 * by a space; neither is valid for a request or status), or
869 * the first character in the line is a space (meaning
870 * the method is empty, which isn't valid for a request,
871 * or the SIP version is empty, which isn't valid for a
876 token_1_len = space_offset;
877 token_2_start = space_offset + 1;
878 space_offset = tvb_find_guint8(tvb, token_2_start, -1, ' ');
879 if (space_offset == -1) {
881 * There's no space after the second token, so we don't
882 * have a third token.
886 token_2_len = space_offset - token_2_start;
887 token_3_start = space_offset + 1;
888 token_3_len = linelen - token_3_start;
890 *token_1_lenp = token_1_len;
893 * Is the first token a version string?
895 if ( (strict_sip_version && (
896 token_1_len == SIP2_HDR_LEN
897 && tvb_strneql(tvb, 0, SIP2_HDR, SIP2_HDR_LEN) == 0)
898 ) || (! strict_sip_version && (
899 tvb_strneql(tvb, 0, "SIP/", 4) == 0)
902 * Yes, so this is either a Status-Line or something
903 * else other than a Request-Line. To be a Status-Line,
904 * the second token must be a 3-digit number.
906 if (token_2_len != 3) {
908 * We don't have 3-character status code.
912 if (!isdigit(tvb_get_guint8(tvb, token_2_start)) ||
913 !isdigit(tvb_get_guint8(tvb, token_2_start + 1)) ||
914 !isdigit(tvb_get_guint8(tvb, token_2_start + 2))) {
916 * 3 characters yes, 3 digits no.
923 * No, so this is either a Request-Line or something
924 * other than a Status-Line. To be a Request-Line, the
925 * second token must be a URI and the third token must
926 * be a version string.
928 if (token_2_len < 3) {
930 * We don't have a URI consisting of at least 3
935 colon_pos = tvb_find_guint8(tvb, token_2_start + 1, -1, ':');
936 if (colon_pos == -1) {
938 * There is no colon after the method, so the URI
939 * doesn't have a colon in it, so it's not valid.
943 if (colon_pos >= token_3_start) {
945 * The colon is in the version string, not the URI.
949 /* XXX - Check for a proper URI prefix? */
950 if ( (strict_sip_version && (
951 token_3_len != SIP2_HDR_LEN
952 || tvb_strneql(tvb, token_3_start, SIP2_HDR, SIP2_HDR_LEN) == -1)
953 ) || (! strict_sip_version && (
954 tvb_strneql(tvb, token_3_start, "SIP/", 4) == -1)
957 * The version string isn't an SIP version 2.0 version
966 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
967 guint meth_len, guint *meth_idx)
971 for (i = 1; i < array_length(sip_methods); i++) {
972 if (meth_len == strlen(sip_methods[i]) &&
973 tvb_strneql(tvb, meth_offset, sip_methods[i], meth_len) == 0)
983 /* Returns index of method in sip_headers */
984 static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset, guint header_len)
988 for (i = 1; i < array_length(sip_headers); i++) {
989 if (header_len == strlen(sip_headers[i].name) &&
990 tvb_strncaseeql(tvb, offset, sip_headers[i].name, header_len) == 0)
992 if (sip_headers[i].compact_name != NULL &&
993 header_len == strlen(sip_headers[i].compact_name) &&
994 tvb_strncaseeql(tvb, offset, sip_headers[i].compact_name, header_len) == 0)
1002 * Display the entire message as raw text.
1005 tvb_raw_text_add(tvbuff_t *tvb, proto_tree *tree)
1007 proto_tree *raw_tree;
1009 int offset, next_offset, linelen;
1011 ti = proto_tree_add_item(tree, proto_raw_sip, tvb, 0, -1, FALSE);
1012 raw_tree = proto_item_add_subtree(ti, ett_raw_text);
1016 while (tvb_offset_exists(tvb, offset)) {
1017 tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
1018 linelen = next_offset - offset;
1019 proto_tree_add_text(raw_tree, tvb, offset, linelen,
1020 "%s", tvb_format_text(tvb, offset, linelen));
1021 offset = next_offset;
1025 /* Register the protocol with Ethereal */
1026 void proto_register_sip(void)
1029 /* Setup list of header fields */
1030 static hf_register_info hf[] = {
1033 { "Message Header", "sip.msg_hdr",
1034 FT_NONE, 0, NULL, 0,
1035 "Message Header in SIP message", HFILL }
1038 { "Method", "sip.Method",
1039 FT_STRING, BASE_NONE,NULL,0x0,
1040 "SIP Method", HFILL }
1043 { "Request-Line", "sip.Request-Line",
1044 FT_STRING, BASE_NONE,NULL,0x0,
1045 "SIP Request-Line", HFILL }
1048 { "Status-Code", "sip.Status-Code",
1049 FT_STRING, BASE_NONE,NULL,0x0,
1050 "SIP Status Code", HFILL }
1053 { "Status-Line", "sip.Status-Line",
1054 FT_STRING, BASE_NONE,NULL,0x0,
1055 "SIP Status-Line", HFILL }
1058 { "SIP to address", "sip.from_addr",
1059 FT_STRING, BASE_NONE,NULL,0x0,
1060 "RFC 3261: from addr", HFILL }
1062 { &hf_sip_from_addr,
1063 { "SIP from address", "sip.to_addr",
1064 FT_STRING, BASE_NONE,NULL,0x0,
1065 "RFC 3261: to addr", HFILL }
1068 { "SIP tag", "sip.tag",
1069 FT_STRING, BASE_NONE,NULL,0x0,
1070 "RFC 3261: tag", HFILL }
1072 { &hf_header_array[POS_ACCEPT],
1073 { "Accept", "sip.Accept",
1074 FT_STRING, BASE_NONE,NULL,0x0,
1075 "RFC 3261: Accept Header", HFILL }
1077 { &hf_header_array[POS_ACCEPT_ENCODING],
1078 { "Accept-Encoding", "sip.Accept-Encoding",
1079 FT_STRING, BASE_NONE,NULL,0x0,
1080 "RFC 3261: Accept-Encoding Header", HFILL }
1082 { &hf_header_array[POS_ACCEPT_LANGUAGE],
1083 { "Accept-Language", "sip.Accept-Language",
1084 FT_STRING, BASE_NONE,NULL,0x0,
1085 "RFC 3261: Accept-Language Header", HFILL }
1087 { &hf_header_array[POS_ALERT_INFO],
1088 { "Alert-Info", "sip.Alert-Info",
1089 FT_STRING, BASE_NONE,NULL,0x0,
1090 "RFC 3261: Alert-Info Header", HFILL }
1092 { &hf_header_array[POS_ALLOW],
1093 { "Allow", "sip.Allow",
1094 FT_STRING, BASE_NONE,NULL,0x0,
1095 "RFC 3261: Allow Header", HFILL }
1097 { &hf_header_array[POS_ALLOW_EVENTS],
1098 { "Allow-Events", "sip.Allow-Events",
1099 FT_STRING, BASE_NONE,NULL,0x0,
1100 "RFC 3265: Allow-Events Header", HFILL }
1102 { &hf_header_array[POS_AUTHENTICATION_INFO],
1103 { "Authentication-Info", "sip.Authentication-Info",
1104 FT_STRING, BASE_NONE,NULL,0x0,
1105 "RFC 3261: Authentication-Info Header", HFILL }
1107 { &hf_header_array[POS_AUTHORIZATION],
1108 { "Authorization", "sip.Authorization",
1109 FT_STRING, BASE_NONE,NULL,0x0,
1110 "RFC 3261: Authorization Header", HFILL }
1112 { &hf_header_array[POS_CALL_ID],
1113 { "Call-ID", "sip.Call-ID",
1114 FT_STRING, BASE_NONE,NULL,0x0,
1115 "RFC 3261: Call-ID Header", HFILL }
1117 { &hf_header_array[POS_CALL_INFO],
1118 { "Call-Info", "sip.Call-Info",
1119 FT_STRING, BASE_NONE,NULL,0x0,
1120 "RFC 3261: Call-Info Header", HFILL }
1122 { &hf_header_array[POS_CONTACT],
1123 { "Contact", "sip.Contact",
1124 FT_STRING, BASE_NONE,NULL,0x0,
1125 "RFC 3261: Contact Header", HFILL }
1127 { &hf_header_array[POS_CONTENT_DISPOSITION],
1128 { "Content-Disposition", "sip.Content-Disposition",
1129 FT_STRING, BASE_NONE,NULL,0x0,
1130 "RFC 3261: Content-Disposition Header", HFILL }
1132 { &hf_header_array[POS_CONTENT_ENCODING],
1133 { "Content-Encoding", "sip.Content-Encoding",
1134 FT_STRING, BASE_NONE,NULL,0x0,
1135 "RFC 3261: Content-Encoding Header", HFILL }
1137 { &hf_header_array[POS_CONTENT_LANGUAGE],
1138 { "Content-Language", "sip.Content-Language",
1139 FT_STRING, BASE_NONE,NULL,0x0,
1140 "RFC 3261: Content-Language Header", HFILL }
1142 { &hf_header_array[POS_CONTENT_LENGTH],
1143 { "Content-Length", "sip.Content-Length",
1144 FT_STRING, BASE_NONE,NULL,0x0,
1145 "RFC 3261: Content-Length Header", HFILL }
1147 { &hf_header_array[POS_CONTENT_TYPE],
1148 { "Content-Type", "sip.Content-Type",
1149 FT_STRING, BASE_NONE,NULL,0x0,
1150 "RFC 3261: Content-Type Header", HFILL }
1152 { &hf_header_array[POS_CSEQ],
1153 { "CSeq", "sip.CSeq",
1154 FT_STRING, BASE_NONE,NULL,0x0,
1155 "RFC 3261: CSeq Header", HFILL }
1157 { &hf_header_array[POS_DATE],
1158 { "Date", "sip.Date",
1159 FT_STRING, BASE_NONE,NULL,0x0,
1160 "RFC 3261: Date Header", HFILL }
1162 { &hf_header_array[POS_ERROR_INFO],
1163 { "Error-Info", "sip.Error-Info",
1164 FT_STRING, BASE_NONE,NULL,0x0,
1165 "RFC 3261: Error-Info Header", HFILL }
1167 { &hf_header_array[POS_EVENT],
1168 { "Event", "sip.Event",
1169 FT_STRING, BASE_NONE,NULL,0x0,
1170 "RFC 3265: Event Header", HFILL }
1172 { &hf_header_array[POS_EXPIRES],
1173 { "Expires", "sip.Expires",
1174 FT_STRING, BASE_NONE,NULL,0x0,
1175 "RFC 3261: Expires Header", HFILL }
1177 { &hf_header_array[POS_FROM],
1178 { "From", "sip.From",
1179 FT_STRING, BASE_NONE,NULL,0x0,
1180 "RFC 3261: From Header", HFILL }
1182 { &hf_header_array[POS_IN_REPLY_TO],
1183 { "In-Reply-To", "sip.In-Reply-To",
1184 FT_STRING, BASE_NONE,NULL,0x0,
1185 "RFC 3261: In-Reply-To Header", HFILL }
1187 { &hf_header_array[POS_MAX_FORWARDS],
1188 { "Max-Forwards", "sip.Max-Forwards",
1189 FT_STRING, BASE_NONE,NULL,0x0,
1190 "RFC 3261: Max-Forwards Header", HFILL }
1192 { &hf_header_array[POS_MIME_VERSION],
1193 { "MIME-Version", "sip.MIME-Version",
1194 FT_STRING, BASE_NONE,NULL,0x0,
1195 "RFC 3261: MIME-Version Header", HFILL }
1197 { &hf_header_array[POS_MIN_EXPIRES],
1198 { "Min-Expires", "sip.Min-Expires",
1199 FT_STRING, BASE_NONE,NULL,0x0,
1200 "RFC 3261: Min-Expires Header", HFILL }
1202 { &hf_header_array[POS_ORGANIZATION],
1203 { "Organization", "sip.Organization",
1204 FT_STRING, BASE_NONE,NULL,0x0,
1205 "RFC 3261: Organization Header", HFILL }
1207 { &hf_header_array[POS_PRIORITY],
1208 { "Priority", "sip.Priority",
1209 FT_STRING, BASE_NONE,NULL,0x0,
1210 "RFC 3261: Priority Header", HFILL }
1212 { &hf_header_array[POS_PROXY_AUTHENTICATE],
1213 { "Proxy-Authenticate", "sip.Proxy-Authenticate",
1214 FT_STRING, BASE_NONE,NULL,0x0,
1215 "RFC 3261: Proxy-Authenticate Header", HFILL }
1217 { &hf_header_array[POS_PROXY_AUTHORIZATION],
1218 { "Proxy-Authorization", "sip.Proxy-Authorization",
1219 FT_STRING, BASE_NONE,NULL,0x0,
1220 "RFC 3261: Proxy-Authorization Header", HFILL }
1222 { &hf_header_array[POS_RACK],
1223 { "RAck", "sip.RAck",
1224 FT_STRING, BASE_NONE,NULL,0x0,
1225 "RFC 3262: RAck Header", HFILL }
1227 { &hf_header_array[POS_RSEQ],
1228 { "RSeq", "sip.RSeq",
1229 FT_STRING, BASE_NONE,NULL,0x0,
1230 "RFC 3262: RSeq Header", HFILL }
1232 { &hf_header_array[POS_PROXY_REQUIRE],
1233 { "Proxy-Require", "sip.Proxy-Require",
1234 FT_STRING, BASE_NONE,NULL,0x0,
1235 "RFC 3261: Proxy-Require Header", HFILL }
1237 { &hf_header_array[POS_RECORD_ROUTE],
1238 { "Record-Route", "sip.Record-Route",
1239 FT_STRING, BASE_NONE,NULL,0x0,
1240 "RFC 3261: Record-Route Header", HFILL }
1242 { &hf_header_array[POS_REPLY_TO],
1243 { "Reply-To", "sip.Reply-To",
1244 FT_STRING, BASE_NONE,NULL,0x0,
1245 "RFC 3261: Reply-To Header", HFILL }
1247 { &hf_header_array[POS_REQUIRE],
1248 { "Require", "sip.Require",
1249 FT_STRING, BASE_NONE,NULL,0x0,
1250 "RFC 3261: Require Header", HFILL }
1252 { &hf_header_array[POS_RETRY_AFTER],
1253 { "Retry-After", "sip.Retry-After",
1254 FT_STRING, BASE_NONE,NULL,0x0,
1255 "RFC 3261: Retry-After Header", HFILL }
1257 { &hf_header_array[POS_ROUTE],
1258 { "Route", "sip.Route",
1259 FT_STRING, BASE_NONE,NULL,0x0,
1260 "RFC 3261: Route Header", HFILL }
1262 { &hf_header_array[POS_SERVER],
1263 { "Server", "sip.Server",
1264 FT_STRING, BASE_NONE,NULL,0x0,
1265 "RFC 3261: Server Header", HFILL }
1267 { &hf_header_array[POS_SUBJECT],
1268 { "Subject", "sip.Subject",
1269 FT_STRING, BASE_NONE,NULL,0x0,
1270 "RFC 3261: Subject Header", HFILL }
1272 { &hf_header_array[POS_SUBSCRIPTION_STATE],
1273 { "Subscription-State", "sip.Subscription-State",
1274 FT_STRING, BASE_NONE,NULL,0x0,
1275 "RFC 3265: Subscription-State Header", HFILL }
1277 { &hf_header_array[POS_SUPPORTED],
1278 { "Supported", "sip.Supported",
1279 FT_STRING, BASE_NONE,NULL,0x0,
1280 "RFC 3261: Supported Header", HFILL }
1282 { &hf_header_array[POS_TIMESTAMP],
1283 { "Timestamp", "sip.Timestamp",
1284 FT_STRING, BASE_NONE,NULL,0x0,
1285 "RFC 3261: Timestamp Header", HFILL }
1287 { &hf_header_array[POS_TO],
1289 FT_STRING, BASE_NONE,NULL,0x0,
1290 "RFC 3261: To Header", HFILL }
1292 { &hf_header_array[POS_UNSUPPORTED],
1293 { "Unsupported", "sip.Unsupported",
1294 FT_STRING, BASE_NONE,NULL,0x0,
1295 "RFC 3261: Unsupported Header", HFILL }
1297 { &hf_header_array[POS_USER_AGENT],
1298 { "User-Agent", "sip.User-Agent",
1299 FT_STRING, BASE_NONE,NULL,0x0,
1300 "RFC 3261: User-Agent Header", HFILL }
1302 { &hf_header_array[POS_VIA],
1304 FT_STRING, BASE_NONE,NULL,0x0,
1305 "RFC 3261: Via Header", HFILL }
1307 { &hf_header_array[POS_WARNING],
1308 { "Warning", "sip.Warning",
1309 FT_STRING, BASE_NONE,NULL,0x0,
1310 "RFC 3261: Warning Header", HFILL }
1312 { &hf_header_array[POS_WWW_AUTHENTICATE],
1313 { "WWW-Authenticate", "sip.WWW-Authenticate",
1314 FT_STRING, BASE_NONE,NULL,0x0,
1315 "RFC 3261: WWW-Authenticate Header", HFILL }
1317 { &hf_header_array[POS_P_ACCESS_NETWORK_INFO],
1318 { "P-Access-Network-Info", "sip.P-Access-Network-Info",
1319 FT_STRING, BASE_NONE,NULL,0x0,
1320 "P-Access-Network-Info Header", HFILL }
1323 { &hf_header_array[POS_P_ASSERTED_IDENTITY],
1324 { "P-Asserted-Identity", "sip.P-Asserted-Identity",
1325 FT_STRING, BASE_NONE,NULL,0x0,
1326 "P-Asserted-Identity Header", HFILL }
1329 { &hf_header_array[POS_P_ASSOCIATED_URI],
1330 { "P-Associated-URI", "sip.P-Associated-URI",
1331 FT_STRING, BASE_NONE,NULL,0x0,
1332 "P-Associated-URI Header", HFILL }
1335 { &hf_header_array[POS_P_CALLED_PARTY_ID],
1336 { "P-Called-Party-ID", "sip.P-Called-Party-ID",
1337 FT_STRING, BASE_NONE,NULL,0x0,
1338 "P-Called-Party-ID Header", HFILL }
1341 { &hf_header_array[POS_P_CHARGING_FUNCTION_ADDRESSES],
1342 { "P-Charging-Function-Addresses","sip.P-Charging-Function-Addresses",
1343 FT_STRING, BASE_NONE,NULL,0x0,
1344 "P-Charging-Function-Addresses", HFILL }
1347 { &hf_header_array[POS_P_CHARGING_VECTOR],
1348 { "P-Charging-Vector", "sip.P-Charging-Vector",
1349 FT_STRING, BASE_NONE,NULL,0x0,
1350 "P-Charging-Vector Header", HFILL }
1353 { &hf_header_array[POS_P_DCS_TRACE_PARTY_ID],
1354 { "P-DCS-Trace-Party-ID", "sip.P-DCS-Trace-Party-ID",
1355 FT_STRING, BASE_NONE,NULL,0x0,
1356 "P-DCS-Trace-Party-ID Header", HFILL }
1359 { &hf_header_array[POS_P_DCS_OSPS],
1360 { "P-DCS-OSPS", "sip.P-DCS-OSPS",
1361 FT_STRING, BASE_NONE,NULL,0x0,
1362 "P-DCS-OSPS Header", HFILL }
1365 { &hf_header_array[POS_P_DCS_BILLING_INFO],
1366 { "P-DCS-Billing-Info", "sip.P-DCS-Billing-Info",
1367 FT_STRING, BASE_NONE,NULL,0x0,
1368 "P-DCS-Billing-Info Header", HFILL }
1371 { &hf_header_array[POS_P_DCS_LAES],
1372 { "P-DCS-LAES", "sip.P-DCS-LAES",
1373 FT_STRING, BASE_NONE,NULL,0x0,
1374 "P-DCS-LAES Header", HFILL }
1377 { &hf_header_array[POS_P_DCS_REDIRECT],
1378 { "P-DCS-Redirect", "sip.P-DCS-Redirect",
1379 FT_STRING, BASE_NONE,NULL,0x0,
1380 "P-DCS-Redirect Header", HFILL }
1383 { &hf_header_array[POS_P_MEDIA_AUTHORIZATION],
1384 { "P-Media-Authorization", "sip.P-Media-Authorization",
1385 FT_STRING, BASE_NONE,NULL,0x0,
1386 "P-Media-Authorization Header", HFILL }
1389 { &hf_header_array[POS_P_PREFERRED_IDENTITY],
1390 { "P-Preferred-Identity", "sip.P-Preferred-Identity",
1391 FT_STRING, BASE_NONE,NULL,0x0,
1392 "P-Preferred-Identity Header", HFILL }
1395 { &hf_header_array[POS_P_VISITED_NETWORK_ID],
1396 { "P-Visited-Network-ID", "sip.P-Visited-Network-ID",
1397 FT_STRING, BASE_NONE,NULL,0x0,
1398 "P-Visited-Network-ID Header", HFILL }
1401 { &hf_header_array[POS_PATH],
1402 { "Path", "sip.Path",
1403 FT_STRING, BASE_NONE,NULL,0x0,
1404 "Path Header", HFILL }
1407 { &hf_header_array[POS_PRIVACY],
1408 { "Privacy", "sip.Privacy",
1409 FT_STRING, BASE_NONE,NULL,0x0,
1410 "Privacy Header", HFILL }
1413 { &hf_header_array[POS_REASON],
1414 { "Reason", "sip.Reason",
1415 FT_STRING, BASE_NONE,NULL,0x0,
1416 "Reason Header", HFILL }
1419 { &hf_header_array[POS_REFER_TO],
1420 { "Refer-To", "sip.Refer-To",
1421 FT_STRING, BASE_NONE,NULL,0x0,
1422 "Refer-To Header", HFILL }
1425 { &hf_header_array[POS_SERVICE_ROUTE],
1426 { "Service-Route", "sip.Service-Route",
1427 FT_STRING, BASE_NONE,NULL,0x0,
1428 "Service-Route Header", HFILL }
1431 { &hf_header_array[POS_ETAG],
1432 { "ETag", "sip.ETag",
1433 FT_STRING, BASE_NONE,NULL,0x0,
1434 "ETag Header", HFILL }
1436 { &hf_header_array[POS_IF_MATCH],
1437 { "If_Match", "sip.If_Match",
1438 FT_STRING, BASE_NONE,NULL,0x0,
1439 "If-Match Header", HFILL }
1443 /* Setup protocol subtree array */
1444 static gint *ett[] = {
1449 &ett_sip_message_body,
1451 static gint *ett_raw[] = {
1455 module_t *sip_module;
1457 /* Register the protocol name and description */
1458 proto_sip = proto_register_protocol("Session Initiation Protocol",
1460 proto_raw_sip = proto_register_protocol("Session Initiation Protocol (SIP as raw text)",
1461 "Raw_SIP", "raw_sip");
1463 /* Required function calls to register the header fields and subtrees used */
1464 proto_register_field_array(proto_sip, hf, array_length(hf));
1465 proto_register_subtree_array(ett, array_length(ett));
1466 proto_register_subtree_array(ett_raw, array_length(ett_raw));
1468 /* SIP content type and internet media type used by other dissectors are the same */
1470 media_type_dissector_table = find_dissector_table("media_type");
1473 sip_module = prefs_register_protocol(proto_sip, NULL);
1475 prefs_register_bool_preference(sip_module, "display_raw_text",
1476 "Display raw text for SIP message",
1477 "Specifies that the raw text of the "
1478 "SIP message should be displayed "
1479 "in addition to the dissection tree",
1480 &global_sip_raw_text);
1481 prefs_register_bool_preference(sip_module, "strict_sip_version",
1482 "Enforce strict SIP version check (" SIP2_HDR ")",
1483 "If enabled, only " SIP2_HDR " traffic will be dissected as SIP. "
1484 "Disable it to allow SIP traffic with a different version "
1485 "to be dissected as SIP.",
1486 &strict_sip_version);
1490 proto_reg_handoff_sip(void)
1492 dissector_handle_t sip_handle, sip_tcp_handle;
1494 sip_handle = new_create_dissector_handle(dissect_sip, proto_sip);
1495 dissector_add("udp.port", UDP_PORT_SIP, sip_handle);
1496 dissector_add_string("media_type", "message/sip", sip_handle);
1498 sip_tcp_handle = create_dissector_handle(dissect_sip_tcp, proto_sip);
1499 dissector_add("tcp.port", TCP_PORT_SIP, sip_tcp_handle);
1501 heur_dissector_add("udp", dissect_sip_heur, proto_sip);
1502 heur_dissector_add("tcp", dissect_sip_heur, proto_sip);
1503 heur_dissector_add("sctp", dissect_sip_heur, proto_sip);