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