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