Fix a typo.
[obnox/wireshark/wip.git] / epan / dissectors / packet-sip.c
1 /* packet-sip.c
2  * Routines for the Session Initiation Protocol (SIP) dissection.
3  * RFCs 3261-3264
4  *
5  * TODO:
6  *      hf_ display filters for headers of SIP extension RFCs (ongoing)
7  *
8  * Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi>
9  * Copyright 2001, Jean-Francois Mule <jfm@cablelabs.com>
10  * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
11  *
12  * $Id$
13  *
14  * Wireshark - Network traffic analyzer
15  * By Gerald Combs <gerald@wireshark.org>
16  * Copyright 1998 Gerald Combs
17  *
18  * Copied from packet-cops.c
19  *
20  * This program is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU General Public License
22  * as published by the Free Software Foundation; either version 2
23  * of the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, write to the Free Software
32  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
33  */
34
35 #ifdef HAVE_CONFIG_H
36 # include "config.h"
37 #endif
38
39 #include <stdlib.h>
40 #include <string.h>
41 #include <ctype.h>
42
43 #include <epan/prefs.h>
44
45 #include <glib.h>
46
47 #include <wsutil/str_util.h>
48
49 #include <epan/packet.h>
50 #include <epan/req_resp_hdrs.h>
51 #include <epan/emem.h>
52 #include <epan/strutil.h>
53
54 #include <wsutil/str_util.h>
55
56 #include "packet-isup.h"
57 #include "packet-sip.h"
58 #include <epan/tap.h>
59 #include <epan/expert.h>
60
61 #include "packet-tcp.h"
62 #include "packet-ssl.h"
63
64 #define TCP_PORT_SIP 5060
65 #define UDP_PORT_SIP 5060
66 #define TLS_PORT_SIP 5061
67
68 static gint sip_tap = -1;
69 static dissector_handle_t sigcomp_handle;
70
71 /* Initialize the protocol and registered fields */
72 static gint proto_sip                     = -1;
73 static gint proto_raw_sip                 = -1;
74 static gint hf_raw_sip_line               = -1;
75 static gint hf_msg_hdr                    = -1;
76 static gint hf_sip_Method                 = -1;
77 static gint hf_Request_Line               = -1;
78 static gint hf_sip_ruri                   = -1;
79 static gint hf_sip_ruri_user              = -1;
80 static gint hf_sip_ruri_host              = -1;
81 static gint hf_sip_ruri_port              = -1;
82 static gint hf_Status_Code                = -1;
83 static gint hf_Status_Line                = -1;
84 static gint hf_sip_display                = -1;
85 static gint hf_sip_to_addr                = -1;
86 static gint hf_sip_to_user                = -1;
87 static gint hf_sip_to_host                = -1;
88 static gint hf_sip_to_port                = -1;
89 static gint hf_sip_from_addr              = -1;
90 static gint hf_sip_from_user              = -1;
91 static gint hf_sip_from_host              = -1;
92 static gint hf_sip_from_port              = -1;
93 static gint hf_sip_tag                    = -1;
94 static gint hf_sip_pai_addr               = -1;
95 static gint hf_sip_pai_user               = -1;
96 static gint hf_sip_pai_host               = -1;
97 static gint hf_sip_pai_port               = -1;
98 static gint hf_sip_pmiss_addr             = -1;
99 static gint hf_sip_pmiss_user             = -1;
100 static gint hf_sip_pmiss_host             = -1;
101 static gint hf_sip_pmiss_port             = -1;
102 static gint hf_sip_ppi_addr               = -1;
103 static gint hf_sip_ppi_user               = -1;
104 static gint hf_sip_ppi_host               = -1;
105 static gint hf_sip_ppi_port               = -1;
106 static gint hf_sip_tc_addr                = -1;
107 static gint hf_sip_tc_user                = -1;
108 static gint hf_sip_tc_host                = -1;
109 static gint hf_sip_tc_port                = -1;
110 static gint hf_sip_tc_turi                = -1;
111 static gint hf_sip_contact_param           = -1;
112 static gint hf_sip_resend                 = -1;
113 static gint hf_sip_original_frame         = -1;
114 static gint hf_sip_matching_request_frame = -1;
115 static gint hf_sip_response_time          = -1;
116 static gint hf_sip_release_time           = -1;
117 static gint hf_sip_curi                   = -1;
118 static gint hf_sip_curi_user              = -1;
119 static gint hf_sip_curi_host              = -1;
120 static gint hf_sip_curi_port              = -1;
121
122 static gint hf_sip_auth                   = -1;
123 static gint hf_sip_auth_scheme            = -1;
124 static gint hf_sip_auth_digest_response   = -1;
125 static gint hf_sip_auth_nc                = -1;
126 static gint hf_sip_auth_username          = -1;
127 static gint hf_sip_auth_realm             = -1;
128 static gint hf_sip_auth_nonce             = -1;
129 static gint hf_sip_auth_algorithm         = -1;
130 static gint hf_sip_auth_opaque            = -1;
131 static gint hf_sip_auth_qop               = -1;
132 static gint hf_sip_auth_cnonce            = -1;
133 static gint hf_sip_auth_uri               = -1;
134 static gint hf_sip_auth_domain            = -1;
135 static gint hf_sip_auth_stale             = -1;
136 static gint hf_sip_auth_auts              = -1;
137 static gint hf_sip_auth_rspauth           = -1;
138 static gint hf_sip_auth_nextnonce         = -1;
139 static gint hf_sip_auth_ik                = -1;
140 static gint hf_sip_auth_ck                = -1;
141
142 static gint hf_sip_cseq_seq_no            = -1;
143 static gint hf_sip_cseq_method            = -1;
144
145 static gint hf_sip_via_transport          = -1;
146 static gint hf_sip_via_sent_by_address    = -1;
147 static gint hf_sip_via_sent_by_port       = -1;
148 static gint hf_sip_via_branch             = -1;
149 static gint hf_sip_via_maddr              = -1;
150 static gint hf_sip_via_rport              = -1;
151 static gint hf_sip_via_received           = -1;
152 static gint hf_sip_via_ttl                = -1;
153 static gint hf_sip_via_comp               = -1;
154 static gint hf_sip_via_sigcomp_id         = -1;
155
156 static gint hf_sip_rack_rseq_no           = -1;
157 static gint hf_sip_rack_cseq_no           = -1;
158 static gint hf_sip_rack_cseq_method       = -1;
159
160 static gint hf_sip_msg_body               = -1;
161
162 /* Initialize the subtree pointers */
163 static gint ett_sip                       = -1;
164 static gint ett_sip_reqresp               = -1;
165 static gint ett_sip_hdr                   = -1;
166 static gint ett_sip_ext_hdr               = -1;
167 static gint ett_raw_text                  = -1;
168 static gint ett_sip_element               = -1;
169 static gint ett_sip_uri                   = -1;
170 static gint ett_sip_contact_item          = -1;
171 static gint ett_sip_message_body          = -1;
172 static gint ett_sip_cseq                  = -1;
173 static gint ett_sip_via                   = -1;
174 static gint ett_sip_reason                = -1;
175 static gint ett_sip_rack                  = -1;
176 static gint ett_sip_ruri                  = -1;
177 static gint ett_sip_to_uri                = -1;
178 static gint ett_sip_curi                  = -1;
179 static gint ett_sip_from_uri              = -1;
180 static gint ett_sip_pai_uri               = -1;
181 static gint ett_sip_pmiss_uri             = -1;
182 static gint ett_sip_ppi_uri               = -1;
183 static gint ett_sip_tc_uri                = -1;
184
185 /* PUBLISH method added as per http://www.ietf.org/internet-drafts/draft-ietf-sip-publish-01.txt */
186 static const char *sip_methods[] = {
187 #define SIP_METHOD_INVALID      0
188         "<Invalid method>",      /* Pad so that the real methods start at index 1 */
189 #define SIP_METHOD_ACK          1
190         "ACK",
191 #define SIP_METHOD_BYE          2
192         "BYE",
193 #define SIP_METHOD_CANCEL       3
194         "CANCEL",
195 #define SIP_METHOD_DO           4
196         "DO",
197 #define SIP_METHOD_INFO         5
198         "INFO",
199 #define SIP_METHOD_INVITE       6
200         "INVITE",
201 #define SIP_METHOD_MESSAGE      7
202         "MESSAGE",
203 #define SIP_METHOD_NOTIFY       8
204         "NOTIFY",
205 #define SIP_METHOD_OPTIONS      9
206         "OPTIONS",
207 #define SIP_METHOD_PRACK        10
208         "PRACK",
209 #define SIP_METHOD_QAUTH        11
210         "QAUTH",
211 #define SIP_METHOD_REFER        12
212         "REFER",
213 #define SIP_METHOD_REGISTER     13
214         "REGISTER",
215 #define SIP_METHOD_SPRACK       14
216         "SPRACK",
217 #define SIP_METHOD_SUBSCRIBE    15
218         "SUBSCRIBE",
219 #define SIP_METHOD_UPDATE       16
220         "UPDATE",
221 #define SIP_METHOD_PUBLISH      17
222         "PUBLISH"
223 };
224
225 /* from RFC 3261
226  * Updated with info from http://www.iana.org/assignments/sip-parameters
227  * (last updated 2009-11-11)
228  * Updated with: http://www.ietf.org/internet-drafts/draft-ietf-sip-resource-priority-05.txt
229  */
230 typedef struct {
231         const char *name;
232         const char *compact_name;
233 } sip_header_t;
234 static const sip_header_t sip_headers[] = {
235         { "Unknown-header",                     NULL }, /* 0 Pad so that the real headers start at index 1 */
236         { "Accept",                                     NULL }, /* 1 */
237         { "Accept-Contact",                             "a"  }, /* 2 RFC3841  */
238         { "Accept-Encoding",                    NULL }, /* 3 */
239         { "Accept-Language",                    NULL }, /* 4 */
240         { "Accept-Resource-Priority",           NULL }, /* 5 RFC4412 */
241         { "Alert-Info",                                 NULL },
242         { "Allow",                                              NULL },
243         { "Allow-Events",                               "u"  }, /* 8 RFC3265  */
244         { "Answer-Mode",                                NULL }, /* 9 RFC5373 */
245         { "Authentication-Info",                NULL },
246         { "Authorization",                              NULL }, /* 11 */
247         { "Call-ID",                                    "i"  },
248         { "Call-Info",                                  NULL },
249         { "Contact",                                    "m"  },
250         { "Content-Disposition",                NULL },
251         { "Content-Encoding",                   "e"  },  /*  16 */
252         { "Content-Language",                   NULL },
253         { "Content-Length",                     "l"  },
254         { "Content-Type",                               "c"  },
255         { "CSeq",                                               NULL },
256         { "Date",                                               NULL },  /*  21 */
257 /*                              Encryption (Deprecated)       [RFC3261] */
258         { "Error-Info",                                 NULL },
259         { "Event",                                              "o"  },
260         { "Expires",                                    NULL },
261         /* Flow-Timer                    [RFC5626]*/
262         { "From",                                               "f"  },  /*  25 */
263 /*                              Hide                          [RFC3261] (deprecated)*/
264         { "History-Info",                               NULL },  /*  26 RFC4244  */
265         { "Identity",                                   "y"  },  /*      27 RFC4474  */
266         { "Identity-Info",                              "n"  },  /*      28 RFC4474  */
267         { "In-Reply-To",                                NULL },  /*  29 RFC3261  */
268         { "Join",                                               NULL },  /*  30 RFC3911  */
269         { "Max-Breadth",                                NULL },  /*  31 RFC5393*/
270         { "Max-Forwards",                               NULL },  /*  32 */
271         { "MIME-Version",                               NULL },  /*  33 */
272         { "Min-Expires",                                NULL },  /*  34 */
273         { "Min-SE",                                             NULL },  /*  35 RFC4028  */
274         { "Organization",                               NULL },  /*  36 RFC3261  */
275         { "P-Access-Network-Info",              NULL },  /*  37 RFC3455  */
276         { "P-Answer-State",                     NULL },  /*  38 RFC4964  */
277         { "P-Asserted-Identity",                NULL },  /*  39 RFC3325  */
278         { "P-Associated-URI",                   NULL },  /*  40 RFC3455  */
279         { "P-Called-Party-ID",                  NULL },  /*  41 RFC3455  */
280         { "P-Charging-Function-Addresses",      NULL },/*  42 RFC3455  */
281         { "P-Charging-Vector",                  NULL },  /*  43 RFC3455  */
282         { "P-DCS-Trace-Party-ID",               NULL },  /*  44 RFC5503  */
283         { "P-DCS-OSPS",                         NULL },  /*  45 RFC5503  */
284         { "P-DCS-Billing-Info",                 NULL },  /*  46 RFC5503  */
285         { "P-DCS-LAES",                         NULL },  /*  47 RFC5503  */
286         { "P-DCS-Redirect",                     NULL },  /*  48 RFC5503  */
287         { "P-Early-Media",                                      NULL },  /*  49 RFC5009  */
288         { "P-Media-Authorization",              NULL },  /*  50 RFC3313  */
289         { "P-Preferred-Identity",               NULL },  /*  51 RFC3325  */
290         { "P-Profile-Key",                                      NULL },  /*  52 RFC5002  */
291         { "P-Refused-URI-List",                         NULL },  /*  53 RFC5318  */
292         { "P-Served-User",                                      NULL },  /*  54 RFC5502  */
293         { "P-User-Database",                            NULL },  /*  55 RFC4457  */
294         { "P-Visited-Network-ID",               NULL },  /*  56 RFC3455  */
295         { "Path",                               NULL },  /*  57 RFC3327  */
296         { "Permission-Missing",                 NULL },  /*  58 RFC5360  */
297         { "Priority",                                           NULL },  /*  59 RFC3261  */
298         { "Priv-Answer-Mode",                   NULL },  /*  60 RFC5373  */
299         { "Privacy",                            NULL },  /*  61 RFC3323  */
300         { "Proxy-Authenticate",                         NULL },  /*  62 */
301         { "Proxy-Authorization",                        NULL },  /*  63 */
302         { "Proxy-Require",                                      NULL },  /*  64 */
303         { "RAck",                                                       NULL },  /*  65 RFC3262  */
304         { "Reason",                             NULL },  /*  66 RFC3326  */
305         { "Record-Route",                                       NULL },  /*  67 */
306         { "Refer-Sub",                                          NULL },  /*  68 RFC4488  */
307         { "Refer-To",                                           "r"  },  /*  69 RFC3515  */
308         { "Referred-By",                                        "b"  },  /*  70 RFC3892  */
309         { "Reject-Contact",                                     "j"  },  /*  71 RFC3841  */
310         { "Replaces",                                           NULL },  /*  72 RFC3891  */
311         { "Reply-To",                                           NULL },  /*  73 RFC3261  */
312         { "Request-Disposition",                        "d"  },  /*  74 RFC3841  */
313         { "Require",                                            NULL },  /*  75 RFC3261  */
314         { "Resource-Priority",                          NULL },  /*  76 RFC4412  */
315         /*
316           { "Response-Key (Deprecated)     [RFC3261]
317         */
318         { "Retry-After",                                        NULL },  /*  77 RFC3261  */
319         { "Route",                                                      NULL },  /*  78 RFC3261  */
320         { "RSeq",                                                       NULL },  /*  79 RFC3262  */
321         { "Security-Client",                            NULL },  /*  80 RFC3329  */
322         { "Security-Server",                            NULL },  /*  81 RFC3329  */
323         { "Security-Verify",                            NULL },  /*  82 RFC3329  */
324         { "Server",                                                     NULL },  /*  83 RFC3261  */
325         { "Service-Route",                                      NULL },  /*  84 RFC3608  */
326         { "Session-Expires",                            "x"  },  /*  85 RFC4028  */
327         { "SIP-ETag",                                           NULL },  /*  86 RFC3903  */
328         { "SIP-If-Match",                                       NULL },  /*  87 RFC3903  */
329         { "Subject",                                            "s"  },  /*  88 RFC3261  */
330         { "Subscription-State",                         NULL },  /*  89 RFC3265  */
331         { "Supported",                                          "k"      },  /*  90 RFC3261  */
332         { "Target-Dialog",                                      NULL },  /*  81 RFC4538  */
333         { "Timestamp",                                          NULL },  /*  92 RFC3261  */
334         { "To",                                                         "t"  },  /*  93 RFC3261  */
335         { "Trigger-Consent",                    NULL },  /*  94 RFC5360  */
336         { "Unsupported",                                        NULL },  /*  95 RFC3261  */
337         { "User-Agent",                                         NULL },  /*  96 RFC3261  */
338         { "Via",                                                        "v"  },  /*  97 RFC3261  */
339         { "Warning",                                            NULL },  /*  98 RFC3261  */
340         { "WWW-Authenticate",                           NULL },  /*  99 RFC3261  */
341 };
342
343
344 #define POS_ACCEPT                                      1
345 #define POS_ACCEPT_CONTACT                       2
346 #define POS_ACCEPT_ENCODING                      3
347 #define POS_ACCEPT_LANGUAGE                      4
348 #define POS_ACCEPT_RESOURCE_PRIORITY             5
349 #define POS_ALERT_INFO                           6
350 #define POS_ALLOW                                7
351 #define POS_ALLOW_EVENTS                         8
352 #define POS_ANSWER_MODE                          9
353 #define POS_AUTHENTICATION_INFO                 10
354 #define POS_AUTHORIZATION                       11
355 #define POS_CALL_ID                             12
356 #define POS_CALL_INFO                           13
357 #define POS_CONTACT                             14
358 #define POS_CONTENT_DISPOSITION                 15
359 #define POS_CONTENT_ENCODING                    16
360 #define POS_CONTENT_LANGUAGE                    17
361 #define POS_CONTENT_LENGTH                      18
362 #define POS_CONTENT_TYPE                        19
363 #define POS_CSEQ                                20
364 #define POS_DATE                                21
365 #define POS_ERROR_INFO                          22
366 #define POS_EVENT                               23
367 #define POS_EXPIRES                             24
368 #define POS_FROM                                25
369 #define POS_HISTORY_INFO                        26
370 #define POS_IDENTITY                            27
371 #define POS_IDENTITY_INFO                       28
372 #define POS_IN_REPLY_TO                         29
373 #define POS_JOIN                                30
374 #define POS_MAX_BREADTH                         31
375 #define POS_MAX_FORWARDS                        32
376 #define POS_MIME_VERSION                        33
377 #define POS_MIN_EXPIRES                         34
378 #define POS_MIN_SE                              35
379 #define POS_ORGANIZATION                        36
380 #define POS_P_ACCESS_NETWORK_INFO               37
381 #define POS_P_ANSWER_STATE                      38
382 #define POS_P_ASSERTED_IDENTITY                 39
383 #define POS_P_ASSOCIATED_URI                    40
384 #define POS_P_CALLED_PARTY_ID                   41
385 #define POS_P_CHARGING_FUNCTION_ADDRESSES       42
386 #define POS_P_CHARGING_VECTOR                   43
387 #define POS_P_DCS_TRACE_PARTY_ID                44
388 #define POS_P_DCS_OSPS                          45
389 #define POS_P_DCS_BILLING_INFO                  46
390 #define POS_P_DCS_LAES                          47
391 #define POS_P_DCS_REDIRECT                      48
392 #define POS_P_EARLY_MEDIA                       49
393 #define POS_P_MEDIA_AUTHORIZATION               50
394 #define POS_P_PREFERRED_IDENTITY                51
395 #define POS_P_PROFILE_KEY                       52
396 #define POS_P_REFUSED_URI_LST                   53
397 #define POS_P_SERVED_USER                       54
398 #define POS_P_USER_DATABASE                     55
399 #define POS_P_VISITED_NETWORK_ID                56
400 #define POS_PATH                                57
401 #define POS_PERMISSION_MISSING                  58
402 #define POS_PRIORITY                            59
403 #define POS_PRIV_ANSWER_MODE                    60
404 #define POS_PRIVACY                             61
405 #define POS_PROXY_AUTHENTICATE                  62
406 #define POS_PROXY_AUTHORIZATION                 63
407 #define POS_PROXY_REQUIRE                       64
408 #define POS_RACK                                65
409 #define POS_REASON                              66
410 #define POS_RECORD_ROUTE                        67
411 #define POS_REFER_SUB                           68
412 #define POS_REFER_TO                            69
413 #define POS_REFERED_BY                          70
414 #define POS_REJECT_CONTACT                      71
415 #define POS_REPLACES                            72
416 #define POS_REPLY_TO                            73
417 #define POS_REQUEST_DISPOSITION                 74
418 #define POS_REQUIRE                             75
419 #define POS_RESOURCE_PRIORITY                   76
420 #define POS_RETRY_AFTER                         77
421 #define POS_ROUTE                               78
422 #define POS_RSEQ                                79
423 #define POS_SECURITY_CLIENT                     80
424 #define POS_SECURITY_SERVER                     81
425 #define POS_SECURITY_VERIFY                     82
426 #define POS_SERVER                              83
427 #define POS_SERVICE_ROUTE                       84
428 #define POS_SESSION_EXPIRES                     85
429 #define POS_SIP_ETAG                            86
430 #define POS_SIP_IF_MATCH                        87
431 #define POS_SUBJECT                             88
432 #define POS_SUBSCRIPTION_STATE                  89
433 #define POS_SUPPORTED                           90
434 #define POS_TARGET_DALOG                        91
435 #define POS_TIMESTAMP                           92
436 #define POS_TO                                  93
437 #define POS_TRIGGER_CONSENT                     94
438 #define POS_UNSUPPORTED                         95
439 #define POS_USER_AGENT                          96
440 #define POS_VIA                                 97
441 #define POS_WARNING                             98
442 #define POS_WWW_AUTHENTICATE                    99
443
444
445 static gint hf_header_array[] = {
446                 -1, /* 0"Unknown-header" - Pad so that the real headers start at index 1 */
447                 -1, /* 1"Accept"                                        */
448                 -1, /* 2"Accept-Contact"                        RFC3841 */
449                 -1, /* 3"Accept-Encoding"                               */
450                 -1, /* 4"Accept-Language"                               */
451                 -1, /* 5"Accept-Resource-Priority"              RFC4412 */
452                 -1, /* 6"Alert-Info",                                   */
453                 -1, /* 7"Allow",                                        */
454                 -1, /* 8"Allow-Events",                         RFC3265 */
455                 -1, /* 9"Answer-Mode"                           RFC5373 */
456                 -1, /* 10"Authentication-Info"                          */
457                 -1, /* 11"Authorization",                               */
458                 -1, /* 12"Call-ID",                                     */
459                 -1, /* 13"Call-Info"                                    */
460                 -1, /* 14"Contact",                                     */
461                 -1, /* 15"Content-Disposition",                         */
462                 -1, /* 16"Content-Encoding",                            */
463                 -1, /* 17"Content-Language",                            */
464                 -1, /* 18"Content-Length",                              */
465                 -1, /* 19"Content-Type",                                */
466                 -1, /* 20"CSeq",                                        */
467                 -1, /* 21"Date",                                        */
468                 -1, /* 22"Error-Info",                                  */
469                 -1, /* 23"Event",                                       */
470                 -1, /* 24"Expires",                                     */
471                 -1, /* 25"From",                                        */
472                 -1, /* 26"History-Info",                        RFC4244 */
473                 -1, /* 27"Identity",                                    */
474                 -1, /* 28"Identity-Info",                       RFC4474 */
475                 -1, /* 29"In-Reply-To",                         RFC3261 */
476                 -1, /* 30"Join",                                RFC3911 */
477                 -1, /* 31"Max-Breadth"                          RFC5393 */
478                 -1, /* 32"Max-Forwards",                                */
479                 -1, /* 33"MIME-Version",                                */
480                 -1, /* 34"Min-Expires",                                 */
481                 -1, /* 35"Min-SE",                              RFC4028 */
482                 -1, /* 36"Organization",                                */
483                 -1, /* 37"P-Access-Network-Info",               RFC3455 */
484                 -1, /* 38"P-Answer-State",                      RFC4964 */
485                 -1, /* 39"P-Asserted-Identity",                 RFC3325 */
486                 -1, /* 40"P-Associated-URI",                    RFC3455 */
487                 -1, /* 41"P-Called-Party-ID",                   RFC3455 */
488                 -1, /* 42"P-Charging-Function-Addresses",       RFC3455 */
489                 -1, /* 43"P-Charging-Vector",                   RFC3455 */
490                 -1, /* 44"P-DCS-Trace-Party-ID",                RFC3603 */
491                 -1, /* 45"P-DCS-OSPS",                          RFC3603 */
492                 -1, /* 46"P-DCS-Billing-Info",                  RFC3603 */
493                 -1, /* 47"P-DCS-LAES",                          RFC3603 */
494                 -1, /* 48"P-DCS-Redirect",                      RFC3603 */
495                 -1, /* 49"P-Early-Media",                               */
496                 -1, /* 50"P-Media-Authorization",               RFC3313 */
497                 -1, /* 51"P-Preferred-Identity",                RFC3325 */
498                 -1, /* 52"P-Profile-Key",                               */
499                 -1, /* 53"P-Refused-URI-List",                  RFC5318 */
500                 -1, /* 54"P-Served-User",                       RFC5502 */
501                 -1, /* 55"P-User-Database                       RFC4457 */
502                 -1, /* 56"P-Visited-Network-ID",                RFC3455 */
503                 -1, /* 57"Path",                                RFC3327 */
504                 -1, /* 58"Permission-Missing"                   RFC5360 */
505                 -1, /* 59"Priority"                                     */
506                 -1, /* 60"Priv-Answer-mode"                     RFC5373 */
507                 -1, /* 61"Privacy",                             RFC3323 */
508                 -1, /* 62"Proxy-Authenticate",                          */
509                 -1, /* 63"Proxy-Authorization",                         */
510                 -1, /* 64"Proxy-Require",                               */
511                 -1, /* 65"RAck",                                RFC3262 */
512                 -1, /* 66"Reason",                              RFC3326 */
513                 -1, /* 67"Record-Route",                                */
514                 -1, /* 68"Refer-Sub",",                         RFC4488 */
515                 -1, /* 69"Refer-To",                            RFC3515 */
516                 -1, /* 70"Referred-By",                                 */
517                 -1, /* 71"Reject-Contact",                      RFC3841 */
518                 -1, /* 72"Replaces",                            RFC3891 */
519                 -1, /* 73"Reply-To",                            RFC3261 */
520                 -1, /* 74"Request-Disposition",                 RFC3841 */
521                 -1, /* 75"Require",                             RFC3261 */
522                 -1, /* 76"Resource-Priority",                   RFC4412 */
523                 -1, /* 77"Retry-After",                         RFC3261 */
524                 -1, /* 78"Route",                               RFC3261 */
525                 -1, /* 79"RSeq",                                RFC3262 */
526                 -1, /* 80"Security-Client",                     RFC3329 */
527                 -1, /* 81"Security-Server",                     RFC3329 */
528                 -1, /* 82"Security-Verify",                     RFC3329 */
529                 -1, /* 83"Server",                              RFC3261 */
530                 -1, /* 84"Service-Route",                       RFC3608 */
531                 -1, /* 85"Session-Expires",                     RFC4028 */
532                 -1, /* 86"SIP-ETag",                            RFC3903 */
533                 -1, /* 87"SIP-If-Match",                        RFC3903 */
534                 -1, /* 88"Subject",                             RFC3261 */
535                 -1, /* 89"Subscription-State",                  RFC3265 */
536                 -1, /* 90"Supported",                           RFC3261 */
537                 -1, /* 91"Target-Dialog",                       RFC4538 */
538                 -1, /* 92"Timestamp",                           RFC3261 */
539                 -1, /* 93"To",                                  RFC3261 */
540                 -1, /* 94"Trigger-Consent"                      RFC5380 */
541                 -1, /* 95"Unsupported",                         RFC3261 */
542                 -1, /* 96"User-Agent",                          RFC3261 */
543                 -1, /* 97"Via",                                 RFC3261 */
544                 -1, /* 98"Warning",                             RFC3261 */
545                 -1, /* 99"WWW-Authenticate",                    RFC3261 */
546
547 };
548
549 /* Track associations between parameter name and hf item */
550 typedef struct {
551         const char  *param_name;
552         const gint  *hf_item;
553 } header_parameter_t;
554
555 static header_parameter_t auth_parameters_hf_array[] =
556 {
557         {"response",        &hf_sip_auth_digest_response},
558         {"nc",              &hf_sip_auth_nc},
559         {"username",        &hf_sip_auth_username},
560         {"realm",           &hf_sip_auth_realm},
561         {"nonce",           &hf_sip_auth_nonce},
562         {"algorithm",       &hf_sip_auth_algorithm},
563         {"opaque",          &hf_sip_auth_opaque},
564         {"qop",             &hf_sip_auth_qop},
565         {"cnonce",          &hf_sip_auth_cnonce},
566         {"uri",             &hf_sip_auth_uri},
567         {"domain",          &hf_sip_auth_domain},
568         {"stale",           &hf_sip_auth_stale},
569         {"auts",            &hf_sip_auth_auts},
570         {"rspauth",         &hf_sip_auth_rspauth},
571         {"nextnonce",       &hf_sip_auth_nextnonce},
572         {"ik",              &hf_sip_auth_ik},
573         {"ck",              &hf_sip_auth_ck}
574 };
575
576 static header_parameter_t via_parameters_hf_array[] =
577 {
578         {"branch",        &hf_sip_via_branch},
579         {"maddr",         &hf_sip_via_maddr},
580         {"rport",         &hf_sip_via_rport},
581         {"received",      &hf_sip_via_received},
582         {"ttl",           &hf_sip_via_ttl},
583         {"comp",          &hf_sip_via_comp},
584         {"sigcomp-id",    &hf_sip_via_sigcomp_id}
585 };
586
587
588 typedef struct {
589         gint *hf_sip_addr;
590         gint *hf_sip_user;
591         gint *hf_sip_host;
592         gint *hf_sip_port;
593         gint *ett_uri;
594 } hf_sip_uri_t;
595
596 static hf_sip_uri_t sip_pai_uri = {
597         &hf_sip_pai_addr,
598         &hf_sip_pai_user,
599         &hf_sip_pai_host,
600         &hf_sip_pai_port,
601         &ett_sip_pai_uri
602 };
603
604 static hf_sip_uri_t sip_ppi_uri = {
605         &hf_sip_ppi_addr,
606         &hf_sip_ppi_user,
607         &hf_sip_ppi_host,
608         &hf_sip_ppi_port,
609         &ett_sip_ppi_uri
610 };
611
612 static hf_sip_uri_t sip_pmiss_uri = {
613         &hf_sip_pmiss_addr,
614         &hf_sip_pmiss_user,
615         &hf_sip_pmiss_host,
616         &hf_sip_pmiss_port,
617         &ett_sip_pmiss_uri
618 };
619
620
621 static hf_sip_uri_t sip_tc_uri = {
622         &hf_sip_tc_addr,
623         &hf_sip_tc_user,
624         &hf_sip_tc_host,
625         &hf_sip_tc_port,
626         &ett_sip_tc_uri
627 };
628
629 static hf_sip_uri_t sip_to_uri = {
630         &hf_sip_to_addr,
631         &hf_sip_to_user,
632         &hf_sip_to_host,
633         &hf_sip_to_port,
634         &ett_sip_to_uri
635 };
636
637 static hf_sip_uri_t sip_from_uri = {
638         &hf_sip_from_addr,
639         &hf_sip_from_user,
640         &hf_sip_from_host,
641         &hf_sip_from_port,
642         &ett_sip_from_uri
643 };
644
645 static hf_sip_uri_t sip_req_uri = {
646         &hf_sip_ruri,
647         &hf_sip_ruri_user,
648         &hf_sip_ruri_host,
649         &hf_sip_ruri_port,
650         &ett_sip_ruri
651 };
652
653 static hf_sip_uri_t sip_contact_uri = {
654         &hf_sip_curi,
655         &hf_sip_curi_user,
656         &hf_sip_curi_host,
657         &hf_sip_curi_port,
658         &ett_sip_curi
659 };
660
661 /*
662  * Type of line.  It's either a SIP Request-Line, a SIP Status-Line, or
663  * another type of line.
664  */
665 typedef enum {
666         REQUEST_LINE,
667         STATUS_LINE,
668         OTHER_LINE
669 } line_type_t;
670
671 /* Preferences */
672 static guint sip_tcp_port = TCP_PORT_SIP;
673 static guint sip_tls_port = TLS_PORT_SIP;
674
675 /* global_sip_raw_text determines whether we are going to display               */
676 /* the raw text of the SIP message, much like the MEGACO dissector does.        */
677 static gboolean global_sip_raw_text = FALSE;
678 /* strict_sip_version determines whether the SIP dissector enforces
679  * the SIP version to be "SIP/2.0". */
680 static gboolean strict_sip_version = TRUE;
681
682 /*
683  * desegmentation of SIP headers
684  * (when we are over TCP or another protocol providing the desegmentation API)
685  */
686 static gboolean sip_desegment_headers = TRUE;
687
688 /*
689  * desegmentation of SIP bodies
690  * (when we are over TCP or another protocol providing the desegmentation API)
691  */
692 static gboolean sip_desegment_body = TRUE;
693
694 /*
695  * same source port for retransmissions
696  */
697 static gboolean sip_retrans_the_same_sport = TRUE;
698
699 /* Extension header subdissectors */
700 static dissector_table_t ext_hdr_subdissector_table;
701
702 /* Forward declaration we need below */
703 void proto_reg_handoff_sip(void);
704 static gboolean dissect_sip_common(tvbuff_t *tvb, int offset, packet_info *pinfo,
705     proto_tree *tree, gboolean is_heur, gboolean use_reassembly);
706 static line_type_t sip_parse_line(tvbuff_t *tvb, int offset, gint linelen,
707     guint *token_1_len);
708 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
709     guint meth_len, guint *meth_idx);
710 static gint sip_is_known_sip_header(gchar *header_name, guint header_len);
711 static void dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint offset,
712     guint meth_len, gint linelen);
713 static void dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree);
714 static void tvb_raw_text_add(tvbuff_t *tvb, int offset, int length, proto_tree *tree);
715 static guint sip_is_packet_resend(packet_info *pinfo,
716                                 gchar* cseq_method,
717                                 gchar* call_id,
718                                 guchar cseq_number_set, guint32 cseq_number,
719                                 line_type_t line_type);
720
721 static guint sip_find_request(packet_info *pinfo,
722                                 gchar* cseq_method,
723                                 gchar* call_id,
724                                 guchar cseq_number_set, guint32 cseq_number,
725                                 guint32 *response_time);
726
727 static guint sip_find_invite(packet_info *pinfo,
728                                 gchar* cseq_method,
729                                 gchar* call_id,
730                                 guchar cseq_number_set, guint32 cseq_number,
731                                 guint32 *response_time);
732
733 /* SIP content type and internet media type used by other dissectors
734  * are the same.  List of media types from IANA at:
735  * http://www.iana.org/assignments/media-types/index.html */
736 static dissector_table_t media_type_dissector_table;
737
738 static heur_dissector_list_t heur_subdissector_list;
739
740 #define SIP2_HDR "SIP/2.0"
741 #define SIP2_HDR_LEN ((gint)strlen (SIP2_HDR))
742
743 /* Store the info needed by the SIP tap for one packet */
744 static sip_info_value_t *stat_info;
745
746 /* The buffer size for the cseq_method name */
747 #define MAX_CSEQ_METHOD_SIZE 16
748
749 /****************************************************************************
750  * Conversation-type definitions
751  *
752  * For each call, keep track of the current cseq number and state of
753  * transaction, in order to be able to detect retransmissions.
754  *
755  * Don't use the conservation mechanism, but instead:
756  * - store with each dissected packet original frame (if any)
757  * - maintain a global hash table of
758  *   (call_id, source_addr, dest_addr) -> (cseq, transaction_state, frame)
759  *
760  * N.B. This is broken for a couple of reasons:
761  * - it won't cope properly with overlapping transactions within the
762  *   same dialog
763  * - request response mapping won't work where the response uses a different
764  *   address pair from the request
765  *
766  * TODO: proper transaction matching uses RFC fields (use Max-forwards or
767  * maybe Via count as extra key to limit view to one hop)
768  ****************************************************************************/
769
770 static GHashTable *sip_hash = NULL;           /* Hash table */
771 static GHashTable *sip_headers_hash = NULL;             /* Hash table */
772
773 /* Types for hash table keys and values */
774 #define MAX_CALL_ID_SIZE 128
775 #define MAGIC_SOURCE_PORT 0
776
777 /* Conversation-type key */
778 typedef struct
779 {
780         char call_id[MAX_CALL_ID_SIZE];
781         address source_address;
782         guint32 source_port;
783         address dest_address;
784         guint32 dest_port;
785 } sip_hash_key;
786
787
788 typedef enum
789 {
790         nothing_seen,
791         request_seen,
792         provisional_response_seen,
793         final_response_seen
794 } transaction_state_t;
795
796 /* Current conversation-type value */
797 typedef struct
798 {
799         guint32             cseq;
800         transaction_state_t transaction_state;
801         gchar               method[MAX_CSEQ_METHOD_SIZE];
802         nstime_t            request_time;
803         guint32             response_code;
804         gint                frame_number;
805 } sip_hash_value;
806
807 /* Result to be stored in per-packet info */
808 typedef struct
809 {
810         gint       original_frame_num;
811         gint       response_request_frame_num;
812         gint       response_time;
813 } sip_frame_result_value;
814
815
816 /************************/
817 /* Hash table functions */
818
819 /* Equal keys */
820 static gint sip_equal(gconstpointer v, gconstpointer v2)
821 {
822         const sip_hash_key* val1 = v;
823         const sip_hash_key* val2 = v2;
824
825         /* Call id must match */
826         if (strcmp(val1->call_id, val2->call_id) != 0)
827         {
828                 return 0;
829         }
830
831         /* Addresses must match */
832         return  (ADDRESSES_EQUAL(&(val1->source_address), &(val2->source_address))) &&
833                 (val1->source_port == val2->source_port) &&
834                 (ADDRESSES_EQUAL(&(val1->dest_address), &(val2->dest_address))) &&
835                 (val1->dest_port == val2->dest_port);
836 }
837
838
839 /* Initializes the hash table and the mem_chunk area each time a new
840  * file is loaded or re-loaded in wireshark */
841 static void
842 sip_init_protocol(void)
843 {
844          guint i;
845          gchar *value_copy;
846
847         /* Destroy any existing hashes. */
848         if (sip_hash)
849                 g_hash_table_destroy(sip_hash);
850
851         /* Now create them over */
852         sip_hash = g_hash_table_new(g_str_hash , sip_equal);
853         /* Create a hastable with the SIP headers it will be used to find the related hf entry (POS_x)
854          * this is faster than the previously used for loop
855          * There is no g_hash_table_destroy as the liftime is the same as the lifetime of Wireshark
856          */
857         if(!sip_headers_hash){
858                 sip_headers_hash = g_hash_table_new(g_str_hash , g_str_equal);
859                 for (i = 1; i < array_length(sip_headers); i++){
860                         value_copy = g_strdup (sip_headers[i].name);
861                         /* Store (and compare) the string in lower case) */
862                         ascii_strdown_inplace(value_copy);
863                         g_hash_table_insert(sip_headers_hash, (gpointer)value_copy, GINT_TO_POINTER(i));
864                 }
865         }
866 }
867
868 /* Structure to collect info about a sip uri */
869 typedef struct _uri_offset_info
870 {
871         gint display_name_start;
872         gint display_name_end;
873         gint uri_start;
874         gint uri_end;
875         gint uri_parameters_start;
876         gint uri_parameters_end;
877         gint name_addr_start;
878         gint name_addr_end;
879         gint uri_user_start;
880         gint uri_user_end;
881         gint uri_host_start;
882         gint uri_host_end;
883         gint uri_host_port_start;
884         gint uri_host_port_end;
885 } uri_offset_info;
886
887 static void
888 sip_uri_offset_init(uri_offset_info *uri_offsets){
889
890         /* Initialize the uri_offsets */
891         uri_offsets->display_name_start = -1;
892         uri_offsets->display_name_end = -1;
893         uri_offsets->uri_start = -1;
894         uri_offsets->uri_end = -1;
895         uri_offsets->uri_parameters_start = -1;
896         uri_offsets->uri_parameters_end = -1;
897         uri_offsets->name_addr_start = -1;
898         uri_offsets->name_addr_end = -1;
899         uri_offsets->uri_user_start = -1;
900         uri_offsets->uri_user_end = -1;
901         uri_offsets->uri_host_start = -1;
902         uri_offsets->uri_host_end = -1;
903         uri_offsets->uri_host_port_start = -1;
904         uri_offsets->uri_host_port_end = -1;
905
906 }
907 /* Code to parse a sip uri.
908  * Returns Offset end off parsing or -1 for unsuccessful parsing
909  * - sip_uri_offset_init() must have been called first.
910  */
911 static gint
912 dissect_sip_uri(tvbuff_t *tvb, packet_info *pinfo _U_, gint start_offset,
913                 gint line_end_offset, uri_offset_info *uri_offsets)
914 {
915         gchar c = '\0';
916         gint current_offset;
917         gint queried_offset;
918         gint comma_offset;
919         gint semicolon_offset;
920         gint parameter_end_offset;
921         gboolean in_ipv6 = FALSE;
922
923         /* skip Spaces and Tabs */
924         current_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
925
926         if(current_offset >= line_end_offset) {
927                 /* Nothing to parse */
928                 return -1;
929         }
930         /* Set uri start offset in case this was called directly */
931         uri_offsets->uri_start = current_offset;
932
933         /* Check if it's realy a sip uri ( it might be a tel uri, parse that?) */
934         queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ':');
935         if (tvb_strneql(tvb, current_offset, "sip", 3) != 0)
936                 return -1;
937
938         if(uri_offsets->uri_end == -1)
939         {
940                 /* name-addr form was NOT used e.g no closing ">" */
941                 /* look for the first ',' or ';' which will mark the end of this URI
942                  * In this case a semicolon indicates a header field parameter, and not an uri parameter.
943                  */
944                 comma_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ',');
945                 semicolon_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ';');
946
947                 if (semicolon_offset != -1 && comma_offset != -1)
948                 {
949                         if(semicolon_offset < comma_offset)
950                         {
951                                 uri_offsets->uri_end = semicolon_offset - 1;
952                         }
953                         else
954                         {
955                                 uri_offsets->uri_end = comma_offset - 1;
956                         }
957                 }
958                 else
959                 {
960                         if (semicolon_offset != -1)
961                         {
962                                 uri_offsets->uri_end = semicolon_offset - 1;
963                         }
964                         else if (comma_offset != -1)
965                         {
966                                 uri_offsets->uri_end = comma_offset - 1;
967                         } else {
968
969                                 /* If both offsets are equal to -1, we don't have a semicolon or a comma.
970                                 * In that case, we assume that the end of the URI is at the line end
971                                  */
972                                 uri_offsets->uri_end = line_end_offset - 3; /* remove '\r\n' */
973                         }
974                 }
975                 uri_offsets->name_addr_end = uri_offsets->uri_end;
976         }
977
978         /* Look for URI address parts (user, host, host-port) */
979
980         /* Look for '@' within URI */
981         queried_offset = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, '@');
982         if(queried_offset == -1)
983         {
984                 /* no '@' = no user part */
985                 uri_offsets->uri_host_start = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, ':')+1;
986         }
987         else
988         {
989                 /* with '@' = with user part */
990                 uri_offsets->uri_user_start = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, ':')+1;
991                 uri_offsets->uri_user_end = tvb_find_guint8(tvb, uri_offsets->uri_user_start, uri_offsets->uri_end - uri_offsets->uri_start, '@')-1;
992                 uri_offsets->uri_host_start = uri_offsets->uri_user_end + 2;
993         }
994
995         /* find URI-Host end*/
996         parameter_end_offset = uri_offsets->uri_host_start;
997
998         in_ipv6 = (tvb_get_guint8(tvb, parameter_end_offset) == '[');
999         while (parameter_end_offset < line_end_offset)
1000         {
1001                         parameter_end_offset++;
1002                         c = tvb_get_guint8(tvb, parameter_end_offset);
1003                         switch (c) {
1004                                 case '>':
1005                                 case ',':
1006                                 case ';':
1007                                 case '?':
1008                                 case ' ':
1009                                 case '\r':
1010                                         goto uri_host_end_found;
1011                                 case ':':
1012                                         if (!in_ipv6)
1013                                                 goto uri_host_end_found;
1014                                         break;
1015                                 case '[':
1016                                         in_ipv6 = TRUE;
1017                                         break;
1018                                 case ']':
1019                                         in_ipv6 = FALSE;
1020                                         break;
1021                                 default :
1022                                 break;
1023                                 }
1024         }
1025
1026         uri_host_end_found:
1027
1028                 uri_offsets->uri_host_end = parameter_end_offset - 1;
1029
1030                 if (c == ':')
1031                 {
1032                         uri_offsets->uri_host_port_start = parameter_end_offset + 1;
1033                         parameter_end_offset = uri_offsets->uri_host_port_start;
1034                                 while (parameter_end_offset < line_end_offset)
1035                                 {
1036                                                 parameter_end_offset++;
1037                                                 c = tvb_get_guint8(tvb, parameter_end_offset);
1038                                                 switch (c) {
1039                                                         case '>':
1040                                                         case ',':
1041                                                         case ';':
1042                                                         case '?':
1043                                                         case ' ':
1044                                                         case '\r':
1045                                                                 goto uri_host_port_end_found;
1046                                                         default :
1047                                                         break;
1048                                                 }
1049                                 }
1050
1051                         uri_host_port_end_found:
1052
1053                         uri_offsets->uri_host_port_end = parameter_end_offset -1;
1054                 }
1055                 return uri_offsets->name_addr_end;
1056 }
1057 /*
1058  *  token         =  1*(alphanum / "-" / "." / "!" / "%" / "*"
1059  *                    / "_" / "+" / "`" / "'" / "~" )
1060  *  LWS           =  [*WSP CRLF] 1*WSP ; linear whitespace
1061  *  name-addr     =  [ display-name ] LAQUOT addr-spec RAQUOT
1062  *  addr-spec     =  SIP-URI / SIPS-URI / absoluteURI
1063  *  display-name  =  *(token LWS)/ quoted-string
1064  */
1065
1066 static gint
1067 dissect_sip_name_addr_or_addr_spec(tvbuff_t *tvb, packet_info *pinfo _U_, gint start_offset,
1068                 gint line_end_offset, uri_offset_info *uri_offsets)
1069 {
1070         gchar c;
1071         gint i;
1072         gint current_offset;
1073         gint queried_offset;
1074         gint colon_offset;
1075         gboolean uri_without_angle_quotes = FALSE;
1076
1077         /* skip Spaces and Tabs */
1078         current_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1079
1080         if(current_offset >= line_end_offset) {
1081                 /* Nothing to parse */
1082                 return -1;
1083         }
1084
1085         uri_offsets->name_addr_start = current_offset;
1086
1087         /* First look, if we have a display name */
1088         c=tvb_get_guint8(tvb, current_offset);
1089         switch(c)
1090         {
1091                 case '"':
1092                         /* We have a display name, look for the next unescaped '"' */
1093                         uri_offsets->display_name_start = current_offset;
1094                         do
1095                         {
1096                                 queried_offset = tvb_find_guint8(tvb, current_offset + 1, line_end_offset - (current_offset + 1), '"');
1097                                 if(queried_offset == -1)
1098                                 {
1099                                         /* malformed URI */
1100                                         return -1;
1101                                 }
1102                                 current_offset = queried_offset;
1103
1104                                 /* Is it escaped? */
1105                                 /* count back slashes before '"' */
1106                                 for(i=1;tvb_get_guint8(tvb, queried_offset - i) == '\\';i++);
1107                                 i--;
1108
1109                                 if(i % 2 == 0)
1110                                 {
1111                                         /* not escaped */
1112                                         break;
1113                                 }
1114                         } while (current_offset < line_end_offset);
1115                         if(current_offset >= line_end_offset)
1116                         {
1117                                 /* malformed URI */
1118                                 return -1;
1119                         }
1120
1121                         uri_offsets->display_name_end = current_offset;
1122
1123                         /* find start of the URI */
1124                         queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, '<');
1125                         if(queried_offset == -1)
1126                         {
1127                                 /* malformed Uri */
1128                                 return -1;
1129                         }
1130                         current_offset = queried_offset + 1;
1131                         break;
1132
1133                 case '<':
1134                         /* We don't have a display name */
1135                         current_offset++;
1136                         break;
1137
1138                 default:
1139                         /* We have either an URI without angles or a display name with a limited character set */
1140                         /* Look for the right angle quote or colon */
1141                         queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, '<');
1142                         colon_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ':');
1143                         if(queried_offset != -1 && colon_offset != -1)
1144                         {
1145                                 if(queried_offset < colon_offset)
1146                                 {
1147                                         /* we have an URI with angle quotes */
1148                                         uri_offsets->display_name_start = current_offset;
1149                                         uri_offsets->display_name_end = queried_offset - 1;
1150                                         current_offset = queried_offset + 1;
1151                                 }
1152                                 else
1153                                 {
1154                                         /* we have an URI without angle quotes */
1155                                         uri_without_angle_quotes = TRUE;
1156                                 }
1157                         }
1158                         else
1159                         {
1160                                 if(queried_offset != -1)
1161                                 {
1162                                         /* we have an URI with angle quotes */
1163                                         uri_offsets->display_name_start = current_offset;
1164                                         uri_offsets->display_name_end = queried_offset - 1;
1165                                         current_offset = queried_offset + 1;
1166                                         break;
1167                                 }
1168                                 if(colon_offset != -1)
1169                                 {
1170                                         /* we have an URI without angle quotes */
1171                                         uri_without_angle_quotes = TRUE;
1172                                         break;
1173                                 }
1174                                 /* If this point is reached, we can't parse the URI */
1175                                 return -1;
1176                         }
1177                         break;
1178         }
1179         /* Start of URI */
1180         uri_offsets->uri_start = current_offset;
1181         if(uri_without_angle_quotes==FALSE){
1182                 /* name-addr form was used */
1183                 /* look for closing angle quote */
1184                 queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, '>');
1185                 if(queried_offset == -1)
1186                 {
1187                         /* malformed Uri */
1188                         return -1;
1189                 }
1190                 uri_offsets->name_addr_end = queried_offset;
1191                 uri_offsets->uri_end = queried_offset - 1;
1192         }
1193         return dissect_sip_uri(tvb, pinfo, current_offset, line_end_offset, uri_offsets);
1194 }
1195
1196
1197 /*
1198 * Code to add dissected SIP URI Information to proto tree
1199 */
1200
1201 static proto_tree *
1202 display_sip_uri (tvbuff_t *tvb, proto_tree *sip_element_tree, uri_offset_info* uri_offsets, hf_sip_uri_t* uri)
1203 {
1204
1205         proto_item *ti;
1206         proto_tree *uri_item_tree = NULL;
1207
1208         if(uri_offsets->display_name_end != uri_offsets->display_name_start) {
1209                 proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, uri_offsets->display_name_start,
1210                                     uri_offsets->display_name_end - uri_offsets->display_name_start + 1, FALSE);
1211         }
1212
1213         ti = proto_tree_add_item(sip_element_tree, *(uri->hf_sip_addr), tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start + 1, FALSE);
1214         uri_item_tree = proto_item_add_subtree(ti, *(uri->ett_uri));
1215
1216         if(uri_offsets->uri_user_end > uri_offsets->uri_user_start) {
1217                 proto_tree_add_item(uri_item_tree, *(uri->hf_sip_user), tvb, uri_offsets->uri_user_start,
1218                                     uri_offsets->uri_user_end - uri_offsets->uri_user_start + 1, FALSE);
1219         }
1220
1221         proto_tree_add_item(uri_item_tree, *(uri->hf_sip_host), tvb, uri_offsets->uri_host_start,
1222                             uri_offsets->uri_host_end - uri_offsets->uri_host_start + 1, FALSE);
1223
1224         if(uri_offsets->uri_host_port_end > uri_offsets->uri_host_port_start) {
1225                 proto_tree_add_item(uri_item_tree, *(uri->hf_sip_port), tvb, uri_offsets->uri_host_port_start,
1226                                 uri_offsets->uri_host_port_end - uri_offsets->uri_host_port_start + 1, FALSE);
1227         }
1228
1229         return uri_item_tree;
1230 }
1231
1232
1233
1234
1235 /* Code to parse a contact header item
1236  * Returns Offset end off parsing or -1 for unsuccessful parsing
1237  * * contact-param  =  (name-addr / addr-spec) *(SEMI contact-params)
1238  */
1239 static gint
1240 dissect_sip_contact_item(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint start_offset, gint line_end_offset)
1241 {
1242         gchar c;
1243         gint current_offset;
1244         gint queried_offset;
1245         gint contact_params_start_offset = -1;
1246         gint contact_param_end_offset = -1;
1247         uri_offset_info uri_offsets;
1248
1249         /* skip Spaces and Tabs */
1250         start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1251
1252         if(start_offset >= line_end_offset) {
1253                 /* Nothing to parse */
1254                 return -1;
1255         }
1256         queried_offset = tvb_find_guint8(tvb, start_offset , line_end_offset - start_offset, ';');
1257         if(queried_offset == -1){
1258                 queried_offset = line_end_offset;
1259         }else{
1260                 /* skip Spaces and Tabs */
1261                 contact_params_start_offset = tvb_skip_wsp(tvb, queried_offset+1, line_end_offset - queried_offset+1);
1262         }
1263         /* Initialize the uri_offsets */
1264         sip_uri_offset_init(&uri_offsets);
1265         /* contact-param  =  (name-addr / addr-spec) *(SEMI contact-params) */
1266         current_offset = dissect_sip_name_addr_or_addr_spec(tvb, pinfo, start_offset, line_end_offset, &uri_offsets);
1267         display_sip_uri(tvb, tree, &uri_offsets, &sip_contact_uri);
1268         if(current_offset == -1)
1269         {
1270                 /* Parsing failed */
1271                 return -1;
1272         }
1273         /* check if contact-params is present */
1274         if(contact_params_start_offset == -1)
1275                 return line_end_offset;
1276
1277         /* Move current offset to the start of the first param */
1278         current_offset = contact_params_start_offset;
1279
1280         /* Put the contact parameters in the tree */
1281
1282         while(current_offset< line_end_offset){
1283                 queried_offset = tvb_pbrk_guint8(tvb, current_offset, line_end_offset - current_offset, ",;", &c);
1284                 if(queried_offset == -1){
1285                         /* Reached line end */
1286                         contact_param_end_offset = line_end_offset - 3;
1287                         current_offset = line_end_offset;
1288                 }else if(c==','){
1289                         /* More contacts, make this the line end for this contact */
1290                         line_end_offset = queried_offset;
1291                         contact_param_end_offset = queried_offset;
1292                         current_offset =  queried_offset;
1293                 }else if (c==';'){
1294                         /* More parameters */
1295                         contact_param_end_offset = queried_offset-1;
1296                         current_offset = tvb_skip_wsp(tvb, queried_offset+1, line_end_offset - queried_offset+1);
1297                 }
1298                 proto_tree_add_item(tree, hf_sip_contact_param, tvb, contact_params_start_offset ,
1299                         contact_param_end_offset - contact_params_start_offset +1, FALSE);
1300                 /* In case there are more parameters, point to the start of it */
1301                 contact_params_start_offset = current_offset;
1302         }
1303
1304
1305         return current_offset;
1306 }
1307
1308 /* Code to parse an authorization header item
1309  * Returns offset at end of parsing, or -1 for unsuccessful parsing
1310  */
1311 static gint
1312 dissect_sip_authorization_item(tvbuff_t *tvb, proto_tree *tree, gint start_offset, gint line_end_offset)
1313 {
1314         gint current_offset, par_name_end_offset;
1315         gint equals_offset = 0;
1316         gchar *name;
1317         header_parameter_t *auth_parameter;
1318         guint i = 0;
1319
1320         /* skip Spaces and Tabs */
1321         start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1322
1323         if (start_offset >= line_end_offset)
1324         {
1325                 /* Nothing to parse */
1326                 return -1;
1327         }
1328
1329         current_offset = start_offset;
1330         equals_offset = tvb_find_guint8(tvb, current_offset + 1, line_end_offset - (current_offset + 1), '=');
1331         if(current_offset == -1){
1332                 /* malformed parameter */
1333                 return -1;
1334         }
1335         par_name_end_offset = equals_offset - 1;
1336         par_name_end_offset = tvb_skip_wsp_return(tvb,par_name_end_offset);
1337
1338         /* Extract the parameter name */
1339         name = tvb_get_ephemeral_string(tvb, start_offset, par_name_end_offset-start_offset+1);
1340         current_offset =  tvb_find_guint8(tvb, par_name_end_offset, line_end_offset - par_name_end_offset, ',');
1341         if(current_offset==-1)
1342                 /* Last parameter, line end */
1343                 current_offset = line_end_offset;
1344
1345         /* Try to add parameter as a filterable item */
1346         for (auth_parameter = &auth_parameters_hf_array[i];
1347              i < array_length(auth_parameters_hf_array);
1348              i++, auth_parameter++)
1349         {
1350                 if (g_ascii_strcasecmp(name, auth_parameter->param_name) == 0)
1351                 {
1352                         proto_tree_add_item(tree, *(auth_parameter->hf_item), tvb,
1353                                             equals_offset+1, current_offset-equals_offset-1,
1354                                             FALSE);
1355                         break;
1356                 }
1357         }
1358
1359         /* If not matched, just add as text... */
1360         if (i == array_length(auth_parameters_hf_array))
1361         {
1362                 proto_tree_add_text(tree, tvb, start_offset, current_offset-start_offset,
1363                                     "%s", tvb_format_text(tvb, start_offset,
1364                                                     current_offset-start_offset));
1365         }
1366
1367         return current_offset;
1368 }
1369
1370 /* Dissect the details of a Reason header */
1371 static void
1372 dissect_sip_reason_header(tvbuff_t *tvb, proto_tree *tree, gint start_offset, gint line_end_offset){
1373
1374         gint  current_offset, semi_colon_offset, length;
1375         gchar *param_name = NULL;
1376         guint cause_value;
1377
1378                 /* skip Spaces and Tabs */
1379         start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1380
1381         if (start_offset >= line_end_offset)
1382         {
1383                 /* Nothing to parse */
1384                 return;
1385         }
1386
1387         current_offset = start_offset;
1388         semi_colon_offset = tvb_find_guint8(tvb, current_offset, line_end_offset-current_offset, ';');
1389         length = semi_colon_offset - current_offset;
1390         proto_tree_add_text(tree, tvb, start_offset, length,
1391                 "Reason Protocols: %s", tvb_format_text(tvb, start_offset, length));
1392
1393         param_name = tvb_get_ephemeral_string(tvb, start_offset, length);
1394         if (g_ascii_strcasecmp(param_name, "Q.850") == 0){
1395                 current_offset = tvb_find_guint8(tvb, semi_colon_offset, line_end_offset-semi_colon_offset, '=')+1;
1396                 length = line_end_offset - current_offset;
1397
1398                 /* q850_cause_code_vals */
1399                 cause_value = atoi(tvb_get_ephemeral_string(tvb, current_offset, length));
1400                 proto_tree_add_text(tree, tvb, current_offset, length,
1401                         "Cause: %u(0x%x)[%s]", cause_value,cause_value,
1402                         val_to_str(cause_value, q850_cause_code_vals, "Unknown (%d)" ));
1403
1404         }
1405
1406 }
1407
1408
1409 /* Dissect the details of a Via header */
1410 static void dissect_sip_via_header(tvbuff_t *tvb, proto_tree *tree, gint start_offset, gint line_end_offset)
1411 {
1412         gint  current_offset;
1413         gint  transport_start_offset;
1414         gint  address_start_offset;
1415         gint  semicolon_offset;
1416         guint transport_slash_count;
1417         gboolean transport_name_started;
1418         gboolean colon_seen;
1419         gboolean ipv6_reference;
1420         gboolean ipv6_address;
1421         guchar c;
1422         gchar *param_name = NULL;
1423         return;
1424
1425         current_offset = start_offset;
1426
1427         while (1)
1428         {
1429                 /* Reset flags and counters */
1430                 transport_start_offset = 0;
1431                 semicolon_offset = 0;
1432                 transport_name_started = FALSE;
1433                 transport_slash_count = 0;
1434                 ipv6_reference = FALSE;
1435                 ipv6_address = FALSE;
1436                 colon_seen = FALSE;
1437
1438                 /* skip Spaces and Tabs */
1439                 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1440
1441                 if (current_offset >= line_end_offset)
1442                 {
1443                         /* Nothing more to parse */
1444                         return;
1445                 }
1446
1447                 /* Now look for the end of the SIP/2.0/transport parameter.
1448                    There may be spaces between the slashes */
1449                 while (current_offset < line_end_offset)
1450                 {
1451                         c = tvb_get_guint8(tvb, current_offset);
1452                         if (c == '/')
1453                         {
1454                                 transport_slash_count++;
1455                         }
1456                         else
1457                         if (!transport_name_started && (transport_slash_count == 2) && isalpha(c))
1458                         {
1459                                 transport_name_started = TRUE;
1460                                 transport_start_offset = current_offset;
1461                         }
1462                         else
1463                         if (transport_name_started && ((c == ' ') || (c == '\t')))
1464                         {
1465                                 proto_tree_add_item(tree, hf_sip_via_transport, tvb, transport_start_offset,
1466                                                                         current_offset - transport_start_offset, FALSE);
1467
1468                                 break;
1469                         }
1470
1471                         current_offset++;
1472                 }
1473
1474                 /* skip Spaces and Tabs */
1475                 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1476
1477                 /* Now read the address part */
1478                 address_start_offset = current_offset;
1479                 while (current_offset < line_end_offset)
1480                 {
1481                         c = tvb_get_guint8(tvb, current_offset);
1482
1483                         if (c == '[') {
1484                                 ipv6_reference = TRUE;
1485                                 ipv6_address = TRUE;
1486                         }
1487                         else if (c == ']')
1488                         {
1489                                 ipv6_reference = FALSE;
1490                         }
1491
1492                         if (colon_seen || (c == ' ') || (c == '\t') || ((c == ':') && (ipv6_reference == FALSE)) || (c == ';'))
1493                         {
1494                                 break;
1495                         }
1496
1497                         current_offset++;
1498                 }
1499                 /* Add address to tree */
1500                 if (ipv6_address == TRUE) {
1501                         proto_tree_add_item(tree, hf_sip_via_sent_by_address, tvb, address_start_offset + 1,
1502                                                                 current_offset - address_start_offset - 2, FALSE);
1503                 } else {
1504                         proto_tree_add_item(tree, hf_sip_via_sent_by_address, tvb, address_start_offset,
1505                                                                 current_offset - address_start_offset, FALSE);
1506                 }
1507
1508                 /* Transport port number may follow ([space] : [space])*/
1509                 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1510                 c = tvb_get_guint8(tvb, current_offset);
1511
1512                 if (c == ':')
1513                 {
1514                         /* Port number will follow any space after : */
1515                         gint port_offset;
1516                         colon_seen = TRUE;
1517                         current_offset++;
1518
1519                         /* Skip optional space after colon */
1520                         current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1521
1522                         port_offset = current_offset;
1523
1524                         /* Find digits of port number */
1525                         while (current_offset < line_end_offset)
1526                         {
1527                                 c = tvb_get_guint8(tvb, current_offset);
1528
1529                                 if (!isdigit(c))
1530                                 {
1531                                         if (current_offset > port_offset)
1532                                         {
1533                                                 /* Add address port number to tree */
1534                                                 proto_tree_add_uint(tree, hf_sip_via_sent_by_port, tvb, port_offset,
1535                                                                                         current_offset - port_offset,
1536                                                                                         atoi(tvb_get_ephemeral_string(tvb, port_offset,
1537                                                                                                                                                   current_offset - port_offset)));
1538                                         }
1539                                         else
1540                                         {
1541                                                 /* Shouldn't see a colon without a port number given */
1542                                                 return;
1543                                         }
1544                                         break;
1545                                 }
1546
1547                                 current_offset++;
1548                         }
1549                 }
1550
1551                 /* skip Spaces and Tabs */
1552                 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1553
1554
1555                 /* Dissect any parameters found */
1556                 while (current_offset < line_end_offset)
1557                 {
1558                         gboolean equals_found = FALSE;
1559                         gboolean found_end_of_parameters = FALSE;
1560                         gint parameter_name_end = 0;
1561                         gint parameter_value_end;
1562                         header_parameter_t *via_parameter;
1563                         guint i = 0;
1564
1565                         /* Look for the semicolon that signals the start of a parameter */
1566                         while (current_offset < line_end_offset)
1567                         {
1568                                 c = tvb_get_guint8(tvb, current_offset);
1569                                 if (c == ';')
1570                                 {
1571                                         semicolon_offset = current_offset;
1572                                         current_offset++;
1573                                         break;
1574                                 }
1575                                 else
1576                                 if ((c != ' ') && (c != '\t'))
1577                                 {
1578                                         found_end_of_parameters = TRUE;
1579                                         break;
1580                                 }
1581                                 current_offset++;
1582                         }
1583
1584                         if (found_end_of_parameters)
1585                         {
1586                                 break;
1587                         }
1588
1589                         if (current_offset == line_end_offset)
1590                         {
1591                                 return;
1592                         }
1593
1594                         /* Look for end of parameter name */
1595                         while (current_offset < line_end_offset)
1596                         {
1597                                 c = tvb_get_guint8(tvb, current_offset);
1598                                 if (!isalpha(c) && (c != '-'))
1599                                 {
1600                                         break;
1601                                 }
1602                                 current_offset++;
1603                         }
1604
1605                         /* Not all params have an = */
1606                         if (c == '=')
1607                         {
1608                                 equals_found = TRUE;
1609                         }
1610                         parameter_name_end = current_offset;
1611
1612                         /* Read until end of parameter value */
1613                         while (current_offset < line_end_offset)
1614                         {
1615                                 c = tvb_get_guint8(tvb, current_offset);
1616                                 if ((c == ' ') || (c == '\t') || (c == ';') || (c == ','))
1617                                 {
1618                                         break;
1619                                 }
1620                                 current_offset++;
1621                         }
1622
1623                         /* Note parameter name */
1624                         parameter_value_end = current_offset;
1625                         param_name = tvb_get_ephemeral_string(tvb, semicolon_offset+1,
1626                                                                                                   parameter_name_end - semicolon_offset - 1);
1627
1628                         /* Try to add parameter as a filterable item */
1629                         for (via_parameter = &via_parameters_hf_array[i];
1630                                  i < array_length(via_parameters_hf_array);
1631                                  i++, via_parameter++)
1632                         {
1633                                 if (g_ascii_strcasecmp(param_name, via_parameter->param_name) == 0)
1634                                 {
1635                                         if (equals_found)
1636                                         {
1637                                                 proto_tree_add_item(tree, *(via_parameter->hf_item), tvb,
1638                                                                                         parameter_name_end+1, current_offset-parameter_name_end-1,
1639                                                                                         FALSE);
1640                                         }
1641                                         else
1642                                         {
1643                                                 proto_tree_add_item(tree, *(via_parameter->hf_item), tvb,
1644                                                                                         semicolon_offset+1, current_offset-semicolon_offset-1,
1645                                                                                         FALSE);
1646                                         }
1647                                         break;
1648                                 }
1649                         }
1650
1651                         /* If not matched, just add as text... */
1652                         if (i == array_length(via_parameters_hf_array))
1653                         {
1654                                 proto_tree_add_text(tree, tvb, semicolon_offset+1, current_offset-semicolon_offset-1,
1655                                                                         "%s", tvb_format_text(tvb, semicolon_offset+1,
1656                                                                         current_offset-semicolon_offset-1));
1657                         }
1658
1659                         /* skip Spaces and Tabs */
1660                         current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1661
1662                         /* There may be a comma, followed by more Via entries... */
1663                         if (current_offset < line_end_offset)
1664                         {
1665                                 c = tvb_get_guint8(tvb, current_offset);
1666                                 if (c == ',')
1667                                 {
1668                                         /* Skip it and get out of parameter loop */
1669                                         current_offset++;
1670                                         break;
1671                                 }
1672                         }
1673                 }
1674         }
1675 }
1676
1677
1678 /* Code to actually dissect the packets */
1679 static int
1680 dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1681 {
1682         guint8 octet;
1683         int len;
1684
1685         octet = tvb_get_guint8(tvb,0);
1686         if ((octet  & 0xf8) == 0xf8){
1687                 call_dissector(sigcomp_handle, tvb, pinfo, tree);
1688                 return tvb_length(tvb);
1689         }
1690
1691         len = dissect_sip_common(tvb, 0, pinfo, tree, FALSE, FALSE);
1692         if (len < 0)
1693                 return 0;       /* not SIP */
1694         else
1695                 return len;
1696 }
1697
1698 static void
1699 dissect_sip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1700 {
1701         guint8 octet;
1702         int offset = 0;
1703         int len;
1704
1705         octet = tvb_get_guint8(tvb,0);
1706         if ((octet  & 0xf8) == 0xf8){
1707                 call_dissector(sigcomp_handle, tvb, pinfo, tree);
1708                 return;
1709         }
1710
1711         while (tvb_reported_length_remaining(tvb, offset) != 0) {
1712                 len = dissect_sip_common(tvb, offset, pinfo, tree, TRUE, TRUE);
1713                 if (len <= 0)
1714                         break;
1715                 offset += len;
1716         }
1717 }
1718
1719 static gboolean
1720 dissect_sip_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1721 {
1722         int offset = 0;
1723         int len;
1724         gboolean first = TRUE;
1725
1726         while (tvb_reported_length_remaining(tvb, offset) != 0) {
1727                 len = dissect_sip_common(tvb, offset, pinfo, tree, !first, TRUE);
1728                 if (len == -2) {
1729                         if (first) {
1730                                 /*
1731                                  * If the first packet doesn't start with
1732                                  * a valid SIP request or response, don't
1733                                  * treat this as SIP.
1734                                  */
1735                                 return FALSE;
1736                         }
1737                         break;
1738                 }
1739                 if (len == -1)
1740                         break;  /* need more data */
1741                 offset += len;
1742         }
1743         return TRUE;
1744 }
1745
1746 static gboolean
1747 dissect_sip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1748 {
1749         return dissect_sip_common(tvb, 0, pinfo, tree, FALSE, FALSE) > 0;
1750 }
1751
1752 static int
1753 dissect_sip_common(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
1754     gboolean dissect_other_as_continuation, gboolean use_reassembly)
1755 {
1756         int orig_offset;
1757         gint next_offset, linelen;
1758         int content_length, datalen, reported_datalen;
1759         line_type_t line_type;
1760         tvbuff_t *next_tvb;
1761         gboolean is_known_request;
1762         gboolean found_match = FALSE;
1763         const char *descr;
1764         guint token_1_len = 0;
1765         guint current_method_idx = SIP_METHOD_INVALID;
1766         proto_item *ts = NULL, *ti_a = NULL, *th = NULL, *sip_element_item = NULL;
1767         proto_tree *sip_tree = NULL, *reqresp_tree = NULL , *hdr_tree = NULL,
1768                 *sip_element_tree = NULL, *message_body_tree = NULL, *cseq_tree = NULL,
1769                 *via_tree = NULL, *reason_tree = NULL, *rack_tree = NULL;
1770         guchar contacts = 0, contact_is_star = 0, expires_is_0 = 0;
1771         guint32 cseq_number = 0;
1772         guchar  cseq_number_set = 0;
1773         char    cseq_method[MAX_CSEQ_METHOD_SIZE] = "";
1774         char    call_id[MAX_CALL_ID_SIZE] = "";
1775         gchar  *media_type_str_lower_case = NULL;
1776         char   *content_type_parameter_str = NULL;
1777         guint   resend_for_packet = 0;
1778         guint   request_for_response = 0;
1779         guint32 response_time = 0;
1780         int     strlen_to_copy;
1781
1782
1783         /*
1784          * Note that "tvb_find_line_end()" will return a value that
1785          * is not longer than what's in the buffer, so the
1786          * "tvb_get_ptr()" calls below won't throw exceptions.
1787          *
1788          * Note that "tvb_strneql()" doesn't throw exceptions, so
1789          * "sip_parse_line()" won't throw an exception.
1790          */
1791         orig_offset = offset;
1792         linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
1793         if (tvb_strnlen(tvb, offset, linelen) > -1)
1794         {
1795                 /*
1796                  * There's a NULL in the line,
1797                  * this may be SIP within another protocol.
1798                  * This heuristic still needs to improve.
1799                  */
1800                 return -2;
1801         }
1802         line_type = sip_parse_line(tvb, offset, linelen, &token_1_len);
1803
1804         if (line_type == OTHER_LINE) {
1805                 /*
1806                  * This is neither a SIP request nor response.
1807                  */
1808                 if (!dissect_other_as_continuation) {
1809                         /*
1810                          * We were asked to reject this.
1811                          */
1812                         return -2;
1813                 }
1814
1815                 /*
1816                  * Just dissect it as a continuation.
1817                  */
1818         } else if (use_reassembly) {
1819                 /*
1820                  * Yes, it's a request or response.
1821                  * Do header desegmentation if we've been told to,
1822                  * and do body desegmentation if we've been told to and
1823                  * we find a Content-Length header.
1824                  */
1825                 if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo,
1826                     sip_desegment_headers, sip_desegment_body)) {
1827                         /*
1828                          * More data needed for desegmentation.
1829                          */
1830                         return -1;
1831                 }
1832         }
1833
1834         /* Initialise stat info for passing to tap */
1835         stat_info = ep_alloc0(sizeof(sip_info_value_t));
1836
1837         col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIP");
1838
1839         switch (line_type) {
1840
1841         case REQUEST_LINE:
1842                 is_known_request = sip_is_known_request(tvb, offset, token_1_len, &current_method_idx);
1843                 descr = is_known_request ? "Request" : "Unknown request";
1844                 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
1845                              descr,
1846                              tvb_format_text(tvb, offset, linelen - SIP2_HDR_LEN - 1));
1847                 break;
1848
1849         case STATUS_LINE:
1850                 descr = "Status";
1851                 col_add_fstr(pinfo->cinfo, COL_INFO, "Status: %s",
1852                              tvb_format_text(tvb, offset + SIP2_HDR_LEN + 1, linelen - SIP2_HDR_LEN - 1));
1853                 stat_info->reason_phrase = tvb_get_ephemeral_string(tvb, offset + SIP2_HDR_LEN + 5, linelen - (SIP2_HDR_LEN + 5));
1854                 break;
1855
1856         case OTHER_LINE:
1857         default: /* Squelch compiler complaints */
1858                 descr = "Continuation";
1859                 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
1860                 break;
1861         }
1862
1863         if (tree) {
1864                 ts = proto_tree_add_item(tree, proto_sip, tvb, offset, -1, FALSE);
1865                 sip_tree = proto_item_add_subtree(ts, ett_sip);
1866         }
1867
1868         switch (line_type) {
1869
1870         case REQUEST_LINE:
1871                 if (sip_tree) {
1872                         ti_a = proto_tree_add_item(sip_tree, hf_Request_Line, tvb,
1873                                                 offset, linelen, FALSE);
1874
1875                         reqresp_tree = proto_item_add_subtree(ti_a, ett_sip_reqresp);
1876                 }
1877                 dfilter_sip_request_line(tvb, reqresp_tree, pinfo, offset, token_1_len, linelen);
1878                 break;
1879
1880         case STATUS_LINE:
1881                 if (sip_tree) {
1882                         ti_a = proto_tree_add_item(sip_tree, hf_Status_Line, tvb,
1883                                                 offset, linelen, FALSE);
1884                         reqresp_tree = proto_item_add_subtree(ti_a, ett_sip_reqresp);
1885                 }
1886                 dfilter_sip_status_line(tvb, reqresp_tree);
1887                 break;
1888
1889         case OTHER_LINE:
1890                 if (sip_tree) {
1891                         ti_a = proto_tree_add_text(sip_tree, tvb, offset, next_offset,
1892                                                  "%s line: %s", descr,
1893                                                  tvb_format_text(tvb, offset, linelen));
1894                         reqresp_tree = proto_item_add_subtree(ti_a, ett_sip_reqresp);
1895                         proto_tree_add_text(sip_tree, tvb, offset, -1,
1896                                             "Continuation data");
1897                 }
1898                 return tvb_length_remaining(tvb, offset);
1899         }
1900
1901         offset = next_offset;
1902         if (sip_tree) {
1903                 th = proto_tree_add_item(sip_tree, hf_msg_hdr, tvb, offset,
1904                                          tvb_length_remaining(tvb, offset), FALSE);
1905                 proto_item_set_text(th, "Message Header");
1906                 hdr_tree = proto_item_add_subtree(th, ett_sip_hdr);
1907         }
1908
1909         /*
1910          * Process the headers - if we're not building a protocol tree,
1911          * we just do this to find the blank line separating the
1912          * headers from the message body.
1913          */
1914         next_offset = offset;
1915         content_length = -1;
1916         while (tvb_reported_length_remaining(tvb, offset) > 0) {
1917                 gint line_end_offset;
1918                 gint colon_offset;
1919                 gint semi_colon_offset;
1920                 gint parameter_offset;
1921                 gint parameter_end_offset;
1922                 gint parameter_len;
1923                 gint content_type_len, content_type_parameter_str_len;
1924                 gint header_len;
1925                 gchar *header_name;
1926                 dissector_handle_t ext_hdr_handle;
1927                 gint hf_index;
1928                 gint value_offset;
1929                 gint sub_value_offset;
1930                 gint comma_offset;
1931                 guchar c;
1932                 gint value_len;
1933                 char *value;
1934                 gboolean is_no_header_termination = FALSE;
1935                 proto_item *cause;
1936                 proto_tree *pai_uri_item_tree = NULL;
1937                 proto_tree *pmiss_uri_item_tree = NULL;
1938                 proto_tree *ppi_uri_item_tree = NULL;
1939                 proto_tree *tc_uri_item_tree = NULL;
1940                 uri_offset_info uri_offsets;
1941
1942
1943
1944
1945
1946                 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
1947                 if (linelen == 0) {
1948                         /*
1949                          * This is a blank line separating the
1950                          * message header from the message body.
1951                          */
1952                         offset = next_offset;
1953                         break;
1954                 }
1955
1956                 line_end_offset = offset + linelen;
1957                 if(tvb_reported_length_remaining(tvb, next_offset) == 0){
1958                         is_no_header_termination = TRUE;
1959                 }else{
1960                         while ((c = tvb_get_guint8(tvb, next_offset)) == ' ' || c == '\t')
1961                         {
1962                                 /*
1963                                  * This line end is not a header seperator.
1964                                  * It just extends the header with another line.
1965                                  * Look for next line end:
1966                                  */
1967                                 linelen += (next_offset - line_end_offset);
1968                                 linelen += tvb_find_line_end(tvb, next_offset, -1, &next_offset, FALSE);
1969                                 line_end_offset = offset + linelen;
1970                         }
1971                 }
1972                 colon_offset = tvb_find_guint8(tvb, offset, linelen, ':');
1973                 if (colon_offset == -1) {
1974                         /*
1975                          * Malformed header - no colon after the name.
1976                          */
1977                         if(hdr_tree) {
1978                                 proto_tree_add_text(hdr_tree, tvb, offset,
1979                                                     next_offset - offset, "%s",
1980                                                     tvb_format_text(tvb, offset, linelen));
1981                         }
1982                 } else {
1983                         header_len = colon_offset - offset;
1984                         header_name = (gchar*)tvb_get_ephemeral_string(tvb, offset, header_len);
1985                         ascii_strdown_inplace(header_name);
1986                         hf_index = sip_is_known_sip_header(header_name, header_len);
1987
1988                         /*
1989                          * Skip whitespace after the colon.
1990                          */
1991                         value_offset = tvb_skip_wsp(tvb, colon_offset + 1, line_end_offset - (colon_offset + 1));
1992
1993                         /*
1994                          * Fetch the value.
1995                          */
1996                         value_len = (gint) (line_end_offset - value_offset);
1997                         value = tvb_get_ephemeral_string(tvb, value_offset, value_len);
1998
1999                         if (hf_index == -1) {
2000                                 proto_item *ti_c = proto_tree_add_text(hdr_tree, tvb,
2001                                                                      offset, next_offset - offset, "%s",
2002                                                                      tvb_format_text(tvb, offset, linelen));
2003                                 ext_hdr_handle = dissector_get_string_handle(ext_hdr_subdissector_table, header_name);
2004                                 if (ext_hdr_handle != NULL) {
2005                                         tvbuff_t *next_tvb2;
2006                                         next_tvb2 = tvb_new_subset(tvb, value_offset, value_len, value_len);
2007                                         dissector_try_string(ext_hdr_subdissector_table, header_name, next_tvb2, pinfo, proto_item_add_subtree(ti_c, ett_sip_ext_hdr));
2008                                 } else {
2009                                         expert_add_info_format(pinfo, ti_c,
2010                                                                PI_UNDECODED, PI_NOTE,
2011                                                                "Unrecognised SIP header (%s)",
2012                                                                tvb_format_text(tvb, offset, header_len));
2013                                 }
2014                         } else {
2015                                 /*
2016                                  * Add it to the protocol tree,
2017                                  * but display the line as is.
2018                                  */
2019                                 switch ( hf_index ) {
2020
2021                                         case POS_TO :
2022
2023                                                 if(hdr_tree) {
2024                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2025                                                                            hf_header_array[hf_index], tvb,
2026                                                                            offset, next_offset - offset,
2027                                                                            value, "%s",
2028                                                                            tvb_format_text(tvb, offset, linelen));
2029                                                         sip_element_tree = proto_item_add_subtree( sip_element_item,
2030                                                                            ett_sip_element);
2031                                                         /* To        =  ( "To" / "t" ) HCOLON ( name-addr
2032                                                          *               / addr-spec ) *( SEMI to-param )
2033                                                          */
2034                                                 }
2035                                                 sip_uri_offset_init(&uri_offsets);
2036                                                 if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1){
2037                                                         display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_to_uri);
2038                                                         if((uri_offsets.name_addr_start != -1) && (uri_offsets.name_addr_end != -1)){
2039                                                                 stat_info->tap_to_addr=tvb_get_ephemeral_string(tvb, uri_offsets.name_addr_start,
2040                                                                         uri_offsets.name_addr_end - uri_offsets.name_addr_start);
2041                                                         }
2042                                                         offset = uri_offsets.name_addr_end +1;
2043                                                 }
2044
2045                                                 if(hdr_tree) {
2046                                                         /* Find parameter tag if present.
2047                                                          * TODO make this generic to find any interesting parameter
2048                                                          * use the same method as for SIP headers ?
2049                                                          */
2050
2051                                                         parameter_offset = offset;
2052                                                         while (parameter_offset < line_end_offset
2053                                                                    && (tvb_strneql(tvb, parameter_offset, "tag=", 4) != 0))
2054                                                                 parameter_offset++;
2055
2056                                                         if ( parameter_offset < line_end_offset ){ /* Tag found */
2057                                                                 parameter_offset = parameter_offset + 4;
2058                                                                 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
2059                                                                                                                                            (line_end_offset - parameter_offset), ';');
2060                                                                 if ( parameter_end_offset == -1)
2061                                                                         parameter_end_offset = line_end_offset;
2062                                                                 parameter_len = parameter_end_offset - parameter_offset;
2063                                                                 proto_tree_add_item(sip_element_tree, hf_sip_tag, tvb, parameter_offset,
2064                                                                                                         parameter_len, FALSE);
2065                                                                 /* Tag indicates in-dialog messages, in case we have a INVITE, SUBSCRIBE or REFER, mark it */
2066                                                                 switch (current_method_idx) {
2067
2068                                                                 case SIP_METHOD_INVITE:
2069                                                                 case SIP_METHOD_SUBSCRIBE:
2070                                                                 case SIP_METHOD_REFER:
2071                                                                         col_append_str(pinfo->cinfo, COL_INFO, ", in-dialog");
2072                                                                         break;
2073                                                                 }
2074                                                         }
2075                                                 } /* if hdr_tree */
2076                                         break;
2077
2078                                         case POS_FROM :
2079                                                 if(hdr_tree) {
2080                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2081                                                                            hf_header_array[hf_index], tvb,
2082                                                                            offset, next_offset - offset,
2083                                                                            value, "%s",
2084                                                                            tvb_format_text(tvb, offset, linelen));
2085                                                         sip_element_tree = proto_item_add_subtree( sip_element_item, ett_sip_element);
2086                                                 }
2087                                                         /*
2088                                                          * From        =  ( "From" / "f" ) HCOLON from-spec
2089                                                          * from-spec   =  ( name-addr / addr-spec )
2090                                                          *                *( SEMI from-param )
2091                                                          */
2092
2093                                                 sip_uri_offset_init(&uri_offsets);
2094                                                 if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1){
2095                                                         display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_from_uri);
2096                                                         if((uri_offsets.name_addr_start != -1) && (uri_offsets.name_addr_end != -1)){
2097                                                                 stat_info->tap_from_addr=tvb_get_ephemeral_string(tvb, uri_offsets.name_addr_start,
2098                                                                         uri_offsets.name_addr_end - uri_offsets.name_addr_start);
2099                                                         }
2100                                                         offset = uri_offsets.name_addr_end +1;
2101                                                 }
2102                                                 if(hdr_tree) {
2103                                                         /* Find parameter tag if present.
2104                                                          * TODO make this generic to find any interesting parameter
2105                                                          * use the same method as for SIP headers ?
2106                                                          */
2107
2108                                                         parameter_offset = offset;
2109                                                         while (parameter_offset < line_end_offset
2110                                                                    && (tvb_strneql(tvb, parameter_offset, "tag=", 4) != 0))
2111                                                                 parameter_offset++;
2112                                                         if ( parameter_offset < line_end_offset ){ /* Tag found */
2113                                                                 parameter_offset = parameter_offset + 4;
2114                                                                 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
2115                                                                                                                                            (line_end_offset - parameter_offset), ';');
2116                                                                 if ( parameter_end_offset == -1)
2117                                                                         parameter_end_offset = line_end_offset;
2118                                                                 parameter_len = parameter_end_offset - parameter_offset;
2119                                                                 proto_tree_add_item(sip_element_tree, hf_sip_tag, tvb, parameter_offset,
2120                                                                                                         parameter_len, FALSE);
2121
2122                                                         }
2123                                                 }/* hdr_tree */
2124                                         break;
2125
2126                                         case POS_P_ASSERTED_IDENTITY :
2127                                                 if(hdr_tree)
2128                                                 {
2129                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2130                                                                            hf_header_array[hf_index], tvb,
2131                                                                            offset, next_offset - offset,
2132                                                                            value, "%s",
2133                                                                            tvb_format_text(tvb, offset, linelen));
2134                                                         sip_element_tree = proto_item_add_subtree( sip_element_item,
2135                                                                            ett_sip_element);
2136
2137                                                         /*
2138                                                          * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value
2139                                                          *                *(COMMA PAssertedID-value)
2140                                                          * PAssertedID-value = name-addr / addr-spec
2141                                                          *
2142                                                          * Initialize the uri_offsets
2143                                                          */
2144                                                         sip_uri_offset_init(&uri_offsets);
2145                                                         if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
2146                                                                  pai_uri_item_tree = display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_pai_uri);
2147                                                 }
2148                                                 break;
2149
2150                                         case POS_P_CHARGING_FUNCTION_ADDRESSES:
2151                                                 if(hdr_tree)
2152                                                 {
2153                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2154                                                                            hf_header_array[hf_index], tvb,
2155                                                                            offset, next_offset - offset,
2156                                                                            value, "%s",
2157                                                                            tvb_format_text(tvb, offset, linelen));
2158                                                         sip_element_tree = proto_item_add_subtree( sip_element_item,
2159                                                                            ett_sip_element);
2160                                                 }
2161                                                 break;
2162
2163                                         case POS_P_PREFERRED_IDENTITY :
2164                                                 if(hdr_tree)
2165                                                 {
2166                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2167                                                                            hf_header_array[hf_index], tvb,
2168                                                                            offset, next_offset - offset,
2169                                                                            value, "%s",
2170                                                                            tvb_format_text(tvb, offset, linelen));
2171                                                         sip_element_tree = proto_item_add_subtree( sip_element_item,
2172                                                                            ett_sip_element);
2173                                                         /*
2174                                                          * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value
2175                                                          *                   *(COMMA PPreferredID-value)
2176                                                          * PPreferredID-value = name-addr / addr-spec
2177                                                          *
2178                                                          * Initialize the uri_offsets
2179                                                          */
2180                                                         sip_uri_offset_init(&uri_offsets);
2181                                                         if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
2182                                                                  ppi_uri_item_tree = display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_ppi_uri);
2183                                                 }
2184                                                 break;
2185
2186                                         case POS_PERMISSION_MISSING :
2187                                                 if(hdr_tree)
2188                                                 {
2189                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2190                                                                                hf_header_array[hf_index], tvb,
2191                                                                                offset, next_offset - offset,
2192                                                                                value, "%s",
2193                                                                                tvb_format_text(tvb, offset, linelen));
2194
2195                                                         sip_element_tree = proto_item_add_subtree( sip_element_item,
2196                                                                                                                            ett_sip_element);
2197                                                         /*
2198                                                          * Permission-Missing  =  "Permission-Missing" HCOLON per-miss-spec
2199                                                          *                        *( COMMA per-miss-spec )
2200                                                          * per-miss-spec       =  ( name-addr / addr-spec )
2201                                                          *                       *( SEMI generic-param )
2202                                                          * Initialize the uri_offsets
2203                                                          */
2204                                                         sip_uri_offset_init(&uri_offsets);
2205                                                         if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
2206                                                                  pmiss_uri_item_tree = display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_pmiss_uri);
2207                                                 }
2208                                                 break;
2209
2210
2211                                         case POS_TRIGGER_CONSENT :
2212                                                 if(hdr_tree)
2213                                                 {
2214                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2215                                                                                        hf_header_array[hf_index], tvb,
2216                                                                                        offset, next_offset - offset,
2217                                                                                        value, "%s",
2218                                                                                        tvb_format_text(tvb, offset, linelen));
2219
2220                                                         sip_element_tree = proto_item_add_subtree( sip_element_item,
2221                                                                                                                                                 ett_sip_element);
2222                                                 }
2223                                                 /*
2224                                                  * Trigger-Consent     =  "Trigger-Consent" HCOLON trigger-cons-spec
2225                                                  *                        *( COMMA trigger-cons-spec )
2226                                                  * trigger-cons-spec   =  ( SIP-URI / SIPS-URI )
2227                                                  *                        *( SEMI trigger-param )
2228                                                  * trigger-param       =  target-uri / generic-param
2229                                                  * target-uri          =  "target-uri" EQUAL
2230                                                  *                            LDQUOT *( qdtext / quoted-pair ) RDQUOT
2231                                                  * Initialize the uri_offsets
2232                                                  */
2233                                                 sip_uri_offset_init(&uri_offsets);
2234                                                 if((dissect_sip_uri(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1) {
2235
2236                                                         tc_uri_item_tree = display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_tc_uri);
2237                                                         if (line_end_offset > uri_offsets.uri_end) {
2238                                                                 gint hparam_offset = uri_offsets.uri_end + 1;
2239                                                                 /* Is there a header parameter */
2240                                                                 if (tvb_find_guint8(tvb, hparam_offset, 1,';')) {
2241                                                                         while ((hparam_offset != -1 && hparam_offset < line_end_offset) )  {
2242                                                                                 /* Is this a target-uri ? */
2243                                                                                 hparam_offset = hparam_offset + 1;
2244                                                                                 if (tvb_strncaseeql(tvb, hparam_offset, "target-uri=\"", 12) == 0) {
2245                                                                                         gint turi_start_offset = hparam_offset + 12;
2246                                                                                         gint turi_end_offset   = tvb_find_guint8(tvb, turi_start_offset, -1,'\"');
2247                                                                                         if (turi_end_offset != -1)
2248                                                                                                 proto_tree_add_item(tc_uri_item_tree, hf_sip_tc_turi, tvb, turi_start_offset,(turi_end_offset - turi_start_offset),FALSE);
2249                                                                                         else
2250                                                                                                 break; /* malformed */
2251                                                                                 }
2252                                                                                 hparam_offset = tvb_find_guint8(tvb, hparam_offset, -1,';');
2253                                                                         }
2254                                                                 }
2255                                                         }
2256                                                 }
2257                                          break;
2258
2259                                         case POS_CSEQ :
2260                                                 /* Store the sequence number */
2261                                                 cseq_number = atoi(value);
2262                                                 cseq_number_set = 1;
2263                                                 stat_info->tap_cseq_number=cseq_number;
2264
2265                                                 /* Add CSeq  tree */
2266                                                 if (hdr_tree) {
2267                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2268                                                                                      hf_header_array[hf_index], tvb,
2269                                                                                      offset, next_offset - offset,
2270                                                                                      value, "%s",
2271                                                                                      tvb_format_text(tvb, offset, linelen));
2272                                                         cseq_tree = proto_item_add_subtree(sip_element_item, ett_sip_cseq);
2273                                                 }
2274
2275                                                 /* Walk past number and spaces characters to get to start
2276                                                    of method name */
2277                                                 for (sub_value_offset=0; sub_value_offset < linelen; sub_value_offset++)
2278                                                 {
2279                                                         if (!isdigit((guchar)value[sub_value_offset]))
2280                                                         {
2281                                                                 proto_tree_add_uint(cseq_tree, hf_sip_cseq_seq_no,
2282                                                                                     tvb, value_offset, sub_value_offset,
2283                                                                                     cseq_number);
2284                                                                 break;
2285                                                         }
2286                                                 }
2287
2288                                                 for (; sub_value_offset < linelen; sub_value_offset++)
2289                                                 {
2290                                                         if (isalpha((guchar)value[sub_value_offset]))
2291                                                         {
2292                                                                 /* Have reached start of method name */
2293                                                                 break;
2294                                                         }
2295                                                 }
2296
2297                                                 if (sub_value_offset == linelen)
2298                                                 {
2299                                                         /* Didn't find method name */
2300                                                         THROW(ReportedBoundsError);
2301                                                         return offset - orig_offset;
2302                                                 }
2303
2304                                                 /* Extract method name from value */
2305                                                 strlen_to_copy = (int)linelen-sub_value_offset;
2306                                                 if (strlen_to_copy > MAX_CSEQ_METHOD_SIZE) {
2307                                                         /* Note the error in the protocol tree */
2308                                                         if (hdr_tree) {
2309                                                                 proto_tree_add_string_format(hdr_tree,
2310                                                                                              hf_header_array[hf_index], tvb,
2311                                                                                              offset, next_offset - offset,
2312                                                                                              value+sub_value_offset, "%s String too big: %d bytes",
2313                                                                                              sip_headers[POS_CSEQ].name,
2314                                                                                              strlen_to_copy);
2315                                                         }
2316                                                         THROW(ReportedBoundsError);
2317                                                         return offset - orig_offset;
2318                                                 }
2319                                                 else {
2320                                                         g_strlcpy(cseq_method, value+sub_value_offset, MAX_CSEQ_METHOD_SIZE);
2321
2322                                                         /* Add CSeq method to the tree */
2323                                                         if (cseq_tree)
2324                                                         {
2325                                                                 proto_tree_add_item(cseq_tree, hf_sip_cseq_method, tvb,
2326                                                                                     value_offset + sub_value_offset, strlen_to_copy, FALSE);
2327                                                         }
2328                                                 }
2329                                         break;
2330
2331                                         case POS_RACK :
2332                                         {
2333                                                 int cseq_no_offset;
2334                                                 int cseq_method_offset;
2335
2336                                                 /* Add RAck  tree */
2337                                                 if (hdr_tree) {
2338                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2339                                                                                      hf_header_array[hf_index], tvb,
2340                                                                                      offset, next_offset - offset,
2341                                                                                      value, "%s",
2342                                                                                      tvb_format_text(tvb, offset, linelen));
2343                                                         rack_tree = proto_item_add_subtree(sip_element_item, ett_sip_rack);
2344                                                 }
2345
2346                                                 /* RSeq number */
2347                                                 for (sub_value_offset=0; sub_value_offset < linelen; sub_value_offset++)
2348                                                 {
2349                                                         if (!isdigit((guchar)value[sub_value_offset]))
2350                                                         {
2351                                                                 proto_tree_add_uint(rack_tree, hf_sip_rack_rseq_no,
2352                                                                                     tvb, value_offset, sub_value_offset,
2353                                                                                     atoi(value));
2354                                                                 break;
2355                                                         }
2356                                                 }
2357
2358                                                 /* Get to start of CSeq number */
2359                                                 for ( ; sub_value_offset < linelen; sub_value_offset++)
2360                                                 {
2361                                                         if (value[sub_value_offset] != ' ' &&
2362                                                         value[sub_value_offset] != '\t')
2363                                                         {
2364                                                                 break;
2365                                                         }
2366                                                 }
2367                                                 cseq_no_offset = sub_value_offset;
2368
2369                                                 /* CSeq number */
2370                                                 for ( ; sub_value_offset < linelen; sub_value_offset++)
2371                                                 {
2372                                                         if (!isdigit((guchar)value[sub_value_offset]))
2373                                                         {
2374                                                                 proto_tree_add_uint(rack_tree, hf_sip_rack_cseq_no,
2375                                                                                     tvb, value_offset+cseq_no_offset,
2376                                                                                     sub_value_offset-cseq_no_offset,
2377                                                                                     atoi(value+cseq_no_offset));
2378                                                                 break;
2379                                                         }
2380                                                 }
2381
2382                                                 /* Get to start of CSeq method name */
2383                                                 for ( ; sub_value_offset < linelen; sub_value_offset++)
2384                                                 {
2385                                                         if (isalpha((guchar)value[sub_value_offset]))
2386                                                         {
2387                                                                 /* Have reached start of method name */
2388                                                                 break;
2389                                                         }
2390                                                 }
2391                                                 cseq_method_offset = sub_value_offset;
2392
2393                                                 if (sub_value_offset == linelen)
2394                                                 {
2395                                                         /* Didn't find method name */
2396                                                         THROW(ReportedBoundsError);
2397                                                         return offset - orig_offset;
2398                                                 }
2399
2400                                                 /* Add CSeq method to the tree */
2401                                                 if (cseq_tree)
2402                                                 {
2403                                                         proto_tree_add_item(rack_tree, hf_sip_rack_cseq_method, tvb,
2404                                                                             value_offset + sub_value_offset,
2405                                                                             (int)linelen-sub_value_offset, FALSE);
2406                                                 }
2407
2408                                                 break;
2409                                         }
2410
2411                                         case POS_CALL_ID :
2412                                                 /* Store the Call-id */
2413                                                 g_strlcpy(call_id, value, MAX_CALL_ID_SIZE);
2414                                                 stat_info->tap_call_id = ep_strdup(call_id);
2415
2416                                                 /* Add 'Call-id' string item to tree */
2417                                                 if(hdr_tree) {
2418                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2419                                                                                      hf_header_array[hf_index], tvb,
2420                                                                                      offset, next_offset - offset,
2421                                                                                      value, "%s",
2422                                                                                      tvb_format_text(tvb, offset, linelen));
2423                                                 }
2424                                         break;
2425
2426                                         case POS_EXPIRES :
2427                                                 if (strcmp(value, "0") == 0)
2428                                                 {
2429                                                         expires_is_0 = 1;
2430                                                 }
2431                                                 /* Add 'Expires' string item to tree */
2432                                                 if(hdr_tree) {
2433                                                         sip_element_item = proto_tree_add_uint(hdr_tree,
2434                                                                             hf_header_array[hf_index], tvb,
2435                                                                             offset, next_offset - offset,
2436                                                                             atoi(value));
2437                                                 }
2438                                         break;
2439
2440                                         /*
2441                                          * Content-Type is the same as Internet
2442                                          * media type used by other dissectors,
2443                                          * appropriate dissector found by
2444                                          * lookup in "media_type" dissector table.
2445                                          */
2446                                         case POS_CONTENT_TYPE :
2447                                                 if(hdr_tree) {
2448                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2449                                                                                      hf_header_array[hf_index], tvb,
2450                                                                                      offset, next_offset - offset,
2451                                                                                      value, "%s",
2452                                                                                      tvb_format_text(tvb, offset, linelen));
2453                                                 }
2454                                                 content_type_len = value_len;
2455                                                 semi_colon_offset = tvb_find_guint8(tvb, value_offset, value_len, ';');
2456                                                 /* Content-Type     =  ( "Content-Type" / "c" ) HCOLON media-type
2457                                                  * media-type       =  m-type SLASH m-subtype *(SEMI m-parameter)
2458                                                  * SEMI    =  SWS ";" SWS ; semicolon
2459                                                  * LWS  =  [*WSP CRLF] 1*WSP ; linear whitespace
2460                                                  * SWS  =  [LWS] ; sep whitespace
2461                                                  */
2462                                                 if ( semi_colon_offset != -1) {
2463                                                         gint content_type_end;
2464                                                         /*
2465                                                          * Skip whitespace after the semicolon.
2466                                                          */
2467                                                         parameter_offset = tvb_skip_wsp(tvb, semi_colon_offset +1, value_offset + value_len - (semi_colon_offset +1));
2468                                                         content_type_end = tvb_skip_wsp_return(tvb, semi_colon_offset-1);
2469                                                         content_type_len = content_type_end - value_offset;
2470                                                         content_type_parameter_str_len = value_offset + value_len - parameter_offset;
2471                                                         content_type_parameter_str = tvb_get_ephemeral_string(tvb, parameter_offset,
2472                                                                                      content_type_parameter_str_len);
2473                                                 }
2474                                                 media_type_str_lower_case = ascii_strdown_inplace(
2475                                                     (gchar *)tvb_get_ephemeral_string(tvb, value_offset, content_type_len));
2476
2477                                                 /* Debug code
2478                                                 proto_tree_add_text(hdr_tree, tvb, value_offset,content_type_len,
2479                                                                     "media_type_str(lower cased)=%s",media_type_str_lower_case);
2480                                                 */
2481                                         break;
2482
2483                                         case POS_CONTENT_LENGTH :
2484                                                 content_length = atoi(value);
2485                                                 if(hdr_tree) {
2486                                                         sip_element_item = proto_tree_add_uint_format(hdr_tree,
2487                                                                            hf_header_array[hf_index], tvb,
2488                                                                            offset, next_offset - offset,
2489                                                                            content_length, "%s",
2490                                                                            tvb_format_text(tvb, offset, linelen));
2491                         }
2492                                                 break;
2493
2494                     case POS_MAX_BREADTH :
2495                                         case POS_MAX_FORWARDS :
2496                                         case POS_RSEQ :
2497                                                 if(hdr_tree) {
2498                                                         sip_element_item = proto_tree_add_uint(hdr_tree,
2499                                                                             hf_header_array[hf_index], tvb,
2500                                                                             offset, next_offset - offset,
2501                                                                             atoi(value));
2502                                                 }
2503                                                 break;
2504
2505                                         case POS_CONTACT :
2506                                                 /*
2507                                                  * Contact        =  ("Contact" / "m" ) HCOLON
2508                                                  *                   ( STAR / (contact-param *(COMMA contact-param)))
2509                                                  * contact-param  =  (name-addr / addr-spec) *(SEMI contact-params)
2510                                                  */
2511                                                 if(hdr_tree) {
2512                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2513                                                                            hf_header_array[hf_index], tvb,
2514                                                                            offset, next_offset - offset,
2515                                                                            value, "%s",
2516                                                                            tvb_format_text(tvb, offset, linelen));
2517                                                         sip_element_tree = proto_item_add_subtree( sip_element_item,
2518                                                                            ett_sip_element);
2519                                                 }
2520                                                 /* value_offset points to the first non SWS character after ':' */
2521                                                 c = tvb_get_guint8(tvb, value_offset);
2522                                                 if (c =='*'){
2523                                                         contact_is_star = 1;
2524                                                         break;
2525                                                 }
2526
2527                                                 comma_offset = value_offset;
2528                                                 while((comma_offset = dissect_sip_contact_item(tvb, pinfo, sip_element_tree, comma_offset, next_offset)) != -1)
2529                                                 {
2530                                                         contacts++;
2531                                                         if(comma_offset == next_offset)
2532                                                         {
2533                                                                 /* Line End reached: Stop Parsing */
2534                                                                 break;
2535                                                         }
2536
2537                                                         if(tvb_get_guint8(tvb, comma_offset) != ',')
2538                                                         {
2539                                                                 /* Undefined value reached: Stop Parsing */
2540                                                                 break;
2541                                                         }
2542                                                         comma_offset++; /* skip comma */
2543                                                 }
2544                                         break;
2545
2546                                         case POS_AUTHORIZATION:
2547                                                 /* Authorization     =  "Authorization" HCOLON credentials
2548                                                  * credentials       =  ("Digest" LWS digest-response)
2549                                                  *                      / other-response
2550                                                  * digest-response   =  dig-resp *(COMMA dig-resp)
2551                                                  * other-response    =  auth-scheme LWS auth-param
2552                                                  *                      *(COMMA auth-param)
2553                                                  */
2554                                         case POS_WWW_AUTHENTICATE:
2555                                                 /* Proxy-Authenticate  =  "Proxy-Authenticate" HCOLON challenge
2556                                                  * challenge           =  ("Digest" LWS digest-cln *(COMMA digest-cln))
2557                                                  *                        / other-challenge
2558                                                  * other-challenge     =  auth-scheme LWS auth-param
2559                                                  *                        *(COMMA auth-param)
2560                                                  * auth-scheme         =  token
2561                                                  */
2562                                         case POS_PROXY_AUTHENTICATE:
2563                                                 /* Proxy-Authenticate  =  "Proxy-Authenticate" HCOLON challenge
2564                                                  */
2565                                         case POS_PROXY_AUTHORIZATION:
2566                                                 /* Proxy-Authorization  =  "Proxy-Authorization" HCOLON credentials
2567                                                  */
2568                                         case POS_AUTHENTICATION_INFO:
2569                                                 /* Authentication-Info  =  "Authentication-Info" HCOLON ainfo
2570                                                  *                        *(COMMA ainfo)
2571                                                  * ainfo                =  nextnonce / message-qop
2572                                                  *                         / response-auth / cnonce
2573                                                  *                         / nonce-count
2574                                                  */
2575                                                 /* Add tree using whole text of line */
2576                                                 if (hdr_tree) {
2577                                                         proto_item *ti_c;
2578                                                         /* Add whole line as header tree */
2579                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2580                                                                            hf_header_array[hf_index], tvb,
2581                                                                            offset, next_offset - offset,
2582                                                                            value, "%s",
2583                                                                            tvb_format_text(tvb, offset, linelen));
2584                                                         sip_element_tree = proto_item_add_subtree( sip_element_item,
2585                                                                            ett_sip_element);
2586
2587                                                         /* Set sip.auth as a hidden field/filter */
2588                                                         ti_c = proto_tree_add_item(hdr_tree, hf_sip_auth, tvb,
2589                                                                                  offset, next_offset-offset,
2590                                                                                  FALSE);
2591                                                         PROTO_ITEM_SET_HIDDEN(ti_c);
2592
2593                                                         /* Authentication-Info does not begin with the scheme name */
2594                                                         if (hf_index != POS_AUTHENTICATION_INFO)
2595                                                         {
2596                                                                 /* The first time comma_offset is "start of parameters" */
2597                                                                 comma_offset = tvb_pbrk_guint8(tvb, value_offset, line_end_offset - value_offset, " \t\r\n", NULL);
2598                                                                 proto_tree_add_item(sip_element_tree, hf_sip_auth_scheme,
2599                                                                                                         tvb, value_offset, comma_offset - value_offset,
2600                                                                                                         FALSE);
2601                                                         }else{
2602                                                                 /* The first time comma_offset is "start of parameters" */
2603                                                                 comma_offset = value_offset;
2604                                                         }
2605
2606                                                         /* Parse each individual parameter in the line */
2607                                                         while ((comma_offset = dissect_sip_authorization_item(tvb, sip_element_tree, comma_offset, line_end_offset)) != -1)
2608                                                         {
2609                                                                 if(comma_offset == line_end_offset)
2610                                                                 {
2611                                                                         /* Line End reached: Stop Parsing */
2612                                                                         break;
2613                                                                 }
2614
2615                                                                 if(tvb_get_guint8(tvb, comma_offset) != ',')
2616                                                                 {
2617                                                                         /* Undefined value reached: Stop Parsing */
2618                                                                         break;
2619                                                                 }
2620                                                                 comma_offset++; /* skip comma */
2621                                                         }
2622                                                 }/*hdr_tree*/
2623                                         break;
2624
2625                                         case POS_VIA:
2626                                                 /* Add Via subtree */
2627                                                 if (hdr_tree) {
2628                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2629                                                                                      hf_header_array[hf_index], tvb,
2630                                                                                      offset, next_offset - offset,
2631                                                                                      value, "%s",
2632                                                                                      tvb_format_text(tvb, offset, linelen));
2633                                                         via_tree = proto_item_add_subtree(sip_element_item, ett_sip_via);
2634                                                         dissect_sip_via_header(tvb, via_tree, value_offset, line_end_offset);
2635                                                 }
2636                                                 break;
2637                                         case POS_REASON:
2638                                                 if(hdr_tree) {
2639                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2640                                                                                      hf_header_array[hf_index], tvb,
2641                                                                                      offset, next_offset - offset,
2642                                                                                      value, "%s",
2643                                                                                      tvb_format_text(tvb, offset, linelen));
2644                                                         reason_tree = proto_item_add_subtree(sip_element_item, ett_sip_reason);
2645                                                         dissect_sip_reason_header(tvb, reason_tree, value_offset, line_end_offset);
2646                                                 }
2647                                                 break;
2648                                         default :
2649                                                 /* Default case is to assume its an FT_STRING field */
2650                                                 if(hdr_tree) {
2651                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2652                                                                                      hf_header_array[hf_index], tvb,
2653                                                                                      offset, next_offset - offset,
2654                                                                                      value, "%s",
2655                                                                                      tvb_format_text(tvb, offset, linelen));
2656                                                 }
2657                                         break;
2658                                 }/* end switch */
2659                         }/*if HF_index */
2660                 }/* if colon_offset */
2661                 if (is_no_header_termination == TRUE){
2662                         /* Header not terminated by empty line CRLF */
2663                         cause=proto_tree_add_text(hdr_tree, tvb, line_end_offset, -1,
2664                                                 "[Header not terminated by empty line (CRLF)]");
2665
2666                         proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
2667                         expert_add_info_format(pinfo, sip_element_item,
2668                                 PI_MALFORMED, PI_WARN,
2669                                 "Header not terminated by empty line (CRLF)");
2670                 }
2671                 offset = next_offset;
2672         }/* End while */
2673
2674         datalen = tvb_length_remaining(tvb, offset);
2675         reported_datalen = tvb_reported_length_remaining(tvb, offset);
2676         if (content_length != -1) {
2677                 if (datalen > content_length)
2678                         datalen = content_length;
2679                 if (reported_datalen > content_length)
2680                         reported_datalen = content_length;
2681         }
2682
2683         if (datalen > 0) {
2684                 /*
2685                  * There's a message body starting at "offset".
2686                  * Set the length of the header item.
2687                  */
2688                 proto_item_set_end(th, tvb, offset);
2689                 next_tvb = tvb_new_subset(tvb, offset, datalen, reported_datalen);
2690                 if(sip_tree) {
2691                         ti_a = proto_tree_add_item(sip_tree, hf_sip_msg_body, next_tvb, 0, -1,
2692                                                  FALSE);
2693                         message_body_tree = proto_item_add_subtree(ti_a, ett_sip_message_body);
2694                 }
2695
2696                 /* give the content type parameters to sub dissectors */
2697
2698                 if ( media_type_str_lower_case != NULL ) {
2699                         void *save_private_data = pinfo->private_data;
2700                         pinfo->private_data = content_type_parameter_str;
2701                         found_match = dissector_try_string(media_type_dissector_table,
2702                                                            media_type_str_lower_case,
2703                                                            next_tvb, pinfo,
2704                                                            message_body_tree);
2705                         pinfo->private_data = save_private_data;
2706                         /* If no match dump as text */
2707                 }
2708                 if ( found_match != TRUE )
2709                 {
2710             if (!(dissector_try_heuristic(heur_subdissector_list,
2711                                           next_tvb, pinfo, message_body_tree))) {
2712                 int tmp_offset = 0;
2713                 while (tvb_offset_exists(next_tvb, tmp_offset)) {
2714                     tvb_find_line_end(next_tvb, tmp_offset, -1, &next_offset, FALSE);
2715                     linelen = next_offset - tmp_offset;
2716                     if(message_body_tree) {
2717                         proto_tree_add_text(message_body_tree, next_tvb,
2718                                             tmp_offset, linelen, "%s",
2719                                             tvb_format_text(next_tvb, tmp_offset, linelen));
2720                         }
2721                     tmp_offset = next_offset;
2722                     }/* end while */
2723                         }
2724                 }
2725                 offset += datalen;
2726         }
2727
2728
2729         /* Add to info column interesting things learned from header fields. */
2730         /* Registration requests */
2731         if (current_method_idx == SIP_METHOD_REGISTER)
2732         {
2733                 if (contact_is_star && expires_is_0)
2734                 {
2735                         col_append_str(pinfo->cinfo, COL_INFO, "    (remove all bindings)");
2736                 }
2737                 else
2738                 if (!contacts)
2739                 {
2740                         col_append_str(pinfo->cinfo, COL_INFO, "    (fetch bindings)");
2741                 }
2742         }
2743
2744         /* Registration responses */
2745         if (line_type == STATUS_LINE && (strcmp(cseq_method, "REGISTER") == 0))
2746         {
2747                 col_append_fstr(pinfo->cinfo, COL_INFO, "    (%d bindings)", contacts);
2748         }
2749         /* Find the total setup time, Must be done before checking for resend
2750          * As that will overwrite the "Request packet no".
2751          */
2752         if ((line_type == REQUEST_LINE)&&(strcmp(cseq_method, "ACK") == 0))
2753         {
2754                 request_for_response = sip_find_invite(pinfo, cseq_method, call_id,
2755                                                         cseq_number_set, cseq_number,
2756                                                         &response_time);
2757                 stat_info->setup_time = response_time;
2758         }
2759
2760         /* Check if this packet is a resend. */
2761         resend_for_packet = sip_is_packet_resend(pinfo, cseq_method, call_id,
2762                                                  cseq_number_set, cseq_number,
2763                                                  line_type);
2764         /* Mark whether this is a resend for the tap */
2765         stat_info->resend = (resend_for_packet > 0);
2766
2767         /* And add the filterable field to the request/response line */
2768         if (reqresp_tree)
2769         {
2770                 proto_item *item;
2771                 item = proto_tree_add_boolean(reqresp_tree, hf_sip_resend, tvb, orig_offset, 0,
2772                                               resend_for_packet > 0);
2773                 PROTO_ITEM_SET_GENERATED(item);
2774                 if (resend_for_packet > 0)
2775                 {
2776                         item = proto_tree_add_uint(reqresp_tree, hf_sip_original_frame,
2777                                                    tvb, orig_offset, 0, resend_for_packet);
2778                         PROTO_ITEM_SET_GENERATED(item);
2779                 }
2780         }
2781
2782         /* For responses, try to link back to request frame */
2783         if (line_type == STATUS_LINE)
2784         {
2785                 request_for_response = sip_find_request(pinfo, cseq_method, call_id,
2786                                                         cseq_number_set, cseq_number,
2787                                                         &response_time);
2788         }
2789
2790         if (reqresp_tree)
2791         {
2792                 proto_item *item;
2793                 if (request_for_response > 0)
2794                 {
2795                         item = proto_tree_add_uint(reqresp_tree, hf_sip_matching_request_frame,
2796                                                    tvb, orig_offset, 0, request_for_response);
2797                         PROTO_ITEM_SET_GENERATED(item);
2798                         item = proto_tree_add_uint(reqresp_tree, hf_sip_response_time,
2799                                                    tvb, orig_offset, 0, response_time);
2800                         PROTO_ITEM_SET_GENERATED(item);
2801                         if ((line_type == STATUS_LINE)&&(strcmp(cseq_method, "BYE") == 0)){
2802                                 item = proto_tree_add_uint(reqresp_tree, hf_sip_release_time,
2803                                                           tvb, orig_offset, 0, response_time);
2804                                 PROTO_ITEM_SET_GENERATED(item);
2805                         }
2806                 }
2807         }
2808
2809         if (ts != NULL)
2810                 proto_item_set_len(ts, offset - orig_offset);
2811
2812         if (global_sip_raw_text)
2813                 tvb_raw_text_add(tvb, orig_offset, offset - orig_offset, tree);
2814
2815         /* Report this packet to the tap */
2816         if (!pinfo->in_error_pkt)
2817         {
2818                 tap_queue_packet(sip_tap, pinfo, stat_info);
2819         }
2820
2821         return offset - orig_offset;
2822 }
2823
2824 /* Display filter for SIP Request-Line */
2825 static void
2826 dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint offset, guint meth_len, gint linelen)
2827 {
2828         char    *value;
2829         guint   parameter_len = meth_len;
2830         uri_offset_info uri_offsets;
2831
2832         /*
2833          * We know we have the entire method; otherwise, "sip_parse_line()"
2834          * would have returned OTHER_LINE.
2835          * Request-Line  =  Method SP Request-URI SP SIP-Version CRLF
2836          * SP = single space
2837          * Request-URI    =  SIP-URI / SIPS-URI / absoluteURI
2838          */
2839
2840         /* get method string*/
2841         value = tvb_get_ephemeral_string(tvb, offset, parameter_len);
2842
2843         /* Copy request method for telling tap */
2844         stat_info->request_method = value;
2845
2846         if (tree) {
2847                 proto_tree_add_string(tree, hf_sip_Method, tvb, offset, parameter_len, value);
2848
2849                 /* build Request-URI tree*/
2850                 offset=offset + parameter_len+1;
2851                 sip_uri_offset_init(&uri_offsets);
2852                 /* calc R-URI len*/
2853                 uri_offsets.uri_end = tvb_find_guint8(tvb, offset, linelen, ' ')-1;
2854                 dissect_sip_uri(tvb, pinfo, offset, offset + linelen, &uri_offsets);
2855                 display_sip_uri(tvb, tree, &uri_offsets, &sip_req_uri);
2856         }
2857 }
2858
2859 /* Display filter for SIP Status-Line */
2860 static void
2861 dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree)
2862 {
2863         char string[3+1];
2864         gint response_code = 0;
2865
2866         /*
2867          * We know we have the entire status code; otherwise,
2868          * "sip_parse_line()" would have returned OTHER_LINE.
2869          * We also know that we have a version string followed by a
2870          * space at the beginning of the line, for the same reason.
2871          */
2872         tvb_memcpy(tvb, (guint8 *)string, SIP2_HDR_LEN + 1, 3);
2873         string[3] = '\0';
2874         response_code = atoi(string);
2875
2876         /* Add numerical response code to tree */
2877         if (tree) {
2878                 proto_tree_add_uint(tree, hf_Status_Code, tvb, SIP2_HDR_LEN + 1,
2879                                     3, response_code);
2880         }
2881
2882         /* Add response code for sending to tap */
2883         stat_info->response_code = response_code;
2884 }
2885
2886 /* From section 4.1 of RFC 2543:
2887  *
2888  * Request-Line  =  Method SP Request-URI SP SIP-Version CRLF
2889  *
2890  * From section 5.1 of RFC 2543:
2891  *
2892  * Status-Line  =  SIP-version SP Status-Code SP Reason-Phrase CRLF
2893  *
2894  * From section 7.1 of RFC 3261:
2895  *
2896  * Unlike HTTP, SIP treats the version number as a literal string.
2897  * In practice, this should make no difference.
2898  */
2899 static line_type_t
2900 sip_parse_line(tvbuff_t *tvb, int offset, gint linelen, guint *token_1_lenp)
2901 {
2902         gint space_offset;
2903         gint token_1_start;
2904         guint token_1_len;
2905         gint token_2_start;
2906         guint token_2_len;
2907         gint token_3_start;
2908         guint token_3_len;
2909         gint colon_pos;
2910
2911         token_1_start = offset;
2912         space_offset = tvb_find_guint8(tvb, token_1_start, -1, ' ');
2913         if ((space_offset == -1) || (space_offset == token_1_start)) {
2914                 /*
2915                  * Either there's no space in the line (which means
2916                  * the line is empty or doesn't have a token followed
2917                  * by a space; neither is valid for a request or status), or
2918                  * the first character in the line is a space (meaning
2919                  * the method is empty, which isn't valid for a request,
2920                  * or the SIP version is empty, which isn't valid for a
2921                  * status).
2922                  */
2923                 return OTHER_LINE;
2924         }
2925         token_1_len = space_offset - token_1_start;
2926         token_2_start = space_offset + 1;
2927         space_offset = tvb_find_guint8(tvb, token_2_start, -1, ' ');
2928         if (space_offset == -1) {
2929                 /*
2930                  * There's no space after the second token, so we don't
2931                  * have a third token.
2932                  */
2933                 return OTHER_LINE;
2934         }
2935         token_2_len = space_offset - token_2_start;
2936         token_3_start = space_offset + 1;
2937         token_3_len = token_1_start + linelen - token_3_start;
2938
2939         *token_1_lenp = token_1_len;
2940
2941         /*
2942          * Is the first token a version string?
2943          */
2944         if ( (strict_sip_version && (
2945                 token_1_len == SIP2_HDR_LEN
2946                 && tvb_strneql(tvb, token_1_start, SIP2_HDR, SIP2_HDR_LEN) == 0)
2947         ) || (! strict_sip_version && (
2948                 tvb_strncaseeql(tvb, token_1_start, "SIP/", 4) == 0)
2949         )) {
2950                 /*
2951                  * Yes, so this is either a Status-Line or something
2952                  * else other than a Request-Line.  To be a Status-Line,
2953                  * the second token must be a 3-digit number.
2954                  */
2955                 if (token_2_len != 3) {
2956                         /*
2957                          * We don't have 3-character status code.
2958                          */
2959                         return OTHER_LINE;
2960                 }
2961                 if (!isdigit(tvb_get_guint8(tvb, token_2_start)) ||
2962                     !isdigit(tvb_get_guint8(tvb, token_2_start + 1)) ||
2963                     !isdigit(tvb_get_guint8(tvb, token_2_start + 2))) {
2964                         /*
2965                          * 3 characters yes, 3 digits no.
2966                          */
2967                         return OTHER_LINE;
2968                 }
2969                 return STATUS_LINE;
2970         } else {
2971                 /*
2972                  * No, so this is either a Request-Line or something
2973                  * other than a Status-Line.  To be a Request-Line, the
2974                  * second token must be a URI and the third token must
2975                  * be a version string.
2976                  */
2977                 if (token_2_len < 3) {
2978                         /*
2979                          * We don't have a URI consisting of at least 3
2980                          * characters.
2981                          */
2982                         return OTHER_LINE;
2983                 }
2984                 colon_pos = tvb_find_guint8(tvb, token_2_start + 1, -1, ':');
2985                 if (colon_pos == -1) {
2986                         /*
2987                          * There is no colon after the method, so the URI
2988                          * doesn't have a colon in it, so it's not valid.
2989                          */
2990                         return OTHER_LINE;
2991                 }
2992                 if (colon_pos >= token_3_start) {
2993                         /*
2994                          * The colon is in the version string, not the URI.
2995                          */
2996                         return OTHER_LINE;
2997                 }
2998                 /* XXX - Check for a proper URI prefix? */
2999                 if ( (strict_sip_version && (
3000                         token_3_len != SIP2_HDR_LEN
3001                         || tvb_strneql(tvb, token_3_start, SIP2_HDR, SIP2_HDR_LEN) == -1)
3002                 ) || (! strict_sip_version && (
3003                         tvb_strncaseeql(tvb, token_3_start, "SIP/", 4) == -1)
3004                 )) {
3005                         /*
3006                          * The version string isn't an SIP version 2.0 version
3007                          * string.
3008                          */
3009                         return OTHER_LINE;
3010                 }
3011                 return REQUEST_LINE;
3012         }
3013 }
3014
3015 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
3016     guint meth_len, guint *meth_idx)
3017 {
3018         guint i;
3019                 gchar *meth_name;
3020
3021                 meth_name = tvb_get_ephemeral_string(tvb, meth_offset, meth_len);
3022
3023         for (i = 1; i < array_length(sip_methods); i++) {
3024                 if (meth_len == strlen(sip_methods[i]) &&
3025                     strncmp(meth_name, sip_methods[i], meth_len) == 0)
3026                 {
3027                      *meth_idx = i;
3028                      return TRUE;
3029                 }
3030         }
3031
3032         return FALSE;
3033 }
3034
3035 /*
3036  * Returns index of method in sip_headers
3037  * Header namne should be in lower case
3038  */
3039 static gint sip_is_known_sip_header(gchar *header_name, guint header_len)
3040 {
3041         guint pos;
3042
3043         /* Compact name is one character long */
3044         if(header_len>1){
3045                 pos = GPOINTER_TO_INT(g_hash_table_lookup(sip_headers_hash, header_name));
3046                 if (pos!=0)
3047                         return pos;
3048         }
3049
3050         /* Look for compact name match */
3051         for (pos = 1; pos < array_length(sip_headers); pos++) {
3052                 if (sip_headers[pos].compact_name != NULL &&
3053                                 header_len == strlen(sip_headers[pos].compact_name) &&
3054                                 g_ascii_strncasecmp(header_name, sip_headers[pos].compact_name, header_len) == 0)
3055                         return pos;
3056         }
3057
3058     return -1;
3059 }
3060
3061 /*
3062  * Display the entire message as raw text.
3063  */
3064 static void
3065 tvb_raw_text_add(tvbuff_t *tvb, int offset, int length, proto_tree *tree)
3066 {
3067         proto_tree *raw_tree = NULL;
3068         proto_item *ti = NULL;
3069         int next_offset, linelen, end_offset;
3070         char *str;
3071
3072         if (tree) {
3073                 ti = proto_tree_add_item(tree, proto_raw_sip, tvb, offset, length, FALSE);
3074                 raw_tree = proto_item_add_subtree(ti, ett_raw_text);
3075         }
3076
3077         end_offset = offset + length;
3078
3079         while (offset < end_offset) {
3080                 tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
3081                 linelen = next_offset - offset;
3082                 if (raw_tree) {
3083                         str = tvb_format_text(tvb, offset, linelen);
3084                         proto_tree_add_string_format(raw_tree, hf_raw_sip_line, tvb, offset, linelen,
3085                                                      str,
3086                                                      "%s",
3087                                                      str);
3088                 }
3089                 offset = next_offset;
3090         }
3091 }
3092
3093 /* Check to see if this packet is a resent request.  Return value is the frame number
3094    of the original frame this packet seems to be resending (0 = no resend). */
3095 guint sip_is_packet_resend(packet_info *pinfo,
3096                         gchar *cseq_method,
3097                         gchar *call_id,
3098                         guchar cseq_number_set,
3099                         guint32 cseq_number, line_type_t line_type)
3100 {
3101         guint32 cseq_to_compare = 0;
3102         sip_hash_key   key;
3103         sip_hash_key   *p_key = 0;
3104         sip_hash_value *p_val = 0;
3105         sip_frame_result_value *sip_frame_result = NULL;
3106         guint result = 0;
3107
3108         /* Only consider retransmission of UDP packets */
3109         if (pinfo->ptype != PT_UDP)
3110         {
3111                 return 0;
3112         }
3113
3114         /* Don't consider packets that appear to be resent only because
3115            they are e.g. returned in ICMP unreachable messages. */
3116         if (pinfo->in_error_pkt)
3117         {
3118                 return 0;
3119         }
3120
3121         /* A broken packet may have no cseq number set. Don't consider it as
3122            a resend */
3123         if (!cseq_number_set)
3124         {
3125                 return 0;
3126         }
3127
3128         /* Return any answer stored from previous dissection */
3129         if (pinfo->fd->flags.visited)
3130         {
3131                 sip_frame_result = (sip_frame_result_value*)p_get_proto_data(pinfo->fd, proto_sip);
3132                 if (sip_frame_result != NULL)
3133                 {
3134                         return sip_frame_result->original_frame_num;
3135                 }
3136                 else
3137                 {
3138                         return 0;
3139                 }
3140         }
3141
3142         /* No packet entry found, consult global hash table */
3143
3144         /* Prepare the key */
3145         g_strlcpy(key.call_id, call_id, MAX_CALL_ID_SIZE);
3146
3147         /*  We're only using these addresses locally (for the hash lookup) so
3148          *  there is no need to make a (g_malloc'd) copy of them.
3149          */
3150         SET_ADDRESS(&key.dest_address, pinfo->net_dst.type, pinfo->net_dst.len,
3151                     pinfo->net_dst.data);
3152         SET_ADDRESS(&key.source_address, pinfo->net_src.type,
3153                     pinfo->net_src.len, pinfo->net_src.data);
3154         key.dest_port = pinfo->destport;
3155         if (sip_retrans_the_same_sport) {
3156                 key.source_port = pinfo->srcport;
3157         } else {
3158                 key.source_port = MAGIC_SOURCE_PORT;
3159         }
3160
3161         /* Do the lookup */
3162         p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
3163
3164         if (p_val)
3165         {
3166                 /* Table entry found, we'll use its value for comparison */
3167                 cseq_to_compare = p_val->cseq;
3168
3169                 /* First time through, must update value with current details if
3170                     cseq number has changed */
3171                 if (cseq_number != p_val->cseq)
3172                 {
3173                         p_val->cseq = cseq_number;
3174                         g_strlcpy(p_val->method, cseq_method, MAX_CSEQ_METHOD_SIZE);
3175                         p_val->transaction_state = nothing_seen;
3176                         p_val->frame_number = 0;
3177                         if (line_type == REQUEST_LINE)
3178                         {
3179                                 p_val->request_time = pinfo->fd->abs_ts;
3180                         }
3181                 }
3182         }
3183         else
3184         {
3185                 /* Need to create a new table entry */
3186
3187                 /* Allocate a new key and value */
3188                 p_key = se_alloc(sizeof(sip_hash_key));
3189                 p_val = se_alloc(sizeof(sip_hash_value));
3190
3191                 /* Fill in key and value details */
3192                 g_snprintf(p_key->call_id, MAX_CALL_ID_SIZE, "%s", call_id);
3193                 SE_COPY_ADDRESS(&(p_key->dest_address), &pinfo->net_dst);
3194                 SE_COPY_ADDRESS(&(p_key->source_address), &pinfo->net_src);
3195                 p_key->dest_port = pinfo->destport;
3196                 if (sip_retrans_the_same_sport) {
3197                         p_key->source_port = pinfo->srcport;
3198                 } else {
3199                         p_key->source_port = MAGIC_SOURCE_PORT;
3200                 }
3201
3202                 p_val->cseq = cseq_number;
3203                 g_strlcpy(p_val->method, cseq_method, MAX_CSEQ_METHOD_SIZE);
3204                 p_val->transaction_state = nothing_seen;
3205                 p_val->frame_number = 0;
3206                 if (line_type == REQUEST_LINE)
3207                 {
3208                         p_val->request_time = pinfo->fd->abs_ts;
3209                 }
3210
3211                 /* Add entry */
3212                 g_hash_table_insert(sip_hash, p_key, p_val);
3213
3214                 /* Assume have seen no cseq yet */
3215                 cseq_to_compare = 0;
3216         }
3217
3218
3219         /******************************************/
3220         /* Is it a resend???                      */
3221
3222         /* Does this look like a resent request (discount ACK, CANCEL, or a
3223            different method from the original one) ? */
3224
3225         if ((line_type == REQUEST_LINE) && (cseq_number == cseq_to_compare) &&
3226             (p_val->transaction_state == request_seen) &&
3227             (strcmp(cseq_method, p_val->method) == 0) &&
3228             (strcmp(cseq_method, "ACK") != 0) &&
3229             (strcmp(cseq_method, "CANCEL") != 0))
3230         {
3231                 result = p_val->frame_number;
3232         }
3233
3234         /* Does this look like a resent final response ? */
3235         if ((line_type == STATUS_LINE) && (cseq_number == cseq_to_compare) &&
3236             (p_val->transaction_state == final_response_seen) &&
3237             (strcmp(cseq_method, p_val->method) == 0) &&
3238             (stat_info->response_code >= 200) &&
3239             (stat_info->response_code == p_val->response_code))
3240         {
3241                 result = p_val->frame_number;
3242         }
3243
3244         /* Update state for this entry */
3245         p_val->cseq = cseq_number;
3246
3247         switch (line_type)
3248         {
3249                 case REQUEST_LINE:
3250                         p_val->transaction_state = request_seen;
3251                         if (!result)
3252                         {
3253                                 /* This frame is the original request */
3254                                 p_val->frame_number = pinfo->fd->num;
3255                         }
3256                         break;
3257                 case STATUS_LINE:
3258                         if (stat_info->response_code >= 200)
3259                         {
3260                                 p_val->response_code = stat_info->response_code;
3261                                 p_val->transaction_state = final_response_seen;
3262                                 if (!result)
3263                                 {
3264                                         /* This frame is the original response */
3265                                         p_val->frame_number = pinfo->fd->num;
3266                                 }
3267                         }
3268                         else
3269                         {
3270                                 p_val->transaction_state = provisional_response_seen;
3271                         }
3272                         break;
3273                 default:
3274                         break;
3275         }
3276
3277         sip_frame_result = p_get_proto_data(pinfo->fd, proto_sip);
3278         if (sip_frame_result == NULL)
3279         {
3280                 sip_frame_result = se_alloc(sizeof(sip_frame_result_value));
3281         }
3282
3283         /* Store return value with this packet */
3284         sip_frame_result->original_frame_num = result;
3285         p_add_proto_data(pinfo->fd, proto_sip, sip_frame_result);
3286
3287         return result;
3288 }
3289
3290
3291 /* Check to see if this packet is a resent request.  Return value is the frame number
3292    of the original frame this packet seems to be resending (0 = no resend). */
3293 guint sip_find_request(packet_info *pinfo,
3294                         gchar *cseq_method,
3295                         gchar *call_id,
3296                         guchar cseq_number_set,
3297                         guint32 cseq_number,
3298                         guint32 *response_time)
3299 {
3300         guint32 cseq_to_compare = 0;
3301         sip_hash_key   key;
3302         sip_hash_value *p_val = 0;
3303         sip_frame_result_value *sip_frame_result = NULL;
3304         guint result = 0;
3305         gint seconds_between_packets;
3306         gint nseconds_between_packets;
3307
3308         /* Only consider UDP */
3309         if (pinfo->ptype != PT_UDP)
3310         {
3311                 return 0;
3312         }
3313
3314         /* Ignore error (usually ICMP) frames */
3315         if (pinfo->in_error_pkt)
3316         {
3317                 return 0;
3318         }
3319
3320         /* A broken packet may have no cseq number set. Ignore. */
3321         if (!cseq_number_set)
3322         {
3323                 return 0;
3324         }
3325
3326         /* Return any answer stored from previous dissection */
3327         if (pinfo->fd->flags.visited)
3328         {
3329                 sip_frame_result = (sip_frame_result_value*)p_get_proto_data(pinfo->fd, proto_sip);
3330                 if (sip_frame_result != NULL)
3331                 {
3332                         *response_time = sip_frame_result->response_time;
3333                         return sip_frame_result->response_request_frame_num;
3334                 }
3335                 else
3336                 {
3337                         return 0;
3338                 }
3339         }
3340
3341         /* No packet entry found, consult global hash table */
3342
3343         /* Prepare the key */
3344         g_strlcpy(key.call_id, call_id, MAX_CALL_ID_SIZE);
3345
3346         /* Looking for matching request, so reverse addresses for this lookup */
3347         SET_ADDRESS(&key.dest_address, pinfo->net_src.type, pinfo->net_src.len,
3348                     pinfo->net_src.data);
3349         SET_ADDRESS(&key.source_address, pinfo->net_dst.type, pinfo->net_dst.len,
3350                         pinfo->net_dst.data);
3351         key.dest_port = pinfo->srcport;
3352         key.source_port = pinfo->destport;
3353
3354         /* Do the lookup */
3355         p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
3356
3357         if (p_val)
3358         {
3359                 /* Table entry found, we'll use its value for comparison */
3360                 cseq_to_compare = p_val->cseq;
3361         }
3362         else
3363         {
3364                 /* We don't have the request */
3365                 return 0;
3366         }
3367
3368
3369         /**************************************************/
3370         /* Is it a response to a request that we've seen? */
3371         if ((cseq_number == cseq_to_compare) &&
3372             (p_val->transaction_state == request_seen) &&
3373             (strcmp(cseq_method, p_val->method) == 0))
3374         {
3375                 result = p_val->frame_number;
3376         }
3377
3378
3379         /* Store return value with this packet */
3380         sip_frame_result = p_get_proto_data(pinfo->fd, proto_sip);
3381         if (sip_frame_result == NULL)
3382         {
3383                 /* Allocate and set all values to zero */
3384                 sip_frame_result = se_alloc0(sizeof(sip_frame_result_value));
3385         }
3386
3387         sip_frame_result->response_request_frame_num = result;
3388
3389         /* Work out response time */
3390         seconds_between_packets = (gint)
3391             (pinfo->fd->abs_ts.secs - p_val->request_time.secs);
3392         nseconds_between_packets =
3393              pinfo->fd->abs_ts.nsecs - p_val->request_time.nsecs;
3394         sip_frame_result->response_time = (seconds_between_packets*1000) +
3395                                           (nseconds_between_packets / 1000000);
3396         *response_time = sip_frame_result->response_time;
3397
3398         p_add_proto_data(pinfo->fd, proto_sip, sip_frame_result);
3399
3400         return result;
3401 }
3402
3403 /*
3404  * Find the initial INVITE to calculate the total setup time
3405  */
3406 guint sip_find_invite(packet_info *pinfo,
3407                         gchar *cseq_method _U_,
3408                         gchar *call_id,
3409                         guchar cseq_number_set,
3410                         guint32 cseq_number _U_,
3411                         guint32 *response_time)
3412 {
3413         guint32 cseq_to_compare = 0;
3414         sip_hash_key   key;
3415         sip_hash_value *p_val = 0;
3416         sip_frame_result_value *sip_frame_result = NULL;
3417         guint result = 0;
3418         gint seconds_between_packets;
3419         gint nseconds_between_packets;
3420
3421         /* Only consider UDP */
3422         if (pinfo->ptype != PT_UDP)
3423         {
3424                 return 0;
3425         }
3426
3427         /* Ignore error (usually ICMP) frames */
3428         if (pinfo->in_error_pkt)
3429         {
3430                 return 0;
3431         }
3432
3433         /* A broken packet may have no cseq number set. Ignore. */
3434         if (!cseq_number_set)
3435         {
3436                 return 0;
3437         }
3438
3439         /* Return any answer stored from previous dissection */
3440         if (pinfo->fd->flags.visited)
3441         {
3442                 sip_frame_result = (sip_frame_result_value*)p_get_proto_data(pinfo->fd, proto_sip);
3443                 if (sip_frame_result != NULL)
3444                 {
3445                         *response_time = sip_frame_result->response_time;
3446                         return sip_frame_result->response_request_frame_num;
3447                 }
3448                 else
3449                 {
3450                         return 0;
3451                 }
3452         }
3453
3454         /* No packet entry found, consult global hash table */
3455
3456         /* Prepare the key */
3457         g_strlcpy(key.call_id, call_id, MAX_CALL_ID_SIZE);
3458
3459         /* Looking for matching INVITE */
3460         SET_ADDRESS(&key.dest_address, pinfo->net_dst.type, pinfo->net_dst.len,
3461                         pinfo->net_dst.data);
3462         SET_ADDRESS(&key.source_address, pinfo->net_src.type, pinfo->net_src.len,
3463                     pinfo->net_src.data);
3464         key.dest_port = pinfo->destport;
3465         key.source_port = pinfo->srcport;
3466
3467         /* Do the lookup */
3468         p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
3469
3470         if (p_val)
3471         {
3472                 /* Table entry found, we'll use its value for comparison */
3473                 cseq_to_compare = p_val->cseq;
3474         }
3475         else
3476         {
3477                 /* We don't have the request */
3478                 return 0;
3479         }
3480
3481
3482         /**************************************************/
3483         /* Is it a response to a request that we've seen? */
3484 #if 0
3485         if ((cseq_number == cseq_to_compare) &&
3486             (p_val->transaction_state == request_seen) &&
3487             (strcmp(cseq_method, p_val->method) == 0))
3488         {
3489                 result = p_val->frame_number;
3490         }
3491 #endif
3492
3493         result = p_val->frame_number;
3494
3495         /* Store return value with this packet */
3496         sip_frame_result = p_get_proto_data(pinfo->fd, proto_sip);
3497         if (sip_frame_result == NULL)
3498         {
3499                 /* Allocate and set all values to zero */
3500                 sip_frame_result = se_alloc0(sizeof(sip_frame_result_value));
3501         }
3502
3503         sip_frame_result->response_request_frame_num = result;
3504
3505         /* Work out response time */
3506         seconds_between_packets = (gint)
3507             (pinfo->fd->abs_ts.secs - p_val->request_time.secs);
3508         nseconds_between_packets =
3509              pinfo->fd->abs_ts.nsecs - p_val->request_time.nsecs;
3510         sip_frame_result->response_time = (seconds_between_packets*1000) +
3511                                           (nseconds_between_packets / 1000000);
3512         *response_time = sip_frame_result->response_time;
3513
3514         p_add_proto_data(pinfo->fd, proto_sip, sip_frame_result);
3515
3516         return result;
3517 }
3518
3519
3520 /* Register the protocol with Wireshark */
3521 void proto_register_sip(void)
3522 {
3523
3524         /* Setup list of header fields */
3525         static hf_register_info hf[] = {
3526
3527                 { &hf_msg_hdr,
3528                                 { "Message Header",           "sip.msg_hdr",
3529                         FT_STRING, BASE_NONE, NULL, 0,
3530                         "Message Header in SIP message", HFILL }
3531                 },
3532                 { &hf_sip_Method,
3533                        { "Method",              "sip.Method",
3534                        FT_STRING, BASE_NONE,NULL,0x0,
3535                         "SIP Method", HFILL }
3536                 },
3537                 { &hf_Request_Line,
3538                                 { "Request-Line",                "sip.Request-Line",
3539                                         FT_STRING, BASE_NONE,NULL,0x0,
3540                        "SIP Request-Line", HFILL }
3541                 },
3542                 { &hf_sip_ruri,
3543                                 { "Request-URI",                "sip.r-uri",
3544                        FT_STRING, BASE_NONE,NULL,0x0,
3545                         "RFC 3261: SIP R-URI", HFILL }
3546                 },
3547                 { &hf_sip_ruri_user,
3548                                 { "Request-URI User Part",              "sip.r-uri.user",
3549                        FT_STRING, BASE_NONE,NULL,0x0,
3550                         "RFC 3261: SIP R-URI User", HFILL }
3551                 },
3552                 { &hf_sip_ruri_host,
3553                                 { "Request-URI Host Part",              "sip.r-uri.host",
3554                        FT_STRING, BASE_NONE,NULL,0x0,
3555                         "RFC 3261: SIP R-URI Host", HFILL }
3556                 },
3557                 { &hf_sip_ruri_port,
3558                                 { "Request-URI Host Port",              "sip.r-uri.port",
3559                        FT_STRING, BASE_NONE,NULL,0x0,
3560                         "RFC 3261: SIP R-URI Port", HFILL }
3561                 },
3562                 { &hf_Status_Code,
3563                        { "Status-Code",                 "sip.Status-Code",
3564                        FT_UINT32, BASE_DEC,NULL,0x0,
3565                         "SIP Status Code", HFILL }
3566                 },
3567                 { &hf_Status_Line,
3568                        { "Status-Line",                 "sip.Status-Line",
3569                        FT_STRING, BASE_NONE,NULL,0x0,
3570                        "SIP Status-Line", HFILL }
3571                 },
3572                 { &hf_sip_display,
3573                         { "SIP Display info",           "sip.display.info",
3574                        FT_STRING, BASE_NONE,NULL,0x0,
3575                         "RFC 3261: Display info", HFILL }
3576                 },
3577                 { &hf_sip_to_addr,
3578                                 { "SIP to address",             "sip.to.addr",
3579                        FT_STRING, BASE_NONE,NULL,0x0,
3580                         "RFC 3261: To Address", HFILL }
3581                 },
3582                 { &hf_sip_to_user,
3583                        { "SIP to address User Part",            "sip.to.user",
3584                        FT_STRING, BASE_NONE,NULL,0x0,
3585                         "RFC 3261: To Address User", HFILL }
3586                 },
3587                 { &hf_sip_to_host,
3588                        { "SIP to address Host Part",            "sip.to.host",
3589                        FT_STRING, BASE_NONE,NULL,0x0,
3590                         "RFC 3261: To Address Host", HFILL }
3591                 },
3592                 { &hf_sip_to_port,
3593                        { "SIP to address Host Port",            "sip.to.port",
3594                        FT_STRING, BASE_NONE,NULL,0x0,
3595                         "RFC 3261: To Address Port", HFILL }
3596                 },
3597                 { &hf_sip_from_addr,
3598                        { "SIP from address",            "sip.from.addr",
3599                        FT_STRING, BASE_NONE,NULL,0x0,
3600                         "RFC 3261: From Address", HFILL }
3601                 },
3602                 { &hf_sip_from_user,
3603                        { "SIP from address User Part",          "sip.from.user",
3604                        FT_STRING, BASE_NONE,NULL,0x0,
3605                         "RFC 3261: From Address User", HFILL }
3606                 },
3607                 { &hf_sip_from_host,
3608                        { "SIP from address Host Part",          "sip.from.host",
3609                        FT_STRING, BASE_NONE,NULL,0x0,
3610                         "RFC 3261: From Address Host", HFILL }
3611                 },
3612                 { &hf_sip_from_port,
3613                        { "SIP from address Host Port",          "sip.from.port",
3614                        FT_STRING, BASE_NONE,NULL,0x0,
3615                         "RFC 3261: From Address Port", HFILL }
3616                 },
3617 /* etxrab */
3618                 { &hf_sip_curi,
3619                                 { "Contact-URI",                "sip.contact.uri",
3620                        FT_STRING, BASE_NONE,NULL,0x0,
3621                         "RFC 3261: SIP C-URI", HFILL }
3622                 },
3623                 { &hf_sip_curi_user,
3624                                 { "Contactt-URI User Part",             "sip.contact.user",
3625                        FT_STRING, BASE_NONE,NULL,0x0,
3626                         "RFC 3261: SIP C-URI User", HFILL }
3627                 },
3628                 { &hf_sip_curi_host,
3629                                 { "Contact-URI Host Part",              "sip.contact.host",
3630                        FT_STRING, BASE_NONE,NULL,0x0,
3631                         "RFC 3261: SIP C-URI Host", HFILL }
3632                 },
3633                 { &hf_sip_curi_port,
3634                                 { "Contact-URI Host Port",              "sip.contact.port",
3635                        FT_STRING, BASE_NONE,NULL,0x0,
3636                         "RFC 3261: SIP C-URI Port", HFILL }
3637                 },
3638                 { &hf_sip_contact_param,
3639                        { "Contact parameter",           "sip.contact.parameter",
3640                        FT_STRING, BASE_NONE,NULL,0x0,
3641                         "RFC 3261: one contact parameter", HFILL }
3642                 },
3643                 { &hf_sip_tag,
3644                        { "SIP tag",             "sip.tag",
3645                        FT_STRING, BASE_NONE,NULL,0x0,
3646                         "RFC 3261: tag", HFILL }
3647                 },
3648                 { &hf_sip_pai_addr,
3649                        { "SIP PAI Address",             "sip.pai.addr",
3650                        FT_STRING, BASE_NONE,NULL,0x0,
3651                         "RFC 3325: P-Asserted-Identity Address", HFILL }
3652                 },
3653                 { &hf_sip_pai_user,
3654                        { "SIP PAI User Part",           "sip.pai.user",
3655                        FT_STRING, BASE_NONE,NULL,0x0,
3656                         "RFC 3325: P-Asserted-Identity User", HFILL }
3657                 },
3658                 { &hf_sip_pai_host,
3659                        { "SIP PAI Host Part",           "sip.pai.host",
3660                        FT_STRING, BASE_NONE,NULL,0x0,
3661                         "RFC 3325: P-Asserted-Identity Host", HFILL }
3662                 },
3663                 { &hf_sip_pai_port,
3664                        { "SIP PAI Host Port",           "sip.pai.port",
3665                        FT_STRING, BASE_NONE,NULL,0x0,
3666                         "RFC 3325: P-Asserted-Identity Port", HFILL }
3667                 },
3668                 { &hf_sip_pmiss_addr,
3669                        { "SIP PMISS Address",           "sip.pmiss.addr",
3670                        FT_STRING, BASE_NONE,NULL,0x0,
3671                         "RFC 3325: Permission Missing Address", HFILL }
3672                 },
3673                 { &hf_sip_pmiss_user,
3674                        { "SIP PMISS User Part",         "sip.pmiss.user",
3675                        FT_STRING, BASE_NONE,NULL,0x0,
3676                         "RFC 3325: Permission Missing User", HFILL }
3677                 },
3678                 { &hf_sip_pmiss_host,
3679                        { "SIP PMISS Host Part",         "sip.pmiss.host",
3680                        FT_STRING, BASE_NONE,NULL,0x0,
3681                         "RFC 3325: Permission Missing Host", HFILL }
3682                 },
3683                 { &hf_sip_pmiss_port,
3684                        { "SIP PMISS Host Port",         "sip.pmiss.port",
3685                        FT_STRING, BASE_NONE,NULL,0x0,
3686                         "RFC 3325: Permission Missing Port", HFILL }
3687                 },
3688
3689                 { &hf_sip_ppi_addr,
3690                        { "SIP PPI Address",             "sip.ppi.addr",
3691                        FT_STRING, BASE_NONE,NULL,0x0,
3692                         "RFC 3325: P-Preferred-Identity Address", HFILL }
3693                 },
3694                 { &hf_sip_ppi_user,
3695                        { "SIP PPI User Part",           "sip.ppi.user",
3696                        FT_STRING, BASE_NONE,NULL,0x0,
3697                         "RFC 3325: P-Preferred-Identity User", HFILL }
3698                 },
3699                 { &hf_sip_ppi_host,
3700                        { "SIP PPI Host Part",           "sip.ppi.host",
3701                        FT_STRING, BASE_NONE,NULL,0x0,
3702                         "RFC 3325: P-Preferred-Identity Host", HFILL }
3703                 },
3704                 { &hf_sip_ppi_port,
3705                        { "SIP PPI Host Port",           "sip.ppi.port",
3706                        FT_STRING, BASE_NONE,NULL,0x0,
3707                         "RFC 3325: P-Preferred-Identity Port", HFILL }
3708                 },
3709                 { &hf_sip_tc_addr,
3710                        { "SIP TC Address",              "sip.tc.addr",
3711                        FT_STRING, BASE_NONE,NULL,0x0,
3712                         "RFC 3325: Trigger Consent Address", HFILL }
3713                 },
3714                 { &hf_sip_tc_user,
3715                        { "SIP TC User Part",            "sip.tc.user",
3716                        FT_STRING, BASE_NONE,NULL,0x0,
3717                         "RFC 3325: Trigger Consent User", HFILL }
3718                 },
3719                 { &hf_sip_tc_host,
3720                        { "SIP TC Host Part",            "sip.tc.host",
3721                        FT_STRING, BASE_NONE,NULL,0x0,
3722                         "RFC 3325: Trigger Consent Host", HFILL }
3723                 },
3724                 { &hf_sip_tc_port,
3725                        { "SIP TC Host Port",            "sip.tc.port",
3726                        FT_STRING, BASE_NONE,NULL,0x0,
3727                         "RFC 3325: Trigger Consent Port", HFILL }
3728                 },
3729                 { &hf_sip_tc_turi,
3730                        { "SIP TC Target URI",           "sip.tc.target-uri",
3731                        FT_STRING, BASE_NONE,NULL,0x0,
3732                         "RFC 3325: Trigger Consent Target URI", HFILL }
3733                 },
3734                 { &hf_header_array[POS_ACCEPT],
3735                        { "Accept",              "sip.Accept",
3736                        FT_STRING, BASE_NONE,NULL,0x0,
3737                         "RFC 3261: Accept Header", HFILL }
3738                 },
3739                 { &hf_header_array[POS_ACCEPT_CONTACT],
3740                        { "Accept-Contact",              "sip.Accept-Contact",
3741                        FT_STRING, BASE_NONE,NULL,0x0,
3742                         "RFC 3841: Accept-Contact Header", HFILL }
3743                 },
3744                 { &hf_header_array[POS_ACCEPT_ENCODING],
3745                        { "Accept-Encoding",             "sip.Accept-Encoding",
3746                        FT_STRING, BASE_NONE,NULL,0x0,
3747                         "RFC 3841: Accept-Encoding Header", HFILL }
3748                 },
3749                 { &hf_header_array[POS_ACCEPT_LANGUAGE],
3750                        { "Accept-Language",             "sip.Accept-Language",
3751                        FT_STRING, BASE_NONE,NULL,0x0,
3752                         "RFC 3261: Accept-Language Header", HFILL }
3753                 },
3754                 { &hf_header_array[POS_ACCEPT_RESOURCE_PRIORITY],
3755                        { "Accept-Resource-Priority",            "sip.Accept-Resource-Priority",
3756                        FT_STRING, BASE_NONE,NULL,0x0,
3757                         "Draft: Accept-Resource-Priority Header", HFILL }
3758                 },
3759                 { &hf_header_array[POS_ALERT_INFO],
3760                        { "Alert-Info",          "sip.Alert-Info",
3761                        FT_STRING, BASE_NONE,NULL,0x0,
3762                         "RFC 3261: Alert-Info Header", HFILL }
3763                 },
3764         { &hf_header_array[POS_ALLOW],
3765                        { "Allow",               "sip.Allow",
3766                        FT_STRING, BASE_NONE,NULL,0x0,
3767                         "RFC 3261: Allow Header", HFILL }
3768                 },
3769                 { &hf_header_array[POS_ALLOW_EVENTS],
3770                        { "Allow-Events",                "sip.Allow-Events",
3771                        FT_STRING, BASE_NONE,NULL,0x0,
3772                         "RFC 3265: Allow-Events Header", HFILL }
3773                 },
3774                 { &hf_header_array[POS_ANSWER_MODE],
3775                        { "Answer-Mode",                 "sip.Answer-Mode",
3776                        FT_STRING, BASE_NONE,NULL,0x0,
3777                         "RFC 5373: Answer-Mode Header", HFILL }
3778                 },
3779                 { &hf_header_array[POS_AUTHENTICATION_INFO],
3780                        { "Authentication-Info",                 "sip.Authentication-Info",
3781                        FT_STRING, BASE_NONE,NULL,0x0,
3782                         "RFC 3261: Authentication-Info Header", HFILL }
3783                 },
3784                 { &hf_header_array[POS_AUTHORIZATION],
3785                        { "Authorization",               "sip.Authorization",
3786                        FT_STRING, BASE_NONE,NULL,0x0,
3787                         "RFC 3261: Authorization Header", HFILL }
3788                 },
3789                 { &hf_header_array[POS_CALL_ID],
3790                        { "Call-ID",             "sip.Call-ID",
3791                        FT_STRING, BASE_NONE,NULL,0x0,
3792                         "RFC 3261: Call-ID Header", HFILL }
3793                 },
3794                 { &hf_header_array[POS_CALL_INFO],
3795                        { "Call-Info",           "sip.Call-Info",
3796                        FT_STRING, BASE_NONE,NULL,0x0,
3797                         "RFC 3261: Call-Info Header", HFILL }
3798                 },
3799                 { &hf_header_array[POS_CONTACT],
3800                        { "Contact",             "sip.Contact",
3801                        FT_STRING, BASE_NONE,NULL,0x0,
3802                         "RFC 3261: Contact Header", HFILL }
3803                 },
3804                 { &hf_header_array[POS_CONTENT_DISPOSITION],
3805                        { "Content-Disposition",                 "sip.Content-Disposition",
3806                        FT_STRING, BASE_NONE,NULL,0x0,
3807                         "RFC 3261: Content-Disposition Header", HFILL }
3808                 },
3809                 { &hf_header_array[POS_CONTENT_ENCODING],
3810                        { "Content-Encoding",            "sip.Content-Encoding",
3811                        FT_STRING, BASE_NONE,NULL,0x0,
3812                         "RFC 3261: Content-Encoding Header", HFILL }
3813                 },
3814                 { &hf_header_array[POS_CONTENT_LANGUAGE],
3815                        { "Content-Language",            "sip.Content-Language",
3816                        FT_STRING, BASE_NONE,NULL,0x0,
3817                         "RFC 3261: Content-Language Header", HFILL }
3818                 },
3819                 { &hf_header_array[POS_CONTENT_LENGTH],
3820                        { "Content-Length",              "sip.Content-Length",
3821                        FT_UINT32, BASE_DEC,NULL,0x0,
3822                         "RFC 3261: Content-Length Header", HFILL }
3823                 },
3824                 { &hf_header_array[POS_CONTENT_TYPE],
3825                        { "Content-Type",                "sip.Content-Type",
3826                        FT_STRING, BASE_NONE,NULL,0x0,
3827                         "RFC 3261: Content-Type Header", HFILL }
3828                 },
3829                 { &hf_header_array[POS_CSEQ],
3830                        { "CSeq",                "sip.CSeq",
3831                        FT_STRING, BASE_NONE,NULL,0x0,
3832                         "RFC 3261: CSeq Header", HFILL }
3833                 },
3834                 { &hf_header_array[POS_DATE],
3835                        { "Date",                "sip.Date",
3836                        FT_STRING, BASE_NONE,NULL,0x0,
3837                         "RFC 3261: Date Header", HFILL }
3838                 },
3839                 { &hf_header_array[POS_ERROR_INFO],
3840                        { "Error-Info",          "sip.Error-Info",
3841                        FT_STRING, BASE_NONE,NULL,0x0,
3842                         "RFC 3261: Error-Info Header", HFILL }
3843                 },
3844                 { &hf_header_array[POS_EVENT],
3845                        { "Event",               "sip.Event",
3846                        FT_STRING, BASE_NONE,NULL,0x0,
3847                         "RFC 3265: Event Header", HFILL }
3848                 },
3849                 { &hf_header_array[POS_EXPIRES],
3850                        { "Expires",             "sip.Expires",
3851                        FT_UINT32, BASE_DEC,NULL,0x0,
3852                         "RFC 3261: Expires Header", HFILL }
3853                 },
3854                 { &hf_header_array[POS_FROM],
3855                        { "From",                "sip.From",
3856                        FT_STRING, BASE_NONE,NULL,0x0,
3857                         "RFC 3261: From Header", HFILL }
3858                 },
3859                 { &hf_header_array[POS_IN_REPLY_TO],
3860                        { "In-Reply-To",                 "sip.In-Reply-To",
3861                        FT_STRING, BASE_NONE,NULL,0x0,
3862                         "RFC 3261: In-Reply-To Header", HFILL }
3863                 },
3864                 { &hf_header_array[POS_JOIN],
3865                        { "Join",                "sip.Join",
3866                        FT_STRING, BASE_NONE,NULL,0x0,
3867                         "Draft: Join Header", HFILL }
3868                 },
3869                 { &hf_header_array[POS_MAX_BREADTH],
3870                        { "Max-Breadth",         "sip.Max-Breadth",
3871                        FT_UINT32, BASE_DEC,NULL,0x0,
3872                         "RFC 5393: Max-Breadth Header", HFILL }
3873                 },
3874                         { &hf_header_array[POS_MAX_FORWARDS],
3875                        { "Max-Forwards",                "sip.Max-Forwards",
3876                        FT_UINT32, BASE_DEC,NULL,0x0,
3877                         "RFC 3261: Max-Forwards Header", HFILL }
3878                 },
3879                 { &hf_header_array[POS_MIME_VERSION],
3880                        { "MIME-Version",                "sip.MIME-Version",
3881                        FT_STRING, BASE_NONE,NULL,0x0,
3882                         "RFC 3261: MIME-Version Header", HFILL }
3883                 },
3884                 { &hf_header_array[POS_MIN_EXPIRES],
3885                        { "Min-Expires",                 "sip.Min-Expires",
3886                        FT_STRING, BASE_NONE,NULL,0x0,
3887                         "RFC 3261: Min-Expires Header", HFILL }
3888                 },
3889                 { &hf_header_array[POS_MIN_SE],
3890                        { "Min-SE",              "sip.Min-SE",
3891                        FT_STRING, BASE_NONE,NULL,0x0,
3892                         "Draft: Min-SE Header", HFILL }
3893                 },
3894                 { &hf_header_array[POS_ORGANIZATION],
3895                        { "Organization",                "sip.Organization",
3896                        FT_STRING, BASE_NONE,NULL,0x0,
3897                         "RFC 3261: Organization Header", HFILL }
3898                 },
3899                 { &hf_header_array[POS_P_ACCESS_NETWORK_INFO],
3900                        { "P-Access-Network-Info",       "sip.P-Access-Network-Info",
3901                        FT_STRING, BASE_NONE,NULL,0x0,
3902                         "P-Access-Network-Info Header", HFILL }
3903                 },
3904                 { &hf_header_array[POS_P_ANSWER_STATE],
3905                        { "P-Answer-State",              "sip.P-Answer-State",
3906                        FT_STRING, BASE_NONE,NULL,0x0,
3907                         "RFC 4964: P-Answer-State Header", HFILL }
3908                 },
3909                 { &hf_header_array[POS_P_ASSERTED_IDENTITY],
3910                        { "P-Asserted-Identity",         "sip.P-Asserted-Identity",
3911                        FT_STRING, BASE_NONE,NULL,0x0,
3912                         "RFC 3325: P-Asserted-Identity Header", HFILL }
3913                 },
3914                 { &hf_header_array[POS_P_ASSOCIATED_URI],
3915                        { "P-Associated-URI",            "sip.P-Associated-URI",
3916                        FT_STRING, BASE_NONE,NULL,0x0,
3917                         "RFC 3455: P-Associated-URI Header", HFILL }
3918                 },
3919
3920                 { &hf_header_array[POS_P_CALLED_PARTY_ID],
3921                        { "P-Called-Party-ID",           "sip.P-Called-Party-ID",
3922                        FT_STRING, BASE_NONE,NULL,0x0,
3923                         "RFC 3455: P-Called-Party-ID Header", HFILL }
3924                 },
3925
3926                 { &hf_header_array[POS_P_CHARGING_FUNCTION_ADDRESSES],
3927                        { "P-Charging-Function-Addresses","sip.P-Charging-Function-Addresses",
3928                        FT_STRING, BASE_NONE,NULL,0x0,
3929                         NULL, HFILL }
3930                 },
3931
3932                 { &hf_header_array[POS_P_CHARGING_VECTOR],
3933                        { "P-Charging-Vector",           "sip.P-Charging-Vector",
3934                        FT_STRING, BASE_NONE,NULL,0x0,
3935                         "P-Charging-Vector Header", HFILL }
3936                 },
3937
3938                 { &hf_header_array[POS_P_DCS_TRACE_PARTY_ID],
3939                        { "P-DCS-Trace-Party-ID",        "sip.P-DCS-Trace-Party-ID",
3940                        FT_STRING, BASE_NONE,NULL,0x0,
3941                         "P-DCS-Trace-Party-ID Header", HFILL }
3942                 },
3943
3944                 { &hf_header_array[POS_P_DCS_OSPS],
3945                        { "P-DCS-OSPS",                  "sip.P-DCS-OSPS",
3946                        FT_STRING, BASE_NONE,NULL,0x0,
3947                         "P-DCS-OSPS Header", HFILL }
3948                 },
3949
3950                 { &hf_header_array[POS_P_DCS_BILLING_INFO],
3951                        { "P-DCS-Billing-Info",          "sip.P-DCS-Billing-Info",
3952                        FT_STRING, BASE_NONE,NULL,0x0,
3953                         "P-DCS-Billing-Info Header", HFILL }
3954                 },
3955
3956                 { &hf_header_array[POS_P_DCS_LAES],
3957                        { "P-DCS-LAES",                  "sip.P-DCS-LAES",
3958                        FT_STRING, BASE_NONE,NULL,0x0,
3959                         "P-DCS-LAES Header", HFILL }
3960                 },
3961
3962                 { &hf_header_array[POS_P_DCS_REDIRECT],
3963                        { "P-DCS-Redirect",              "sip.P-DCS-Redirect",
3964                        FT_STRING, BASE_NONE,NULL,0x0,
3965                         "P-DCS-Redirect Header", HFILL }
3966                 },
3967
3968                 { &hf_header_array[POS_P_EARLY_MEDIA],
3969                        { "P-Early-Media",               "sip.P-Early-Media",
3970                        FT_STRING, BASE_NONE,NULL,0x0,
3971                         "P-Early-Media Header", HFILL }
3972                 },
3973
3974                 { &hf_header_array[POS_P_MEDIA_AUTHORIZATION],
3975                        { "P-Media-Authorization",       "sip.P-Media-Authorization",
3976                        FT_STRING, BASE_NONE,NULL,0x0,
3977                            "RFC 3313: P-Media-Authorization Header", HFILL }
3978                 },
3979
3980                 { &hf_header_array[POS_P_PREFERRED_IDENTITY],
3981                        { "P-Preferred-Identity",        "sip.P-Preferred-Identity",
3982                        FT_STRING, BASE_NONE,NULL,0x0,
3983                         "RFC 3325: P-Preferred-Identity Header", HFILL }
3984                 },
3985
3986                 { &hf_header_array[POS_P_PROFILE_KEY],
3987                        { "P-Profile-Key",       "sip.P-Profile-Key",
3988                        FT_STRING, BASE_NONE,NULL,0x0,
3989                         "P-Profile-Key Header", HFILL }
3990                 },
3991                 { &hf_header_array[POS_P_REFUSED_URI_LST],
3992                        { "P-Refused-URI-List",          "sip.P-Refused-URI-List",
3993                        FT_STRING, BASE_NONE,NULL,0x0,
3994                         "P-Refused-URI-List Header", HFILL }
3995                 },
3996                 { &hf_header_array[POS_P_SERVED_USER],
3997                        { "P-Served-User",       "sip.P-Served-User",
3998                        FT_STRING, BASE_NONE,NULL,0x0,
3999                         "P-Served-User", HFILL }
4000                 },
4001                 { &hf_header_array[POS_P_USER_DATABASE],
4002                        { "P-User-Database",     "sip.P-User-Database",
4003                        FT_STRING, BASE_NONE,NULL,0x0,
4004                         "P-User-Database Header", HFILL }
4005                 },
4006
4007                 { &hf_header_array[POS_P_VISITED_NETWORK_ID],
4008                        { "P-Visited-Network-ID",        "sip.P-Visited-Network-ID",
4009                        FT_STRING, BASE_NONE,NULL,0x0,
4010                            "RFC 3455: P-Visited-Network-ID Header", HFILL }
4011                 },
4012
4013                 { &hf_header_array[POS_PATH],
4014                        { "Path",                        "sip.Path",
4015                        FT_STRING, BASE_NONE,NULL,0x0,
4016                            "RFC 3327: Path Header", HFILL }
4017                 },
4018
4019                 { &hf_header_array[POS_PERMISSION_MISSING],
4020                        { "Permission-Missing",          "sip.Permission-Missing",
4021                        FT_STRING, BASE_NONE,NULL,0x0,
4022                            "RFC 5360: Permission Missing Header", HFILL }
4023                 },
4024
4025                 { &hf_header_array[POS_PRIORITY],
4026                        { "Priority",            "sip.Priority",
4027                        FT_STRING, BASE_NONE,NULL,0x0,
4028                         "RFC 3261: Priority Header", HFILL }
4029                 },
4030                 { &hf_header_array[POS_PRIV_ANSWER_MODE],
4031                        { "Priv-Answer-mode",    "sip.Priv-Answer-mode",
4032                        FT_STRING, BASE_NONE,NULL,0x0,
4033                         NULL, HFILL }
4034                 },
4035                 { &hf_header_array[POS_PRIVACY],
4036                        { "Privacy",                     "sip.Privacy",
4037                        FT_STRING, BASE_NONE,NULL,0x0,
4038                         "Privacy Header", HFILL }
4039                 },
4040
4041                 { &hf_header_array[POS_PROXY_AUTHENTICATE],
4042                        { "Proxy-Authenticate",          "sip.Proxy-Authenticate",
4043                        FT_STRING, BASE_NONE,NULL,0x0,
4044                         "RFC 3261: Proxy-Authenticate Header", HFILL }
4045                 },
4046                 { &hf_header_array[POS_PROXY_AUTHORIZATION],
4047                        { "Proxy-Authorization",                 "sip.Proxy-Authorization",
4048                        FT_STRING, BASE_NONE,NULL,0x0,
4049                         "RFC 3261: Proxy-Authorization Header", HFILL }
4050                 },
4051
4052                 { &hf_header_array[POS_PROXY_REQUIRE],
4053                        { "Proxy-Require",               "sip.Proxy-Require",
4054                        FT_STRING, BASE_NONE,NULL,0x0,
4055                         "RFC 3261: Proxy-Require Header", HFILL }
4056                 },
4057                 { &hf_header_array[POS_RACK],
4058                        { "RAck",                "sip.RAck",
4059                        FT_STRING, BASE_NONE,NULL,0x0,
4060                         "RFC 3262: RAck Header", HFILL }
4061                 },
4062                 { &hf_header_array[POS_REASON],
4063                        { "Reason",                      "sip.Reason",
4064                        FT_STRING, BASE_NONE,NULL,0x0,
4065                         "RFC 3326 Reason Header", HFILL }
4066                 },
4067                 { &hf_header_array[POS_RECORD_ROUTE],
4068                        { "Record-Route",                "sip.Record-Route",
4069                        FT_STRING, BASE_NONE,NULL,0x0,
4070                         "RFC 3261: Record-Route Header", HFILL }
4071                 },
4072                 { &hf_header_array[POS_REFER_SUB],
4073                        { "Refer-Sub",           "sip.Refer-Sub",
4074                        FT_STRING, BASE_NONE,NULL,0x0,
4075                         "RFC 4488: Refer-Sub Header", HFILL }
4076                 },
4077                 { &hf_header_array[POS_REFERED_BY],
4078                        { "Refered By",          "sip.Refered-by",
4079                        FT_STRING, BASE_NONE,NULL,0x0,
4080                         "RFC 3892: Refered-by Header", HFILL }
4081                 },
4082                 { &hf_header_array[POS_REJECT_CONTACT],
4083                         { "Reject-Contact",             "sip.Reject-Contact",
4084                         FT_STRING, BASE_NONE,NULL,0x0,
4085                         "RFC 3841: Reject-Contact Header", HFILL }
4086                 },
4087                 { &hf_header_array[POS_REPLACES],
4088                         { "Replaces",           "sip.Replaces",
4089                         FT_STRING, BASE_NONE,NULL,0x0,
4090                         "RFC 3891: Replaces Header", HFILL }
4091                 },
4092                 { &hf_header_array[POS_REPLY_TO],
4093                        { "Reply-To",            "sip.Reply-To",
4094                        FT_STRING, BASE_NONE,NULL,0x0,
4095                         "RFC 3261: Reply-To Header", HFILL }
4096                 },
4097                 { &hf_header_array[POS_REQUEST_DISPOSITION],
4098                        { "Request-Disposition",         "sip.Request-Disposition",
4099                        FT_STRING, BASE_NONE,NULL,0x0,
4100                         "RFC 3841: Request-Disposition Header", HFILL }
4101                 },
4102                 { &hf_header_array[POS_REQUIRE],
4103                         { "Require",            "sip.Require",
4104                        FT_STRING, BASE_NONE,NULL,0x0,
4105                         "RFC 3261: Require Header", HFILL }
4106                 },
4107                 { &hf_header_array[POS_RESOURCE_PRIORITY],
4108                         { "Resource-Priority",          "sip.Resource-Priority",
4109                        FT_STRING, BASE_NONE,NULL,0x0,
4110                         "Draft: Resource-Priority Header", HFILL }
4111                 },
4112                 { &hf_header_array[POS_RETRY_AFTER],
4113                         { "Retry-After",                "sip.Retry-After",
4114                        FT_STRING, BASE_NONE,NULL,0x0,
4115                         "RFC 3261: Retry-After Header", HFILL }
4116                 },
4117                 { &hf_header_array[POS_ROUTE],
4118                        { "Route",               "sip.Route",
4119                        FT_STRING, BASE_NONE,NULL,0x0,
4120                         "RFC 3261: Route Header", HFILL }
4121                 },
4122                 { &hf_header_array[POS_RSEQ],
4123                        { "RSeq",                "sip.RSeq",
4124                        FT_UINT32, BASE_DEC,NULL,0x0,
4125                         "RFC 3262: RSeq Header", HFILL }
4126                 },
4127                 { &hf_header_array[ POS_SECURITY_CLIENT],
4128                        { "Security-Client",             "sip.Security-Client",
4129                        FT_STRING, BASE_NONE,NULL,0x0,
4130                         "RFC 3329 Security-Client Header", HFILL }
4131                 },
4132                 { &hf_header_array[ POS_SECURITY_SERVER],
4133                        { "Security-Server",             "sip.Security-Server",
4134                        FT_STRING, BASE_NONE,NULL,0x0,
4135                         "RFC 3329 Security-Server Header", HFILL }
4136                 },
4137                 { &hf_header_array[ POS_SECURITY_VERIFY],
4138                        { "Security-Verify",             "sip.Security-Verify",
4139                        FT_STRING, BASE_NONE,NULL,0x0,
4140                         "RFC 3329 Security-Verify Header", HFILL }
4141                 },
4142                 { &hf_header_array[POS_SERVER],
4143                         { "Server",             "sip.Server",
4144                        FT_STRING, BASE_NONE,NULL,0x0,
4145                         "RFC 3261: Server Header", HFILL }
4146                 },
4147                 { &hf_header_array[POS_SERVICE_ROUTE],
4148                        { "Service-Route",               "sip.Service-Route",
4149                        FT_STRING, BASE_NONE,NULL,0x0,
4150                         "RFC 3608: Service-Route Header", HFILL }
4151                 },
4152                 { &hf_header_array[POS_SESSION_EXPIRES],
4153                        { "Session-Expires",             "sip.Session-Expires",
4154                        FT_STRING, BASE_NONE,NULL,0x0,
4155                            "RFC 4028: Session-Expires Header", HFILL }
4156                 },
4157                 { &hf_header_array[POS_SIP_ETAG],
4158                        { "ETag",                "sip.ETag",
4159                        FT_STRING, BASE_NONE,NULL,0x0,
4160                            "RFC 3903: SIP-ETag Header", HFILL }
4161                 },
4162                 { &hf_header_array[POS_SIP_IF_MATCH],
4163                        { "If_Match",            "sip.If_Match",
4164                        FT_STRING, BASE_NONE,NULL,0x0,
4165                         "RFC 3903: SIP-If-Match Header", HFILL }
4166                 },
4167                 { &hf_header_array[POS_SUBJECT],
4168                        { "Subject",             "sip.Subject",
4169                        FT_STRING, BASE_NONE,NULL,0x0,
4170                         "RFC 3261: Subject Header", HFILL }
4171                 },
4172                 { &hf_header_array[POS_SUBSCRIPTION_STATE],
4173                        { "Subscription-State",          "sip.Subscription-State",
4174                        FT_STRING, BASE_NONE,NULL,0x0,
4175                         "RFC 3265: Subscription-State Header", HFILL }
4176                 },
4177                 { &hf_header_array[POS_SUPPORTED],
4178                         { "Supported",          "sip.Supported",
4179                        FT_STRING, BASE_NONE,NULL,0x0,
4180                         "RFC 3261: Supported Header", HFILL }
4181                 },
4182                 { &hf_header_array[POS_TARGET_DALOG],
4183                         { "Target-Dialog",              "sip.Target-Dialog",
4184                        FT_STRING, BASE_NONE,NULL,0x0,
4185                         "RFC 4538: Target-Dialog Header", HFILL }
4186                 },
4187                 { &hf_header_array[POS_TIMESTAMP],
4188                         { "Timestamp",          "sip.Timestamp",
4189                        FT_STRING, BASE_NONE,NULL,0x0,
4190                         "RFC 3261: Timestamp Header", HFILL }
4191                 },
4192                 { &hf_header_array[POS_TO],
4193                         { "To",                 "sip.To",
4194                        FT_STRING, BASE_NONE,NULL,0x0,
4195                         "RFC 3261: To Header", HFILL }
4196                 },
4197
4198                 { &hf_header_array[POS_TRIGGER_CONSENT],
4199                         { "Trigger-Consent",            "sip.Trigger-Consent",
4200                        FT_STRING, BASE_NONE,NULL,0x0,
4201                         "RFC 5380: Trigger Consent", HFILL }
4202                 },
4203
4204                 { &hf_header_array[POS_UNSUPPORTED],
4205                         { "Unsupported",                "sip.Unsupported",
4206                        FT_STRING, BASE_NONE,NULL,0x0,
4207                         "RFC 3261: Unsupported Header", HFILL }
4208                 },
4209                 { &hf_header_array[POS_USER_AGENT],
4210                         { "User-Agent",                 "sip.User-Agent",
4211                        FT_STRING, BASE_NONE,NULL,0x0,
4212                         "RFC 3261: User-Agent Header", HFILL }
4213                 },
4214                 { &hf_header_array[POS_VIA],
4215                         { "Via",                "sip.Via",
4216                        FT_STRING, BASE_NONE,NULL,0x0,
4217                         "RFC 3261: Via Header", HFILL }
4218                 },
4219                 { &hf_header_array[POS_WARNING],
4220                         { "Warning",            "sip.Warning",
4221                        FT_STRING, BASE_NONE,NULL,0x0,
4222                         "RFC 3261: Warning Header", HFILL }
4223                 },
4224
4225                 { &hf_header_array[POS_WWW_AUTHENTICATE],
4226                         { "WWW-Authenticate",           "sip.WWW-Authenticate",
4227                        FT_STRING, BASE_NONE,NULL,0x0,
4228                         "RFC 3261: WWW-Authenticate Header", HFILL }
4229                 },
4230                 { &hf_header_array[POS_REFER_TO],
4231                         { "Refer-To",                   "sip.Refer-To",
4232                        FT_STRING, BASE_NONE,NULL,0x0,
4233                         "RFC 3515: Refer-To Header", HFILL }
4234                 },
4235                 { &hf_header_array[POS_HISTORY_INFO],
4236                         { "History-Info",                       "sip.History-Info",
4237                        FT_STRING, BASE_NONE,NULL,0x0,
4238                         "RFC 4244: Request History Information", HFILL }
4239                 },
4240                 { &hf_header_array[POS_IDENTITY],
4241                         { "Identity",                   "sip.Identity",
4242                        FT_STRING, BASE_NONE,NULL,0x0,
4243                         "RFC 4474: Request Identity", HFILL }
4244                 },
4245                 { &hf_header_array[POS_IDENTITY_INFO],
4246                         { "Identity-info",                      "sip.Identity-info",
4247                        FT_STRING, BASE_NONE,NULL,0x0,
4248                         "RFC 4474: Request Identity-info", HFILL }
4249                 },
4250
4251                 { &hf_sip_resend,
4252                         { "Resent Packet", "sip.resend",
4253                         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4254                         NULL, HFILL }
4255                 },
4256                 { &hf_sip_original_frame,
4257                         { "Suspected resend of frame",  "sip.resend-original",
4258                         FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4259                         "Original transmission of frame", HFILL}
4260                 },
4261                 { &hf_sip_matching_request_frame,
4262                         { "Request Frame",  "sip.response-request",
4263                         FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4264                         NULL, HFILL}
4265                 },
4266                 { &hf_sip_response_time,
4267                         { "Response Time (ms)",  "sip.response-time",
4268                         FT_UINT32, BASE_DEC, NULL, 0x0,
4269                         "Response time since original request (in milliseconds)", HFILL}
4270                 },
4271                 { &hf_sip_release_time,
4272                         { "Release Time (ms)",  "sip.release-time",
4273                         FT_UINT32, BASE_DEC, NULL, 0x0,
4274                         "release time since original BYE (in milliseconds)", HFILL}
4275                 },
4276                 { &hf_sip_auth,
4277                         { "Authentication",  "sip.auth",
4278                         FT_STRING, BASE_NONE, NULL, 0x0,
4279                         "SIP Authentication", HFILL}
4280                 },
4281                 { &hf_sip_auth_scheme,
4282                         { "Authentication Scheme",  "sip.auth.scheme",
4283                         FT_STRING, BASE_NONE, NULL, 0x0,
4284                         "SIP Authentication Scheme", HFILL}
4285                 },
4286                 { &hf_sip_auth_digest_response,
4287                         { "Digest Authentication Response",  "sip.auth.digest.response",
4288                         FT_STRING, BASE_NONE, NULL, 0x0,
4289                         "SIP Digest Authentication Response Value", HFILL}
4290                 },
4291                 { &hf_sip_auth_nc,
4292                         { "Nonce Count",  "sip.auth.nc",
4293                         FT_STRING, BASE_NONE, NULL, 0x0,
4294                         "SIP Authentication Nonce count", HFILL}
4295                 },
4296                 { &hf_sip_auth_username,
4297                         { "Username",  "sip.auth.username",
4298                         FT_STRING, BASE_NONE, NULL, 0x0,
4299                         "SIP Authentication Username", HFILL}
4300                 },
4301                 { &hf_sip_auth_realm,
4302                         { "Realm",  "sip.auth.realm",
4303                         FT_STRING, BASE_NONE, NULL, 0x0,
4304                         "SIP Authentication Realm", HFILL}
4305                 },
4306                 { &hf_sip_auth_nonce,
4307                         { "Nonce Value",  "sip.auth.nonce",
4308                         FT_STRING, BASE_NONE, NULL, 0x0,
4309                         "SIP Authentication Nonce", HFILL}
4310                 },
4311                 { &hf_sip_auth_algorithm,
4312                         { "Algorithm",  "sip.auth.algorithm",
4313                         FT_STRING, BASE_NONE, NULL, 0x0,
4314                         "SIP Authentication Algorithm", HFILL}
4315                 },
4316                 { &hf_sip_auth_opaque,
4317                         { "Opaque Value",  "sip.auth.opaque",
4318                         FT_STRING, BASE_NONE, NULL, 0x0,
4319                         "SIP Authentication Opaque value", HFILL}
4320                 },
4321                 { &hf_sip_auth_qop,
4322                         { "QOP",  "sip.auth.qop",
4323                         FT_STRING, BASE_NONE, NULL, 0x0,
4324                         "SIP Authentication QOP", HFILL}
4325                 },
4326                 { &hf_sip_auth_cnonce,
4327                         { "CNonce Value",  "sip.auth.cnonce",
4328                         FT_STRING, BASE_NONE, NULL, 0x0,
4329                         "SIP Authentication Client Nonce", HFILL}
4330                 },
4331                 { &hf_sip_auth_uri,
4332                         { "Authentication URI",  "sip.auth.uri",
4333                         FT_STRING, BASE_NONE, NULL, 0x0,
4334                         "SIP Authentication URI", HFILL}
4335                 },
4336                 { &hf_sip_auth_domain,
4337                         { "Authentication Domain",  "sip.auth.domain",
4338                         FT_STRING, BASE_NONE, NULL, 0x0,
4339                         "SIP Authentication Domain", HFILL}
4340                 },
4341                 { &hf_sip_auth_stale,
4342                         { "Stale Flag",  "sip.auth.stale",
4343                         FT_STRING, BASE_NONE, NULL, 0x0,
4344                         "SIP Authentication Stale Flag", HFILL}
4345                 },
4346                 { &hf_sip_auth_auts,
4347                         { "Authentication Token",  "sip.auth.auts",
4348                         FT_STRING, BASE_NONE, NULL, 0x0,
4349                         "SIP Authentication Token", HFILL}
4350                 },
4351                 { &hf_sip_auth_rspauth,
4352                         { "Response auth",  "sip.auth.rspauth",
4353                         FT_STRING, BASE_NONE, NULL, 0x0,
4354                         "SIP Authentication Response auth", HFILL}
4355                 },
4356                 { &hf_sip_auth_nextnonce,
4357                         { "Next Nonce",  "sip.auth.nextnonce",
4358                         FT_STRING, BASE_NONE, NULL, 0x0,
4359                         "SIP Authentication Next Nonce", HFILL}
4360                 },
4361                 { &hf_sip_auth_ik,
4362                         { "Integrity Key",  "sip.auth.ik",
4363                         FT_STRING, BASE_NONE, NULL, 0x0,
4364                         "SIP Authentication Integrity Key", HFILL}
4365                 },
4366                 { &hf_sip_auth_ck,
4367                         { "Cyphering Key",  "sip.auth.ck",
4368                         FT_STRING, BASE_NONE, NULL, 0x0,
4369                         "SIP Authentication Cyphering Key", HFILL}
4370                 },
4371                 { &hf_sip_cseq_seq_no,
4372                         { "Sequence Number",  "sip.CSeq.seq",
4373                         FT_UINT32, BASE_DEC, NULL, 0x0,
4374                         "CSeq header sequence number", HFILL}
4375                 },
4376                 { &hf_sip_cseq_method,
4377                         { "Method",  "sip.CSeq.method",
4378                         FT_STRING, BASE_NONE, NULL, 0x0,
4379                         "CSeq header method", HFILL}
4380                 },
4381                 { &hf_sip_via_transport,
4382                         { "Transport",  "sip.Via.transport",
4383                         FT_STRING, BASE_NONE, NULL, 0x0,
4384                         "Via header Transport", HFILL}
4385                 },
4386                 { &hf_sip_via_sent_by_address,
4387                         { "Sent-by Address",  "sip.Via.sent-by.address",
4388                         FT_STRING, BASE_NONE, NULL, 0x0,
4389                         "Via header Sent-by Address", HFILL}
4390                 },
4391                 { &hf_sip_via_sent_by_port,
4392                         { "Sent-by port",  "sip.Via.sent-by.port",
4393                         FT_UINT16, BASE_DEC, NULL, 0x0,
4394                         "Via header Sent-by Port", HFILL}
4395                 },
4396                 { &hf_sip_via_branch,
4397                         { "Branch",  "sip.Via.branch",
4398                         FT_STRING, BASE_NONE, NULL, 0x0,
4399                         "SIP Via Branch", HFILL},
4400                 },
4401                 { &hf_sip_via_maddr,
4402                         { "Maddr",  "sip.Via.maddr",
4403                         FT_STRING, BASE_NONE, NULL, 0x0,
4404                         "SIP Via Maddr", HFILL},
4405                 },
4406                 { &hf_sip_via_rport,
4407                         { "RPort",  "sip.Via.rport",
4408                         FT_STRING, BASE_NONE, NULL, 0x0,
4409                         "SIP Via RPort", HFILL},
4410                 },
4411                 { &hf_sip_via_received,
4412                         { "Received",  "sip.Via.received",
4413                         FT_STRING, BASE_NONE, NULL, 0x0,
4414                         "SIP Via Received", HFILL},
4415                 },
4416                 { &hf_sip_via_ttl,
4417                         { "TTL",  "sip.Via.ttl",
4418                         FT_STRING, BASE_NONE, NULL, 0x0,
4419                         "SIP Via TTL", HFILL}
4420                 },
4421                 { &hf_sip_via_comp,
4422                         { "Comp",  "sip.Via.comp",
4423                         FT_STRING, BASE_NONE, NULL, 0x0,
4424                         "SIP Via comp", HFILL}
4425                 },
4426                 { &hf_sip_via_sigcomp_id,
4427                         { "Sigcomp identifier",  "sip.Via.sigcomp-id",
4428                         FT_STRING, BASE_NONE, NULL, 0x0,
4429                         "SIP Via sigcomp identifier", HFILL}
4430                 },
4431                 { &hf_sip_rack_rseq_no,
4432                         { "RSeq Sequence Number",  "sip.RAck.RSeq.seq",
4433                         FT_UINT32, BASE_DEC, NULL, 0x0,
4434                         "RAck RSeq header sequence number (from prov response)", HFILL}
4435                 },
4436                 { &hf_sip_rack_cseq_no,
4437                         { "CSeq Sequence Number",  "sip.RAck.CSeq.seq",
4438                         FT_UINT32, BASE_DEC, NULL, 0x0,
4439                         "RAck CSeq header sequence number (from prov response)", HFILL}
4440                 },
4441                 { &hf_sip_rack_cseq_method,
4442                         { "CSeq Method",  "sip.RAck.CSeq.method",
4443                         FT_STRING, BASE_NONE, NULL, 0x0,
4444                         "RAck CSeq header method (from prov response)", HFILL}
4445                 },
4446                 { &hf_sip_msg_body,
4447                                 { "Message Body",           "sip.msg_body",
4448                                 FT_NONE, BASE_NONE, NULL, 0x0,
4449                                 "Message Body in SIP message", HFILL }
4450                 }};
4451
4452         /* raw_sip header field(s) */
4453         static hf_register_info raw_hf[] = {
4454
4455                 { &hf_raw_sip_line,
4456                                 { "Raw SIP Line",                "raw_sip.line",
4457                                         FT_STRING, BASE_NONE,NULL,0x0,
4458                                 NULL, HFILL }
4459         }};
4460
4461         /* Setup protocol subtree array */
4462         static gint *ett[] = {
4463                 &ett_sip,
4464                 &ett_sip_reqresp,
4465                 &ett_sip_hdr,
4466                 &ett_sip_ext_hdr,
4467                 &ett_sip_element,
4468                 &ett_sip_uri,
4469                 &ett_sip_contact_item,
4470                 &ett_sip_message_body,
4471                 &ett_sip_cseq,
4472                 &ett_sip_via,
4473                 &ett_sip_reason,
4474                 &ett_sip_rack,
4475                 &ett_sip_ruri,
4476                 &ett_sip_pai_uri,
4477                 &ett_sip_pmiss_uri,
4478                 &ett_sip_ppi_uri,
4479                 &ett_sip_tc_uri,
4480                 &ett_sip_to_uri,
4481                 &ett_sip_from_uri,
4482                 &ett_sip_curi
4483         };
4484         static gint *ett_raw[] = {
4485                 &ett_raw_text,
4486         };
4487
4488         module_t *sip_module;
4489
4490         /* Register the protocol name and description */
4491         proto_sip = proto_register_protocol("Session Initiation Protocol",
4492                                             "SIP", "sip");
4493         proto_raw_sip = proto_register_protocol("Session Initiation Protocol (SIP as raw text)",
4494                                                 "Raw_SIP", "raw_sip");
4495         new_register_dissector("sip", dissect_sip, proto_sip);
4496         register_dissector("sip.tcp", dissect_sip_tcp, proto_sip);
4497
4498         /* Required function calls to register the header fields and subtrees used */
4499         proto_register_field_array(proto_sip, hf, array_length(hf));
4500         proto_register_subtree_array(ett, array_length(ett));
4501         proto_register_subtree_array(ett_raw, array_length(ett_raw));
4502
4503         /* Register raw_sip field(s) */
4504         proto_register_field_array(proto_raw_sip, raw_hf, array_length(raw_hf));
4505
4506         sip_module = prefs_register_protocol(proto_sip, proto_reg_handoff_sip);
4507
4508         prefs_register_uint_preference(sip_module, "tcp.port",
4509                                  "SIP TCP Port",
4510                                  "SIP Server TCP Port",
4511                                  10, &sip_tcp_port);
4512         prefs_register_uint_preference(sip_module, "tls.port",
4513                                  "SIP TLS Port",
4514                                  "SIP Server TLS Port",
4515                                  10, &sip_tls_port);
4516
4517         prefs_register_bool_preference(sip_module, "display_raw_text",
4518                 "Display raw text for SIP message",
4519                 "Specifies that the raw text of the "
4520                 "SIP message should be displayed "
4521                 "in addition to the dissection tree",
4522                 &global_sip_raw_text);
4523         prefs_register_bool_preference(sip_module, "strict_sip_version",
4524                 "Enforce strict SIP version check (" SIP2_HDR ")",
4525                 "If enabled, only " SIP2_HDR " traffic will be dissected as SIP. "
4526                 "Disable it to allow SIP traffic with a different version "
4527                 "to be dissected as SIP.",
4528                 &strict_sip_version);
4529         prefs_register_bool_preference(sip_module, "desegment_headers",
4530             "Reassemble SIP headers spanning multiple TCP segments",
4531             "Whether the SIP dissector should reassemble headers "
4532             "of a request spanning multiple TCP segments. "
4533                 "To use this option, you must also enable "
4534         "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
4535             &sip_desegment_headers);
4536         prefs_register_bool_preference(sip_module, "desegment_body",
4537             "Reassemble SIP bodies spanning multiple TCP segments",
4538             "Whether the SIP dissector should use the "
4539             "\"Content-length:\" value, if present, to reassemble "
4540             "the body of a request spanning multiple TCP segments, "
4541             "and reassemble chunked data spanning multiple TCP segments. "
4542                 "To use this option, you must also enable "
4543         "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
4544             &sip_desegment_body);
4545         prefs_register_bool_preference(sip_module, "retrans_the_same_sport",
4546             "Retransmissions always use the same source port",
4547             "Whether retransmissions are detected coming from the same source port only.",
4548             &sip_retrans_the_same_sport);
4549
4550         register_init_routine(&sip_init_protocol);
4551         register_heur_dissector_list("sip", &heur_subdissector_list);
4552         /* Register for tapping */
4553         sip_tap = register_tap("sip");
4554
4555         ext_hdr_subdissector_table = register_dissector_table("sip.hdr", "SIP Extension header", FT_STRING, BASE_NONE);
4556
4557 }
4558
4559 void
4560 proto_reg_handoff_sip(void)
4561 {
4562         static dissector_handle_t sip_tcp_handle;
4563         static guint saved_sip_tcp_port;
4564         static guint saved_sip_tls_port;
4565         static gboolean sip_prefs_initialized = FALSE;
4566
4567         if (!sip_prefs_initialized) {
4568                 dissector_handle_t sip_handle;
4569                 sip_handle = find_dissector("sip");
4570                 sip_tcp_handle = find_dissector("sip.tcp");
4571                 sigcomp_handle = find_dissector("sigcomp");
4572                 /* SIP content type and internet media type used by other dissectors are the same */
4573                 media_type_dissector_table = find_dissector_table("media_type");
4574
4575                 dissector_add("udp.port", UDP_PORT_SIP, sip_handle);
4576                 dissector_add_string("media_type", "message/sip", sip_handle);
4577
4578                 heur_dissector_add("udp", dissect_sip_heur, proto_sip);
4579                 heur_dissector_add("tcp", dissect_sip_tcp_heur, proto_sip);
4580                 heur_dissector_add("sctp", dissect_sip_heur, proto_sip);
4581                 heur_dissector_add("stun", dissect_sip_heur, proto_sip);
4582                 sip_prefs_initialized = TRUE;
4583         } else {
4584                 dissector_delete("tcp.port", saved_sip_tcp_port, sip_tcp_handle);
4585                 ssl_dissector_delete(saved_sip_tls_port, "sip.tcp", TRUE);
4586         }
4587         /* Set our port number for future use */
4588         saved_sip_tcp_port = sip_tcp_port;
4589         saved_sip_tls_port = sip_tls_port;
4590         dissector_add("tcp.port", saved_sip_tcp_port, sip_tcp_handle);
4591         ssl_dissector_add(saved_sip_tls_port, "sip.tcp", TRUE);
4592
4593 }