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