Rewrote to use g_strlcpy and g_strlcat.
[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 #if GLIB_MAJOR_VERSION < 2
2182                                                 media_type_str_lower_case = ep_strdup(media_type_str);
2183                                                 g_strdown(media_type_str_lower_case);
2184 #else
2185                                                 media_type_str_lower_case = g_ascii_strdown(media_type_str, -1);
2186 #endif
2187                                                 /* Debug code
2188                                                 proto_tree_add_text(hdr_tree, tvb, value_offset,content_type_len,"media_type_str=%s",media_type_str);
2189                                                 */
2190                                         break;
2191
2192                                         case POS_CONTENT_LENGTH :
2193                                                 content_length = atoi(value);
2194                                                 if(hdr_tree) {
2195                                                         proto_tree_add_uint(hdr_tree,
2196                                                                             hf_header_array[hf_index], tvb,
2197                                                                             offset, next_offset - offset,
2198                                                                             content_length);
2199                                                 }
2200                                                 break;
2201
2202                                         case POS_MAX_FORWARDS :
2203                                         case POS_RSEQ :
2204                                                 if(hdr_tree) {
2205                                                         proto_tree_add_uint(hdr_tree,
2206                                                                             hf_header_array[hf_index], tvb,
2207                                                                             offset, next_offset - offset,
2208                                                                             atoi(value));
2209                                                 }
2210                                                 break;
2211
2212                                         case POS_CONTACT :
2213                                                 if(hdr_tree) {
2214                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2215                                                                            hf_header_array[hf_index], tvb,
2216                                                                            offset, next_offset - offset,
2217                                                                            value, "%s",
2218                                                                            tvb_format_text(tvb, offset, linelen));
2219                                                         sip_element_tree = proto_item_add_subtree( sip_element_item,
2220                                                                            ett_sip_element);
2221                                                 }
2222                                                 if (strcmp(value, "*") == 0)
2223                                                 {
2224                                                         contact_is_star = 1;
2225                                                         break;
2226                                                 }
2227
2228                                                 comma_offset = value_offset;
2229                                                 while((comma_offset = dissect_sip_contact_item(tvb, pinfo, sip_element_tree, comma_offset, next_offset)) != -1)
2230                                                 {
2231                                                         contacts++;
2232                                                         if(comma_offset == next_offset)
2233                                                         {
2234                                                                 /* Line End reached: Stop Parsing */
2235                                                                 break;
2236                                                         }
2237
2238                                                         if(tvb_get_guint8(tvb, comma_offset) != ',')
2239                                                         {
2240                                                                 /* Undefined value reached: Stop Parsing */
2241                                                                 break;
2242                                                         }
2243                                                         comma_offset++; /* skip comma */
2244                                                 }
2245                                         break;
2246
2247                                         case POS_AUTHORIZATION:
2248                                         case POS_WWW_AUTHENTICATE:
2249                                         case POS_PROXY_AUTHENTICATE:
2250                                         case POS_PROXY_AUTHORIZATION:
2251                                         case POS_AUTHENTICATION_INFO:
2252                                                 /* Add tree using whole text of line */
2253                                                 if (hdr_tree) {
2254                                                         proto_item *ti;
2255                                                         /* Add whole line as header tree */
2256                                                         sip_element_item = proto_tree_add_string_format(hdr_tree,
2257                                                                            hf_header_array[hf_index], tvb,
2258                                                                            offset, next_offset - offset,
2259                                                                            value, "%s",
2260                                                                            tvb_format_text(tvb, offset, linelen));
2261                                                         sip_element_tree = proto_item_add_subtree( sip_element_item,
2262                                                                            ett_sip_element);
2263
2264                                                         /* Set sip.auth as a hidden field/filter */
2265                                                         ti = proto_tree_add_item(hdr_tree, hf_sip_auth, tvb,
2266                                                                                  offset, next_offset-offset,
2267                                                                                  FALSE);
2268                                                         PROTO_ITEM_SET_HIDDEN(ti);
2269                                                 }
2270
2271                                                 /* Parse each individual parameter in the line */
2272                                                 comma_offset = tvb_pbrk_guint8(tvb, value_offset, line_end_offset - value_offset, " \t\r\n");
2273
2274                                                 /* Authentication-Info does not begin with the scheme name */
2275                                                 if (hf_index != POS_AUTHENTICATION_INFO)
2276                                                 {
2277                                                         proto_tree_add_item(sip_element_tree, hf_sip_auth_scheme,
2278                                                                             tvb, value_offset, comma_offset - value_offset,
2279                                                                             FALSE);
2280                                                 }
2281
2282                                                 while ((comma_offset = dissect_sip_authorization_item(tvb, sip_element_tree, comma_offset, line_end_offset)) != -1)
2283                                                 {
2284                                                         if(comma_offset == line_end_offset)
2285                                                         {
2286                                                                 /* Line End reached: Stop Parsing */
2287                                                                 break;
2288                                                         }
2289
2290                                                         if(tvb_get_guint8(tvb, comma_offset) != ',')
2291                                                         {
2292                                                                 /* Undefined value reached: Stop Parsing */
2293                                                                 break;
2294                                                         }
2295                                                         comma_offset++; /* skip comma */
2296                                                 }
2297                                         break;
2298
2299                                         case POS_VIA:
2300                                                 /* Add Via subtree */
2301                                                 if (hdr_tree) {
2302                                                         ti = proto_tree_add_string_format(hdr_tree,
2303                                                                                      hf_header_array[hf_index], tvb,
2304                                                                                      offset, next_offset - offset,
2305                                                                                      value, "%s",
2306                                                                                      tvb_format_text(tvb, offset, linelen));
2307                                                         via_tree = proto_item_add_subtree(ti, ett_sip_via);
2308                                                 }
2309                                                 dissect_sip_via_header(tvb, via_tree, value_offset, line_end_offset);
2310                                                 break;
2311                                         case POS_REASON:
2312                                                 if(hdr_tree) {
2313                                                         ti = proto_tree_add_string_format(hdr_tree,
2314                                                                                      hf_header_array[hf_index], tvb,
2315                                                                                      offset, next_offset - offset,
2316                                                                                      value, "%s",
2317                                                                                      tvb_format_text(tvb, offset, linelen));
2318                                                         reason_tree = proto_item_add_subtree(ti, ett_sip_reason);
2319                                                 }
2320                                                 dissect_sip_reason_header(tvb, reason_tree, value_offset, line_end_offset);
2321                                                 break;
2322                                         default :
2323                                                 /* Default case is to assume its an FT_STRING field */
2324                                                 if(hdr_tree) {
2325                                                         proto_tree_add_string_format(hdr_tree,
2326                                                                                      hf_header_array[hf_index], tvb,
2327                                                                                      offset, next_offset - offset,
2328                                                                                      value, "%s",
2329                                                                                      tvb_format_text(tvb, offset, linelen));
2330                                                 }
2331                                         break;
2332                                 }/* end switch */
2333                         }/*if HF_index */
2334                 }/* if colon_offset */
2335                 offset = next_offset;
2336         }/* End while */
2337
2338         datalen = tvb_length_remaining(tvb, offset);
2339         reported_datalen = tvb_reported_length_remaining(tvb, offset);
2340         if (content_length != -1) {
2341                 if (datalen > content_length)
2342                         datalen = content_length;
2343                 if (reported_datalen > content_length)
2344                         reported_datalen = content_length;
2345         }
2346
2347         if (datalen > 0) {
2348                 /*
2349                  * There's a message body starting at "offset".
2350                  * Set the length of the header item.
2351                  */
2352                 proto_item_set_end(th, tvb, offset);
2353                 next_tvb = tvb_new_subset(tvb, offset, datalen, reported_datalen);
2354                 if(sip_tree) {
2355                         ti = proto_tree_add_item(sip_tree, hf_sip_msg_body, next_tvb, 0, -1,
2356                                                  FALSE);
2357                         message_body_tree = proto_item_add_subtree(ti, ett_sip_message_body);
2358                 }
2359
2360                 /* give the content type parameters to sub dissectors */
2361
2362                 if ( media_type_str_lower_case != NULL ) {
2363                         void *save_private_data = pinfo->private_data;
2364                         pinfo->private_data = content_type_parameter_str;
2365                         found_match = dissector_try_string(media_type_dissector_table,
2366                                                            media_type_str_lower_case,
2367                                                            next_tvb, pinfo,
2368                                                            message_body_tree);
2369                         pinfo->private_data = save_private_data;
2370                         /* If no match dump as text */
2371                 }
2372                 if ( found_match != TRUE )
2373                 {
2374             if (!(dissector_try_heuristic(heur_subdissector_list,
2375                                           next_tvb, pinfo, message_body_tree))) {
2376                 int tmp_offset = 0;
2377                 while (tvb_offset_exists(next_tvb, tmp_offset)) {
2378                     tvb_find_line_end(next_tvb, tmp_offset, -1, &next_offset, FALSE);
2379                     linelen = next_offset - tmp_offset;
2380                     if(message_body_tree) {
2381                         proto_tree_add_text(message_body_tree, next_tvb,
2382                                             tmp_offset, linelen, "%s",
2383                                             tvb_format_text(next_tvb, tmp_offset, linelen));
2384                         }
2385                     tmp_offset = next_offset;
2386                     }/* end while */
2387                         }
2388                 }
2389                 offset += datalen;
2390         }
2391
2392
2393         /* Add to info column interesting things learned from header fields. */
2394         if (check_col(pinfo->cinfo, COL_INFO))
2395         {
2396                 /* Registration requests */
2397                 if (strcmp(sip_methods[current_method_idx], "REGISTER") == 0)
2398                 {
2399                         if (contact_is_star && expires_is_0)
2400                         {
2401                                 col_append_str(pinfo->cinfo, COL_INFO, "    (remove all bindings)");
2402                         }
2403                         else
2404                         if (!contacts)
2405                         {
2406                                 col_append_str(pinfo->cinfo, COL_INFO, "    (fetch bindings)");
2407                         }
2408                 }
2409
2410                 /* Registration responses */
2411                 if (line_type == STATUS_LINE && (strcmp(cseq_method, "REGISTER") == 0))
2412                 {
2413                         col_append_fstr(pinfo->cinfo, COL_INFO, "    (%d bindings)", contacts);
2414                 }
2415         }
2416
2417         /* Check if this packet is a resend. */
2418         resend_for_packet = sip_is_packet_resend(pinfo, cseq_method, call_id,
2419                                                  cseq_number_set, cseq_number,
2420                                                  line_type);
2421         /* Mark whether this is a resend for the tap */
2422         stat_info->resend = (resend_for_packet > 0);
2423
2424         /* And add the filterable field to the request/response line */
2425         if (reqresp_tree)
2426         {
2427                 proto_item *item;
2428                 item = proto_tree_add_boolean(reqresp_tree, hf_sip_resend, tvb, orig_offset, 0,
2429                                               resend_for_packet > 0);
2430                 PROTO_ITEM_SET_GENERATED(item);
2431                 if (resend_for_packet > 0)
2432                 {
2433                         item = proto_tree_add_uint(reqresp_tree, hf_sip_original_frame,
2434                                                    tvb, orig_offset, 0, resend_for_packet);
2435                         PROTO_ITEM_SET_GENERATED(item);
2436                 }
2437         }
2438
2439
2440         if (ts != NULL)
2441                 proto_item_set_len(ts, offset - orig_offset);
2442
2443         if (global_sip_raw_text)
2444                 tvb_raw_text_add(tvb, orig_offset, offset - orig_offset, tree);
2445
2446         /* Report this packet to the tap */
2447         if (!pinfo->in_error_pkt)
2448         {
2449                 tap_queue_packet(sip_tap, pinfo, stat_info);
2450         }
2451
2452         return offset - orig_offset;
2453 }
2454
2455 /* Display filter for SIP Request-Line */
2456 static void
2457 dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, guint meth_len)
2458 {
2459         char    *string;
2460
2461         /*
2462          * We know we have the entire method; otherwise, "sip_parse_line()"
2463          * would have returned OTHER_LINE.
2464          */
2465         string = tvb_get_ephemeral_string(tvb, 0, meth_len);
2466         if (tree) {
2467                 proto_tree_add_string(tree, hf_Method, tvb, 0, meth_len, string);
2468         }
2469         /* Copy request method for telling tap */
2470         stat_info->request_method = string;
2471 }
2472
2473 /* Display filter for SIP Status-Line */
2474 static void
2475 dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree)
2476 {
2477         char string[3+1];
2478         gint response_code = 0;
2479
2480         /*
2481          * We know we have the entire status code; otherwise,
2482          * "sip_parse_line()" would have returned OTHER_LINE.
2483          * We also know that we have a version string followed by a
2484          * space at the beginning of the line, for the same reason.
2485          */
2486         tvb_memcpy(tvb, (guint8 *)string, SIP2_HDR_LEN + 1, 3);
2487         string[3] = '\0';
2488         response_code = atoi(string);
2489
2490         /* Add numerical response code to tree */
2491         if (tree) {
2492                 proto_tree_add_uint(tree, hf_Status_Code, tvb, SIP2_HDR_LEN + 1,
2493                                     3, response_code);
2494         }
2495
2496         /* Add response code for sending to tap */
2497         stat_info->response_code = response_code;
2498 }
2499
2500 void dfilter_store_sip_from_addr(tvbuff_t *tvb,proto_tree *tree,guint parameter_offset,
2501                                           guint parameter_len)
2502 {
2503         proto_tree_add_item(tree, hf_sip_from_addr, tvb, parameter_offset,
2504                                                         parameter_len, FALSE);
2505
2506 }
2507 /* From section 4.1 of RFC 2543:
2508  *
2509  * Request-Line  =  Method SP Request-URI SP SIP-Version CRLF
2510  *
2511  * From section 5.1 of RFC 2543:
2512  *
2513  * Status-Line  =  SIP-version SP Status-Code SP Reason-Phrase CRLF
2514  *
2515  * From section 7.1 of RFC 3261:
2516  *
2517  * Unlike HTTP, SIP treats the version number as a literal string.
2518  * In practice, this should make no difference.
2519  */
2520 static line_type_t
2521 sip_parse_line(tvbuff_t *tvb, int offset, gint linelen, guint *token_1_lenp)
2522 {
2523         gint space_offset;
2524         gint token_1_start;
2525         guint token_1_len;
2526         gint token_2_start;
2527         guint token_2_len;
2528         gint token_3_start;
2529         guint token_3_len;
2530         gint colon_pos;
2531
2532         token_1_start = offset;
2533         space_offset = tvb_find_guint8(tvb, token_1_start, -1, ' ');
2534         if ((space_offset == -1) || (space_offset == token_1_start)) {
2535                 /*
2536                  * Either there's no space in the line (which means
2537                  * the line is empty or doesn't have a token followed
2538                  * by a space; neither is valid for a request or status), or
2539                  * the first character in the line is a space (meaning
2540                  * the method is empty, which isn't valid for a request,
2541                  * or the SIP version is empty, which isn't valid for a
2542                  * status).
2543                  */
2544                 return OTHER_LINE;
2545         }
2546         token_1_len = space_offset - token_1_start;
2547         token_2_start = space_offset + 1;
2548         space_offset = tvb_find_guint8(tvb, token_2_start, -1, ' ');
2549         if (space_offset == -1) {
2550                 /*
2551                  * There's no space after the second token, so we don't
2552                  * have a third token.
2553                  */
2554                 return OTHER_LINE;
2555         }
2556         token_2_len = space_offset - token_2_start;
2557         token_3_start = space_offset + 1;
2558         token_3_len = token_1_start + linelen - token_3_start;
2559
2560         *token_1_lenp = token_1_len;
2561
2562         /*
2563          * Is the first token a version string?
2564          */
2565         if ( (strict_sip_version && (
2566                 token_1_len == SIP2_HDR_LEN
2567                 && tvb_strneql(tvb, token_1_start, SIP2_HDR, SIP2_HDR_LEN) == 0)
2568         ) || (! strict_sip_version && (
2569                 tvb_strncaseeql(tvb, token_1_start, "SIP/", 4) == 0)
2570         )) {
2571                 /*
2572                  * Yes, so this is either a Status-Line or something
2573                  * else other than a Request-Line.  To be a Status-Line,
2574                  * the second token must be a 3-digit number.
2575                  */
2576                 if (token_2_len != 3) {
2577                         /*
2578                          * We don't have 3-character status code.
2579                          */
2580                         return OTHER_LINE;
2581                 }
2582                 if (!isdigit(tvb_get_guint8(tvb, token_2_start)) ||
2583                     !isdigit(tvb_get_guint8(tvb, token_2_start + 1)) ||
2584                     !isdigit(tvb_get_guint8(tvb, token_2_start + 2))) {
2585                         /*
2586                          * 3 characters yes, 3 digits no.
2587                          */
2588                         return OTHER_LINE;
2589                 }
2590                 return STATUS_LINE;
2591         } else {
2592                 /*
2593                  * No, so this is either a Request-Line or something
2594                  * other than a Status-Line.  To be a Request-Line, the
2595                  * second token must be a URI and the third token must
2596                  * be a version string.
2597                  */
2598                 if (token_2_len < 3) {
2599                         /*
2600                          * We don't have a URI consisting of at least 3
2601                          * characters.
2602                          */
2603                         return OTHER_LINE;
2604                 }
2605                 colon_pos = tvb_find_guint8(tvb, token_2_start + 1, -1, ':');
2606                 if (colon_pos == -1) {
2607                         /*
2608                          * There is no colon after the method, so the URI
2609                          * doesn't have a colon in it, so it's not valid.
2610                          */
2611                         return OTHER_LINE;
2612                 }
2613                 if (colon_pos >= token_3_start) {
2614                         /*
2615                          * The colon is in the version string, not the URI.
2616                          */
2617                         return OTHER_LINE;
2618                 }
2619                 /* XXX - Check for a proper URI prefix? */
2620                 if ( (strict_sip_version && (
2621                         token_3_len != SIP2_HDR_LEN
2622                         || tvb_strneql(tvb, token_3_start, SIP2_HDR, SIP2_HDR_LEN) == -1)
2623                 ) || (! strict_sip_version && (
2624                         tvb_strncaseeql(tvb, token_3_start, "SIP/", 4) == -1)
2625                 )) {
2626                         /*
2627                          * The version string isn't an SIP version 2.0 version
2628                          * string.
2629                          */
2630                         return OTHER_LINE;
2631                 }
2632                 return REQUEST_LINE;
2633         }
2634 }
2635
2636 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
2637     guint meth_len, guint *meth_idx)
2638 {
2639         guint i;
2640
2641         for (i = 1; i < array_length(sip_methods); i++) {
2642                 if (meth_len == strlen(sip_methods[i]) &&
2643                     tvb_strneql(tvb, meth_offset, sip_methods[i], meth_len) == 0)
2644                 {
2645                      *meth_idx = i;
2646                      return TRUE;
2647                 }
2648         }
2649
2650         return FALSE;
2651 }
2652
2653 /* Returns index of method in sip_headers */
2654 static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset, guint header_len)
2655 {
2656         guint i;
2657
2658         for (i = 1; i < array_length(sip_headers); i++) {
2659                 if (header_len == strlen(sip_headers[i].name) &&
2660                     tvb_strncaseeql(tvb, offset, sip_headers[i].name, header_len) == 0)
2661                         return i;
2662                 if (sip_headers[i].compact_name != NULL &&
2663                     header_len == strlen(sip_headers[i].compact_name) &&
2664                     tvb_strncaseeql(tvb, offset, sip_headers[i].compact_name, header_len) == 0)
2665                         return i;
2666         }
2667
2668         return -1;
2669 }
2670
2671 /*
2672  * Display the entire message as raw text.
2673  */
2674 static void
2675 tvb_raw_text_add(tvbuff_t *tvb, int offset, int length, proto_tree *tree)
2676 {
2677     proto_tree *raw_tree = NULL;
2678     proto_item *ti = NULL;
2679     int next_offset, linelen, end_offset;
2680
2681     if (tree) {
2682         ti = proto_tree_add_item(tree, proto_raw_sip, tvb, offset, length, FALSE);
2683         raw_tree = proto_item_add_subtree(ti, ett_raw_text);
2684     }
2685
2686     end_offset = offset + length;
2687
2688     while (offset < end_offset) {
2689         tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
2690         linelen = next_offset - offset;
2691         if (raw_tree) {
2692             proto_tree_add_string_format(raw_tree, hf_raw_sip_line, tvb, offset, linelen,
2693                                          tvb_format_text(tvb, offset, linelen),
2694                                          "%s",
2695                                          tvb_format_text(tvb, offset, linelen));
2696         }
2697         offset = next_offset;
2698     }
2699 }
2700
2701 /* Check to see if this packet is a resent request.  Return value is number
2702    of the original frame this packet seems to be resending (0 = no resend). */
2703 guint sip_is_packet_resend(packet_info *pinfo,
2704                         gchar *cseq_method,
2705                         gchar *call_id,
2706                         guchar cseq_number_set,
2707                         guint32 cseq_number, line_type_t line_type)
2708 {
2709         guint32 cseq_to_compare = 0;
2710         sip_hash_key   key;
2711         sip_hash_key   *p_key = 0;
2712         sip_hash_value *p_val = 0;
2713         guint result = 0;
2714
2715         /* Only consider retransmission of UDP packets */
2716         if (pinfo->ptype != PT_UDP)
2717         {
2718                 return 0;
2719         }
2720
2721         /* Don't consider packets that appear to be resent only because
2722            they are e.g. returned in ICMP unreachable messages. */
2723         if (pinfo->in_error_pkt)
2724         {
2725                 return 0;
2726         }
2727
2728         /* A broken packet may have no cseq number set. Don't consider it as
2729            a resend */
2730         if (!cseq_number_set)
2731         {
2732                 return 0;
2733         }
2734
2735         /* Return any answer stored from previous dissection */
2736         if (pinfo->fd->flags.visited)
2737         {
2738                 return GPOINTER_TO_UINT(p_get_proto_data(pinfo->fd, proto_sip));
2739         }
2740
2741         /* No packet entry found, consult global hash table */
2742
2743         /* Prepare the key */
2744         g_strlcpy(key.call_id, call_id, MAX_CALL_ID_SIZE);
2745
2746         /*  We're only using these addresses locally (for the hash lookup) so
2747          *  there is no need to make a (g_malloc'd) copy of them.
2748          */
2749         SET_ADDRESS(&key.dest_address, pinfo->net_dst.type, pinfo->net_dst.len,
2750                     pinfo->net_dst.data);
2751         SET_ADDRESS(&key.source_address, pinfo->net_src.type,
2752                     pinfo->net_src.len, pinfo->net_src.data);
2753         key.dest_port = pinfo->destport;
2754         key.source_port = pinfo->srcport;
2755
2756         /* Do the lookup */
2757         p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
2758
2759         if (p_val)
2760         {
2761                 /* Table entry found, we'll use its value for comparison */
2762                 cseq_to_compare = p_val->cseq;
2763         }
2764         else
2765         {
2766                 /* Need to create a new table entry */
2767
2768                 /* Allocate a new key and value */
2769                 p_key = se_alloc(sizeof(sip_hash_key));
2770                 p_val = se_alloc(sizeof(sip_hash_value));
2771
2772                 /* Just give up if allocations failed */
2773                 if (!p_key || !p_val)
2774                 {
2775                         return 0;
2776                 }
2777
2778                 /* Fill in key and value details */
2779                 g_snprintf(p_key->call_id, MAX_CALL_ID_SIZE, "%s", call_id);
2780                 SE_COPY_ADDRESS(&(p_key->dest_address), &pinfo->net_dst);
2781                 SE_COPY_ADDRESS(&(p_key->source_address), &pinfo->net_src);
2782                 p_key->dest_port = pinfo->destport;
2783                 p_key->source_port = pinfo->srcport;
2784
2785                 p_val->cseq = cseq_number;
2786                 g_strlcpy(p_val->method, cseq_method, MAX_CSEQ_METHOD_SIZE);
2787                 p_val->transaction_state = nothing_seen;
2788                 p_val->frame_number = 0;
2789
2790                 /* Add entry */
2791                 g_hash_table_insert(sip_hash, p_key, p_val);
2792
2793                 /* Assume have seen no cseq yet */
2794                 cseq_to_compare = 0;
2795         }
2796
2797
2798         /******************************************/
2799         /* Is it a resend???                      */
2800
2801         /* Does this look like a resent request (discount ACK, CANCEL, or a
2802            different method from the original one) ? */
2803
2804         if ((line_type == REQUEST_LINE) && (cseq_number == cseq_to_compare) &&
2805             (p_val->transaction_state == request_seen) &&
2806             (strcmp(cseq_method, p_val->method) == 0) &&
2807             (strcmp(cseq_method, "ACK") != 0) &&
2808             (strcmp(cseq_method, "CANCEL") != 0))
2809         {
2810                 result = p_val->frame_number;
2811         }
2812
2813         /* Does this look like a resent final response ? */
2814         if ((line_type == STATUS_LINE) && (cseq_number == cseq_to_compare) &&
2815             (p_val->transaction_state == final_response_seen) &&
2816             (strcmp(cseq_method, p_val->method) == 0) &&
2817             (stat_info->response_code >= 200) &&
2818             (stat_info->response_code == p_val->response_code))
2819         {
2820                 result = p_val->frame_number;
2821         }
2822
2823         /* Update state for this entry */
2824         p_val->cseq = cseq_number;
2825
2826         switch (line_type)
2827         {
2828                 case REQUEST_LINE:
2829                         p_val->transaction_state = request_seen;
2830                         if (!result)
2831                         {
2832                                 p_val->frame_number = pinfo->fd->num;
2833                         }
2834                         break;
2835                 case STATUS_LINE:
2836                         if (stat_info->response_code >= 200)
2837                         {
2838                                 p_val->response_code = stat_info->response_code;
2839                                 p_val->transaction_state = final_response_seen;
2840                                 if (!result)
2841                                 {
2842                                         p_val->frame_number = pinfo->fd->num;
2843                                 }
2844                         }
2845                         else
2846                         {
2847                                 p_val->transaction_state = provisional_response_seen;
2848                         }
2849                         break;
2850                 default:
2851                         break;
2852         }
2853
2854         /* Store return value with this packet */
2855         p_add_proto_data(pinfo->fd, proto_sip, GUINT_TO_POINTER(result));
2856
2857         return result;
2858 }
2859
2860
2861 /* Register the protocol with Wireshark */
2862 void proto_register_sip(void)
2863 {
2864
2865         /* Setup list of header fields */
2866         static hf_register_info hf[] = {
2867
2868                 { &hf_raw_sip_line,
2869                                 { "Raw SIP Line",                "raw_sip.line",
2870                                         FT_STRING, BASE_NONE,NULL,0x0,
2871                        "Raw SIP Line", HFILL }
2872                 },
2873                 { &hf_msg_hdr,
2874                                 { "Message Header",           "sip.msg_hdr",
2875                         FT_NONE, 0, NULL, 0,
2876                         "Message Header in SIP message", HFILL }
2877                 },
2878                 { &hf_Method,
2879                        { "Method",              "sip.Method",
2880                        FT_STRING, BASE_NONE,NULL,0x0,
2881                         "SIP Method", HFILL }
2882                 },
2883                 { &hf_Request_Line,
2884                                 { "Request-Line",                "sip.Request-Line",
2885                                         FT_STRING, BASE_NONE,NULL,0x0,
2886                        "SIP Request-Line", HFILL }
2887                 },
2888                 { &hf_Status_Code,
2889                        { "Status-Code",                 "sip.Status-Code",
2890                        FT_UINT32, BASE_DEC,NULL,0x0,
2891                         "SIP Status Code", HFILL }
2892                 },
2893                 { &hf_Status_Line,
2894                        { "Status-Line",                 "sip.Status-Line",
2895                        FT_STRING, BASE_NONE,NULL,0x0,
2896                        "SIP Status-Line", HFILL }
2897                 },
2898                 { &hf_sip_display,
2899                         { "SIP Display info",           "sip.display.info",
2900                        FT_STRING, BASE_NONE,NULL,0x0,
2901                         "RFC 3261: Display info", HFILL }
2902                 },
2903                 { &hf_sip_to_addr,
2904                                 { "SIP to address",             "sip.to.addr",
2905                        FT_STRING, BASE_NONE,NULL,0x0,
2906                         "RFC 3261: to addr", HFILL }
2907                 },
2908                 { &hf_sip_from_addr,
2909                        { "SIP from address",            "sip.from.addr",
2910                        FT_STRING, BASE_NONE,NULL,0x0,
2911                         "RFC 3261: from addr", HFILL }
2912                 },
2913                 { &hf_sip_contact_addr,
2914                        { "SIP contact address",         "sip.contact.addr",
2915                        FT_STRING, BASE_NONE,NULL,0x0,
2916                         "RFC 3261: contact addr", HFILL }
2917                 },
2918                 { &hf_sip_uri,
2919                                 { "URI",                "sip.uri",
2920                        FT_STRING, BASE_NONE,NULL,0x0,
2921                         "RFC 3261: SIP Uri", HFILL }
2922                 },
2923                 { &hf_sip_contact_item,
2924                        { "Contact Binding",             "sip.contact.binding",
2925                        FT_STRING, BASE_NONE,NULL,0x0,
2926                         "RFC 3261: one contact binding", HFILL }
2927                 },
2928                 { &hf_sip_tag,
2929                        { "SIP tag",             "sip.tag",
2930                        FT_STRING, BASE_NONE,NULL,0x0,
2931                         "RFC 3261: tag", HFILL }
2932                 },
2933                 { &hf_header_array[POS_ACCEPT],
2934                        { "Accept",              "sip.Accept",
2935                        FT_STRING, BASE_NONE,NULL,0x0,
2936                         "RFC 3261: Accept Header", HFILL }
2937                 },
2938                 { &hf_header_array[POS_ACCEPT_CONTACT],
2939                        { "Accept-Contact",              "sip.Accept-Contact",
2940                        FT_STRING, BASE_NONE,NULL,0x0,
2941                         "RFC 3841: Accept-Contact Header", HFILL }
2942                 },
2943                 { &hf_header_array[POS_ACCEPT_ENCODING],
2944                        { "Accept-Encoding",             "sip.Accept-Encoding",
2945                        FT_STRING, BASE_NONE,NULL,0x0,
2946                         "RFC 3841: Accept-Encoding Header", HFILL }
2947                 },
2948                 { &hf_header_array[POS_ACCEPT_LANGUAGE],
2949                        { "Accept-Language",             "sip.Accept-Language",
2950                        FT_STRING, BASE_NONE,NULL,0x0,
2951                         "RFC 3261: Accept-Language Header", HFILL }
2952                 },
2953                 { &hf_header_array[POS_ACCEPT_RESOURCE_PRIORITY],
2954                        { "Accept-Resource-Priority",            "sip.Accept-Resource-Priority",
2955                        FT_STRING, BASE_NONE,NULL,0x0,
2956                         "Draft: Accept-Resource-Priority Header", HFILL }
2957                 },
2958                 { &hf_header_array[POS_ALERT_INFO],
2959                        { "Alert-Info",          "sip.Alert-Info",
2960                        FT_STRING, BASE_NONE,NULL,0x0,
2961                         "RFC 3261: Alert-Info Header", HFILL }
2962                 },
2963                 { &hf_header_array[POS_ALLOW],
2964                        { "Allow",               "sip.Allow",
2965                        FT_STRING, BASE_NONE,NULL,0x0,
2966                         "RFC 3261: Allow Header", HFILL }
2967                 },
2968                 { &hf_header_array[POS_ALLOW_EVENTS],
2969                        { "Allow-Events",                "sip.Allow-Events",
2970                        FT_STRING, BASE_NONE,NULL,0x0,
2971                         "RFC 3265: Allow-Events Header", HFILL }
2972                 },
2973                 { &hf_header_array[POS_AUTHENTICATION_INFO],
2974                        { "Authentication-Info",                 "sip.Authentication-Info",
2975                        FT_STRING, BASE_NONE,NULL,0x0,
2976                         "RFC 3261: Authentication-Info Header", HFILL }
2977                 },
2978                 { &hf_header_array[POS_AUTHORIZATION],
2979                        { "Authorization",               "sip.Authorization",
2980                        FT_STRING, BASE_NONE,NULL,0x0,
2981                         "RFC 3261: Authorization Header", HFILL }
2982                 },
2983                 { &hf_header_array[POS_CALL_ID],
2984                        { "Call-ID",             "sip.Call-ID",
2985                        FT_STRING, BASE_NONE,NULL,0x0,
2986                         "RFC 3261: Call-ID Header", HFILL }
2987                 },
2988                 { &hf_header_array[POS_CALL_INFO],
2989                        { "Call-Info",           "sip.Call-Info",
2990                        FT_STRING, BASE_NONE,NULL,0x0,
2991                         "RFC 3261: Call-Info Header", HFILL }
2992                 },
2993                 { &hf_header_array[POS_CONTACT],
2994                        { "Contact",             "sip.Contact",
2995                        FT_STRING, BASE_NONE,NULL,0x0,
2996                         "RFC 3261: Contact Header", HFILL }
2997                 },
2998                 { &hf_header_array[POS_CONTENT_DISPOSITION],
2999                        { "Content-Disposition",                 "sip.Content-Disposition",
3000                        FT_STRING, BASE_NONE,NULL,0x0,
3001                         "RFC 3261: Content-Disposition Header", HFILL }
3002                 },
3003                 { &hf_header_array[POS_CONTENT_ENCODING],
3004                        { "Content-Encoding",            "sip.Content-Encoding",
3005                        FT_STRING, BASE_NONE,NULL,0x0,
3006                         "RFC 3261: Content-Encoding Header", HFILL }
3007                 },
3008                 { &hf_header_array[POS_CONTENT_LANGUAGE],
3009                        { "Content-Language",            "sip.Content-Language",
3010                        FT_STRING, BASE_NONE,NULL,0x0,
3011                         "RFC 3261: Content-Language Header", HFILL }
3012                 },
3013                 { &hf_header_array[POS_CONTENT_LENGTH],
3014                        { "Content-Length",              "sip.Content-Length",
3015                        FT_UINT32, BASE_DEC,NULL,0x0,
3016                         "RFC 3261: Content-Length Header", HFILL }
3017                 },
3018                 { &hf_header_array[POS_CONTENT_TYPE],
3019                        { "Content-Type",                "sip.Content-Type",
3020                        FT_STRING, BASE_NONE,NULL,0x0,
3021                         "RFC 3261: Content-Type Header", HFILL }
3022                 },
3023                 { &hf_header_array[POS_CSEQ],
3024                        { "CSeq",                "sip.CSeq",
3025                        FT_STRING, BASE_NONE,NULL,0x0,
3026                         "RFC 3261: CSeq Header", HFILL }
3027                 },
3028                 { &hf_header_array[POS_DATE],
3029                        { "Date",                "sip.Date",
3030                        FT_STRING, BASE_NONE,NULL,0x0,
3031                         "RFC 3261: Date Header", HFILL }
3032                 },
3033                 { &hf_header_array[POS_ERROR_INFO],
3034                        { "Error-Info",          "sip.Error-Info",
3035                        FT_STRING, BASE_NONE,NULL,0x0,
3036                         "RFC 3261: Error-Info Header", HFILL }
3037                 },
3038                 { &hf_header_array[POS_EVENT],
3039                        { "Event",               "sip.Event",
3040                        FT_STRING, BASE_NONE,NULL,0x0,
3041                         "RFC 3265: Event Header", HFILL }
3042                 },
3043                 { &hf_header_array[POS_EXPIRES],
3044                        { "Expires",             "sip.Expires",
3045                        FT_UINT32, BASE_DEC,NULL,0x0,
3046                         "RFC 3261: Expires Header", HFILL }
3047                 },
3048                 { &hf_header_array[POS_FROM],
3049                        { "From",                "sip.From",
3050                        FT_STRING, BASE_NONE,NULL,0x0,
3051                         "RFC 3261: From Header", HFILL }
3052                 },
3053                 { &hf_header_array[POS_IN_REPLY_TO],
3054                        { "In-Reply-To",                 "sip.In-Reply-To",
3055                        FT_STRING, BASE_NONE,NULL,0x0,
3056                         "RFC 3261: In-Reply-To Header", HFILL }
3057                 },
3058                 { &hf_header_array[POS_JOIN],
3059                        { "Join",                "sip.Join",
3060                        FT_STRING, BASE_NONE,NULL,0x0,
3061                         "Draft: Join Header", HFILL }
3062                 },
3063                 { &hf_header_array[POS_MAX_FORWARDS],
3064                        { "Max-Forwards",                "sip.Max-Forwards",
3065                        FT_UINT32, BASE_DEC,NULL,0x0,
3066                         "RFC 3261: Max-Forwards Header", HFILL }
3067                 },
3068                 { &hf_header_array[POS_MIME_VERSION],
3069                        { "MIME-Version",                "sip.MIME-Version",
3070                        FT_STRING, BASE_NONE,NULL,0x0,
3071                         "RFC 3261: MIME-Version Header", HFILL }
3072                 },
3073                 { &hf_header_array[POS_MIN_EXPIRES],
3074                        { "Min-Expires",                 "sip.Min-Expires",
3075                        FT_STRING, BASE_NONE,NULL,0x0,
3076                         "RFC 3261: Min-Expires Header", HFILL }
3077                 },
3078                 { &hf_header_array[POS_MIN_SE],
3079                        { "Min-SE",              "sip.Min-SE",
3080                        FT_STRING, BASE_NONE,NULL,0x0,
3081                         "Draft: Min-SE Header", HFILL }
3082                 },
3083                 { &hf_header_array[POS_ORGANIZATION],
3084                        { "Organization",                "sip.Organization",
3085                        FT_STRING, BASE_NONE,NULL,0x0,
3086                         "RFC 3261: Organization Header", HFILL }
3087                 },
3088                 { &hf_header_array[POS_P_ACCESS_NETWORK_INFO],
3089                        { "P-Access-Network-Info",       "sip.P-Access-Network-Info",
3090                        FT_STRING, BASE_NONE,NULL,0x0,
3091                         "P-Access-Network-Info Header", HFILL }
3092                 },
3093
3094                 { &hf_header_array[POS_P_ASSERTED_IDENTITY],
3095                        { "P-Asserted-Identity",         "sip.P-Asserted-Identity",
3096                        FT_STRING, BASE_NONE,NULL,0x0,
3097                         "RFC 3325: P-Asserted-Identity Header", HFILL }
3098                 },
3099                 { &hf_header_array[POS_P_ANSWER_STATE],
3100                        { "P-Answer-State",              "sip.P-Answer-State",
3101                        FT_STRING, BASE_NONE,NULL,0x0,
3102                         "P-Answer-State Header", HFILL }
3103                 },
3104                 { &hf_header_array[POS_P_ASSOCIATED_URI],
3105                        { "P-Associated-URI",            "sip.P-Associated-URI",
3106                        FT_STRING, BASE_NONE,NULL,0x0,
3107                         "RFC 3455: P-Associated-URI Header", HFILL }
3108                 },
3109
3110                 { &hf_header_array[POS_P_CALLED_PARTY_ID],
3111                        { "P-Called-Party-ID",           "sip.P-Called-Party-ID",
3112                        FT_STRING, BASE_NONE,NULL,0x0,
3113                         "RFC 3455: P-Called-Party-ID Header", HFILL }
3114                 },
3115
3116                 { &hf_header_array[POS_P_CHARGING_FUNCTION_ADDRESSES],
3117                        { "P-Charging-Function-Addresses","sip.P-Charging-Function-Addresses",
3118                        FT_STRING, BASE_NONE,NULL,0x0,
3119                         "P-Charging-Function-Addresses", HFILL }
3120                 },
3121
3122                 { &hf_header_array[POS_P_CHARGING_VECTOR],
3123                        { "P-Charging-Vector",           "sip.P-Charging-Vector",
3124                        FT_STRING, BASE_NONE,NULL,0x0,
3125                         "P-Charging-Vector Header", HFILL }
3126                 },
3127
3128                 { &hf_header_array[POS_P_DCS_TRACE_PARTY_ID],
3129                        { "P-DCS-Trace-Party-ID",        "sip.P-DCS-Trace-Party-ID",
3130                        FT_STRING, BASE_NONE,NULL,0x0,
3131                         "P-DCS-Trace-Party-ID Header", HFILL }
3132                 },
3133
3134                 { &hf_header_array[POS_P_DCS_OSPS],
3135                        { "P-DCS-OSPS",                  "sip.P-DCS-OSPS",
3136                        FT_STRING, BASE_NONE,NULL,0x0,
3137                         "P-DCS-OSPS Header", HFILL }
3138                 },
3139
3140                 { &hf_header_array[POS_P_DCS_BILLING_INFO],
3141                        { "P-DCS-Billing-Info",          "sip.P-DCS-Billing-Info",
3142                        FT_STRING, BASE_NONE,NULL,0x0,
3143                         "P-DCS-Billing-Info Header", HFILL }
3144                 },
3145
3146                 { &hf_header_array[POS_P_DCS_LAES],
3147                        { "P-DCS-LAES",                  "sip.P-DCS-LAES",
3148                        FT_STRING, BASE_NONE,NULL,0x0,
3149                         "P-DCS-LAES Header", HFILL }
3150                 },
3151
3152                 { &hf_header_array[POS_P_DCS_REDIRECT],
3153                        { "P-DCS-Redirect",              "sip.P-DCS-Redirect",
3154                        FT_STRING, BASE_NONE,NULL,0x0,
3155                         "P-DCS-Redirect Header", HFILL }
3156                 },
3157
3158                 { &hf_header_array[POS_P_EARLY_MEDIA],
3159                        { "P-Early-Media",               "sip.P-Early-Media",
3160                        FT_STRING, BASE_NONE,NULL,0x0,
3161                         "P-Early-Media Header", HFILL }
3162                 },
3163
3164                 { &hf_header_array[POS_P_MEDIA_AUTHORIZATION],
3165                        { "P-Media-Authorization",       "sip.P-Media-Authorization",
3166                        FT_STRING, BASE_NONE,NULL,0x0,
3167                            "RFC 3313: P-Media-Authorization Header", HFILL }
3168                 },
3169
3170                 { &hf_header_array[POS_P_PREFERRED_IDENTITY],
3171                        { "P-Preferred-Identity",        "sip.P-Preferred-Identity",
3172                        FT_STRING, BASE_NONE,NULL,0x0,
3173                         "RFC 3325: P-Preferred-Identity Header", HFILL }
3174                 },
3175
3176                 { &hf_header_array[POS_P_PROFILE_KEY],
3177                        { "P-Profile-Key",       "sip.P-Profile-Key",
3178                        FT_STRING, BASE_NONE,NULL,0x0,
3179                         "P-Profile-Key Header", HFILL }
3180                 },
3181
3182                 { &hf_header_array[POS_P_USER_DATABASE],
3183                        { "P-User-Database",     "sip.P-User-Database",
3184                        FT_STRING, BASE_NONE,NULL,0x0,
3185                         "P-User-Database Header", HFILL }
3186                 },
3187
3188                 { &hf_header_array[POS_P_VISITED_NETWORK_ID],
3189                        { "P-Visited-Network-ID",        "sip.P-Visited-Network-ID",
3190                        FT_STRING, BASE_NONE,NULL,0x0,
3191                            "RFC 3455: P-Visited-Network-ID Header", HFILL }
3192                 },
3193
3194                 { &hf_header_array[POS_PATH],
3195                        { "Path",                        "sip.Path",
3196                        FT_STRING, BASE_NONE,NULL,0x0,
3197                            "RFC 3327: Path Header", HFILL }
3198                 },
3199
3200         { &hf_header_array[POS_PRIORITY],
3201                        { "Priority",            "sip.Priority",
3202                        FT_STRING, BASE_NONE,NULL,0x0,
3203                         "RFC 3261: Priority Header", HFILL }
3204                 },
3205                 { &hf_header_array[POS_PRIVACY],
3206                        { "Privacy",                     "sip.Privacy",
3207                        FT_STRING, BASE_NONE,NULL,0x0,
3208                         "Privacy Header", HFILL }
3209                 },
3210
3211         { &hf_header_array[POS_PROXY_AUTHENTICATE],
3212                        { "Proxy-Authenticate",          "sip.Proxy-Authenticate",
3213                        FT_STRING, BASE_NONE,NULL,0x0,
3214                         "RFC 3261: Proxy-Authenticate Header", HFILL }
3215                 },
3216                 { &hf_header_array[POS_PROXY_AUTHORIZATION],
3217                        { "Proxy-Authorization",                 "sip.Proxy-Authorization",
3218                        FT_STRING, BASE_NONE,NULL,0x0,
3219                         "RFC 3261: Proxy-Authorization Header", HFILL }
3220                 },
3221
3222         { &hf_header_array[POS_PROXY_REQUIRE],
3223                        { "Proxy-Require",               "sip.Proxy-Require",
3224                        FT_STRING, BASE_NONE,NULL,0x0,
3225                         "RFC 3261: Proxy-Require Header", HFILL }
3226                 },
3227                 { &hf_header_array[POS_RACK],
3228                        { "RAck",                "sip.RAck",
3229                        FT_STRING, BASE_NONE,NULL,0x0,
3230                         "RFC 3262: RAck Header", HFILL }
3231                 },
3232                 { &hf_header_array[POS_REASON],
3233                        { "Reason",                      "sip.Reason",
3234                        FT_STRING, BASE_NONE,NULL,0x0,
3235                         "RFC 3326 Reason Header", HFILL }
3236                 },
3237                 { &hf_header_array[POS_RECORD_ROUTE],
3238                        { "Record-Route",                "sip.Record-Route",
3239                        FT_STRING, BASE_NONE,NULL,0x0,
3240                         "RFC 3261: Record-Route Header", HFILL }
3241                 },
3242                 { &hf_header_array[POS_REFER_SUB],
3243                        { "Refer-Sub",           "sip.Refer-Sub",
3244                        FT_STRING, BASE_NONE,NULL,0x0,
3245                         "RFC 4488: Refer-Sub Header", HFILL }
3246                 },
3247                 { &hf_header_array[POS_REFERED_BY],
3248                        { "Refered By",          "sip.Refered-by",
3249                        FT_STRING, BASE_NONE,NULL,0x0,
3250                         "RFC 3892: Refered-by Header", HFILL }
3251                 },
3252                 { &hf_header_array[POS_REJECT_CONTACT],
3253                         { "Reject-Contact",             "sip.Reject-Contact",
3254                         FT_STRING, BASE_NONE,NULL,0x0,
3255                         "RFC 3841: Reject-Contact Header", HFILL }
3256                 },
3257                 { &hf_header_array[POS_REPLACES],
3258                         { "Replaces",           "sip.Replaces",
3259                         FT_STRING, BASE_NONE,NULL,0x0,
3260                         "RFC 3891: Replaces Header", HFILL }
3261                 },
3262                 { &hf_header_array[POS_REPLY_TO],
3263                        { "Reply-To",            "sip.Reply-To",
3264                        FT_STRING, BASE_NONE,NULL,0x0,
3265                         "RFC 3261: Reply-To Header", HFILL }
3266                 },
3267                 { &hf_header_array[POS_REQUEST_DISPOSITION],
3268                        { "Request-Disposition",         "sip.Request-Disposition",
3269                        FT_STRING, BASE_NONE,NULL,0x0,
3270                         "RFC 3841: Request-Disposition Header", HFILL }
3271                 },
3272                 { &hf_header_array[POS_REQUIRE],
3273                         { "Require",            "sip.Require",
3274                        FT_STRING, BASE_NONE,NULL,0x0,
3275                         "RFC 3261: Require Header", HFILL }
3276                 },
3277                 { &hf_header_array[POS_RESOURCE_PRIORITY],
3278                         { "Resource-Priority",          "sip.Resource-Priority",
3279                        FT_STRING, BASE_NONE,NULL,0x0,
3280                         "Draft: Resource-Priority Header", HFILL }
3281                 },
3282                 { &hf_header_array[POS_RETRY_AFTER],
3283                         { "Retry-After",                "sip.Retry-After",
3284                        FT_STRING, BASE_NONE,NULL,0x0,
3285                         "RFC 3261: Retry-After Header", HFILL }
3286                 },
3287                 { &hf_header_array[POS_ROUTE],
3288                        { "Route",               "sip.Route",
3289                        FT_STRING, BASE_NONE,NULL,0x0,
3290                         "RFC 3261: Route Header", HFILL }
3291                 },
3292         { &hf_header_array[POS_RSEQ],
3293                        { "RSeq",                "sip.RSeq",
3294                        FT_UINT32, BASE_DEC,NULL,0x0,
3295                         "RFC 3262: RSeq Header", HFILL }
3296                 },
3297                 { &hf_header_array[ POS_SECURITY_CLIENT],
3298                        { "Security-Client",             "sip.Security-Client",
3299                        FT_STRING, BASE_NONE,NULL,0x0,
3300                         "RFC 3329 Security-Client Header", HFILL }
3301                 },
3302                 { &hf_header_array[ POS_SECURITY_SERVER],
3303                        { "Security-Server",             "sip.Security-Server",
3304                        FT_STRING, BASE_NONE,NULL,0x0,
3305                         "RFC 3329 Security-Server Header", HFILL }
3306                 },
3307                 { &hf_header_array[ POS_SECURITY_VERIFY],
3308                        { "Security-Verify",             "sip.Security-Verify",
3309                        FT_STRING, BASE_NONE,NULL,0x0,
3310                         "RFC 3329 Security-Verify Header", HFILL }
3311                 },
3312                 { &hf_header_array[POS_SERVER],
3313                         { "Server",             "sip.Server",
3314                        FT_STRING, BASE_NONE,NULL,0x0,
3315                         "RFC 3261: Server Header", HFILL }
3316                 },
3317                 { &hf_header_array[POS_SERVICE_ROUTE],
3318                        { "Service-Route",               "sip.Service-Route",
3319                        FT_STRING, BASE_NONE,NULL,0x0,
3320                         "RFC 3608: Service-Route Header", HFILL }
3321                 },
3322                 { &hf_header_array[POS_SESSION_EXPIRES],
3323                        { "Session-Expires",             "sip.Session-Expires",
3324                        FT_STRING, BASE_NONE,NULL,0x0,
3325                            "RFC 4028: Session-Expires Header", HFILL }
3326                 },
3327                 { &hf_header_array[POS_SIP_ETAG],
3328                        { "ETag",                "sip.ETag",
3329                        FT_STRING, BASE_NONE,NULL,0x0,
3330                            "RFC 3903: SIP-ETag Header", HFILL }
3331                 },
3332                 { &hf_header_array[POS_SIP_IF_MATCH],
3333                        { "If_Match",            "sip.If_Match",
3334                        FT_STRING, BASE_NONE,NULL,0x0,
3335                         "RFC 3903: SIP-If-Match Header", HFILL }
3336                 },
3337                 { &hf_header_array[POS_SUBJECT],
3338                        { "Subject",             "sip.Subject",
3339                        FT_STRING, BASE_NONE,NULL,0x0,
3340                         "RFC 3261: Subject Header", HFILL }
3341                 },
3342                 { &hf_header_array[POS_SUBSCRIPTION_STATE],
3343                        { "Subscription-State",          "sip.Subscription-State",
3344                        FT_STRING, BASE_NONE,NULL,0x0,
3345                         "RFC 3265: Subscription-State Header", HFILL }
3346                 },
3347                 { &hf_header_array[POS_SUPPORTED],
3348                         { "Supported",          "sip.Supported",
3349                        FT_STRING, BASE_NONE,NULL,0x0,
3350                         "RFC 3261: Supported Header", HFILL }
3351                 },
3352                 { &hf_header_array[POS_TARGET_DALOG],
3353                         { "Target-Dialog",              "sip.Target-Dialog",
3354                        FT_STRING, BASE_NONE,NULL,0x0,
3355                         "RFC 4538: Target-Dialog Header", HFILL }
3356                 },
3357                 { &hf_header_array[POS_TIMESTAMP],
3358                         { "Timestamp",          "sip.Timestamp",
3359                        FT_STRING, BASE_NONE,NULL,0x0,
3360                         "RFC 3261: Timestamp Header", HFILL }
3361                 },
3362                 { &hf_header_array[POS_TO],
3363                         { "To",                 "sip.To",
3364                        FT_STRING, BASE_NONE,NULL,0x0,
3365                         "RFC 3261: To Header", HFILL }
3366                 },
3367
3368                 { &hf_header_array[POS_UNSUPPORTED],
3369                         { "Unsupported",                "sip.Unsupported",
3370                        FT_STRING, BASE_NONE,NULL,0x0,
3371                         "RFC 3261: Unsupported Header", HFILL }
3372                 },
3373                 { &hf_header_array[POS_USER_AGENT],
3374                         { "User-Agent",                 "sip.User-Agent",
3375                        FT_STRING, BASE_NONE,NULL,0x0,
3376                         "RFC 3261: User-Agent Header", HFILL }
3377                 },
3378                 { &hf_header_array[POS_VIA],
3379                         { "Via",                "sip.Via",
3380                        FT_STRING, BASE_NONE,NULL,0x0,
3381                         "RFC 3261: Via Header", HFILL }
3382                 },
3383                 { &hf_header_array[POS_WARNING],
3384                         { "Warning",            "sip.Warning",
3385                        FT_STRING, BASE_NONE,NULL,0x0,
3386                         "RFC 3261: Warning Header", HFILL }
3387                 },
3388
3389                 { &hf_header_array[POS_WWW_AUTHENTICATE],
3390                         { "WWW-Authenticate",           "sip.WWW-Authenticate",
3391                        FT_STRING, BASE_NONE,NULL,0x0,
3392                         "RFC 3261: WWW-Authenticate Header", HFILL }
3393                 },
3394                 { &hf_header_array[POS_REFER_TO],
3395                         { "Refer-To",                   "sip.Refer-To",
3396                        FT_STRING, BASE_NONE,NULL,0x0,
3397                         "RFC 3515: Refer-To Header", HFILL }
3398                 },
3399                 { &hf_header_array[POS_HISTORY_INFO],
3400                         { "History-Info",                       "sip.History-Info",
3401                        FT_STRING, BASE_NONE,NULL,0x0,
3402                         "RFC 4244: Request History Information", HFILL }
3403                 },
3404                 { &hf_header_array[POS_IDENTITY],
3405                         { "Identity",                   "sip.Identity",
3406                        FT_STRING, BASE_NONE,NULL,0x0,
3407                         "RFC 4474: Request Identity", HFILL }
3408                 },
3409                 { &hf_header_array[POS_IDENTITY_INFO],
3410                         { "Identity-info",                      "sip.Identity-info",
3411                        FT_STRING, BASE_NONE,NULL,0x0,
3412                         "RFC 4474: Request Identity-info", HFILL }
3413                 },
3414
3415                 { &hf_sip_resend,
3416                         { "Resent Packet", "sip.resend",
3417                         FT_BOOLEAN, BASE_NONE, NULL, 0x0,
3418                         "", HFILL }
3419                 },
3420                 { &hf_sip_original_frame,
3421                         { "Suspected resend of frame",  "sip.resend-original",
3422                         FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3423                         "Original transmission of frame", HFILL}
3424                 },
3425                 { &hf_sip_auth,
3426                         { "Authentication",  "sip.auth",
3427                         FT_STRING, BASE_NONE, NULL, 0x0,
3428                         "SIP Authentication", HFILL}
3429                 },
3430                 { &hf_sip_auth_scheme,
3431                         { "Authentication Scheme",  "sip.auth.scheme",
3432                         FT_STRING, BASE_NONE, NULL, 0x0,
3433                         "SIP Authentication Scheme", HFILL}
3434                 },
3435                 { &hf_sip_auth_digest_response,
3436                         { "Digest Authentication Response",  "sip.auth.digest.response",
3437                         FT_STRING, BASE_NONE, NULL, 0x0,
3438                         "SIP Digest Authentication Response Value ", HFILL}
3439                 },
3440                 { &hf_sip_auth_nc,
3441                         { "Nonce Count",  "sip.auth.nc",
3442                         FT_STRING, BASE_NONE, NULL, 0x0,
3443                         "SIP Authentication Nonce count", HFILL}
3444                 },
3445                 { &hf_sip_auth_username,
3446                         { "Username",  "sip.auth.username",
3447                         FT_STRING, BASE_NONE, NULL, 0x0,
3448                         "SIP Authentication Username", HFILL}
3449                 },
3450                 { &hf_sip_auth_realm,
3451                         { "Realm",  "sip.auth.realm",
3452                         FT_STRING, BASE_NONE, NULL, 0x0,
3453                         "SIP Authentication Realm", HFILL}
3454                 },
3455                 { &hf_sip_auth_nonce,
3456                         { "Nonce Value",  "sip.auth.nonce",
3457                         FT_STRING, BASE_NONE, NULL, 0x0,
3458                         "SIP Authentication Nonce", HFILL}
3459                 },
3460                 { &hf_sip_auth_algorithm,
3461                         { "Algorithm",  "sip.auth.algorithm",
3462                         FT_STRING, BASE_NONE, NULL, 0x0,
3463                         "SIP Authentication Algorithm", HFILL}
3464                 },
3465                 { &hf_sip_auth_opaque,
3466                         { "Opaque Value",  "sip.auth.opaque",
3467                         FT_STRING, BASE_NONE, NULL, 0x0,
3468                         "SIP Authentication Opaque value", HFILL}
3469                 },
3470                 { &hf_sip_auth_qop,
3471                         { "QOP",  "sip.auth.qop",
3472                         FT_STRING, BASE_NONE, NULL, 0x0,
3473                         "SIP Authentication QOP", HFILL}
3474                 },
3475                 { &hf_sip_auth_cnonce,
3476                         { "CNonce Value",  "sip.auth.cnonce",
3477                         FT_STRING, BASE_NONE, NULL, 0x0,
3478                         "SIP Authentication Client Nonce", HFILL}
3479                 },
3480                 { &hf_sip_auth_uri,
3481                         { "Authentication URI",  "sip.auth.uri",
3482                         FT_STRING, BASE_NONE, NULL, 0x0,
3483                         "SIP Authentication URI", HFILL}
3484                 },
3485                 { &hf_sip_auth_domain,
3486                         { "Authentication Domain",  "sip.auth.domain",
3487                         FT_STRING, BASE_NONE, NULL, 0x0,
3488                         "SIP Authentication Domain", HFILL}
3489                 },
3490                 { &hf_sip_auth_stale,
3491                         { "Stale Flag",  "sip.auth.stale",
3492                         FT_STRING, BASE_NONE, NULL, 0x0,
3493                         "SIP Authentication Stale Flag", HFILL}
3494                 },
3495                 { &hf_sip_auth_auts,
3496                         { "Authentication Token",  "sip.auth.auts",
3497                         FT_STRING, BASE_NONE, NULL, 0x0,
3498                         "SIP Authentication Token", HFILL}
3499                 },
3500                 { &hf_sip_auth_rspauth,
3501                         { "Response auth",  "sip.auth.rspauth",
3502                         FT_STRING, BASE_NONE, NULL, 0x0,
3503                         "SIP Authentication Response auth", HFILL}
3504                 },
3505                 { &hf_sip_auth_nextnonce,
3506                         { "Next Nonce",  "sip.auth.nextnonce",
3507                         FT_STRING, BASE_NONE, NULL, 0x0,
3508                         "SIP Authentication Next Nonce", HFILL}
3509                 },
3510                 { &hf_sip_auth_ik,
3511                         { "Integrity Key",  "sip.auth.ik",
3512                         FT_STRING, BASE_NONE, NULL, 0x0,
3513                         "SIP Authentication Integrity Key", HFILL}
3514                 },
3515                 { &hf_sip_auth_ck,
3516                         { "Cyphering Key",  "sip.auth.ck",
3517                         FT_STRING, BASE_NONE, NULL, 0x0,
3518                         "SIP Authentication Cyphering Key", HFILL}
3519                 },
3520                 { &hf_sip_cseq_seq_no,
3521                         { "Sequence Number",  "sip.CSeq.seq",
3522                         FT_UINT32, BASE_DEC, NULL, 0x0,
3523                         "CSeq header sequence number", HFILL}
3524                 },
3525                 { &hf_sip_cseq_method,
3526                         { "Method",  "sip.CSeq.method",
3527                         FT_STRING, BASE_NONE, NULL, 0x0,
3528                         "CSeq header method", HFILL}
3529                 },
3530                 { &hf_sip_via_transport,
3531                         { "Transport",  "sip.Via.transport",
3532                         FT_STRING, BASE_NONE, NULL, 0x0,
3533                         "Via header Transport", HFILL}
3534                 },
3535                 { &hf_sip_via_sent_by_address,
3536                         { "Sent-by Address",  "sip.Via.sent-by.address",
3537                         FT_STRING, BASE_NONE, NULL, 0x0,
3538                         "Via header Sent-by Address", HFILL}
3539                 },
3540                 { &hf_sip_via_sent_by_port,
3541                         { "Sent-by port",  "sip.Via.sent-by.port",
3542                         FT_UINT16, BASE_DEC, NULL, 0x0,
3543                         "Via header Sent-by Port", HFILL}
3544                 },
3545                 { &hf_sip_via_branch,
3546                         { "Branch",  "sip.Via.branch",
3547                         FT_STRING, BASE_NONE, NULL, 0x0,
3548                         "SIP Via Branch", HFILL},
3549                 },
3550                 { &hf_sip_via_maddr,
3551                         { "Maddr",  "sip.Via.maddr",
3552                         FT_STRING, BASE_NONE, NULL, 0x0,
3553                         "SIP Via Maddr", HFILL},
3554                 },
3555                 { &hf_sip_via_rport,
3556                         { "RPort",  "sip.Via.rport",
3557                         FT_STRING, BASE_NONE, NULL, 0x0,
3558                         "SIP Via RPort", HFILL},
3559                 },
3560                 { &hf_sip_via_received,
3561                         { "Received",  "sip.Via.received",
3562                         FT_STRING, BASE_NONE, NULL, 0x0,
3563                         "SIP Via Received", HFILL},
3564                 },
3565                 { &hf_sip_via_ttl,
3566                         { "TTL",  "sip.Via.ttl",
3567                         FT_STRING, BASE_NONE, NULL, 0x0,
3568                         "SIP Via TTL", HFILL}
3569                 },
3570                 { &hf_sip_via_comp,
3571                         { "Comp",  "sip.Via.comp",
3572                         FT_STRING, BASE_NONE, NULL, 0x0,
3573                         "SIP Via comp", HFILL}
3574                 },
3575                 { &hf_sip_via_sigcomp_id,
3576                         { "Sigcomp identifier",  "sip.Via.sigcomp-id",
3577                         FT_STRING, BASE_NONE, NULL, 0x0,
3578                         "SIP Via sigcomp identifier", HFILL}
3579                 },
3580                 { &hf_sip_rack_rseq_no,
3581                         { "RSeq Sequence Number",  "sip.RAck.RSeq.seq",
3582                         FT_UINT32, BASE_DEC, NULL, 0x0,
3583                         "RAck RSeq header sequence number (from prov response)", HFILL}
3584                 },
3585                 { &hf_sip_rack_cseq_no,
3586                         { "CSeq Sequence Number",  "sip.RAck.CSeq.seq",
3587                         FT_UINT32, BASE_DEC, NULL, 0x0,
3588                         "RAck CSeq header sequence number (from prov response)", HFILL}
3589                 },
3590                 { &hf_sip_rack_cseq_method,
3591                         { "CSeq Method",  "sip.RAck.CSeq.method",
3592                         FT_STRING, BASE_NONE, NULL, 0x0,
3593                         "RAck CSeq header method (from prov response)", HFILL}
3594                 },
3595                 { &hf_sip_msg_body,
3596                                 { "Message Body",           "sip.msg_body",
3597                                 FT_NONE, BASE_NONE, NULL, 0x0,
3598                                 "Message Body in SIP message", HFILL }
3599                 }};
3600
3601
3602         /* Setup protocol subtree array */
3603         static gint *ett[] = {
3604                 &ett_sip,
3605                 &ett_sip_reqresp,
3606                 &ett_sip_hdr,
3607                 &ett_sip_element,
3608                 &ett_sip_uri,
3609                 &ett_sip_contact_item,
3610                 &ett_sip_message_body,
3611                 &ett_sip_cseq,
3612                 &ett_sip_via,
3613                 &ett_sip_reason,
3614                 &ett_sip_rack
3615         };
3616         static gint *ett_raw[] = {
3617                 &ett_raw_text,
3618         };
3619
3620         module_t *sip_module;
3621
3622         /* Register the protocol name and description */
3623         proto_sip = proto_register_protocol("Session Initiation Protocol",
3624                                             "SIP", "sip");
3625         proto_raw_sip = proto_register_protocol("Session Initiation Protocol (SIP as raw text)",
3626                                                 "Raw_SIP", "raw_sip");
3627         new_register_dissector("sip", dissect_sip, proto_sip);
3628         sip_handle = find_dissector("sip");
3629         register_dissector("sip.tcp", dissect_sip_tcp, proto_sip);
3630         sip_tcp_handle = find_dissector("sip.tcp");
3631
3632         /* Required function calls to register the header fields and subtrees used */
3633         proto_register_field_array(proto_sip, hf, array_length(hf));
3634         proto_register_subtree_array(ett, array_length(ett));
3635         proto_register_subtree_array(ett_raw, array_length(ett_raw));
3636
3637         /* SIP content type and internet media type used by other dissectors are the same */
3638         media_type_dissector_table = find_dissector_table("media_type");
3639
3640         sip_module = prefs_register_protocol(proto_sip, proto_reg_handoff_sip);
3641
3642   prefs_register_uint_preference(sip_module, "tcp.port",
3643                                  "SIP TCP Port",
3644                                  "SIP Server TCP Port",
3645                                  10, &sip_tcp_port);
3646   prefs_register_uint_preference(sip_module, "tls.port",
3647                                  "SIP TLS Port",
3648                                  "SIP Server TLS Port",
3649                                  10, &sip_tls_port);
3650
3651         prefs_register_bool_preference(sip_module, "display_raw_text",
3652                 "Display raw text for SIP message",
3653                 "Specifies that the raw text of the "
3654                 "SIP message should be displayed "
3655                 "in addition to the dissection tree",
3656                 &global_sip_raw_text);
3657         prefs_register_bool_preference(sip_module, "strict_sip_version",
3658                 "Enforce strict SIP version check (" SIP2_HDR ")",
3659                 "If enabled, only " SIP2_HDR " traffic will be dissected as SIP. "
3660                 "Disable it to allow SIP traffic with a different version "
3661                 "to be dissected as SIP.",
3662                 &strict_sip_version);
3663         prefs_register_bool_preference(sip_module, "desegment_headers",
3664             "Reassemble SIP headers spanning multiple TCP segments",
3665             "Whether the SIP dissector should reassemble headers "
3666             "of a request spanning multiple TCP segments. "
3667                 "To use this option, you must also enable "
3668         "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
3669             &sip_desegment_headers);
3670         prefs_register_bool_preference(sip_module, "desegment_body",
3671             "Reassemble SIP bodies spanning multiple TCP segments",
3672             "Whether the SIP dissector should use the "
3673             "\"Content-length:\" value, if present, to reassemble "
3674             "the body of a request spanning multiple TCP segments, "
3675             "and reassemble chunked data spanning multiple TCP segments. "
3676                 "To use this option, you must also enable "
3677         "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
3678             &sip_desegment_body);
3679
3680         register_init_routine(&sip_init_protocol);
3681     register_heur_dissector_list("sip", &heur_subdissector_list);
3682         /* Register for tapping */
3683         sip_tap = register_tap("sip");
3684 }
3685
3686 void
3687 proto_reg_handoff_sip(void)
3688 {
3689   static gboolean sip_prefs_initialized = FALSE;
3690
3691   if (sip_prefs_initialized) {
3692     dissector_delete("tcp.port", saved_sip_tcp_port, sip_tcp_handle);
3693     ssl_dissector_delete(saved_sip_tls_port, "sip.tcp", TRUE);
3694   } else {
3695     sip_prefs_initialized = TRUE;
3696   }
3697   /* Set our port number for future use */
3698   saved_sip_tcp_port = sip_tcp_port;
3699   dissector_add("tcp.port", saved_sip_tcp_port, sip_tcp_handle);
3700   saved_sip_tls_port = sip_tls_port;
3701   ssl_dissector_add(saved_sip_tls_port, "sip.tcp", TRUE);
3702
3703         dissector_add("udp.port", UDP_PORT_SIP, sip_handle);
3704         dissector_add_string("media_type", "message/sip", sip_handle);
3705         sigcomp_handle = find_dissector("sigcomp");
3706
3707         heur_dissector_add("udp", dissect_sip_heur, proto_sip);
3708         heur_dissector_add("tcp", dissect_sip_tcp_heur, proto_sip);
3709         heur_dissector_add("sctp", dissect_sip_heur, proto_sip);
3710 }