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