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 RCF 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.35 2003/03/11 01:48:55 gerald 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.
52 #include <epan/packet.h>
54 #define TCP_PORT_SIP 5060
55 #define UDP_PORT_SIP 5060
57 /* Initialize the protocol and registered fields */
58 static gint proto_sip = -1;
59 static gint hf_msg_hdr = -1;
60 static gint hf_Method = -1;
61 static gint hf_Status_Code = -1;
63 /* Initialize the subtree pointers */
64 static gint ett_sip = -1;
65 static gint ett_sip_hdr = -1;
67 static const char *sip_methods[] = {
68 "<Invalid method>", /* Pad so that the real methods start at index 1 */
87 static const char *sip_headers[] = {
88 "Unknown-header", /* Pad so that the real headers start at index 1 */
95 "Authentication-Info",
100 "Content-Disposition",
117 "Proxy-Authenticate",
118 "Proxy-Authorization",
129 "Subscription-State",
142 #define POS_ACCEPT_ENCODING 2
143 #define POS_ACCEPT_LANGUAGE 3
144 #define POS_ALERT_INFO 4
146 #define POS_ALLOW_EVENTS 6
147 #define POS_AUTHENTICATION_INFO 7
148 #define POS_AUTHORIZATION 8
149 #define POS_CALL_ID 9
150 #define POS_CALL_INFO 10
151 #define POS_CONTACT 11
152 #define POS_CONTENT_DISPOSITION 12
153 #define POS_CONTENT_ENCODING 13
154 #define POS_CONTENT_LANGUAGE 14
155 #define POS_CONTENT_LENGTH 15
156 #define POS_CONTENT_TYPE 16
159 #define POS_ERROR_INFO 19
161 #define POS_EXPIRES 21
163 #define POS_IN_REPLY_TO 23
164 #define POS_MAX_FORWARDS 24
165 #define POS_MIME_VERSION 25
166 #define POS_MIN_EXPIRES 26
167 #define POS_ORGANIZATION 27
168 #define POS_PRIORITY 28
169 #define POS_PROXY_AUTHENTICATE 29
170 #define POS_PROXY_AUTHORIZATION 30
171 #define POS_PROXY_REQUIRE 31
174 #define POS_RECORD_ROUTE 34
175 #define POS_REPLY_TO 35
176 #define POS_REQUIRE 36
177 #define POS_RETRY_AFTER 37
179 #define POS_SERVER 39
180 #define POS_SUBJECT 40
181 #define POS_SUBSCRIPTION_STATE 41
182 #define POS_SUPPORTED 42
183 #define POS_TIMESTAMP 43
185 #define POS_UNSUPPORTED 45
186 #define POS_USER_AGENT 46
188 #define POS_WARNING 48
189 #define POS_WWW_AUTHENTICATE 49
191 static gint hf_header_array[] = {
192 -1, /* "Unknown-header" - Pad so that the real headers start at index 1 */
194 -1, /* "Accept-Encoding" */
195 -1, /* "Accept-Language" */
196 -1, /* "Alert-Info" */
198 -1, /* "Allow-Events" - RFC 3265 */
199 -1, /* "Authentication-Info" */
200 -1, /* "Authorization" */
202 -1, /* "Call-Info" */
204 -1, /* "Content-Disposition" */
205 -1, /* "Content-Encoding" */
206 -1, /* "Content-Language" */
207 -1, /* "Content-Length" */
208 -1, /* "Content-Type" */
211 -1, /* "Error-Info" */
213 -1, /* "Event" - RFC 3265 */
215 -1, /* "In-Reply-To" */
216 -1, /* "Max-Forwards" */
217 -1, /* "MIME-Version" */
218 -1, /* "Min-Expires" */
219 -1, /* "Organization" */
221 -1, /* "Proxy-Authenticate" */
222 -1, /* "Proxy-Authorization" */
223 -1, /* "Proxy-Require" */
224 -1, /* "RAck" - RFC 3262 */
225 -1, /* "RSeq" - RFC 3261 */
226 -1, /* "Record-Route" */
229 -1, /* "Retry-After" */
233 -1, /* "Subscription-State" - RFC 3265 */
234 -1, /* "Supported" */
235 -1, /* "Timestamp" */
237 -1, /* "Unsupported" */
238 -1, /* "User-Agent" */
241 -1 /* "WWW-Authenticate" */
245 static gboolean sip_is_request(tvbuff_t *tvb, gint eol);
246 static gboolean sip_is_known_request(tvbuff_t *tvb, guint32 offset);
247 static gint sip_get_msg_offset(tvbuff_t *tvb, guint32 offset);
248 static gint sip_is_known_sip_header(tvbuff_t *tvb, guint32 offset, guint8* header_len);
249 void dfilter_sip_message_line(gboolean is_request, tvbuff_t *tvb, proto_tree *tree);
251 static dissector_handle_t sdp_handle;
252 static dissector_handle_t data_handle;
254 #define SIP2_HDR "SIP/2.0"
255 #define SIP2_HDR_LEN (strlen (SIP2_HDR))
257 /* Code to actually dissect the packets */
258 static void dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
261 gint eol, next_offset, msg_offset;
263 gboolean is_request, is_known_request;
267 * Note that "tvb_strneql()" doesn't throw exceptions, so
268 * "sip_is_request()" won't throw an exception.
270 * Note that "tvb_find_line_end()" will return a value that
271 * is not longer than what's in the buffer, so the
272 * "tvb_get_ptr()" call s below won't throw exceptions.
275 eol = tvb_find_line_end(tvb, 0, -1, &next_offset, FALSE);
276 /* XXX - Check for a valid status message as well. */
277 is_request = sip_is_request(tvb, eol);
278 is_known_request = sip_is_known_request(tvb, 0);
279 /* XXX - Is this case-sensitive? RFC 2543 didn't explicitly say. */
280 if (tvb_strneql(tvb, 0, SIP2_HDR, SIP2_HDR_LEN) != 0 && ! is_request)
283 if (check_col(pinfo->cinfo, COL_PROTOCOL))
284 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIP");
286 req_descr = is_known_request ? "Request" : "Unknown request";
287 if (check_col(pinfo->cinfo, COL_INFO))
288 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
289 is_request ? req_descr : "Status",
291 tvb_format_text(tvb, 0, eol - SIP2_HDR_LEN - 1) :
292 tvb_format_text(tvb, SIP2_HDR_LEN + 1, eol - SIP2_HDR_LEN - 1));
293 msg_offset = sip_get_msg_offset(tvb, offset);
294 if (msg_offset < 0) {
296 * XXX - this may just mean that the entire SIP message
297 * didn't fit in this TCP segment.
304 proto_tree *sip_tree, *hdr_tree;
306 ti = proto_tree_add_item(tree, proto_sip, tvb, 0, -1, FALSE);
307 sip_tree = proto_item_add_subtree(ti, ett_sip);
309 proto_tree_add_text(sip_tree, tvb, 0, next_offset, "%s line: %s",
310 is_request ? req_descr : "Status",
311 tvb_format_text(tvb, 0, eol));
313 dfilter_sip_message_line(is_request , tvb, sip_tree);
315 offset = next_offset;
316 th = proto_tree_add_item(sip_tree, hf_msg_hdr, tvb, offset, msg_offset - offset, FALSE);
317 hdr_tree = proto_item_add_subtree(th, ett_sip_hdr);
319 /* - 2 since we have a CRLF separating the message-body */
320 while (msg_offset - 2 > (int) offset) {
324 eol = tvb_find_line_end(tvb, offset, -1, &next_offset,
326 hf_index = sip_is_known_sip_header(tvb, offset, &header_len);
328 if (hf_index == -1) {
329 proto_tree_add_text(hdr_tree, tvb, offset , next_offset - offset, "%s",
330 tvb_format_text(tvb, offset, eol));
333 proto_tree_add_string(hdr_tree, hf_header_array[hf_index], tvb, offset, next_offset - offset ,
334 tvb_format_text(tvb, offset + header_len + 2, eol - header_len - 2));
337 offset = next_offset;
339 offset += 2; /* Skip the CRLF mentioned above */
342 if (tvb_offset_exists(tvb, msg_offset)) {
343 next_tvb = tvb_new_subset(tvb, msg_offset, -1, -1);
344 call_dissector(sdp_handle, next_tvb, pinfo, tree);
350 next_tvb = tvb_new_subset(tvb, offset, -1, -1);
351 call_dissector(data_handle,next_tvb, pinfo, tree);
356 /* Display filter for SIP-message line */
357 void dfilter_sip_message_line(gboolean is_request, tvbuff_t *tvb, proto_tree *tree)
363 code_len = tvb_find_guint8(tvb, 0, -1, ' ');
366 code_len = tvb_find_guint8(tvb, SIP2_HDR_LEN + 1, -1, ' ');
369 string = g_malloc(code_len + 1);
371 CLEANUP_PUSH(g_free, string);
374 tvb_memcpy(tvb, (guint8 *)string, 0, code_len);
375 string[code_len] = '\0';
376 proto_tree_add_string(tree, hf_Method, tvb, 0,
380 tvb_memcpy(tvb, (guint8 *)string, SIP2_HDR_LEN + 1, code_len - SIP2_HDR_LEN);
381 string[code_len - SIP2_HDR_LEN - 1] = '\0';
382 proto_tree_add_string(tree, hf_Status_Code,
383 tvb, SIP2_HDR_LEN + 1, code_len - SIP2_HDR_LEN - 1, string);
386 CLEANUP_CALL_AND_POP;
390 dissect_sip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
392 gint eol, next_offset;
395 * This is a heuristic dissector, which means we get all the
396 * UDP and TCP traffic not sent to a known dissector and not
397 * claimed by a heuristic dissector called before us!
398 * So we first check if the frame is really meant for us.
402 * Check for a response.
403 * First, make sure we have enough data to do the check.
405 if (!tvb_bytes_exist(tvb, 0, SIP2_HDR_LEN)) {
413 * Now see if we have a response header; they begin with
416 if (tvb_strneql(tvb, 0, SIP2_HDR, SIP2_HDR_LEN) != 0) {
418 * We don't, so this isn't a response; check for a request.
419 * They *end* with "SIP/2.0".
421 eol = tvb_find_line_end(tvb, 0, -1, &next_offset, FALSE);
422 if (eol <= (gint)SIP2_HDR_LEN) {
424 * The line isn't long enough to end with "SIP/2.0".
428 if (!tvb_bytes_exist(tvb, eol - SIP2_HDR_LEN, SIP2_HDR_LEN)) {
430 * We don't have enough of the data in the line
436 if (tvb_strneql(tvb, eol - SIP2_HDR_LEN, SIP2_HDR, SIP2_HDR_LEN - 1) != 0) {
438 * Not a request, either.
445 * The message seems to be a valid SIP message!
447 dissect_sip(tvb, pinfo, tree);
452 /* Returns the offset to the start of the optional message-body, or
455 static gint sip_get_msg_offset(tvbuff_t *tvb, guint32 offset)
459 while ((eol = tvb_find_guint8(tvb, offset, -1, '\r')) > 0
460 && tvb_bytes_exist(tvb, eol, 4)) {
461 if (tvb_get_guint8(tvb, eol + 1) == '\n' &&
462 tvb_get_guint8(tvb, eol + 2) == '\r' &&
463 tvb_get_guint8(tvb, eol + 3) == '\n')
471 /* From section 4.1 of RFC 2543:
473 * Request-Line = Method SP Request-URI SP SIP-Version CRLF
476 static gboolean sip_is_request(tvbuff_t *tvb, gint eol)
478 gint meth_len, req_len, req_colon_pos;
479 guint8 req_start, ver_start, ver_len;
481 meth_len = tvb_find_guint8(tvb, 0, -1, ' ');
482 req_start = meth_len + 1;
483 req_len = tvb_find_guint8(tvb, req_start, -1, ' ') - meth_len - 1;
484 req_colon_pos = tvb_find_guint8(tvb, req_start + 1, -1, ':');
485 ver_start = meth_len + req_len + 2;
486 ver_len = eol - req_len - meth_len - 2; /*CRLF, plus two spaces */
489 * A method of at least one character?
490 * A URI consisting of at least three characters?
491 * A version string length matching that of SIP2_HDR?
493 if (meth_len <= 0 || req_len <= 3 || ver_len != SIP2_HDR_LEN)
496 /* Does our method have a colon character? */
497 if (req_colon_pos < 0 || req_colon_pos > ver_start)
499 /* XXX - Check for a proper URI prefix? */
501 /* Do we have a proper version string? */
502 if (tvb_strneql(tvb, ver_start, SIP2_HDR, SIP2_HDR_LEN))
508 static gboolean sip_is_known_request(tvbuff_t *tvb, guint32 offset)
512 meth_len = tvb_find_guint8(tvb, 0, -1, ' ');
514 for (i = 1; i < array_length(sip_methods); i++) {
515 if ((meth_len == strlen(sip_methods[i])) && tvb_strneql(tvb, offset, sip_methods[i], strlen(sip_methods[i])) == 0)
522 /* Returns index of method in sip_headers */
523 static gint sip_is_known_sip_header(tvbuff_t *tvb, guint32 offset, guint8* header_len)
527 *header_len = tvb_find_guint8(tvb, offset, -1, ':') - offset;
529 for (i = 1; i < array_length(sip_headers); i++) {
530 if ((*header_len == strlen(sip_headers[i])) && tvb_strneql(tvb, offset, sip_headers[i], strlen(sip_headers[i])) == 0)
537 /* Register the protocol with Ethereal */
538 void proto_register_sip(void)
541 /* Setup list of header fields */
542 static hf_register_info hf[] = {
545 { "Message Header", "sip.msg_hdr",
547 "Message Header in SIP message", HFILL }
550 { "Method", "sip.Method",
551 FT_STRING, BASE_NONE,NULL,0x0,
552 "SIP Method", HFILL }
555 { "Status-Code", "sip.Status-Code",
556 FT_STRING, BASE_NONE,NULL,0x0,
557 "SIP Status Code", HFILL }
559 { &hf_header_array[POS_ACCEPT],
560 { "Accept", "sip.Accept",
561 FT_STRING, BASE_NONE,NULL,0x0,
562 "RFC 3261: Accept Header", HFILL }
564 { &hf_header_array[POS_ACCEPT_ENCODING],
565 { "Accept-Encoding", "sip.Accept-Encoding",
566 FT_STRING, BASE_NONE,NULL,0x0,
567 "RFC 3261: Accept-Encoding Header", HFILL }
569 { &hf_header_array[POS_ACCEPT_LANGUAGE],
570 { "Accept-Language", "sip.Accept-Language",
571 FT_STRING, BASE_NONE,NULL,0x0,
572 "RFC 3261: Accept-Language Header", HFILL }
574 { &hf_header_array[POS_ALERT_INFO],
575 { "Alert-Info", "sip.Alert-Info",
576 FT_STRING, BASE_NONE,NULL,0x0,
577 "RFC 3261: Alert-Info Header", HFILL }
579 { &hf_header_array[POS_ALLOW],
580 { "Allow", "sip.Allow",
581 FT_STRING, BASE_NONE,NULL,0x0,
582 "RFC 3261: Allow Header", HFILL }
584 { &hf_header_array[POS_ALLOW_EVENTS],
585 { "Allow-Events", "sip.Allow-Events",
586 FT_STRING, BASE_NONE,NULL,0x0,
587 "RFC 3265: Allow-Events Header", HFILL }
589 { &hf_header_array[POS_AUTHENTICATION_INFO],
590 { "Authentication-Info", "sip.Authentication-Info",
591 FT_STRING, BASE_NONE,NULL,0x0,
592 "RFC 3261: Authentication-Info Header", HFILL }
594 { &hf_header_array[POS_AUTHORIZATION],
595 { "Authorization", "sip.Authorization",
596 FT_STRING, BASE_NONE,NULL,0x0,
597 "RFC 3261: Authorization Header", HFILL }
599 { &hf_header_array[POS_CALL_ID],
600 { "Call-ID", "sip.Call-ID",
601 FT_STRING, BASE_NONE,NULL,0x0,
602 "RFC 3261: Call-ID Header", HFILL }
604 { &hf_header_array[POS_CALL_INFO],
605 { "Call-Info", "sip.Call-Info",
606 FT_STRING, BASE_NONE,NULL,0x0,
607 "RFC 3261: Call-Info Header", HFILL }
609 { &hf_header_array[POS_CONTACT],
610 { "Contact", "sip.Contact",
611 FT_STRING, BASE_NONE,NULL,0x0,
612 "RFC 3261: Contact Header", HFILL }
614 { &hf_header_array[POS_CONTENT_DISPOSITION],
615 { "Content-Disposition", "sip.Content-Disposition",
616 FT_STRING, BASE_NONE,NULL,0x0,
617 "RFC 3261: Content-Disposition Header", HFILL }
619 { &hf_header_array[POS_CONTENT_ENCODING],
620 { "Content-Encoding", "sip.Content-Encoding",
621 FT_STRING, BASE_NONE,NULL,0x0,
622 "RFC 3261: Content-Encoding Header", HFILL }
624 { &hf_header_array[POS_CONTENT_LANGUAGE],
625 { "Content-Language", "sip.Content-Language",
626 FT_STRING, BASE_NONE,NULL,0x0,
627 "RFC 3261: Content-Language Header", HFILL }
629 { &hf_header_array[POS_CONTENT_LENGTH],
630 { "Content-Length", "sip.Content-Length",
631 FT_STRING, BASE_NONE,NULL,0x0,
632 "RFC 3261: Content-Length Header", HFILL }
634 { &hf_header_array[POS_CONTENT_TYPE],
635 { "Content-Type", "sip.Content-Type",
636 FT_STRING, BASE_NONE,NULL,0x0,
637 "RFC 3261: Content-Type Header", HFILL }
639 { &hf_header_array[POS_CSEQ],
640 { "CSeq", "sip.CSeq",
641 FT_STRING, BASE_NONE,NULL,0x0,
642 "RFC 3261: CSeq Header", HFILL }
644 { &hf_header_array[POS_DATE],
645 { "Date", "sip.Date",
646 FT_STRING, BASE_NONE,NULL,0x0,
647 "RFC 3261: Date Header", HFILL }
649 { &hf_header_array[POS_ERROR_INFO],
650 { "Error-Info", "sip.Error-Info",
651 FT_STRING, BASE_NONE,NULL,0x0,
652 "RFC 3261: Error-Info Header", HFILL }
654 { &hf_header_array[POS_EVENT],
655 { "Event", "sip.Event",
656 FT_STRING, BASE_NONE,NULL,0x0,
657 "RFC 3265: Event Header", HFILL }
659 { &hf_header_array[POS_EXPIRES],
660 { "Expires", "sip.Expires",
661 FT_STRING, BASE_NONE,NULL,0x0,
662 "RFC 3261: Expires Header", HFILL }
664 { &hf_header_array[POS_FROM],
665 { "From", "sip.From",
666 FT_STRING, BASE_NONE,NULL,0x0,
667 "RFC 3261: From Header", HFILL }
669 { &hf_header_array[POS_IN_REPLY_TO],
670 { "In-Reply-To", "sip.In-Reply-To",
671 FT_STRING, BASE_NONE,NULL,0x0,
672 "RFC 3261: In-Reply-To Header", HFILL }
674 { &hf_header_array[POS_MAX_FORWARDS],
675 { "Max-Forwards", "sip.Max-Forwards",
676 FT_STRING, BASE_NONE,NULL,0x0,
677 "RFC 3261: Max-Forwards Header", HFILL }
679 { &hf_header_array[POS_MIME_VERSION],
680 { "MIME-Version", "sip.MIME-Version",
681 FT_STRING, BASE_NONE,NULL,0x0,
682 "RFC 3261: MIME-Version Header", HFILL }
684 { &hf_header_array[POS_MIN_EXPIRES],
685 { "Min-Expires", "sip.Min-Expires",
686 FT_STRING, BASE_NONE,NULL,0x0,
687 "RFC 3261: Min-Expires Header", HFILL }
689 { &hf_header_array[POS_ORGANIZATION],
690 { "Organization", "sip.Organization",
691 FT_STRING, BASE_NONE,NULL,0x0,
692 "RFC 3261: Organization Header", HFILL }
694 { &hf_header_array[POS_PRIORITY],
695 { "Priority", "sip.Priority",
696 FT_STRING, BASE_NONE,NULL,0x0,
697 "RFC 3261: Priority Header", HFILL }
699 { &hf_header_array[POS_PROXY_AUTHENTICATE],
700 { "Proxy-Authenticate", "sip.Proxy-Authenticate",
701 FT_STRING, BASE_NONE,NULL,0x0,
702 "RFC 3261: Proxy-Authenticate Header", HFILL }
704 { &hf_header_array[POS_PROXY_AUTHORIZATION],
705 { "Proxy-Authorization", "sip.Proxy-Authorization",
706 FT_STRING, BASE_NONE,NULL,0x0,
707 "RFC 3261: Proxy-Authorization Header", HFILL }
709 { &hf_header_array[POS_RACK],
710 { "RAck", "sip.RAck",
711 FT_STRING, BASE_NONE,NULL,0x0,
712 "RFC 3262: RAck Header", HFILL }
714 { &hf_header_array[POS_RSEQ],
715 { "RSeq", "sip.RSeq",
716 FT_STRING, BASE_NONE,NULL,0x0,
717 "RFC 3262: RSeq Header", HFILL }
719 { &hf_header_array[POS_PROXY_REQUIRE],
720 { "Proxy-Require", "sip.Proxy-Require",
721 FT_STRING, BASE_NONE,NULL,0x0,
722 "RFC 3261: Proxy-Require Header", HFILL }
724 { &hf_header_array[POS_RECORD_ROUTE],
725 { "Record-Route", "sip.Record-Route",
726 FT_STRING, BASE_NONE,NULL,0x0,
727 "RFC 3261: Record-Route Header", HFILL }
729 { &hf_header_array[POS_REPLY_TO],
730 { "Reply-To", "sip.Reply-To",
731 FT_STRING, BASE_NONE,NULL,0x0,
732 "RFC 3261: Reply-To Header", HFILL }
734 { &hf_header_array[POS_REQUIRE],
735 { "Require", "sip.Require",
736 FT_STRING, BASE_NONE,NULL,0x0,
737 "RFC 3261: Require Header", HFILL }
739 { &hf_header_array[POS_RETRY_AFTER],
740 { "Retry-After", "sip.Retry-After",
741 FT_STRING, BASE_NONE,NULL,0x0,
742 "RFC 3261: Retry-After Header", HFILL }
744 { &hf_header_array[POS_ROUTE],
745 { "Route", "sip.Route",
746 FT_STRING, BASE_NONE,NULL,0x0,
747 "RFC 3261: Route Header", HFILL }
749 { &hf_header_array[POS_SERVER],
750 { "Server", "sip.Server",
751 FT_STRING, BASE_NONE,NULL,0x0,
752 "RFC 3261: Server Header", HFILL }
754 { &hf_header_array[POS_SUBJECT],
755 { "Subject", "sip.Subject",
756 FT_STRING, BASE_NONE,NULL,0x0,
757 "RFC 3261: Subject Header", HFILL }
759 { &hf_header_array[POS_SUBSCRIPTION_STATE],
760 { "Subscription-State", "sip.Subscription-State",
761 FT_STRING, BASE_NONE,NULL,0x0,
762 "RFC 3265: Subscription-State Header", HFILL }
764 { &hf_header_array[POS_SUPPORTED],
765 { "Supported", "sip.Supported",
766 FT_STRING, BASE_NONE,NULL,0x0,
767 "RFC 3261: Supported Header", HFILL }
769 { &hf_header_array[POS_TIMESTAMP],
770 { "Timestamp", "sip.Timestamp",
771 FT_STRING, BASE_NONE,NULL,0x0,
772 "RFC 3261: Timestamp Header", HFILL }
774 { &hf_header_array[POS_TO],
776 FT_STRING, BASE_NONE,NULL,0x0,
777 "RFC 3261: To Header", HFILL }
779 { &hf_header_array[POS_UNSUPPORTED],
780 { "Unsupported", "sip.Unsupported",
781 FT_STRING, BASE_NONE,NULL,0x0,
782 "RFC 3261: Unsupported Header", HFILL }
784 { &hf_header_array[POS_USER_AGENT],
785 { "User-Agent", "sip.User-Agent",
786 FT_STRING, BASE_NONE,NULL,0x0,
787 "RFC 3261: User-Agent Header", HFILL }
789 { &hf_header_array[POS_VIA],
791 FT_STRING, BASE_NONE,NULL,0x0,
792 "RFC 3261: Via Header", HFILL }
794 { &hf_header_array[POS_WARNING],
795 { "Warning", "sip.Warning",
796 FT_STRING, BASE_NONE,NULL,0x0,
797 "RFC 3261: Warning Header", HFILL }
799 { &hf_header_array[POS_WWW_AUTHENTICATE],
800 { "WWW-Authenticate", "sip.WWW-Authenticate",
801 FT_STRING, BASE_NONE,NULL,0x0,
802 "RFC 3261: WWW-Authenticate Header", HFILL }
807 /* Setup protocol subtree array */
808 static gint *ett[] = {
813 /* Register the protocol name and description */
814 proto_sip = proto_register_protocol("Session Initiation Protocol",
817 /* Required function calls to register the header fields and subtrees used */
818 proto_register_field_array(proto_sip, hf, array_length(hf));
819 proto_register_subtree_array(ett, array_length(ett));
823 proto_reg_handoff_sip(void)
825 dissector_handle_t sip_handle;
827 sip_handle = create_dissector_handle(dissect_sip, proto_sip);
828 dissector_add("tcp.port", TCP_PORT_SIP, sip_handle);
829 dissector_add("udp.port", UDP_PORT_SIP, sip_handle);
831 heur_dissector_add( "udp", dissect_sip_heur, proto_sip );
832 heur_dissector_add( "tcp", dissect_sip_heur, proto_sip );
835 * Get a handle for the SDP dissector.
837 sdp_handle = find_dissector("sdp");
838 data_handle = find_dissector("data");