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