MSWSP: add two more Property Sets
[wireshark-wip.git] / epan / dissectors / packet-sip.c
blob0dfdd8cdcc5db72756181743ef0726f43d7e20ef
1 /* packet-sip.c
2 * Routines for the Session Initiation Protocol (SIP) dissection.
3 * RFCs 3261-3264
5 * TODO:
6 * hf_ display filters for headers of SIP extension RFCs (ongoing)
8 * Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi>
9 * Copyright 2001, Jean-Francois Mule <jfm@cablelabs.com>
10 * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
11 * Copyright 2011, Anders Broman <anders.broman@ericsson.com>, Johan Wahl <johan.wahl@ericsson.com>
13 * $Id$
15 * Wireshark - Network traffic analyzer
16 * By Gerald Combs <gerald@wireshark.org>
17 * Copyright 1998 Gerald Combs
19 * Copied from packet-cops.c
21 * This program is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU General Public License
23 * as published by the Free Software Foundation; either version 2
24 * of the License, or (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with this program; if not, write to the Free Software
33 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
36 #include "config.h"
38 #include <ctype.h>
40 #include <glib.h>
42 #include <epan/packet.h>
43 #include <epan/exceptions.h>
44 #include <epan/prefs.h>
45 #include <epan/req_resp_hdrs.h>
46 #include <epan/wmem/wmem.h>
47 #include <epan/strutil.h>
48 #include <epan/tap.h>
49 #include <epan/exported_pdu.h>
50 #include <epan/expert.h>
52 #include <wsutil/str_util.h>
54 #include "packet-tcp.h"
55 #include "packet-ssl.h"
57 #include "packet-isup.h"
58 #include "packet-sip.h"
60 #include "packet-sdp.h" /* SDP needs a transport layer to determine request/response */
63 #define TCP_PORT_SIP 5060
64 #define UDP_PORT_SIP 5060
65 #define TLS_PORT_SIP 5061
66 #define DEFAULT_SIP_PORT_RANGE "5060"
68 static dissector_handle_t sip_tcp_handle;
70 static gint sip_tap = -1;
71 static gint exported_pdu_tap = -1;
72 static dissector_handle_t sigcomp_handle;
73 static dissector_handle_t sip_diag_handle;
75 /* Initialize the protocol and registered fields */
76 static gint proto_sip = -1;
77 static gint proto_raw_sip = -1;
78 static gint hf_sip_raw_line = -1;
79 static gint hf_sip_msg_hdr = -1;
80 static gint hf_sip_Method = -1;
81 static gint hf_Request_Line = -1;
82 static gint hf_sip_ruri = -1;
83 static gint hf_sip_ruri_user = -1;
84 static gint hf_sip_ruri_host = -1;
85 static gint hf_sip_ruri_port = -1;
86 static gint hf_sip_ruri_param = -1;
87 static gint hf_sip_Status_Code = -1;
88 static gint hf_sip_Status_Line = -1;
89 static gint hf_sip_display = -1;
90 static gint hf_sip_to_addr = -1;
91 static gint hf_sip_to_user = -1;
92 static gint hf_sip_to_host = -1;
93 static gint hf_sip_to_port = -1;
94 static gint hf_sip_to_param = -1;
95 static gint hf_sip_to_tag = -1;
96 static gint hf_sip_from_addr = -1;
97 static gint hf_sip_from_user = -1;
98 static gint hf_sip_from_host = -1;
99 static gint hf_sip_from_port = -1;
100 static gint hf_sip_from_param = -1;
101 static gint hf_sip_from_tag = -1;
102 static gint hf_sip_tag = -1;
103 static gint hf_sip_pai_addr = -1;
104 static gint hf_sip_pai_user = -1;
105 static gint hf_sip_pai_host = -1;
106 static gint hf_sip_pai_port = -1;
107 static gint hf_sip_pai_param = -1;
108 static gint hf_sip_pmiss_addr = -1;
109 static gint hf_sip_pmiss_user = -1;
110 static gint hf_sip_pmiss_host = -1;
111 static gint hf_sip_pmiss_port = -1;
112 static gint hf_sip_pmiss_param = -1;
113 static gint hf_sip_ppi_addr = -1;
114 static gint hf_sip_ppi_user = -1;
115 static gint hf_sip_ppi_host = -1;
116 static gint hf_sip_ppi_port = -1;
117 static gint hf_sip_ppi_param = -1;
118 static gint hf_sip_tc_addr = -1;
119 static gint hf_sip_tc_user = -1;
120 static gint hf_sip_tc_host = -1;
121 static gint hf_sip_tc_port = -1;
122 static gint hf_sip_tc_param = -1;
123 static gint hf_sip_tc_turi = -1;
124 static gint hf_sip_contact_param = -1;
125 static gint hf_sip_resend = -1;
126 static gint hf_sip_original_frame = -1;
127 static gint hf_sip_matching_request_frame = -1;
128 static gint hf_sip_response_time = -1;
129 static gint hf_sip_release_time = -1;
130 static gint hf_sip_curi = -1;
131 static gint hf_sip_curi_user = -1;
132 static gint hf_sip_curi_host = -1;
133 static gint hf_sip_curi_port = -1;
134 static gint hf_sip_curi_param = -1;
135 static gint hf_sip_route = -1;
136 static gint hf_sip_route_user = -1;
137 static gint hf_sip_route_host = -1;
138 static gint hf_sip_route_port = -1;
139 static gint hf_sip_route_param = -1;
140 static gint hf_sip_record_route = -1;
141 static gint hf_sip_record_route_user = -1;
142 static gint hf_sip_record_route_host = -1;
143 static gint hf_sip_record_route_port = -1;
144 static gint hf_sip_record_route_param = -1;
146 static gint hf_sip_auth = -1;
147 static gint hf_sip_auth_scheme = -1;
148 static gint hf_sip_auth_digest_response = -1;
149 static gint hf_sip_auth_nc = -1;
150 static gint hf_sip_auth_username = -1;
151 static gint hf_sip_auth_realm = -1;
152 static gint hf_sip_auth_nonce = -1;
153 static gint hf_sip_auth_algorithm = -1;
154 static gint hf_sip_auth_opaque = -1;
155 static gint hf_sip_auth_qop = -1;
156 static gint hf_sip_auth_cnonce = -1;
157 static gint hf_sip_auth_uri = -1;
158 static gint hf_sip_auth_domain = -1;
159 static gint hf_sip_auth_stale = -1;
160 static gint hf_sip_auth_auts = -1;
161 static gint hf_sip_auth_rspauth = -1;
162 static gint hf_sip_auth_nextnonce = -1;
163 static gint hf_sip_auth_ik = -1;
164 static gint hf_sip_auth_ck = -1;
166 static gint hf_sip_cseq_seq_no = -1;
167 static gint hf_sip_cseq_method = -1;
169 static gint hf_sip_via_transport = -1;
170 static gint hf_sip_via_sent_by_address = -1;
171 static gint hf_sip_via_sent_by_port = -1;
172 static gint hf_sip_via_branch = -1;
173 static gint hf_sip_via_maddr = -1;
174 static gint hf_sip_via_rport = -1;
175 static gint hf_sip_via_received = -1;
176 static gint hf_sip_via_ttl = -1;
177 static gint hf_sip_via_comp = -1;
178 static gint hf_sip_via_sigcomp_id = -1;
180 static gint hf_sip_rack_rseq_no = -1;
181 static gint hf_sip_rack_cseq_no = -1;
182 static gint hf_sip_rack_cseq_method = -1;
184 static gint hf_sip_msg_body = -1;
186 /* Initialize the subtree pointers */
187 static gint ett_sip = -1;
188 static gint ett_sip_reqresp = -1;
189 static gint ett_sip_hdr = -1;
190 static gint ett_sip_ext_hdr = -1;
191 static gint ett_raw_text = -1;
192 static gint ett_sip_element = -1;
193 static gint ett_sip_hist = -1;
194 static gint ett_sip_uri = -1;
195 static gint ett_sip_contact_item = -1;
196 static gint ett_sip_message_body = -1;
197 static gint ett_sip_cseq = -1;
198 static gint ett_sip_via = -1;
199 static gint ett_sip_reason = -1;
200 static gint ett_sip_rack = -1;
201 static gint ett_sip_route = -1;
202 static gint ett_sip_record_route = -1;
203 static gint ett_sip_ruri = -1;
204 static gint ett_sip_to_uri = -1;
205 static gint ett_sip_curi = -1;
206 static gint ett_sip_from_uri = -1;
207 static gint ett_sip_pai_uri = -1;
208 static gint ett_sip_pmiss_uri = -1;
209 static gint ett_sip_ppi_uri = -1;
210 static gint ett_sip_tc_uri = -1;
212 static expert_field ei_sip_unrecognized_header = EI_INIT;
213 static expert_field ei_sip_header_not_terminated = EI_INIT;
215 /* PUBLISH method added as per http://www.ietf.org/internet-drafts/draft-ietf-sip-publish-01.txt */
216 static const char *sip_methods[] = {
217 #define SIP_METHOD_INVALID 0
218 "<Invalid method>", /* Pad so that the real methods start at index 1 */
219 #define SIP_METHOD_ACK 1
220 "ACK",
221 #define SIP_METHOD_BYE 2
222 "BYE",
223 #define SIP_METHOD_CANCEL 3
224 "CANCEL",
225 #define SIP_METHOD_DO 4
226 "DO",
227 #define SIP_METHOD_INFO 5
228 "INFO",
229 #define SIP_METHOD_INVITE 6
230 "INVITE",
231 #define SIP_METHOD_MESSAGE 7
232 "MESSAGE",
233 #define SIP_METHOD_NOTIFY 8
234 "NOTIFY",
235 #define SIP_METHOD_OPTIONS 9
236 "OPTIONS",
237 #define SIP_METHOD_PRACK 10
238 "PRACK",
239 #define SIP_METHOD_QAUTH 11
240 "QAUTH",
241 #define SIP_METHOD_REFER 12
242 "REFER",
243 #define SIP_METHOD_REGISTER 13
244 "REGISTER",
245 #define SIP_METHOD_SPRACK 14
246 "SPRACK",
247 #define SIP_METHOD_SUBSCRIBE 15
248 "SUBSCRIBE",
249 #define SIP_METHOD_UPDATE 16
250 "UPDATE",
251 #define SIP_METHOD_PUBLISH 17
252 "PUBLISH"
255 /* from RFC 3261
256 * Updated with info from http://www.iana.org/assignments/sip-parameters
257 * (last updated 2009-11-11)
258 * Updated with: http://www.ietf.org/internet-drafts/draft-ietf-sip-resource-priority-05.txt
260 typedef struct {
261 const char *name;
262 const char *compact_name;
263 } sip_header_t;
264 static const sip_header_t sip_headers[] = {
265 { "Unknown-header", NULL }, /* 0 Pad so that the real headers start at index 1 */
266 { "Accept", NULL }, /* 1 */
267 #define POS_ACCEPT 1
268 { "Accept-Contact", "a" }, /* 2 RFC3841 */
269 #define POS_ACCEPT_CONTACT 2
270 { "Accept-Encoding", NULL }, /* 3 */
271 #define POS_ACCEPT_ENCODING 3
272 { "Accept-Language", NULL }, /* 4 */
273 #define POS_ACCEPT_LANGUAGE 4
274 { "Accept-Resource-Priority", NULL }, /* 5 RFC4412 */
275 #define POS_ACCEPT_RESOURCE_PRIORITY 5
276 { "Alert-Info", NULL },
277 #define POS_ALERT_INFO 6
278 { "Allow", NULL },
279 #define POS_ALLOW 7
280 { "Allow-Events", "u" }, /* 8 RFC3265 */
281 #define POS_ALLOW_EVENTS 8
282 { "Answer-Mode", NULL }, /* 9 RFC5373 */
283 #define POS_ANSWER_MODE 9
284 { "Authentication-Info", NULL },
285 #define POS_AUTHENTICATION_INFO 10
286 { "Authorization", NULL }, /* 11 */
287 #define POS_AUTHORIZATION 11
288 { "Call-ID", "i" },
289 #define POS_CALL_ID 12
290 { "Call-Info", NULL },
291 #define POS_CALL_INFO 13
292 { "Contact", "m" },
293 #define POS_CONTACT 14
294 { "Content-Disposition", NULL },
295 #define POS_CONTENT_DISPOSITION 15
296 { "Content-Encoding", "e" }, /* 16 */
297 #define POS_CONTENT_ENCODING 16
298 { "Content-Language", NULL },
299 #define POS_CONTENT_LANGUAGE 17
300 { "Content-Length", "l" },
301 #define POS_CONTENT_LENGTH 18
302 { "Content-Type", "c" },
303 #define POS_CONTENT_TYPE 19
304 { "CSeq", NULL },
305 #define POS_CSEQ 20
306 { "Date", NULL }, /* 21 */
307 #define POS_DATE 21
308 /* Encryption (Deprecated) [RFC3261] */
309 { "Error-Info", NULL }, /* 22 */
310 #define POS_ERROR_INFO 22
311 { "Event", "o" }, /* 23 */
312 #define POS_EVENT 23
313 { "Expires", NULL }, /* 24 */
314 #define POS_EXPIRES 24
315 { "Feature-Caps", NULL }, /* 25 [RFC6809 */
316 #define POS_FEATURE_CAPS 25
317 { "Flow-Timer", NULL }, /* 26 RFC5626 */
318 #define POS_FLOW_TIMER 26
319 { "From", "f" }, /* 27 */
320 #define POS_FROM 27
322 { "Geolocation", NULL }, /* 28 */
323 #define POS_GEOLOCATION 28
324 { "Geolocation-Error", NULL }, /* 29 */
325 #define POS_GEOLOCATION_ERROR 29
326 { "Geolocation-Routing", NULL }, /* 30 */
327 #define POS_GEOLOCATION_ROUTING 30
329 /* Hide [RFC3261] (deprecated)*/
330 { "History-Info", NULL }, /* 31 RFC4244 */
331 #define POS_HISTORY_INFO 31
332 { "Identity", "y" }, /* 32 RFC4474 */
333 #define POS_IDENTITY 32
334 { "Identity-Info", "n" }, /* 33 RFC4474 */
335 #define POS_IDENTITY_INFO 33
336 { "Info-Package", NULL }, /* 34 RFC-ietf-sipcore-info-events-10.txt */
337 #define POS_INFO_PKG 34
338 { "In-Reply-To", NULL }, /* 35 RFC3261 */
339 #define POS_IN_REPLY_TO 35
340 { "Join", NULL }, /* 36 RFC3911 */
341 #define POS_JOIN 36
342 { "Max-Breadth", NULL }, /* 37 RFC5393*/
343 #define POS_MAX_BREADTH 37
344 { "Max-Forwards", NULL }, /* 38 */
345 #define POS_MAX_FORWARDS 38
346 { "MIME-Version", NULL }, /* 39 */
347 #define POS_MIME_VERSION 39
348 { "Min-Expires", NULL }, /* 40 */
349 #define POS_MIN_EXPIRES 40
350 { "Min-SE", NULL }, /* 41 RFC4028 */
351 #define POS_MIN_SE 41
352 { "Organization", NULL }, /* 42 RFC3261 */
353 #define POS_ORGANIZATION 42
354 { "P-Access-Network-Info", NULL }, /* 43 RFC3455 */
355 #define POS_P_ACCESS_NETWORK_INFO 43
356 { "P-Answer-State", NULL }, /* 44 RFC4964 */
357 #define POS_P_ANSWER_STATE 44
358 { "P-Asserted-Identity", NULL }, /* 45 RFC3325 */
359 #define POS_P_ASSERTED_IDENTITY 45
360 { "P-Asserted-Service", NULL }, /* 46 RFC6050 */
361 #define POS_P_ASSERTED_SERV 46
362 { "P-Associated-URI", NULL }, /* 47 RFC3455 */
363 #define POS_P_ASSOCIATED_URI 47
364 { "P-Called-Party-ID", NULL }, /* 48 RFC3455 */
365 #define POS_P_CALLED_PARTY_ID 48
366 { "P-Charging-Function-Addresses", NULL }, /* 49 RFC3455 */
367 #define POS_P_CHARGING_FUNC_ADDRESSES 49
368 { "P-Charging-Vector", NULL }, /* 50 RFC3455 */
369 #define POS_P_CHARGING_VECTOR 50
370 { "P-DCS-Trace-Party-ID", NULL }, /* 51 RFC5503 */
371 #define POS_P_DCS_TRACE_PARTY_ID 51
372 { "P-DCS-OSPS", NULL }, /* 52 RFC5503 */
373 #define POS_P_DCS_OSPS 52
374 { "P-DCS-Billing-Info", NULL }, /* 53 RFC5503 */
375 #define POS_P_DCS_BILLING_INFO 53
376 { "P-DCS-LAES", NULL }, /* 54 RFC5503 */
377 #define POS_P_DCS_LAES 54
378 { "P-DCS-Redirect", NULL }, /* 55 RFC5503 */
379 #define POS_P_DCS_REDIRECT 55
380 { "P-Early-Media", NULL }, /* 56 RFC5009 */
381 #define POS_P_EARLY_MEDIA 56
382 { "P-Media-Authorization", NULL }, /* 57 RFC3313 */
383 #define POS_P_MEDIA_AUTHORIZATION 57
384 { "P-Preferred-Identity", NULL }, /* 58 RFC3325 */
385 #define POS_P_PREFERRED_IDENTITY 58
386 { "P-Preferred-Service", NULL }, /* 58 RFC6050 */
387 #define POS_P_PREFERRED_SERV 59
388 { "P-Profile-Key", NULL }, /* 60 RFC5002 */
389 #define POS_P_PROFILE_KEY 60
390 { "P-Refused-URI-List", NULL }, /* 61 RFC5318 */
391 #define POS_P_REFUSED_URI_LST 61
392 { "P-Served-User", NULL }, /* 62 RFC5502 */
393 #define POS_P_SERVED_USER 62
394 { "P-User-Database", NULL }, /* 63 RFC4457 */
395 #define POS_P_USER_DATABASE 63
396 { "P-Visited-Network-ID", NULL }, /* 64 RFC3455 */
397 #define POS_P_VISITED_NETWORK_ID 64
398 { "Path", NULL }, /* 65 RFC3327 */
399 #define POS_PATH 65
400 { "Permission-Missing", NULL }, /* 66 RFC5360 */
401 #define POS_PERMISSION_MISSING 66
402 { "Policy-Contact", NULL }, /* 67 RFC3261 */
403 #define POS_POLICY_CONTACT 67
404 { "Policy-ID", NULL }, /* 68 RFC3261 */
405 #define POS_POLICY_ID 68
406 { "Priority", NULL }, /* 69 RFC3261 */
407 #define POS_PRIORITY 69
408 { "Priv-Answer-Mode", NULL }, /* 70 RFC5373 */
409 #define POS_PRIV_ANSWER_MODE 70
410 { "Privacy", NULL }, /* 71 RFC3323 */
411 #define POS_PRIVACY 71
412 { "Proxy-Authenticate", NULL }, /* 72 */
413 #define POS_PROXY_AUTHENTICATE 72
414 { "Proxy-Authorization", NULL }, /* 73 */
415 #define POS_PROXY_AUTHORIZATION 73
416 { "Proxy-Require", NULL }, /* 74 */
417 #define POS_PROXY_REQUIRE 74
418 { "RAck", NULL }, /* 75 RFC3262 */
419 #define POS_RACK 75
420 { "Reason", NULL }, /* 76 RFC3326 */
421 #define POS_REASON 76
422 { "Reason-Phrase", NULL }, /* 77 RFC3326 */
423 #define POS_REASON_PHRASE 77
424 { "Record-Route", NULL }, /* 78 */
425 #define POS_RECORD_ROUTE 78
426 { "Recv-Info", NULL }, /* 79 RFC-ietf-sipcore-info-events-10.txt*/
427 #define POS_RECV_INFO 79
428 { "Refer-Sub", NULL }, /* 80 RFC4488 */
429 #define POS_REFER_SUB 80
430 { "Refer-To", "r" }, /* 81 RFC3515 */
431 #define POS_REFER_TO 81
432 { "Referred-By", "b" }, /* 82 RFC3892 */
433 #define POS_REFERED_BY 82
434 { "Reject-Contact", "j" }, /* 83 RFC3841 */
435 #define POS_REJECT_CONTACT 83
436 { "Replaces", NULL }, /* 84 RFC3891 */
437 #define POS_REPLACES 84
438 { "Reply-To", NULL }, /* 85 RFC3261 */
439 #define POS_REPLY_TO 85
440 { "Request-Disposition", "d" }, /* 86 RFC3841 */
441 #define POS_REQUEST_DISPOSITION 86
442 { "Require", NULL }, /* 87 RFC3261 */
443 #define POS_REQUIRE 87
444 { "Resource-Priority", NULL }, /* 88 RFC4412 */
445 #define POS_RESOURCE_PRIORITY 88
446 /*{ "Response-Key (Deprecated) [RFC3261]*/
447 { "Retry-After", NULL }, /* 89 RFC3261 */
448 #define POS_RETRY_AFTER 89
449 { "Route", NULL }, /* 90 RFC3261 */
450 #define POS_ROUTE 90
451 { "RSeq", NULL }, /* 91 RFC3262 */
452 #define POS_RSEQ 91
453 { "Security-Client", NULL }, /* 92 RFC3329 */
454 #define POS_SECURITY_CLIENT 92
455 { "Security-Server", NULL }, /* 93 RFC3329 */
456 #define POS_SECURITY_SERVER 93
457 { "Security-Verify", NULL }, /* 94 RFC3329 */
458 #define POS_SECURITY_VERIFY 94
459 { "Server", NULL }, /* 95 RFC3261 */
460 #define POS_SERVER 95
461 { "Service-Route", NULL }, /* 96 RFC3608 */
462 #define POS_SERVICE_ROUTE 96
463 { "Session-Expires", "x" }, /* 97 RFC4028 */
464 #define POS_SESSION_EXPIRES 97
465 { "SIP-ETag", NULL }, /* 98 RFC3903 */
466 #define POS_SIP_ETAG 98
467 { "SIP-If-Match", NULL }, /* 99 RFC3903 */
468 #define POS_SIP_IF_MATCH 99
469 { "Subject", "s" }, /* 100 RFC3261 */
470 #define POS_SUBJECT 100
471 { "Subscription-State", NULL }, /* 101 RFC3265 */
472 #define POS_SUBSCRIPTION_STATE 101
473 { "Supported", "k" }, /* 102 RFC3261 */
474 #define POS_SUPPORTED 102
475 { "Suppress-If-Match", NULL }, /* 103 RFC5839 */
476 #define POS_SUPPRESS_IF_MATCH 103
477 { "Target-Dialog", NULL }, /* 104 RFC4538 */
478 #define POS_TARGET_DIALOG 104
479 { "Timestamp", NULL }, /* 105 RFC3261 */
480 #define POS_TIMESTAMP 105
481 { "To", "t" }, /* 106 RFC3261 */
482 #define POS_TO 106
483 { "Trigger-Consent", NULL }, /* 107 RFC5360 */
484 #define POS_TRIGGER_CONSENT 107
485 { "Unsupported", NULL }, /* 108 RFC3261 */
486 #define POS_UNSUPPORTED 108
487 { "User-Agent", NULL }, /* 109 RFC3261 */
488 #define POS_USER_AGENT 109
489 { "Via", "v" }, /* 110 RFC3261 */
490 #define POS_VIA 110
491 { "Warning", NULL }, /* 111 RFC3261 */
492 #define POS_WARNING 111
493 { "WWW-Authenticate", NULL }, /* 112 RFC3261 */
494 #define POS_WWW_AUTHENTICATE 112
495 { "Diversion", NULL }, /* 113 RFC5806 */
496 #define POS_DIVERSION 113
497 { "User-to-User", NULL }, /* 106 draft-johnston-sipping-cc-uui-09 */
498 #define POS_USER_TO_USER 114
504 static gint hf_header_array[] = {
505 -1, /* 0"Unknown-header" - Pad so that the real headers start at index 1 */
506 -1, /* 1"Accept" */
507 -1, /* 2"Accept-Contact" RFC3841 */
508 -1, /* 3"Accept-Encoding" */
509 -1, /* 4"Accept-Language" */
510 -1, /* 5"Accept-Resource-Priority" RFC4412 */
511 -1, /* 6"Alert-Info", */
512 -1, /* 7"Allow", */
513 -1, /* 8"Allow-Events", RFC3265 */
514 -1, /* 9"Answer-Mode" RFC5373 */
515 -1, /* 10"Authentication-Info" */
516 -1, /* 11"Authorization", */
517 -1, /* 12"Call-ID", */
518 -1, /* 13"Call-Info" */
519 -1, /* 14"Contact", */
520 -1, /* 15"Content-Disposition", */
521 -1, /* 16"Content-Encoding", */
522 -1, /* 17"Content-Language", */
523 -1, /* 18"Content-Length", */
524 -1, /* 19"Content-Type", */
525 -1, /* 20"CSeq", */
526 -1, /* 21"Date", */
527 -1, /* 22"Error-Info", */
528 -1, /* 23"Event", */
529 -1, /* 24"Expires", */
530 -1, /* 25"Feature-Caps", */
531 -1, /* 26"Flow-Timer", RFC5626 */
532 -1, /* 27"From", */
533 -1, /* 28"Geolocation", */
534 -1, /* 29"Geolocation-Error", */
535 -1, /* 30"Geolocation-Routing", */
536 -1, /* 31"History-Info", RFC4244 */
537 -1, /* 32"Identity", */
538 -1, /* 33"Identity-Info", RFC4474 */
539 -1, /* 34"Info-Package", RFC-ietf-sipcore-info-events-10.txt */
540 -1, /* 35"In-Reply-To", RFC3261 */
541 -1, /* 36"Join", RFC3911 */
542 -1, /* 37"Max-Breadth" RFC5393 */
543 -1, /* 38"Max-Forwards", */
544 -1, /* 39"MIME-Version", */
545 -1, /* 40"Min-Expires", */
546 -1, /* 41"Min-SE", RFC4028 */
547 -1, /* 42"Organization", */
548 -1, /* 43"P-Access-Network-Info", RFC3455 */
549 -1, /* 44"P-Answer-State", RFC4964 */
550 -1, /* 45"P-Asserted-Identity", RFC3325 */
551 -1, /* 46"P-Asserted-Service", RFC-drage-sipping-service-identification-05.txt */
552 -1, /* 47"P-Associated-URI", RFC3455 */
553 -1, /* 48"P-Called-Party-ID", RFC3455 */
554 -1, /* 49"P-Charging-Function-Addresses", RFC3455 */
555 -1, /* 50"P-Charging-Vector", RFC3455 */
556 -1, /* 51"P-DCS-Trace-Party-ID", RFC3603 */
557 -1, /* 52"P-DCS-OSPS", RFC3603 */
558 -1, /* 53"P-DCS-Billing-Info", RFC3603 */
559 -1, /* 54"P-DCS-LAES", RFC3603 */
560 -1, /* 55"P-DCS-Redirect", RFC3603 */
561 -1, /* 56"P-Early-Media", */
562 -1, /* 57"P-Media-Authorization", RFC3313 */
563 -1, /* 58"P-Preferred-Identity", RFC3325 */
564 -1, /* 59"P-Preferred-Service", RFC-drage-sipping-service-identification-05.txt */
565 -1, /* 60"P-Profile-Key", */
566 -1, /* 61"P-Refused-URI-List", RFC5318 */
567 -1, /* 62"P-Served-User", RFC5502 */
568 -1, /* 63"P-User-Database RFC4457 */
569 -1, /* 64"P-Visited-Network-ID", RFC3455 */
570 -1, /* 65"Path", RFC3327 */
571 -1, /* 66"Permission-Missing" RFC5360 */
572 -1, /* 67"Policy-Contact" RFC5360 */
573 -1, /* 68"Policy-ID" RFC5360 */
574 -1, /* 69"Priority" */
575 -1, /* 70"Priv-Answer-mode" RFC5373 */
576 -1, /* 71"Privacy", RFC3323 */
577 -1, /* 72"Proxy-Authenticate", */
578 -1, /* 73"Proxy-Authorization", */
579 -1, /* 74"Proxy-Require", */
580 -1, /* 75"RAck", RFC3262 */
581 -1, /* 76"Reason", RFC3326 */
582 -1, /* 77"Reason-Phrase", RFC3326 */
583 -1, /* 78"Record-Route", */
584 -1, /* 79"Recv-Info", RFC-ietf-sipcore-info-events-10.txt */
585 -1, /* 80"Refer-Sub",", RFC4488 */
586 -1, /* 81"Refer-To", RFC3515 */
587 -1, /* 82"Referred-By", */
588 -1, /* 83"Reject-Contact", RFC3841 */
589 -1, /* 84"Replaces", RFC3891 */
590 -1, /* 85"Reply-To", RFC3261 */
591 -1, /* 86"Request-Disposition", RFC3841 */
592 -1, /* 87"Require", RFC3261 */
593 -1, /* 88"Resource-Priority", RFC4412 */
594 -1, /* 89"Retry-After", RFC3261 */
595 -1, /* 90"Route", RFC3261 */
596 -1, /* 91"RSeq", RFC3262 */
597 -1, /* 92"Security-Client", RFC3329 */
598 -1, /* 93"Security-Server", RFC3329 */
599 -1, /* 94"Security-Verify", RFC3329 */
600 -1, /* 95"Server", RFC3261 */
601 -1, /* 96"Service-Route", RFC3608 */
602 -1, /* 97"Session-Expires", RFC4028 */
603 -1, /* 98"SIP-ETag", RFC3903 */
604 -1, /* 99"SIP-If-Match", RFC3903 */
605 -1, /* 100"Subject", RFC3261 */
606 -1, /* 101"Subscription-State", RFC3265 */
607 -1, /* 102"Supported", RFC3261 */
608 -1, /* 103"Suppress-If-Match", RFC4538 */
609 -1, /* 104"Target-Dialog", RFC4538 */
610 -1, /* 105"Timestamp", RFC3261 */
611 -1, /* 106"To", RFC3261 */
612 -1, /* 107"Trigger-Consent" RFC5380 */
613 -1, /* 108"Unsupported", RFC3261 */
614 -1, /* 109"User-Agent", RFC3261 */
615 -1, /* 110"Via", RFC3261 */
616 -1, /* 111"Warning", RFC3261 */
617 -1, /* 112"WWW-Authenticate", RFC3261 */
618 -1, /* 113"Diversion", RFC5806 */
619 -1, /* 114"User-to-User", draft-johnston-sipping-cc-uui-09 */
623 /* Track associations between parameter name and hf item */
624 typedef struct {
625 const char *param_name;
626 const gint *hf_item;
627 } header_parameter_t;
629 static header_parameter_t auth_parameters_hf_array[] =
631 {"response", &hf_sip_auth_digest_response},
632 {"nc", &hf_sip_auth_nc},
633 {"username", &hf_sip_auth_username},
634 {"realm", &hf_sip_auth_realm},
635 {"nonce", &hf_sip_auth_nonce},
636 {"algorithm", &hf_sip_auth_algorithm},
637 {"opaque", &hf_sip_auth_opaque},
638 {"qop", &hf_sip_auth_qop},
639 {"cnonce", &hf_sip_auth_cnonce},
640 {"uri", &hf_sip_auth_uri},
641 {"domain", &hf_sip_auth_domain},
642 {"stale", &hf_sip_auth_stale},
643 {"auts", &hf_sip_auth_auts},
644 {"rspauth", &hf_sip_auth_rspauth},
645 {"nextnonce", &hf_sip_auth_nextnonce},
646 {"ik", &hf_sip_auth_ik},
647 {"ck", &hf_sip_auth_ck}
650 static header_parameter_t via_parameters_hf_array[] =
652 {"branch", &hf_sip_via_branch},
653 {"maddr", &hf_sip_via_maddr},
654 {"rport", &hf_sip_via_rport},
655 {"received", &hf_sip_via_received},
656 {"ttl", &hf_sip_via_ttl},
657 {"comp", &hf_sip_via_comp},
658 {"sigcomp-id", &hf_sip_via_sigcomp_id}
662 typedef struct {
663 gint *hf_sip_addr;
664 gint *hf_sip_user;
665 gint *hf_sip_host;
666 gint *hf_sip_port;
667 gint *hf_sip_param;
668 gint *ett_uri;
669 } hf_sip_uri_t;
671 static hf_sip_uri_t sip_pai_uri = {
672 &hf_sip_pai_addr,
673 &hf_sip_pai_user,
674 &hf_sip_pai_host,
675 &hf_sip_pai_port,
676 &hf_sip_pai_param,
677 &ett_sip_pai_uri
680 static hf_sip_uri_t sip_ppi_uri = {
681 &hf_sip_ppi_addr,
682 &hf_sip_ppi_user,
683 &hf_sip_ppi_host,
684 &hf_sip_ppi_port,
685 &hf_sip_ppi_param,
686 &ett_sip_ppi_uri
689 static hf_sip_uri_t sip_pmiss_uri = {
690 &hf_sip_pmiss_addr,
691 &hf_sip_pmiss_user,
692 &hf_sip_pmiss_host,
693 &hf_sip_pmiss_port,
694 &hf_sip_pmiss_param,
695 &ett_sip_pmiss_uri
699 static hf_sip_uri_t sip_tc_uri = {
700 &hf_sip_tc_addr,
701 &hf_sip_tc_user,
702 &hf_sip_tc_host,
703 &hf_sip_tc_port,
704 &hf_sip_tc_param,
705 &ett_sip_tc_uri
708 static hf_sip_uri_t sip_to_uri = {
709 &hf_sip_to_addr,
710 &hf_sip_to_user,
711 &hf_sip_to_host,
712 &hf_sip_to_port,
713 &hf_sip_to_param,
714 &ett_sip_to_uri
717 static hf_sip_uri_t sip_from_uri = {
718 &hf_sip_from_addr,
719 &hf_sip_from_user,
720 &hf_sip_from_host,
721 &hf_sip_from_port,
722 &hf_sip_from_param,
723 &ett_sip_from_uri
726 static hf_sip_uri_t sip_req_uri = {
727 &hf_sip_ruri,
728 &hf_sip_ruri_user,
729 &hf_sip_ruri_host,
730 &hf_sip_ruri_port,
731 &hf_sip_ruri_param,
732 &ett_sip_ruri
735 static hf_sip_uri_t sip_contact_uri = {
736 &hf_sip_curi,
737 &hf_sip_curi_user,
738 &hf_sip_curi_host,
739 &hf_sip_curi_port,
740 &hf_sip_curi_param,
741 &ett_sip_curi
744 static hf_sip_uri_t sip_route_uri = {
745 &hf_sip_route,
746 &hf_sip_route_user,
747 &hf_sip_route_host,
748 &hf_sip_route_port,
749 &hf_sip_route_param,
750 &ett_sip_route
753 static hf_sip_uri_t sip_record_route_uri = {
754 &hf_sip_record_route,
755 &hf_sip_record_route_user,
756 &hf_sip_record_route_host,
757 &hf_sip_record_route_port,
758 &hf_sip_record_route_param,
759 &ett_sip_record_route
763 * Type of line. It's either a SIP Request-Line, a SIP Status-Line, or
764 * another type of line.
766 typedef enum {
767 REQUEST_LINE,
768 STATUS_LINE,
769 OTHER_LINE
770 } line_type_t;
772 /* Preferences */
773 static guint sip_tls_port = TLS_PORT_SIP;
774 static range_t *global_sip_tcp_port_range;
776 /* global_sip_raw_text determines whether we are going to display */
777 /* the raw text of the SIP message, much like the MEGACO dissector does. */
778 static gboolean global_sip_raw_text = FALSE;
779 /* global_sip_raw_text_without_crlf determines whether we are going to display */
780 /* the raw text of the SIP message with or without the '\r\n'. */
781 static gboolean global_sip_raw_text_without_crlf = FALSE;
782 /* strict_sip_version determines whether the SIP dissector enforces
783 * the SIP version to be "SIP/2.0". */
784 static gboolean strict_sip_version = TRUE;
787 * desegmentation of SIP headers
788 * (when we are over TCP or another protocol providing the desegmentation API)
790 static gboolean sip_desegment_headers = TRUE;
793 * desegmentation of SIP bodies
794 * (when we are over TCP or another protocol providing the desegmentation API)
796 static gboolean sip_desegment_body = TRUE;
799 * same source port for retransmissions
801 static gboolean sip_retrans_the_same_sport = TRUE;
803 /* Extension header subdissectors */
804 static dissector_table_t ext_hdr_subdissector_table;
806 /* Forward declaration we need below */
807 void proto_reg_handoff_sip(void);
808 static gboolean dissect_sip_common(tvbuff_t *tvb, int offset, packet_info *pinfo,
809 proto_tree *tree, gboolean is_heur, gboolean use_reassembly);
810 static line_type_t sip_parse_line(tvbuff_t *tvb, int offset, gint linelen,
811 guint *token_1_len);
812 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
813 guint meth_len, guint *meth_idx);
814 static gint sip_is_known_sip_header(gchar *header_name, guint header_len);
815 static void dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint offset,
816 guint meth_len, gint linelen);
817 static void dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint line_end, gint offset);
818 static void tvb_raw_text_add(tvbuff_t *tvb, int offset, int length, proto_tree *tree);
819 static guint sip_is_packet_resend(packet_info *pinfo,
820 gchar* cseq_method,
821 gchar* call_id,
822 guchar cseq_number_set, guint32 cseq_number,
823 line_type_t line_type);
825 static guint sip_find_request(packet_info *pinfo,
826 gchar* cseq_method,
827 gchar* call_id,
828 guchar cseq_number_set, guint32 cseq_number,
829 guint32 *response_time);
831 static guint sip_find_invite(packet_info *pinfo,
832 gchar* cseq_method,
833 gchar* call_id,
834 guchar cseq_number_set, guint32 cseq_number,
835 guint32 *response_time);
837 /* SIP content type and internet media type used by other dissectors
838 * are the same. List of media types from IANA at:
839 * http://www.iana.org/assignments/media-types/index.html */
840 static dissector_table_t media_type_dissector_table;
842 static heur_dissector_list_t heur_subdissector_list;
844 #define SIP2_HDR "SIP/2.0"
845 #define SIP2_HDR_LEN 7
847 /* Store the info needed by the SIP tap for one packet */
848 static sip_info_value_t *stat_info;
850 /* The buffer size for the cseq_method name */
851 #define MAX_CSEQ_METHOD_SIZE 16
853 /****************************************************************************
854 * Conversation-type definitions
856 * For each call, keep track of the current cseq number and state of
857 * transaction, in order to be able to detect retransmissions.
859 * Don't use the conversation mechanism, but instead:
860 * - store with each dissected packet original frame (if any)
861 * - maintain a global hash table of
862 * (call_id, source_addr, dest_addr) -> (cseq, transaction_state, frame)
864 * N.B. This is broken for a couple of reasons:
865 * - it won't cope properly with overlapping transactions within the
866 * same dialog
867 * - request response mapping won't work where the response uses a different
868 * address pair from the request
870 * TODO: proper transaction matching uses RFC fields (use Max-forwards or
871 * maybe Via count as extra key to limit view to one hop)
872 ****************************************************************************/
874 static GHashTable *sip_hash = NULL; /* Hash table */
875 static GHashTable *sip_headers_hash = NULL; /* Hash table */
877 /* Types for hash table keys and values */
878 #define MAX_CALL_ID_SIZE 128
879 #define MAGIC_SOURCE_PORT 0
881 /* Conversation-type key */
882 typedef struct
884 char call_id[MAX_CALL_ID_SIZE];
885 address source_address;
886 guint32 source_port;
887 address dest_address;
888 guint32 dest_port;
889 } sip_hash_key;
892 typedef enum
894 nothing_seen,
895 request_seen,
896 provisional_response_seen,
897 final_response_seen
898 } transaction_state_t;
900 /* Current conversation-type value */
901 typedef struct
903 guint32 cseq;
904 transaction_state_t transaction_state;
905 gchar method[MAX_CSEQ_METHOD_SIZE];
906 nstime_t request_time;
907 guint32 response_code;
908 gint frame_number;
909 } sip_hash_value;
911 /* Result to be stored in per-packet info */
912 typedef struct
914 gint original_frame_num;
915 gint response_request_frame_num;
916 gint response_time;
917 } sip_frame_result_value;
920 /************************/
921 /* Hash table functions */
923 /* Equal keys */
924 static gint sip_equal(gconstpointer v, gconstpointer v2)
926 const sip_hash_key* val1 = (const sip_hash_key*)v;
927 const sip_hash_key* val2 = (const sip_hash_key*)v2;
929 /* Call id must match */
930 if (strcmp(val1->call_id, val2->call_id) != 0)
932 return 0;
935 /* Addresses must match */
936 return (ADDRESSES_EQUAL(&(val1->source_address), &(val2->source_address))) &&
937 (val1->source_port == val2->source_port) &&
938 (ADDRESSES_EQUAL(&(val1->dest_address), &(val2->dest_address))) &&
939 (val1->dest_port == val2->dest_port);
943 /* Initializes the hash table each time a new
944 * file is loaded or re-loaded in wireshark */
945 static void
946 sip_init_protocol(void)
948 guint i;
949 gchar *value_copy;
951 /* Destroy any existing hashes. */
952 if (sip_hash)
953 g_hash_table_destroy(sip_hash);
955 /* Now create them again */
956 sip_hash = g_hash_table_new(g_str_hash , sip_equal);
957 /* Create a hashtable with the SIP headers; it will be used to find the related hf entry (POS_x).
958 * This is faster than the previously used for loop.
959 * There is no g_hash_table_destroy as the lifetime is the same as the lifetime of Wireshark.
961 if(!sip_headers_hash){
962 sip_headers_hash = g_hash_table_new(g_str_hash , g_str_equal);
963 for (i = 1; i < array_length(sip_headers); i++){
964 value_copy = g_strdup (sip_headers[i].name);
965 /* Store (and compare) the string in lower case) */
966 ascii_strdown_inplace(value_copy);
967 g_hash_table_insert(sip_headers_hash, (gpointer)value_copy, GINT_TO_POINTER(i));
971 /* Call the export PDU tap with relevant data */
972 static void
973 export_sip_pdu(packet_info *pinfo, tvbuff_t *tvb)
976 exp_pdu_data_t *exp_pdu_data;
977 guint32 tags_bit_field;
979 tags_bit_field = EXP_PDU_TAG_IP_SRC_BIT + EXP_PDU_TAG_IP_DST_BIT + EXP_PDU_TAG_SRC_PORT_BIT+
980 EXP_PDU_TAG_DST_PORT_BIT + EXP_PDU_TAG_ORIG_FNO_BIT;
982 exp_pdu_data = load_export_pdu_tags(pinfo, "sip", -1, tags_bit_field);
984 exp_pdu_data->tvb_length = tvb_length(tvb);
985 exp_pdu_data->pdu_tvb = tvb;
987 tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);
991 /* Structure to collect info about a sip uri */
992 typedef struct _uri_offset_info
994 gint display_name_start;
995 gint display_name_end;
996 gint uri_start;
997 gint uri_end;
998 gint uri_parameters_start;
999 gint uri_parameters_end;
1000 gint name_addr_start;
1001 gint name_addr_end;
1002 gint uri_user_start;
1003 gint uri_user_end;
1004 gint uri_host_start;
1005 gint uri_host_end;
1006 gint uri_host_port_start;
1007 gint uri_host_port_end;
1008 } uri_offset_info;
1010 static void
1011 sip_uri_offset_init(uri_offset_info *uri_offsets){
1013 /* Initialize the uri_offsets */
1014 uri_offsets->display_name_start = -1;
1015 uri_offsets->display_name_end = -1;
1016 uri_offsets->uri_start = -1;
1017 uri_offsets->uri_end = -1;
1018 uri_offsets->uri_parameters_start = -1;
1019 uri_offsets->uri_parameters_end = -1;
1020 uri_offsets->name_addr_start = -1;
1021 uri_offsets->name_addr_end = -1;
1022 uri_offsets->uri_user_start = -1;
1023 uri_offsets->uri_user_end = -1;
1024 uri_offsets->uri_host_start = -1;
1025 uri_offsets->uri_host_end = -1;
1026 uri_offsets->uri_host_port_start = -1;
1027 uri_offsets->uri_host_port_end = -1;
1030 /* Code to parse a sip uri.
1031 * Returns Offset end off parsing or -1 for unsuccessful parsing
1032 * - sip_uri_offset_init() must have been called first.
1034 static gint
1035 dissect_sip_uri(tvbuff_t *tvb, packet_info *pinfo _U_, gint start_offset,
1036 gint line_end_offset, uri_offset_info *uri_offsets)
1038 gchar c = '\0';
1039 gint current_offset;
1040 gint queried_offset;
1041 gint comma_offset;
1042 gint semicolon_offset;
1043 gint parameter_end_offset;
1044 gboolean in_ipv6 = FALSE;
1046 /* skip Spaces and Tabs */
1047 current_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1049 if(current_offset >= line_end_offset) {
1050 /* Nothing to parse */
1051 return -1;
1053 /* Set uri start offset in case this was called directly */
1054 uri_offsets->uri_start = current_offset;
1056 /* Check if it's really a sip uri ( it might be a tel uri, parse that?) */
1057 tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ':');
1058 if (tvb_strneql(tvb, current_offset, "sip", 3) != 0)
1059 return -1;
1061 if(uri_offsets->uri_end == -1)
1063 /* name-addr form was NOT used e.g no closing ">" */
1064 /* look for the first ',' or ';' which will mark the end of this URI
1065 * In this case a semicolon indicates a header field parameter, and not an uri parameter.
1067 comma_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ',');
1068 semicolon_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ';');
1070 if (semicolon_offset != -1 && comma_offset != -1)
1072 if(semicolon_offset < comma_offset)
1074 uri_offsets->uri_end = semicolon_offset - 1;
1076 else
1078 uri_offsets->uri_end = comma_offset - 1;
1081 else
1083 if (semicolon_offset != -1)
1085 uri_offsets->uri_end = semicolon_offset - 1;
1087 else if (comma_offset != -1)
1089 uri_offsets->uri_end = comma_offset - 1;
1090 } else {
1092 /* If both offsets are equal to -1, we don't have a semicolon or a comma.
1093 * In that case, we assume that the end of the URI is at the line end
1095 uri_offsets->uri_end = line_end_offset - 3; /* remove '\r\n' */
1098 uri_offsets->name_addr_end = uri_offsets->uri_end;
1101 /* Look for URI address parts (user, host, host-port) */
1103 /* Look for '@' within URI */
1104 queried_offset = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, '@');
1105 if(queried_offset == -1)
1107 /* no '@' = no user part */
1108 uri_offsets->uri_host_start = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, ':')+1;
1110 else
1112 /* with '@' = with user part */
1113 uri_offsets->uri_user_start = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, ':')+1;
1114 uri_offsets->uri_user_end = tvb_find_guint8(tvb, uri_offsets->uri_user_start, uri_offsets->uri_end - uri_offsets->uri_start, '@')-1;
1115 uri_offsets->uri_host_start = uri_offsets->uri_user_end + 2;
1118 /* find URI-Host end*/
1119 parameter_end_offset = uri_offsets->uri_host_start;
1121 in_ipv6 = (tvb_get_guint8(tvb, parameter_end_offset) == '[');
1122 while (parameter_end_offset < line_end_offset)
1124 parameter_end_offset++;
1125 c = tvb_get_guint8(tvb, parameter_end_offset);
1126 switch (c) {
1127 case '>':
1128 case ',':
1129 goto uri_host_end_found;
1130 case ';':
1131 uri_offsets->uri_parameters_start = parameter_end_offset + 1;
1132 goto uri_host_end_found;
1133 case '?':
1134 case ' ':
1135 case '\r':
1136 goto uri_host_end_found;
1137 case ':':
1138 if (!in_ipv6)
1139 goto uri_host_end_found;
1140 break;
1141 case '[':
1142 in_ipv6 = TRUE;
1143 break;
1144 case ']':
1145 in_ipv6 = FALSE;
1146 break;
1147 default :
1148 break;
1152 uri_host_end_found:
1154 uri_offsets->uri_host_end = parameter_end_offset - 1;
1156 if (c == ':')
1158 uri_offsets->uri_host_port_start = parameter_end_offset + 1;
1159 parameter_end_offset = uri_offsets->uri_host_port_start;
1160 while (parameter_end_offset < line_end_offset)
1162 parameter_end_offset++;
1163 c = tvb_get_guint8(tvb, parameter_end_offset);
1164 switch (c) {
1165 case '>':
1166 case ',':
1167 goto uri_host_port_end_found;
1168 case ';':
1169 uri_offsets->uri_parameters_start = parameter_end_offset + 1;
1170 goto uri_host_port_end_found;
1171 case '?':
1172 case ' ':
1173 case '\r':
1174 goto uri_host_port_end_found;
1175 default :
1176 break;
1180 uri_host_port_end_found:
1182 uri_offsets->uri_host_port_end = parameter_end_offset -1;
1185 return uri_offsets->name_addr_end;
1189 * History-Info = "History-Info" HCOLON
1190 * hi-entry *(COMMA hi-entry)
1192 * hi-entry = hi-targeted-to-uri *( SEMI hi-param )
1193 * hi-targeted-to-uri= name-addr
1196 * hi-param = hi-index / hi-extension
1198 * hi-index = "index" EQUAL 1*DIGIT *(DOT 1*DIGIT)
1200 * hi-extension = generic-param
1203 static gint
1204 dissect_sip_history_info(tvbuff_t *tvb, proto_tree* tree, packet_info *pinfo _U_, gint current_offset,
1205 gint line_end_offset)
1207 int comma_offset;
1208 gboolean first_time = TRUE;
1210 /* split the line at the commas */
1211 while (line_end_offset > current_offset){
1212 comma_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ',');
1213 if(comma_offset == -1){
1214 if(first_time == TRUE){
1215 /* It was only on parameter no need to split it up */
1216 return line_end_offset;
1218 /* Last parameter */
1219 comma_offset = line_end_offset;
1221 first_time = FALSE;
1222 proto_tree_add_text(tree, tvb, current_offset, comma_offset-current_offset,
1223 "%s", tvb_format_text(tvb, current_offset,
1224 comma_offset-current_offset));
1226 current_offset = comma_offset+1;
1229 return line_end_offset;
1235 * The syntax for the P-Charging-Function-Addresses header is described
1236 * as follows:
1238 * P-Charging-Addr = "P-Charging-Function-Addresses" HCOLON
1239 * charge-addr-params
1240 * *(SEMI charge-addr-params)
1241 * charge-addr-params = ccf / ecf / generic-param
1242 * ccf = "ccf" EQUAL gen-value
1243 * ecf = "ecf" EQUAL gen-value
1244 * generic-param = token [ EQUAL gen-value ]
1245 * gen-value = token / host / quoted-string
1249 static gint
1250 dissect_sip_p_charging_func_addresses(tvbuff_t *tvb, proto_tree* tree, packet_info *pinfo _U_, gint current_offset,
1251 gint line_end_offset)
1253 int semi_offset, quote_offset;
1254 gboolean first_time = TRUE;
1256 while (line_end_offset > current_offset){
1257 /* Do we have a quoted string ? */
1258 quote_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, '"');
1259 if(quote_offset>0){
1260 /* Find end of quoted string */
1261 quote_offset = tvb_find_guint8(tvb, quote_offset+1, line_end_offset - current_offset, '"');
1262 /* Find parameter end */
1263 semi_offset = tvb_find_guint8(tvb, quote_offset+1, line_end_offset - quote_offset, ';');
1264 }else{
1265 /* Find parameter end */
1266 semi_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ';');
1268 if(semi_offset == -1){
1269 if(first_time == TRUE){
1270 /* It was only on parameter no need to split it up */
1271 return line_end_offset;
1273 /* Last parameter */
1274 semi_offset = line_end_offset;
1276 first_time = FALSE;
1277 proto_tree_add_text(tree, tvb, current_offset, semi_offset-current_offset,
1278 "%s", tvb_format_text(tvb, current_offset,
1279 semi_offset-current_offset));
1281 current_offset = semi_offset+1;
1285 return current_offset;
1289 * token = 1*(alphanum / "-" / "." / "!" / "%" / "*"
1290 * / "_" / "+" / "`" / "'" / "~" )
1291 * LWS = [*WSP CRLF] 1*WSP ; linear whitespace
1292 * name-addr = [ display-name ] LAQUOT addr-spec RAQUOT
1293 * addr-spec = SIP-URI / SIPS-URI / absoluteURI
1294 * display-name = *(token LWS)/ quoted-string
1297 static gint
1298 dissect_sip_name_addr_or_addr_spec(tvbuff_t *tvb, packet_info *pinfo _U_, gint start_offset,
1299 gint line_end_offset, uri_offset_info *uri_offsets)
1301 gchar c;
1302 gint i;
1303 gint current_offset;
1304 gint queried_offset;
1305 gint colon_offset;
1306 gboolean uri_without_angle_quotes = FALSE;
1308 /* skip Spaces and Tabs */
1309 current_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1311 if(current_offset >= line_end_offset) {
1312 /* Nothing to parse */
1313 return -1;
1316 uri_offsets->name_addr_start = current_offset;
1318 /* First look, if we have a display name */
1319 c=tvb_get_guint8(tvb, current_offset);
1320 switch(c)
1322 case '"':
1323 /* We have a display name, look for the next unescaped '"' */
1324 uri_offsets->display_name_start = current_offset;
1327 queried_offset = tvb_find_guint8(tvb, current_offset + 1, line_end_offset - (current_offset + 1), '"');
1328 if(queried_offset == -1)
1330 /* malformed URI */
1331 return -1;
1333 current_offset = queried_offset;
1335 /* Is it escaped? */
1336 /* count back slashes before '"' */
1337 for(i=1;tvb_get_guint8(tvb, queried_offset - i) == '\\';i++);
1338 i--;
1340 if(i % 2 == 0)
1342 /* not escaped */
1343 break;
1345 } while (current_offset < line_end_offset);
1346 if(current_offset >= line_end_offset)
1348 /* malformed URI */
1349 return -1;
1352 uri_offsets->display_name_end = current_offset;
1354 /* find start of the URI */
1355 queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, '<');
1356 if(queried_offset == -1)
1358 /* malformed Uri */
1359 return -1;
1361 current_offset = queried_offset + 1;
1362 break;
1364 case '<':
1365 /* We don't have a display name */
1366 current_offset++;
1367 break;
1369 default:
1370 /* We have either an URI without angles or a display name with a limited character set */
1371 /* Look for the right angle quote or colon */
1372 queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, '<');
1373 colon_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ':');
1374 if(queried_offset != -1 && colon_offset != -1)
1376 if(queried_offset < colon_offset)
1378 /* we have an URI with angle quotes */
1379 uri_offsets->display_name_start = current_offset;
1380 uri_offsets->display_name_end = queried_offset - 1;
1381 current_offset = queried_offset + 1;
1383 else
1385 /* we have an URI without angle quotes */
1386 uri_without_angle_quotes = TRUE;
1389 else
1391 if(queried_offset != -1)
1393 /* we have an URI with angle quotes */
1394 uri_offsets->display_name_start = current_offset;
1395 uri_offsets->display_name_end = queried_offset - 1;
1396 current_offset = queried_offset + 1;
1397 break;
1399 if(colon_offset != -1)
1401 /* we have an URI without angle quotes */
1402 uri_without_angle_quotes = TRUE;
1403 break;
1405 /* If this point is reached, we can't parse the URI */
1406 return -1;
1408 break;
1410 /* Start of URI */
1411 uri_offsets->uri_start = current_offset;
1412 if(uri_without_angle_quotes==FALSE){
1413 /* name-addr form was used */
1414 /* look for closing angle quote */
1415 queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, '>');
1416 if(queried_offset == -1)
1418 /* malformed Uri */
1419 return -1;
1421 uri_offsets->name_addr_end = queried_offset;
1422 uri_offsets->uri_end = queried_offset - 1;
1424 return dissect_sip_uri(tvb, pinfo, current_offset, line_end_offset, uri_offsets);
1429 * Code to add dissected SIP URI Information to proto tree
1432 static proto_tree *
1433 display_sip_uri (tvbuff_t *tvb, proto_tree *sip_element_tree, uri_offset_info* uri_offsets, hf_sip_uri_t* uri)
1435 proto_item *ti;
1436 proto_tree *uri_item_tree = NULL;
1438 if(uri_offsets->display_name_end != uri_offsets->display_name_start) {
1439 proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, uri_offsets->display_name_start,
1440 uri_offsets->display_name_end - uri_offsets->display_name_start + 1, ENC_ASCII|ENC_NA);
1443 ti = proto_tree_add_item(sip_element_tree, *(uri->hf_sip_addr),
1444 tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start + 1, ENC_ASCII|ENC_NA);
1445 uri_item_tree = proto_item_add_subtree(ti, *(uri->ett_uri));
1447 if(uri_offsets->uri_user_end > uri_offsets->uri_user_start) {
1448 proto_tree_add_item(uri_item_tree, *(uri->hf_sip_user), tvb, uri_offsets->uri_user_start,
1449 uri_offsets->uri_user_end - uri_offsets->uri_user_start + 1, ENC_ASCII|ENC_NA);
1452 proto_tree_add_item(uri_item_tree, *(uri->hf_sip_host), tvb, uri_offsets->uri_host_start,
1453 uri_offsets->uri_host_end - uri_offsets->uri_host_start + 1, ENC_ASCII|ENC_NA);
1455 if(uri_offsets->uri_host_port_end > uri_offsets->uri_host_port_start) {
1456 proto_tree_add_item(uri_item_tree, *(uri->hf_sip_port), tvb, uri_offsets->uri_host_port_start,
1457 uri_offsets->uri_host_port_end - uri_offsets->uri_host_port_start + 1, ENC_ASCII|ENC_NA);
1460 if (uri_offsets->uri_parameters_start != -1) {
1461 /* Move current offset to the start of the first param */
1462 gint current_offset = uri_offsets->uri_parameters_start;
1463 gint uri_params_start_offset = current_offset;
1464 gint queried_offset;
1465 gint uri_param_end_offset = -1;
1466 gchar c;
1468 /* Put the contact parameters in the tree */
1470 while (current_offset < uri_offsets->name_addr_end) {
1471 queried_offset = tvb_pbrk_guint8(tvb, current_offset, uri_offsets->name_addr_end - current_offset, ",;", &c);
1473 if (queried_offset == -1) {
1474 /* Reached line end */
1475 /* Check if the line ends with a ">", if so decrement end offset. */
1476 c = tvb_get_guint8(tvb, uri_offsets->name_addr_end);
1478 if (c == '>') {
1479 uri_param_end_offset = uri_offsets->name_addr_end - 1;
1480 } else {
1481 uri_param_end_offset = uri_offsets->name_addr_end;
1483 current_offset = uri_offsets->name_addr_end;
1484 } else if (c==',') {
1485 uri_param_end_offset = queried_offset;
1486 current_offset = queried_offset+1; /* must move forward */
1487 } else if (c==';') {
1488 /* More parameters */
1489 uri_param_end_offset = queried_offset-1;
1490 current_offset = tvb_skip_wsp(tvb, queried_offset+1, uri_offsets->name_addr_end - queried_offset + 1);
1493 proto_tree_add_item(uri_item_tree, *(uri->hf_sip_param), tvb, uri_params_start_offset ,
1494 uri_param_end_offset - uri_params_start_offset +1, ENC_ASCII|ENC_NA);
1496 /* In case there are more parameters, point to the start of it */
1497 uri_params_start_offset = current_offset;
1501 return uri_item_tree;
1507 /* Code to parse a contact header item
1508 * Returns Offset end off parsing or -1 for unsuccessful parsing
1509 * * contact-param = (name-addr / addr-spec) *(SEMI contact-params)
1511 static gint
1512 dissect_sip_contact_item(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint start_offset, gint line_end_offset)
1514 gchar c;
1515 gint current_offset;
1516 gint queried_offset;
1517 gint contact_params_start_offset = -1;
1518 /*gint contact_param_end_offset = -1;*/
1519 uri_offset_info uri_offsets;
1521 /* skip Spaces and Tabs */
1522 start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1524 if(start_offset >= line_end_offset) {
1525 /* Nothing to parse */
1526 return -1;
1529 /* Initialize the uri_offsets */
1530 sip_uri_offset_init(&uri_offsets);
1531 /* contact-param = (name-addr / addr-spec) *(SEMI contact-params) */
1532 current_offset = dissect_sip_name_addr_or_addr_spec(tvb, pinfo, start_offset, line_end_offset, &uri_offsets);
1533 if(current_offset == -1)
1535 /* Parsing failed */
1536 return -1;
1538 display_sip_uri(tvb, tree, &uri_offsets, &sip_contact_uri);
1540 /* Check if we have contact parameters, the uri should be followed by a ';' */
1541 contact_params_start_offset = tvb_find_guint8(tvb, uri_offsets.uri_end, line_end_offset - uri_offsets.uri_end, ';');
1542 /* check if contact-params is present */
1543 if(contact_params_start_offset == -1)
1544 return line_end_offset;
1546 /* Move current offset to the start of the first param */
1547 contact_params_start_offset++;
1548 current_offset = contact_params_start_offset;
1550 /* Put the contact parameters in the tree */
1552 queried_offset = current_offset;
1554 while(current_offset< line_end_offset){
1555 c = '\0';
1556 while (queried_offset < line_end_offset)
1558 queried_offset++;
1559 c = tvb_get_guint8(tvb, queried_offset);
1560 switch (c) {
1561 case ',':
1562 case ';':
1563 case '"':
1564 goto found;
1565 break;
1566 default :
1567 break;
1570 found:
1571 if(queried_offset==line_end_offset){
1572 /* Last parameter, line end */
1573 current_offset = line_end_offset;
1574 }else if(c=='"'){
1575 /* Do we have a quoted string ? */
1576 queried_offset = tvb_find_guint8(tvb, queried_offset+1, line_end_offset - queried_offset, '"');
1577 if(queried_offset==-1){
1578 /* We have an opening quote but no closing quote. */
1579 current_offset = line_end_offset;
1580 } else {
1581 current_offset = tvb_pbrk_guint8(tvb, queried_offset+1, line_end_offset - queried_offset, ",;", &c);
1582 if(current_offset==-1){
1583 /* Last parameter, line end */
1584 current_offset = line_end_offset;
1587 }else{
1588 current_offset = queried_offset;
1590 proto_tree_add_item(tree, hf_sip_contact_param, tvb, contact_params_start_offset ,
1591 current_offset - contact_params_start_offset, ENC_ASCII|ENC_NA);
1592 /* In case there are more parameters, point to the start of it */
1593 contact_params_start_offset = current_offset+1;
1594 queried_offset = contact_params_start_offset;
1595 if (c == ',') {
1596 /* comma separator found, stop parsing of current contact-param here */
1597 break;
1601 return current_offset;
1604 /* Code to parse an authorization header item
1605 * Returns offset at end of parsing, or -1 for unsuccessful parsing
1607 static gint
1608 dissect_sip_authorization_item(tvbuff_t *tvb, proto_tree *tree, gint start_offset, gint line_end_offset)
1610 gint current_offset, par_name_end_offset, queried_offset;
1611 gint equals_offset = 0;
1612 gchar *name;
1613 header_parameter_t *auth_parameter;
1614 guint i = 0;
1615 gchar c = '\0';
1617 /* skip Spaces and Tabs */
1618 start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1620 if (start_offset >= line_end_offset)
1622 /* Nothing to parse */
1623 return -1;
1626 current_offset = start_offset;
1627 equals_offset = tvb_find_guint8(tvb, current_offset + 1, line_end_offset - (current_offset + 1), '=');
1628 if(equals_offset == -1){
1629 /* malformed parameter */
1630 return -1;
1632 par_name_end_offset = equals_offset - 1;
1633 par_name_end_offset = tvb_skip_wsp_return(tvb,par_name_end_offset);
1635 /* Extract the parameter name */
1636 name = tvb_get_string(wmem_packet_scope(), tvb, start_offset, par_name_end_offset-start_offset);
1638 /* Find end of parameter, it can be a quoted string so check for quoutes too */
1639 queried_offset = par_name_end_offset;
1640 while (queried_offset < line_end_offset)
1642 queried_offset++;
1643 c = tvb_get_guint8(tvb, queried_offset);
1644 switch (c) {
1645 case ',':
1646 case '"':
1647 goto found;
1648 break;
1649 default :
1650 break;
1653 found:
1654 if(queried_offset==line_end_offset){
1655 /* Last parameter, line end */
1656 current_offset = line_end_offset;
1657 }else if(c=='"'){
1658 /* Do we have a quoted string ? */
1659 queried_offset = tvb_find_guint8(tvb, queried_offset+1, line_end_offset - queried_offset, '"');
1660 if(queried_offset==-1){
1661 /* We have an opening quote but no closing quote. */
1662 queried_offset = line_end_offset;
1664 current_offset = tvb_find_guint8(tvb, queried_offset+1, line_end_offset - queried_offset, ',');
1665 if(current_offset==-1){
1666 /* Last parameter, line end */
1667 current_offset = line_end_offset;
1669 }else{
1670 current_offset = queried_offset;
1673 /* Try to add parameter as a filterable item */
1674 for (auth_parameter = &auth_parameters_hf_array[i];
1675 i < array_length(auth_parameters_hf_array);
1676 i++, auth_parameter++)
1678 if (g_ascii_strcasecmp(name, auth_parameter->param_name) == 0)
1680 proto_tree_add_item(tree, *(auth_parameter->hf_item), tvb,
1681 equals_offset+1, current_offset-equals_offset-1,
1682 ENC_ASCII|ENC_NA);
1683 break;
1687 /* If not matched, just add as text... */
1688 if (i == array_length(auth_parameters_hf_array))
1690 proto_tree_add_text(tree, tvb, start_offset, current_offset-start_offset,
1691 "%s", tvb_format_text(tvb, start_offset,
1692 current_offset-start_offset));
1695 return current_offset;
1698 /* Dissect the details of a Reason header */
1699 static void
1700 dissect_sip_reason_header(tvbuff_t *tvb, proto_tree *tree, gint start_offset, gint line_end_offset){
1702 gint current_offset, semi_colon_offset, length;
1703 gchar *param_name = NULL;
1704 guint cause_value;
1706 /* skip Spaces and Tabs */
1707 start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1709 if (start_offset >= line_end_offset)
1711 /* Nothing to parse */
1712 return;
1715 current_offset = start_offset;
1716 semi_colon_offset = tvb_find_guint8(tvb, current_offset, line_end_offset-current_offset, ';');
1718 if(semi_colon_offset == -1)
1719 return;
1721 length = semi_colon_offset - current_offset;
1722 proto_tree_add_text(tree, tvb, start_offset, length,
1723 "Reason Protocols: %s", tvb_format_text(tvb, start_offset, length));
1725 param_name = tvb_get_string(wmem_packet_scope(), tvb, start_offset, length);
1726 if (g_ascii_strcasecmp(param_name, "Q.850") == 0){
1727 current_offset = tvb_find_guint8(tvb, semi_colon_offset, line_end_offset-semi_colon_offset, '=')+1;
1728 length = line_end_offset - current_offset;
1730 /* q850_cause_code_vals */
1731 cause_value = (guint)strtoul(tvb_get_string(wmem_packet_scope(), tvb, current_offset, length), NULL, 10);
1732 proto_tree_add_text(tree, tvb, current_offset, length,
1733 "Cause: %u(0x%x)[%s]", cause_value,cause_value,
1734 val_to_str_ext(cause_value, &q850_cause_code_vals_ext, "Unknown (%d)" ));
1740 /* Dissect the details of a Route (and Record-Route) header */
1741 static void dissect_sip_route_header(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, hf_sip_uri_t *sip_route_uri_p, gint start_offset, gint line_end_offset)
1743 gint current_offset;
1744 guchar c;
1745 uri_offset_info uri_offsets;
1747 current_offset = start_offset;
1749 /* skip Spaces and Tabs */
1750 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1752 if (current_offset >= line_end_offset) {
1753 return;
1756 while (current_offset < line_end_offset) {
1757 c = tvb_get_guint8(tvb, current_offset);
1759 if (c == ',') {
1760 sip_uri_offset_init(&uri_offsets);
1761 current_offset = dissect_sip_name_addr_or_addr_spec(tvb, pinfo, start_offset, current_offset, &uri_offsets);
1762 if(current_offset == -1)
1763 return;
1764 display_sip_uri(tvb, tree, &uri_offsets, sip_route_uri_p);
1766 current_offset++;
1767 start_offset = current_offset + 1;
1769 } else if (current_offset == line_end_offset - 1) {
1770 sip_uri_offset_init(&uri_offsets);
1771 current_offset = dissect_sip_name_addr_or_addr_spec(tvb, pinfo, start_offset, line_end_offset, &uri_offsets);
1772 if(current_offset == -1)
1773 return;
1774 display_sip_uri(tvb, tree, &uri_offsets, sip_route_uri_p);
1776 return;
1779 current_offset++;
1782 return;
1785 /* Dissect the details of a Via header */
1786 static void dissect_sip_via_header(tvbuff_t *tvb, proto_tree *tree, gint start_offset, gint line_end_offset)
1788 gint current_offset;
1789 gint transport_start_offset;
1790 gint address_start_offset;
1791 gint semicolon_offset;
1792 guint transport_slash_count;
1793 gboolean transport_name_started;
1794 gboolean colon_seen;
1795 gboolean ipv6_reference;
1796 gboolean ipv6_address;
1797 guchar c;
1798 gchar *param_name = NULL;
1800 current_offset = start_offset;
1802 while (1)
1804 /* Reset flags and counters */
1805 transport_start_offset = 0;
1806 semicolon_offset = 0;
1807 transport_name_started = FALSE;
1808 transport_slash_count = 0;
1809 ipv6_reference = FALSE;
1810 ipv6_address = FALSE;
1811 colon_seen = FALSE;
1813 /* skip Spaces and Tabs */
1814 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1816 if (current_offset >= line_end_offset)
1818 /* Nothing more to parse */
1819 return;
1822 /* Now look for the end of the SIP/2.0/transport parameter.
1823 There may be spaces between the slashes */
1824 while (current_offset < line_end_offset)
1826 c = tvb_get_guint8(tvb, current_offset);
1827 if (c == '/')
1829 transport_slash_count++;
1831 else
1832 if (!transport_name_started && (transport_slash_count == 2) && isalpha(c))
1834 transport_name_started = TRUE;
1835 transport_start_offset = current_offset;
1837 else
1838 if (transport_name_started && ((c == ' ') || (c == '\t')))
1840 proto_tree_add_item(tree, hf_sip_via_transport, tvb, transport_start_offset,
1841 current_offset - transport_start_offset, ENC_ASCII|ENC_NA);
1843 break;
1846 current_offset++;
1849 /* skip Spaces and Tabs */
1850 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1852 /* Now read the address part */
1853 address_start_offset = current_offset;
1854 while (current_offset < line_end_offset)
1856 c = tvb_get_guint8(tvb, current_offset);
1858 if (c == '[') {
1859 ipv6_reference = TRUE;
1860 ipv6_address = TRUE;
1862 else if (c == ']')
1864 ipv6_reference = FALSE;
1867 if (colon_seen || (c == ' ') || (c == '\t') || ((c == ':') && (ipv6_reference == FALSE)) || (c == ';'))
1869 break;
1872 current_offset++;
1874 /* Add address to tree */
1875 if (ipv6_address == TRUE) {
1876 proto_tree_add_item(tree, hf_sip_via_sent_by_address, tvb, address_start_offset + 1,
1877 current_offset - address_start_offset - 2, ENC_ASCII|ENC_NA);
1878 } else {
1879 proto_tree_add_item(tree, hf_sip_via_sent_by_address, tvb, address_start_offset,
1880 current_offset - address_start_offset, ENC_ASCII|ENC_NA);
1883 /* Transport port number may follow ([space] : [space])*/
1884 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1885 c = tvb_get_guint8(tvb, current_offset);
1887 if (c == ':')
1889 /* Port number will follow any space after : */
1890 gint port_offset;
1891 current_offset++;
1893 /* Skip optional space after colon */
1894 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1896 port_offset = current_offset;
1898 /* Find digits of port number */
1899 while (current_offset < line_end_offset)
1901 c = tvb_get_guint8(tvb, current_offset);
1903 if (!isdigit(c))
1905 if (current_offset > port_offset)
1907 /* Add address port number to tree */
1908 proto_tree_add_uint(tree, hf_sip_via_sent_by_port, tvb, port_offset,
1909 current_offset - port_offset,
1910 atoi(tvb_get_string(wmem_packet_scope(), tvb, port_offset,
1911 current_offset - port_offset)));
1913 else
1915 /* Shouldn't see a colon without a port number given */
1916 return;
1918 break;
1921 current_offset++;
1925 /* skip Spaces and Tabs */
1926 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1929 /* Dissect any parameters found */
1930 while (current_offset < line_end_offset)
1932 gboolean equals_found = FALSE;
1933 gboolean found_end_of_parameters = FALSE;
1934 gint parameter_name_end = 0;
1935 header_parameter_t *via_parameter;
1936 guint i = 0;
1938 /* Look for the semicolon that signals the start of a parameter */
1939 while (current_offset < line_end_offset)
1941 c = tvb_get_guint8(tvb, current_offset);
1942 if (c == ';')
1944 semicolon_offset = current_offset;
1945 current_offset++;
1946 break;
1948 else
1949 if ((c != ' ') && (c != '\t'))
1951 found_end_of_parameters = TRUE;
1952 break;
1954 current_offset++;
1957 if (found_end_of_parameters)
1959 break;
1962 if (current_offset == line_end_offset)
1964 return;
1967 /* Look for end of parameter name */
1968 while (current_offset < line_end_offset)
1970 c = tvb_get_guint8(tvb, current_offset);
1971 if (!isalpha(c) && (c != '-'))
1973 break;
1975 current_offset++;
1978 /* Not all params have an = */
1979 if (c == '=')
1981 equals_found = TRUE;
1983 parameter_name_end = current_offset;
1985 /* Read until end of parameter value */
1986 while (current_offset < line_end_offset)
1988 c = tvb_get_guint8(tvb, current_offset);
1989 if ((c == ' ') || (c == '\t') || (c == ';') || (c == ','))
1991 break;
1993 current_offset++;
1996 /* Note parameter name */
1997 param_name = tvb_get_string(wmem_packet_scope(), tvb, semicolon_offset+1,
1998 parameter_name_end - semicolon_offset - 1);
2000 /* Try to add parameter as a filterable item */
2001 for (via_parameter = &via_parameters_hf_array[i];
2002 i < array_length(via_parameters_hf_array);
2003 i++, via_parameter++)
2005 if (g_ascii_strcasecmp(param_name, via_parameter->param_name) == 0)
2007 if (equals_found)
2009 proto_tree_add_item(tree, *(via_parameter->hf_item), tvb,
2010 parameter_name_end+1, current_offset-parameter_name_end-1,
2011 ENC_ASCII|ENC_NA);
2013 else
2015 proto_tree_add_item(tree, *(via_parameter->hf_item), tvb,
2016 semicolon_offset+1, current_offset-semicolon_offset-1,
2017 ENC_ASCII|ENC_NA);
2019 break;
2023 /* If not matched, just add as text... */
2024 if (i == array_length(via_parameters_hf_array))
2026 proto_tree_add_text(tree, tvb, semicolon_offset+1, current_offset-semicolon_offset-1,
2027 "%s", tvb_format_text(tvb, semicolon_offset+1,
2028 current_offset-semicolon_offset-1));
2031 /* skip Spaces and Tabs */
2032 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
2034 /* There may be a comma, followed by more Via entries... */
2035 if (current_offset < line_end_offset)
2037 c = tvb_get_guint8(tvb, current_offset);
2038 if (c == ',')
2040 /* Skip it and get out of parameter loop */
2041 current_offset++;
2042 break;
2049 /* Code to actually dissect the packets */
2050 static int
2051 dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2053 guint8 octet;
2054 int len;
2056 octet = tvb_get_guint8(tvb,0);
2057 if ((octet & 0xf8) == 0xf8){
2058 call_dissector(sigcomp_handle, tvb, pinfo, tree);
2059 return tvb_length(tvb);
2062 len = dissect_sip_common(tvb, 0, pinfo, tree, FALSE, FALSE);
2063 if (len < 0)
2064 return 0; /* not SIP */
2065 else
2066 return len;
2069 static void
2070 dissect_sip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2072 guint8 octet;
2073 int offset = 0;
2074 int len;
2076 octet = tvb_get_guint8(tvb,0);
2077 if ((octet & 0xf8) == 0xf8){
2078 call_dissector(sigcomp_handle, tvb, pinfo, tree);
2079 return;
2082 while (tvb_reported_length_remaining(tvb, offset) > 0) {
2083 len = dissect_sip_common(tvb, offset, pinfo, tree, TRUE, TRUE);
2084 if (len <= 0)
2085 break;
2086 offset += len;
2090 static gboolean
2091 dissect_sip_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2093 int offset = 0;
2094 int len;
2095 gboolean first = TRUE;
2097 while (tvb_reported_length_remaining(tvb, offset) > 0) {
2098 len = dissect_sip_common(tvb, offset, pinfo, tree, !first, TRUE);
2099 if (len == -2) {
2100 if (first) {
2102 * If the first packet doesn't start with
2103 * a valid SIP request or response, don't
2104 * treat this as SIP.
2106 return FALSE;
2108 break;
2110 if (len == -1)
2111 break; /* need more data */
2112 offset += len;
2113 first = FALSE;
2115 return TRUE;
2118 static gboolean
2119 dissect_sip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
2121 return dissect_sip_common(tvb, 0, pinfo, tree, FALSE, FALSE) > 0;
2124 static int
2125 dissect_sip_common(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
2126 gboolean dissect_other_as_continuation, gboolean use_reassembly)
2128 int orig_offset;
2129 gint next_offset, linelen;
2130 int content_length, datalen, reported_datalen;
2131 line_type_t line_type;
2132 tvbuff_t *next_tvb;
2133 gboolean is_known_request;
2134 gboolean found_match = FALSE;
2135 const char *descr;
2136 guint token_1_len = 0;
2137 guint current_method_idx = SIP_METHOD_INVALID;
2138 proto_item *ts = NULL, *ti_a = NULL, *th = NULL, *sip_element_item = NULL;
2139 proto_tree *sip_tree = NULL, *reqresp_tree = NULL, *hdr_tree = NULL,
2140 *sip_element_tree = NULL, *message_body_tree = NULL, *cseq_tree = NULL,
2141 *via_tree = NULL, *reason_tree = NULL, *rack_tree = NULL,
2142 *route_tree = NULL;
2143 guchar contacts = 0, contact_is_star = 0, expires_is_0 = 0;
2144 guint32 cseq_number = 0;
2145 guchar cseq_number_set = 0;
2146 char cseq_method[MAX_CSEQ_METHOD_SIZE] = "";
2147 char call_id[MAX_CALL_ID_SIZE] = "";
2148 gchar *media_type_str_lower_case = NULL;
2149 char *content_type_parameter_str = NULL;
2150 char *content_encoding_parameter_str = NULL;
2151 guint resend_for_packet = 0;
2152 guint request_for_response = 0;
2153 guint32 response_time = 0;
2154 int strlen_to_copy;
2157 * If this should be a request of response, do this quick check to see if
2158 * it begins with a string...
2159 * Otherwise, SIP heuristics are expensive...
2162 if (!dissect_other_as_continuation &&
2163 ((tvb_reported_length_remaining(tvb, offset) < 1) || !isprint(tvb_get_guint8(tvb, offset))))
2165 return -2;
2169 * Note that "tvb_find_line_end()" will return a value that
2170 * is not longer than what's in the buffer, so the
2171 * "tvb_get_ptr()" calls below won't throw exceptions.
2173 * Note that "tvb_strneql()" doesn't throw exceptions, so
2174 * "sip_parse_line()" won't throw an exception.
2176 orig_offset = offset;
2177 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
2178 if(linelen==0){
2179 return -2;
2182 if (tvb_strnlen(tvb, offset, linelen) > -1)
2185 * There's a NULL in the line,
2186 * this may be SIP within another protocol.
2187 * This heuristic still needs to improve.
2189 return -2;
2191 line_type = sip_parse_line(tvb, offset, linelen, &token_1_len);
2193 if (line_type == OTHER_LINE) {
2195 * This is neither a SIP request nor response.
2197 if (!dissect_other_as_continuation) {
2199 * We were asked to reject this.
2201 return -2;
2205 * Just dissect it as a continuation.
2207 } else if ((use_reassembly)&&( pinfo->ptype == PT_TCP)) {
2209 * Yes, it's a request or response.
2210 * Do header desegmentation if we've been told to,
2211 * and do body desegmentation if we've been told to and
2212 * we find a Content-Length header.
2214 if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo,
2215 sip_desegment_headers, sip_desegment_body)) {
2217 * More data needed for desegmentation.
2219 return -1;
2223 /* Initialise stat info for passing to tap */
2224 stat_info = wmem_new0(wmem_packet_scope(), sip_info_value_t);
2226 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIP");
2228 switch (line_type) {
2230 case REQUEST_LINE:
2231 is_known_request = sip_is_known_request(tvb, offset, token_1_len, &current_method_idx);
2232 descr = is_known_request ? "Request" : "Unknown request";
2233 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
2234 descr,
2235 tvb_format_text(tvb, offset, linelen - SIP2_HDR_LEN - 1));
2236 break;
2238 case STATUS_LINE:
2239 descr = "Status";
2240 col_add_fstr(pinfo->cinfo, COL_INFO, "Status: %s",
2241 tvb_format_text(tvb, offset + SIP2_HDR_LEN + 1, linelen - SIP2_HDR_LEN - 1));
2242 stat_info->reason_phrase = tvb_get_string(wmem_packet_scope(), tvb, offset + SIP2_HDR_LEN + 5, linelen - (SIP2_HDR_LEN + 5));
2243 break;
2245 case OTHER_LINE:
2246 default: /* Squelch compiler complaints */
2247 descr = "Continuation";
2248 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
2249 break;
2252 if (tree) {
2253 ts = proto_tree_add_item(tree, proto_sip, tvb, offset, -1, ENC_NA);
2254 sip_tree = proto_item_add_subtree(ts, ett_sip);
2257 switch (line_type) {
2259 case REQUEST_LINE:
2260 if (sip_tree) {
2261 ti_a = proto_tree_add_item(sip_tree, hf_Request_Line, tvb,
2262 offset, linelen, ENC_ASCII|ENC_NA);
2264 reqresp_tree = proto_item_add_subtree(ti_a, ett_sip_reqresp);
2266 dfilter_sip_request_line(tvb, reqresp_tree, pinfo, offset, token_1_len, linelen);
2267 break;
2269 case STATUS_LINE:
2270 if (sip_tree) {
2271 ti_a = proto_tree_add_item(sip_tree, hf_sip_Status_Line, tvb,
2272 offset, linelen, ENC_ASCII|ENC_NA);
2273 reqresp_tree = proto_item_add_subtree(ti_a, ett_sip_reqresp);
2275 dfilter_sip_status_line(tvb, reqresp_tree, pinfo, linelen, offset);
2276 break;
2278 case OTHER_LINE:
2279 if (sip_tree) {
2280 ti_a = proto_tree_add_text(sip_tree, tvb, offset, next_offset,
2281 "%s line: %s", descr,
2282 tvb_format_text(tvb, offset, linelen));
2283 reqresp_tree = proto_item_add_subtree(ti_a, ett_sip_reqresp);
2284 /* XXX: Is adding to 'reqresp_tree as intended ? Changed from original 'sip_tree' */
2285 proto_tree_add_text(reqresp_tree, tvb, offset, -1, "Continuation data");
2287 return tvb_length_remaining(tvb, offset);
2290 offset = next_offset;
2291 if (sip_tree) {
2292 th = proto_tree_add_item(sip_tree, hf_sip_msg_hdr, tvb, offset,
2293 tvb_length_remaining(tvb, offset), ENC_ASCII|ENC_NA);
2294 proto_item_set_text(th, "Message Header");
2295 hdr_tree = proto_item_add_subtree(th, ett_sip_hdr);
2299 * Process the headers - if we're not building a protocol tree,
2300 * we just do this to find the blank line separating the
2301 * headers from the message body.
2303 next_offset = offset;
2304 content_length = -1;
2305 while (tvb_reported_length_remaining(tvb, offset) > 0) {
2306 gint line_end_offset;
2307 gint colon_offset;
2308 gint semi_colon_offset;
2309 gint parameter_offset;
2310 gint parameter_end_offset;
2311 gint parameter_len;
2312 gint content_type_len, content_type_parameter_str_len;
2313 gint header_len;
2314 gchar *header_name;
2315 dissector_handle_t ext_hdr_handle;
2316 gint hf_index;
2317 gint value_offset;
2318 gint sub_value_offset;
2319 gint comma_offset;
2320 guchar c;
2321 gint value_len;
2322 char *value;
2323 gboolean is_no_header_termination = FALSE;
2324 proto_tree *tc_uri_item_tree = NULL;
2325 uri_offset_info uri_offsets;
2331 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
2332 if (linelen == 0) {
2334 * This is a blank line separating the
2335 * message header from the message body.
2337 offset = next_offset;
2338 break;
2341 line_end_offset = offset + linelen;
2342 if(tvb_reported_length_remaining(tvb, next_offset) <= 0){
2343 is_no_header_termination = TRUE;
2344 }else{
2345 while ((c = tvb_get_guint8(tvb, next_offset)) == ' ' || c == '\t')
2348 * This line end is not a header seperator.
2349 * It just extends the header with another line.
2350 * Look for next line end:
2352 linelen += (next_offset - line_end_offset);
2353 linelen += tvb_find_line_end(tvb, next_offset, -1, &next_offset, FALSE);
2354 line_end_offset = offset + linelen;
2357 colon_offset = tvb_find_guint8(tvb, offset, linelen, ':');
2358 if (colon_offset == -1) {
2360 * Malformed header - no colon after the name.
2362 if(hdr_tree) {
2363 proto_tree_add_text(hdr_tree, tvb, offset,
2364 next_offset - offset, "%s",
2365 tvb_format_text(tvb, offset, linelen));
2367 } else {
2368 header_len = colon_offset - offset;
2369 header_name = (gchar*)tvb_get_string(wmem_packet_scope(), tvb, offset, header_len);
2370 ascii_strdown_inplace(header_name);
2371 hf_index = sip_is_known_sip_header(header_name, header_len);
2374 * Skip whitespace after the colon.
2376 value_offset = tvb_skip_wsp(tvb, colon_offset + 1, line_end_offset - (colon_offset + 1));
2379 * Fetch the value.
2381 value_len = (gint) (line_end_offset - value_offset);
2382 value = tvb_get_string(wmem_packet_scope(), tvb, value_offset, value_len);
2384 if (hf_index == -1) {
2385 proto_item *ti_c = proto_tree_add_text(hdr_tree, tvb,
2386 offset, next_offset - offset, "%s",
2387 tvb_format_text(tvb, offset, linelen));
2388 ext_hdr_handle = dissector_get_string_handle(ext_hdr_subdissector_table, header_name);
2389 if (ext_hdr_handle != NULL) {
2390 tvbuff_t *next_tvb2;
2391 next_tvb2 = tvb_new_subset(tvb, value_offset, value_len, value_len);
2392 dissector_try_string(ext_hdr_subdissector_table, header_name, next_tvb2, pinfo, proto_item_add_subtree(ti_c, ett_sip_ext_hdr), NULL);
2393 } else {
2394 expert_add_info_format(pinfo, ti_c, &ei_sip_unrecognized_header,
2395 "Unrecognised SIP header (%s)",
2396 tvb_format_text(tvb, offset, header_len));
2398 } else {
2400 * Add it to the protocol tree,
2401 * but display the line as is.
2403 switch ( hf_index ) {
2405 case POS_TO :
2407 if(hdr_tree) {
2408 proto_item *item;
2410 sip_element_item = proto_tree_add_string_format(hdr_tree,
2411 hf_header_array[hf_index], tvb,
2412 offset, next_offset - offset,
2413 value, "%s",
2414 tvb_format_text(tvb, offset, linelen));
2415 sip_element_tree = proto_item_add_subtree( sip_element_item,
2416 ett_sip_element);
2417 /* To = ( "To" / "t" ) HCOLON ( name-addr
2418 * / addr-spec ) *( SEMI to-param )
2420 sip_uri_offset_init(&uri_offsets);
2421 if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1){
2422 display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_to_uri);
2423 if((uri_offsets.name_addr_start != -1) && (uri_offsets.name_addr_end != -1)){
2424 stat_info->tap_to_addr=tvb_get_string(wmem_packet_scope(), tvb, uri_offsets.name_addr_start,
2425 uri_offsets.name_addr_end - uri_offsets.name_addr_start);
2427 offset = uri_offsets.name_addr_end +1;
2430 /* Find parameter tag if present.
2431 * TODO make this generic to find any interesting parameter
2432 * use the same method as for SIP headers ?
2435 parameter_offset = offset;
2436 while (parameter_offset < line_end_offset
2437 && (tvb_strneql(tvb, parameter_offset, "tag=", 4) != 0))
2438 parameter_offset++;
2440 if ( parameter_offset < line_end_offset ){ /* Tag found */
2441 parameter_offset = parameter_offset + 4;
2442 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
2443 (line_end_offset - parameter_offset), ';');
2444 if ( parameter_end_offset == -1)
2445 parameter_end_offset = line_end_offset;
2446 parameter_len = parameter_end_offset - parameter_offset;
2447 proto_tree_add_item(sip_element_tree, hf_sip_to_tag, tvb, parameter_offset,
2448 parameter_len, ENC_ASCII|ENC_NA);
2449 item = proto_tree_add_item(sip_element_tree, hf_sip_tag, tvb, parameter_offset,
2450 parameter_len, ENC_ASCII|ENC_NA);
2451 PROTO_ITEM_SET_HIDDEN(item);
2453 /* Tag indicates in-dialog messages, in case we have a INVITE, SUBSCRIBE or REFER, mark it */
2454 switch (current_method_idx) {
2456 case SIP_METHOD_INVITE:
2457 case SIP_METHOD_SUBSCRIBE:
2458 case SIP_METHOD_REFER:
2459 col_append_str(pinfo->cinfo, COL_INFO, ", in-dialog");
2460 break;
2463 } /* if hdr_tree */
2464 break;
2466 case POS_FROM :
2467 if(hdr_tree) {
2468 proto_item *item;
2470 sip_element_item = proto_tree_add_string_format(hdr_tree,
2471 hf_header_array[hf_index], tvb,
2472 offset, next_offset - offset,
2473 value, "%s",
2474 tvb_format_text(tvb, offset, linelen));
2475 sip_element_tree = proto_item_add_subtree( sip_element_item, ett_sip_element);
2477 * From = ( "From" / "f" ) HCOLON from-spec
2478 * from-spec = ( name-addr / addr-spec )
2479 * *( SEMI from-param )
2482 sip_uri_offset_init(&uri_offsets);
2483 if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1){
2484 display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_from_uri);
2485 if((uri_offsets.name_addr_start != -1) && (uri_offsets.name_addr_end != -1)){
2486 stat_info->tap_from_addr=tvb_get_string(wmem_packet_scope(), tvb, uri_offsets.name_addr_start,
2487 uri_offsets.name_addr_end - uri_offsets.name_addr_start);
2489 offset = uri_offsets.name_addr_end +1;
2492 /* Find parameter tag if present.
2493 * TODO make this generic to find any interesting parameter
2494 * use the same method as for SIP headers ?
2497 parameter_offset = offset;
2498 while (parameter_offset < line_end_offset
2499 && (tvb_strneql(tvb, parameter_offset, "tag=", 4) != 0))
2500 parameter_offset++;
2501 if ( parameter_offset < line_end_offset ){ /* Tag found */
2502 parameter_offset = parameter_offset + 4;
2503 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
2504 (line_end_offset - parameter_offset), ';');
2505 if ( parameter_end_offset == -1)
2506 parameter_end_offset = line_end_offset;
2507 parameter_len = parameter_end_offset - parameter_offset;
2508 proto_tree_add_item(sip_element_tree, hf_sip_from_tag, tvb, parameter_offset,
2509 parameter_len, ENC_ASCII|ENC_NA);
2510 item = proto_tree_add_item(sip_element_tree, hf_sip_tag, tvb, parameter_offset,
2511 parameter_len, ENC_ASCII|ENC_NA);
2512 PROTO_ITEM_SET_HIDDEN(item);
2514 }/* hdr_tree */
2515 break;
2517 case POS_P_ASSERTED_IDENTITY :
2518 if(hdr_tree)
2520 sip_element_item = proto_tree_add_string_format(hdr_tree,
2521 hf_header_array[hf_index], tvb,
2522 offset, next_offset - offset,
2523 value, "%s",
2524 tvb_format_text(tvb, offset, linelen));
2525 sip_element_tree = proto_item_add_subtree( sip_element_item,
2526 ett_sip_element);
2529 * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value
2530 * *(COMMA PAssertedID-value)
2531 * PAssertedID-value = name-addr / addr-spec
2533 * Initialize the uri_offsets
2535 sip_uri_offset_init(&uri_offsets);
2536 if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
2537 display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_pai_uri);
2539 break;
2540 case POS_HISTORY_INFO:
2541 if(hdr_tree)
2543 sip_element_item = proto_tree_add_string_format(hdr_tree,
2544 hf_header_array[hf_index], tvb,
2545 offset, next_offset - offset,
2546 value, "%s",
2547 tvb_format_text(tvb, offset, linelen));
2548 sip_element_tree = proto_item_add_subtree( sip_element_item,
2549 ett_sip_hist);
2550 dissect_sip_history_info(tvb, sip_element_tree, pinfo, value_offset, line_end_offset);
2552 break;
2554 case POS_P_CHARGING_FUNC_ADDRESSES:
2555 if(hdr_tree)
2557 sip_element_item = proto_tree_add_string_format(hdr_tree,
2558 hf_header_array[hf_index], tvb,
2559 offset, next_offset - offset,
2560 value, "%s",
2561 tvb_format_text(tvb, offset, linelen));
2562 sip_element_tree = proto_item_add_subtree( sip_element_item,
2563 ett_sip_element);
2564 dissect_sip_p_charging_func_addresses(tvb, sip_element_tree, pinfo, value_offset, line_end_offset);
2566 break;
2568 case POS_P_PREFERRED_IDENTITY :
2569 if(hdr_tree)
2571 sip_element_item = proto_tree_add_string_format(hdr_tree,
2572 hf_header_array[hf_index], tvb,
2573 offset, next_offset - offset,
2574 value, "%s",
2575 tvb_format_text(tvb, offset, linelen));
2576 sip_element_tree = proto_item_add_subtree( sip_element_item,
2577 ett_sip_element);
2579 * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value
2580 * *(COMMA PPreferredID-value)
2581 * PPreferredID-value = name-addr / addr-spec
2583 * Initialize the uri_offsets
2585 sip_uri_offset_init(&uri_offsets);
2586 if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
2587 display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_ppi_uri);
2589 break;
2591 case POS_PERMISSION_MISSING :
2592 if(hdr_tree)
2594 sip_element_item = proto_tree_add_string_format(hdr_tree,
2595 hf_header_array[hf_index], tvb,
2596 offset, next_offset - offset,
2597 value, "%s",
2598 tvb_format_text(tvb, offset, linelen));
2600 sip_element_tree = proto_item_add_subtree( sip_element_item,
2601 ett_sip_element);
2603 * Permission-Missing = "Permission-Missing" HCOLON per-miss-spec
2604 * *( COMMA per-miss-spec )
2605 * per-miss-spec = ( name-addr / addr-spec )
2606 * *( SEMI generic-param )
2607 * Initialize the uri_offsets
2609 sip_uri_offset_init(&uri_offsets);
2610 if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
2611 display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_pmiss_uri);
2613 break;
2616 case POS_TRIGGER_CONSENT :
2617 if(hdr_tree)
2619 sip_element_item = proto_tree_add_string_format(hdr_tree,
2620 hf_header_array[hf_index], tvb,
2621 offset, next_offset - offset,
2622 value, "%s",
2623 tvb_format_text(tvb, offset, linelen));
2625 sip_element_tree = proto_item_add_subtree( sip_element_item,
2626 ett_sip_element);
2628 * Trigger-Consent = "Trigger-Consent" HCOLON trigger-cons-spec
2629 * *( COMMA trigger-cons-spec )
2630 * trigger-cons-spec = ( SIP-URI / SIPS-URI )
2631 * *( SEMI trigger-param )
2632 * trigger-param = target-uri / generic-param
2633 * target-uri = "target-uri" EQUAL
2634 * LDQUOT *( qdtext / quoted-pair ) RDQUOT
2635 * Initialize the uri_offsets
2637 sip_uri_offset_init(&uri_offsets);
2638 if((dissect_sip_uri(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1) {
2640 tc_uri_item_tree = display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_tc_uri);
2641 if (line_end_offset > uri_offsets.uri_end) {
2642 gint hparam_offset = uri_offsets.uri_end + 1;
2643 /* Is there a header parameter */
2644 if (tvb_find_guint8(tvb, hparam_offset, 1,';')) {
2645 while ((hparam_offset != -1 && hparam_offset < line_end_offset) ) {
2646 /* Is this a target-uri ? */
2647 hparam_offset = hparam_offset + 1;
2648 if (tvb_strncaseeql(tvb, hparam_offset, "target-uri=\"", 12) == 0) {
2649 gint turi_start_offset = hparam_offset + 12;
2650 gint turi_end_offset = tvb_find_guint8(tvb, turi_start_offset, -1,'\"');
2651 if (turi_end_offset != -1)
2652 proto_tree_add_item(tc_uri_item_tree, hf_sip_tc_turi, tvb, turi_start_offset,(turi_end_offset - turi_start_offset),ENC_ASCII|ENC_NA);
2653 else
2654 break; /* malformed */
2656 hparam_offset = tvb_find_guint8(tvb, hparam_offset, -1,';');
2661 }/* hdr_tree */
2662 break;
2664 case POS_CSEQ :
2665 /* Store the sequence number */
2666 cseq_number = (guint32)strtoul(value, NULL, 10);
2667 cseq_number_set = 1;
2668 stat_info->tap_cseq_number=cseq_number;
2670 /* Add CSeq tree */
2671 if (hdr_tree) {
2672 sip_element_item = proto_tree_add_string_format(hdr_tree,
2673 hf_header_array[hf_index], tvb,
2674 offset, next_offset - offset,
2675 value, "%s",
2676 tvb_format_text(tvb, offset, linelen));
2677 cseq_tree = proto_item_add_subtree(sip_element_item, ett_sip_cseq);
2680 /* Walk past number and spaces characters to get to start
2681 of method name */
2682 for (sub_value_offset=0; sub_value_offset < value_len; sub_value_offset++)
2684 if (!isdigit((guchar)value[sub_value_offset]))
2686 proto_tree_add_uint(cseq_tree, hf_sip_cseq_seq_no,
2687 tvb, value_offset, sub_value_offset,
2688 cseq_number);
2689 break;
2693 for (; sub_value_offset < value_len; sub_value_offset++)
2695 if (isalpha((guchar)value[sub_value_offset]))
2697 /* Have reached start of method name */
2698 break;
2702 if (sub_value_offset == value_len)
2704 /* Didn't find method name */
2705 THROW(ReportedBoundsError);
2706 return offset - orig_offset;
2709 /* Extract method name from value */
2710 strlen_to_copy = (int)value_len-sub_value_offset;
2711 if (strlen_to_copy > MAX_CSEQ_METHOD_SIZE) {
2712 /* Note the error in the protocol tree */
2713 if (hdr_tree) {
2714 proto_tree_add_string_format(hdr_tree,
2715 hf_header_array[hf_index], tvb,
2716 offset, next_offset - offset,
2717 value+sub_value_offset, "%s String too big: %d bytes",
2718 sip_headers[POS_CSEQ].name,
2719 strlen_to_copy);
2721 THROW(ReportedBoundsError);
2722 return offset - orig_offset;
2724 else {
2725 g_strlcpy(cseq_method, value+sub_value_offset, MAX_CSEQ_METHOD_SIZE);
2727 /* Add CSeq method to the tree */
2728 if (cseq_tree)
2730 proto_tree_add_item(cseq_tree, hf_sip_cseq_method, tvb,
2731 value_offset + sub_value_offset, strlen_to_copy, ENC_ASCII|ENC_NA);
2734 break;
2736 case POS_RACK :
2738 int cseq_no_offset;
2739 /*int cseq_method_offset;*/
2741 /* Add RAck tree */
2742 if (hdr_tree) {
2743 sip_element_item = proto_tree_add_string_format(hdr_tree,
2744 hf_header_array[hf_index], tvb,
2745 offset, next_offset - offset,
2746 value, "%s",
2747 tvb_format_text(tvb, offset, linelen));
2748 rack_tree = proto_item_add_subtree(sip_element_item, ett_sip_rack);
2751 /* RSeq number */
2752 for (sub_value_offset=0; sub_value_offset < value_len; sub_value_offset++)
2754 if (!isdigit((guchar)value[sub_value_offset]))
2756 proto_tree_add_uint(rack_tree, hf_sip_rack_rseq_no,
2757 tvb, value_offset, sub_value_offset,
2758 (guint32)strtoul(value, NULL, 10));
2759 break;
2763 /* Get to start of CSeq number */
2764 for ( ; sub_value_offset < value_len; sub_value_offset++)
2766 if (value[sub_value_offset] != ' ' &&
2767 value[sub_value_offset] != '\t')
2769 break;
2772 cseq_no_offset = sub_value_offset;
2774 /* CSeq number */
2775 for ( ; sub_value_offset < value_len; sub_value_offset++)
2777 if (!isdigit((guchar)value[sub_value_offset]))
2779 proto_tree_add_uint(rack_tree, hf_sip_rack_cseq_no,
2780 tvb, value_offset+cseq_no_offset,
2781 sub_value_offset-cseq_no_offset,
2782 (guint32)strtoul(value+cseq_no_offset, NULL, 10));
2783 break;
2787 /* Get to start of CSeq method name */
2788 for ( ; sub_value_offset < value_len; sub_value_offset++)
2790 if (isalpha((guchar)value[sub_value_offset]))
2792 /* Have reached start of method name */
2793 break;
2796 /*cseq_method_offset = sub_value_offset;*/
2798 if (sub_value_offset == linelen)
2800 /* Didn't find method name */
2801 THROW(ReportedBoundsError);
2802 return offset - orig_offset;
2805 /* Add CSeq method to the tree */
2806 if (cseq_tree)
2808 proto_tree_add_item(rack_tree, hf_sip_rack_cseq_method, tvb,
2809 value_offset + sub_value_offset,
2810 (int)value_len-sub_value_offset, ENC_ASCII|ENC_NA);
2813 break;
2816 case POS_CALL_ID :
2817 /* Store the Call-id */
2818 g_strlcpy(call_id, value, MAX_CALL_ID_SIZE);
2819 stat_info->tap_call_id = wmem_strdup(wmem_packet_scope(), call_id);
2821 /* Add 'Call-id' string item to tree */
2822 if(hdr_tree) {
2823 proto_tree_add_string_format(hdr_tree,
2824 hf_header_array[hf_index], tvb,
2825 offset, next_offset - offset,
2826 value, "%s",
2827 tvb_format_text(tvb, offset, linelen));
2829 break;
2831 case POS_EXPIRES :
2832 if (strcmp(value, "0") == 0)
2834 expires_is_0 = 1;
2836 /* Add 'Expires' string item to tree */
2837 if(hdr_tree) {
2838 proto_tree_add_uint(hdr_tree,
2839 hf_header_array[hf_index], tvb,
2840 offset, next_offset - offset,
2841 atoi(value));
2843 break;
2846 * Content-Type is the same as Internet
2847 * media type used by other dissectors,
2848 * appropriate dissector found by
2849 * lookup in "media_type" dissector table.
2851 case POS_CONTENT_TYPE :
2852 proto_tree_add_string_format(hdr_tree,
2853 hf_header_array[hf_index], tvb,
2854 offset, next_offset - offset,
2855 value, "%s",
2856 tvb_format_text(tvb, offset, linelen));
2857 content_type_len = value_len;
2858 semi_colon_offset = tvb_find_guint8(tvb, value_offset, value_len, ';');
2859 /* Content-Type = ( "Content-Type" / "c" ) HCOLON media-type
2860 * media-type = m-type SLASH m-subtype *(SEMI m-parameter)
2861 * SEMI = SWS ";" SWS ; semicolon
2862 * LWS = [*WSP CRLF] 1*WSP ; linear whitespace
2863 * SWS = [LWS] ; sep whitespace
2865 if ( semi_colon_offset != -1) {
2866 gint content_type_end;
2868 * Skip whitespace after the semicolon.
2870 parameter_offset = tvb_skip_wsp(tvb, semi_colon_offset +1, value_offset + value_len - (semi_colon_offset +1));
2871 content_type_end = tvb_skip_wsp_return(tvb, semi_colon_offset-1);
2872 content_type_len = content_type_end - value_offset;
2873 content_type_parameter_str_len = value_offset + value_len - parameter_offset;
2874 content_type_parameter_str = tvb_get_string(wmem_packet_scope(), tvb, parameter_offset,
2875 content_type_parameter_str_len);
2877 media_type_str_lower_case = ascii_strdown_inplace(
2878 (gchar *)tvb_get_string(wmem_packet_scope(), tvb, value_offset, content_type_len));
2880 /* Debug code
2881 proto_tree_add_text(hdr_tree, tvb, value_offset,content_type_len,
2882 "media_type_str(lower cased)=%s",media_type_str_lower_case);
2884 break;
2886 case POS_CONTENT_LENGTH :
2887 content_length = atoi(value);
2888 if(hdr_tree) {
2889 proto_tree_add_uint_format(hdr_tree,
2890 hf_header_array[hf_index], tvb,
2891 offset, next_offset - offset,
2892 content_length, "%s",
2893 tvb_format_text(tvb, offset, linelen));
2895 break;
2897 case POS_MAX_BREADTH :
2898 case POS_MAX_FORWARDS :
2899 case POS_RSEQ :
2900 if(hdr_tree) {
2901 proto_tree_add_uint(hdr_tree,
2902 hf_header_array[hf_index], tvb,
2903 offset, next_offset - offset,
2904 (guint32)strtoul(value, NULL, 10));
2906 break;
2908 case POS_CONTACT :
2910 * Contact = ("Contact" / "m" ) HCOLON
2911 * ( STAR / (contact-param *(COMMA contact-param)))
2912 * contact-param = (name-addr / addr-spec) *(SEMI contact-params)
2914 sip_element_item = proto_tree_add_string_format(hdr_tree,
2915 hf_header_array[hf_index], tvb,
2916 offset, next_offset - offset,
2917 value, "%s",
2918 tvb_format_text(tvb, offset, linelen));
2919 sip_element_tree = proto_item_add_subtree( sip_element_item,
2920 ett_sip_element);
2922 /* value_offset points to the first non SWS character after ':' */
2923 c = tvb_get_guint8(tvb, value_offset);
2924 if (c =='*'){
2925 contact_is_star = 1;
2926 break;
2929 if(hdr_tree) {
2930 comma_offset = value_offset;
2931 while((comma_offset = dissect_sip_contact_item(tvb, pinfo, sip_element_tree, comma_offset, next_offset)) != -1)
2933 contacts++;
2934 if(comma_offset == next_offset)
2936 /* Line End reached: Stop Parsing */
2937 break;
2940 if(tvb_get_guint8(tvb, comma_offset) != ',')
2942 /* Undefined value reached: Stop Parsing */
2943 break;
2945 comma_offset++; /* skip comma */
2948 break;
2950 case POS_AUTHORIZATION:
2951 /* Authorization = "Authorization" HCOLON credentials
2952 * credentials = ("Digest" LWS digest-response)
2953 * / other-response
2954 * digest-response = dig-resp *(COMMA dig-resp)
2955 * other-response = auth-scheme LWS auth-param
2956 * *(COMMA auth-param)
2958 case POS_WWW_AUTHENTICATE:
2959 /* Proxy-Authenticate = "Proxy-Authenticate" HCOLON challenge
2960 * challenge = ("Digest" LWS digest-cln *(COMMA digest-cln))
2961 * / other-challenge
2962 * other-challenge = auth-scheme LWS auth-param
2963 * *(COMMA auth-param)
2964 * auth-scheme = token
2966 case POS_PROXY_AUTHENTICATE:
2967 /* Proxy-Authenticate = "Proxy-Authenticate" HCOLON challenge
2969 case POS_PROXY_AUTHORIZATION:
2970 /* Proxy-Authorization = "Proxy-Authorization" HCOLON credentials
2972 case POS_AUTHENTICATION_INFO:
2973 /* Authentication-Info = "Authentication-Info" HCOLON ainfo
2974 * *(COMMA ainfo)
2975 * ainfo = nextnonce / message-qop
2976 * / response-auth / cnonce
2977 * / nonce-count
2979 /* Add tree using whole text of line */
2980 if (hdr_tree) {
2981 proto_item *ti_c;
2982 /* Add whole line as header tree */
2983 sip_element_item = proto_tree_add_string_format(hdr_tree,
2984 hf_header_array[hf_index], tvb,
2985 offset, next_offset - offset,
2986 value, "%s",
2987 tvb_format_text(tvb, offset, linelen));
2988 sip_element_tree = proto_item_add_subtree( sip_element_item,
2989 ett_sip_element);
2991 /* Set sip.auth as a hidden field/filter */
2992 ti_c = proto_tree_add_item(hdr_tree, hf_sip_auth, tvb,
2993 offset, next_offset-offset,
2994 ENC_ASCII|ENC_NA);
2995 PROTO_ITEM_SET_HIDDEN(ti_c);
2997 /* Authentication-Info does not begin with the scheme name */
2998 if (hf_index != POS_AUTHENTICATION_INFO)
3000 /* The first time comma_offset is "start of parameters" */
3001 comma_offset = tvb_pbrk_guint8(tvb, value_offset, line_end_offset - value_offset, " \t\r\n", NULL);
3002 proto_tree_add_item(sip_element_tree, hf_sip_auth_scheme,
3003 tvb, value_offset, comma_offset - value_offset,
3004 ENC_ASCII|ENC_NA);
3005 }else{
3006 /* The first time comma_offset is "start of parameters" */
3007 comma_offset = value_offset;
3010 /* Parse each individual parameter in the line */
3011 while ((comma_offset = dissect_sip_authorization_item(tvb, sip_element_tree, comma_offset, line_end_offset)) != -1)
3013 if(comma_offset == line_end_offset)
3015 /* Line End reached: Stop Parsing */
3016 break;
3019 if(tvb_get_guint8(tvb, comma_offset) != ',')
3021 /* Undefined value reached: Stop Parsing */
3022 break;
3024 comma_offset++; /* skip comma */
3026 }/*hdr_tree*/
3027 break;
3029 case POS_ROUTE:
3030 /* Add Route subtree */
3031 if (hdr_tree) {
3032 sip_element_item = proto_tree_add_string_format(hdr_tree,
3033 hf_header_array[hf_index], tvb,
3034 offset, next_offset - offset,
3035 value, "%s",
3036 tvb_format_text(tvb, offset, linelen));
3037 route_tree = proto_item_add_subtree(sip_element_item, ett_sip_route);
3038 dissect_sip_route_header(tvb, route_tree, pinfo, &sip_route_uri, value_offset, line_end_offset);
3040 break;
3041 case POS_RECORD_ROUTE:
3042 /* Add Record-Route subtree */
3043 if (hdr_tree) {
3044 sip_element_item = proto_tree_add_string_format(hdr_tree,
3045 hf_header_array[hf_index], tvb,
3046 offset, next_offset - offset,
3047 value, "%s",
3048 tvb_format_text(tvb, offset, linelen));
3049 route_tree = proto_item_add_subtree(sip_element_item, ett_sip_route);
3050 dissect_sip_route_header(tvb, route_tree, pinfo, &sip_record_route_uri, value_offset, line_end_offset);
3052 break;
3053 case POS_VIA:
3054 /* Add Via subtree */
3055 if (hdr_tree) {
3056 sip_element_item = proto_tree_add_string_format(hdr_tree,
3057 hf_header_array[hf_index], tvb,
3058 offset, next_offset - offset,
3059 value, "%s",
3060 tvb_format_text(tvb, offset, linelen));
3061 via_tree = proto_item_add_subtree(sip_element_item, ett_sip_via);
3062 dissect_sip_via_header(tvb, via_tree, value_offset, line_end_offset);
3064 break;
3065 case POS_REASON:
3066 if(hdr_tree) {
3067 sip_element_item = proto_tree_add_string_format(hdr_tree,
3068 hf_header_array[hf_index], tvb,
3069 offset, next_offset - offset,
3070 value, "%s",
3071 tvb_format_text(tvb, offset, linelen));
3072 reason_tree = proto_item_add_subtree(sip_element_item, ett_sip_reason);
3073 dissect_sip_reason_header(tvb, reason_tree, value_offset, line_end_offset);
3075 break;
3076 case POS_CONTENT_ENCODING:
3077 /* Content-Encoding = ( "Content-Encoding" / "e" ) HCOLON
3078 * content-coding *(COMMA content-coding)
3080 proto_tree_add_string_format(hdr_tree,
3081 hf_header_array[hf_index], tvb,
3082 offset, next_offset - offset,
3083 value, "%s",
3084 tvb_format_text(tvb, offset, linelen));
3086 content_encoding_parameter_str = ascii_strdown_inplace(tvb_get_string(wmem_packet_scope(), tvb, value_offset,
3087 (line_end_offset-value_offset)));
3088 break;
3089 default :
3090 /* Default case is to assume it's an FT_STRING field */
3091 proto_tree_add_string_format(hdr_tree,
3092 hf_header_array[hf_index], tvb,
3093 offset, next_offset - offset,
3094 value, "%s",
3095 tvb_format_text(tvb, offset, linelen));
3096 break;
3097 }/* end switch */
3098 }/*if HF_index */
3099 }/* if colon_offset */
3100 if (is_no_header_termination == TRUE){
3101 /* Header not terminated by empty line CRLF */
3102 proto_tree_add_expert(hdr_tree, pinfo, &ei_sip_header_not_terminated,
3103 tvb, line_end_offset, -1);
3105 offset = next_offset;
3106 }/* End while */
3108 datalen = tvb_length_remaining(tvb, offset);
3109 reported_datalen = tvb_reported_length_remaining(tvb, offset);
3110 if (content_length != -1) {
3111 if (datalen > content_length)
3112 datalen = content_length;
3113 if (reported_datalen > content_length)
3114 reported_datalen = content_length;
3117 /* Add to info column interesting things learned from header fields. */
3118 /* Registration requests */
3119 if (current_method_idx == SIP_METHOD_REGISTER)
3121 if (contact_is_star && expires_is_0)
3123 col_append_str(pinfo->cinfo, COL_INFO, " (remove all bindings)");
3125 else
3126 if (!contacts)
3128 col_append_str(pinfo->cinfo, COL_INFO, " (fetch bindings)");
3132 /* Registration responses */
3133 if (line_type == STATUS_LINE && (strcmp(cseq_method, "REGISTER") == 0))
3135 col_append_fstr(pinfo->cinfo, COL_INFO, " (%d bindings)", contacts);
3138 /* We've finished writing to the info col for this SIP message
3139 * Set fence in case there is more than one (SIP)message in the frame
3141 col_append_str(pinfo->cinfo, COL_INFO, " | ");
3142 col_set_fence(pinfo->cinfo, COL_INFO);
3144 /* Find the total setup time, Must be done before checking for resend
3145 * As that will overwrite the "Request packet no".
3147 if ((line_type == REQUEST_LINE)&&(strcmp(cseq_method, "ACK") == 0))
3149 request_for_response = sip_find_invite(pinfo, cseq_method, call_id,
3150 cseq_number_set, cseq_number,
3151 &response_time);
3152 stat_info->setup_time = response_time;
3155 /* Check if this packet is a resend. */
3156 resend_for_packet = sip_is_packet_resend(pinfo, cseq_method, call_id,
3157 cseq_number_set, cseq_number,
3158 line_type);
3159 /* Mark whether this is a resend for the tap */
3160 stat_info->resend = (resend_for_packet > 0);
3162 /* For responses, try to link back to request frame */
3163 if (line_type == STATUS_LINE)
3165 request_for_response = sip_find_request(pinfo, cseq_method, call_id,
3166 cseq_number_set, cseq_number,
3167 &response_time);
3170 if (datalen > 0) {
3172 * There's a message body starting at "offset".
3173 * Set the length of the header item.
3175 proto_item_set_end(th, tvb, offset);
3176 if(content_encoding_parameter_str != NULL &&
3177 (!strncmp(content_encoding_parameter_str, "gzip", 4) ||
3178 !strncmp(content_encoding_parameter_str,"deflate",7))){
3179 /* The body is gzip:ed */
3180 next_tvb = tvb_uncompress(tvb, offset, datalen);
3181 if (next_tvb) {
3182 add_new_data_source(pinfo, next_tvb, "gunziped data");
3183 if(sip_tree) {
3184 ti_a = proto_tree_add_item(sip_tree, hf_sip_msg_body, next_tvb, 0, -1,
3185 ENC_NA);
3186 message_body_tree = proto_item_add_subtree(ti_a, ett_sip_message_body);
3188 } else {
3189 next_tvb = tvb_new_subset(tvb, offset, datalen, reported_datalen);
3190 if(sip_tree) {
3191 ti_a = proto_tree_add_item(sip_tree, hf_sip_msg_body, next_tvb, 0, -1,
3192 ENC_NA);
3193 message_body_tree = proto_item_add_subtree(ti_a, ett_sip_message_body);
3196 }else{
3197 next_tvb = tvb_new_subset(tvb, offset, datalen, reported_datalen);
3198 if(sip_tree) {
3199 ti_a = proto_tree_add_item(sip_tree, hf_sip_msg_body, next_tvb, 0, -1,
3200 ENC_NA);
3201 message_body_tree = proto_item_add_subtree(ti_a, ett_sip_message_body);
3205 /* give the content type parameters to sub dissectors */
3206 if ( media_type_str_lower_case != NULL ) {
3207 void *save_private_data = pinfo->private_data;
3208 pinfo->private_data = content_type_parameter_str;
3210 /* SDP needs a transport layer to determine request/response */
3211 if (!strcmp(media_type_str_lower_case, "application/sdp")) {
3212 /* Resends don't count */
3213 if (resend_for_packet == 0) {
3214 if (line_type == REQUEST_LINE) {
3215 setup_sdp_transport(next_tvb, pinfo, SDP_EXCHANGE_OFFER, pinfo->fd->num);
3216 } else if (line_type == STATUS_LINE) {
3217 if (stat_info->response_code >= 400) {
3218 /* SIP client request failed, so SDP offer should fail */
3219 setup_sdp_transport(next_tvb, pinfo, SDP_EXCHANGE_ANSWER_REJECT, request_for_response);
3221 else if ((stat_info->response_code >= 200) && (stat_info->response_code <= 299)) {
3222 /* SIP success request, so SDP offer should be accepted */
3223 setup_sdp_transport(next_tvb, pinfo, SDP_EXCHANGE_ANSWER_ACCEPT, request_for_response);
3226 } else {
3227 setup_sdp_transport_resend(pinfo->fd->num, resend_for_packet);
3231 found_match = dissector_try_string(media_type_dissector_table,
3232 media_type_str_lower_case,
3233 next_tvb, pinfo,
3234 message_body_tree, NULL);
3235 if (!found_match &&
3236 !strncmp(media_type_str_lower_case, "multipart/", sizeof("multipart/")-1)) {
3237 /* Try to decode the unknown multipart subtype anyway */
3238 found_match = dissector_try_string(media_type_dissector_table,
3239 "multipart/",
3240 next_tvb, pinfo,
3241 message_body_tree, NULL);
3243 pinfo->private_data = save_private_data;
3244 /* If no match dump as text */
3246 if ( found_match != TRUE )
3248 if (!(dissector_try_heuristic(heur_subdissector_list,
3249 next_tvb, pinfo, message_body_tree, NULL))) {
3250 int tmp_offset = 0;
3251 while (tvb_offset_exists(next_tvb, tmp_offset)) {
3252 tvb_find_line_end(next_tvb, tmp_offset, -1, &next_offset, FALSE);
3253 linelen = next_offset - tmp_offset;
3254 if(message_body_tree) {
3255 proto_tree_add_text(message_body_tree, next_tvb,
3256 tmp_offset, linelen, "%s",
3257 tvb_format_text(next_tvb, tmp_offset, linelen));
3259 tmp_offset = next_offset;
3260 }/* end while */
3263 offset += datalen;
3266 /* And add the filterable field to the request/response line */
3267 if (reqresp_tree)
3269 proto_item *item;
3270 item = proto_tree_add_boolean(reqresp_tree, hf_sip_resend, tvb, orig_offset, 0,
3271 resend_for_packet > 0);
3272 PROTO_ITEM_SET_GENERATED(item);
3273 if (resend_for_packet > 0)
3275 item = proto_tree_add_uint(reqresp_tree, hf_sip_original_frame,
3276 tvb, orig_offset, 0, resend_for_packet);
3277 PROTO_ITEM_SET_GENERATED(item);
3280 if (request_for_response > 0)
3282 item = proto_tree_add_uint(reqresp_tree, hf_sip_matching_request_frame,
3283 tvb, orig_offset, 0, request_for_response);
3284 PROTO_ITEM_SET_GENERATED(item);
3285 item = proto_tree_add_uint(reqresp_tree, hf_sip_response_time,
3286 tvb, orig_offset, 0, response_time);
3287 PROTO_ITEM_SET_GENERATED(item);
3288 if ((line_type == STATUS_LINE)&&(strcmp(cseq_method, "BYE") == 0)){
3289 item = proto_tree_add_uint(reqresp_tree, hf_sip_release_time,
3290 tvb, orig_offset, 0, response_time);
3291 PROTO_ITEM_SET_GENERATED(item);
3296 if (ts != NULL)
3297 proto_item_set_len(ts, offset - orig_offset);
3299 if (global_sip_raw_text)
3300 tvb_raw_text_add(tvb, orig_offset, offset - orig_offset, tree);
3302 /* Report this packet to the tap */
3303 if (!pinfo->flags.in_error_pkt)
3305 tap_queue_packet(sip_tap, pinfo, stat_info);
3306 if(have_tap_listener(exported_pdu_tap)){
3307 export_sip_pdu(pinfo,tvb);
3311 /* Append a brief summary to the SIP root item */
3312 if (stat_info->request_method) {
3313 proto_item_append_text(ts, " (%s)", stat_info->request_method);
3315 else {
3316 proto_item_append_text(ts, " (%u)", stat_info->response_code);
3318 return offset - orig_offset;
3321 /* Display filter for SIP Request-Line */
3322 static void
3323 dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint offset, guint meth_len, gint linelen)
3325 char *value;
3326 guint parameter_len = meth_len;
3327 uri_offset_info uri_offsets;
3330 * We know we have the entire method; otherwise, "sip_parse_line()"
3331 * would have returned OTHER_LINE.
3332 * Request-Line = Method SP Request-URI SP SIP-Version CRLF
3333 * SP = single space
3334 * Request-URI = SIP-URI / SIPS-URI / absoluteURI
3337 /* get method string*/
3338 value = tvb_get_string(wmem_packet_scope(), tvb, offset, parameter_len);
3340 /* Copy request method for telling tap */
3341 stat_info->request_method = value;
3343 if (tree) {
3344 proto_tree_add_string(tree, hf_sip_Method, tvb, offset, parameter_len, value);
3346 /* build Request-URI tree*/
3347 offset=offset + parameter_len+1;
3348 sip_uri_offset_init(&uri_offsets);
3349 /* calc R-URI len*/
3350 uri_offsets.uri_end = tvb_find_guint8(tvb, offset, linelen, ' ')-1;
3351 dissect_sip_uri(tvb, pinfo, offset, offset + linelen, &uri_offsets);
3352 display_sip_uri(tvb, tree, &uri_offsets, &sip_req_uri);
3356 /* Display filter for SIP Status-Line */
3357 static void
3358 dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint line_end, gint offset)
3360 gint response_code = 0;
3361 int diag_len;
3362 tvbuff_t *next_tvb;
3365 * We know we have the entire status code; otherwise,
3366 * "sip_parse_line()" would have returned OTHER_LINE.
3367 * We also know that we have a version string followed by a
3368 * space at the beginning of the line, for the same reason.
3370 response_code = atoi((char*)tvb_get_string(wmem_packet_scope(), tvb, offset + SIP2_HDR_LEN + 1, 3));
3372 /* Add numerical response code to tree */
3373 if (tree) {
3374 proto_tree_add_uint(tree, hf_sip_Status_Code, tvb, offset + SIP2_HDR_LEN + 1,
3375 3, response_code);
3378 /* Add response code for sending to tap */
3379 stat_info->response_code = response_code;
3381 /* Skip past the responce code and possible trailing space */
3382 offset = SIP2_HDR_LEN + 1 + 3 + 1;
3384 /* Check for diagnostics */
3385 diag_len = line_end - offset;
3386 if((diag_len) <= 0)
3387 return;
3389 /* If we have a SIP diagnostics sub dissector call it */
3390 if(sip_diag_handle){
3391 next_tvb = tvb_new_subset(tvb, offset, diag_len, diag_len);
3392 call_dissector(sip_diag_handle, next_tvb, pinfo, tree);
3396 /* From section 4.1 of RFC 2543:
3398 * Request-Line = Method SP Request-URI SP SIP-Version CRLF
3400 * From section 5.1 of RFC 2543:
3402 * Status-Line = SIP-version SP Status-Code SP Reason-Phrase CRLF
3404 * From section 7.1 of RFC 3261:
3406 * Unlike HTTP, SIP treats the version number as a literal string.
3407 * In practice, this should make no difference.
3409 static line_type_t
3410 sip_parse_line(tvbuff_t *tvb, int offset, gint linelen, guint *token_1_lenp)
3412 gint space_offset;
3413 gint token_1_start;
3414 guint token_1_len;
3415 gint token_2_start;
3416 guint token_2_len;
3417 gint token_3_start;
3418 guint token_3_len;
3419 gint colon_pos;
3421 token_1_start = offset;
3422 space_offset = tvb_find_guint8(tvb, token_1_start, -1, ' ');
3423 if ((space_offset == -1) || (space_offset == token_1_start)) {
3425 * Either there's no space in the line (which means
3426 * the line is empty or doesn't have a token followed
3427 * by a space; neither is valid for a request or status), or
3428 * the first character in the line is a space (meaning
3429 * the method is empty, which isn't valid for a request,
3430 * or the SIP version is empty, which isn't valid for a
3431 * status).
3433 return OTHER_LINE;
3435 token_1_len = space_offset - token_1_start;
3436 token_2_start = space_offset + 1;
3437 space_offset = tvb_find_guint8(tvb, token_2_start, -1, ' ');
3438 if (space_offset == -1) {
3440 * There's no space after the second token, so we don't
3441 * have a third token.
3443 return OTHER_LINE;
3445 token_2_len = space_offset - token_2_start;
3446 token_3_start = space_offset + 1;
3447 token_3_len = token_1_start + linelen - token_3_start;
3449 *token_1_lenp = token_1_len;
3452 * Is the first token a version string?
3454 if ( (strict_sip_version && (
3455 token_1_len == SIP2_HDR_LEN
3456 && tvb_strneql(tvb, token_1_start, SIP2_HDR, SIP2_HDR_LEN) == 0)
3457 ) || (! strict_sip_version && (
3458 tvb_strncaseeql(tvb, token_1_start, "SIP/", 4) == 0)
3459 )) {
3461 * Yes, so this is either a Status-Line or something
3462 * else other than a Request-Line. To be a Status-Line,
3463 * the second token must be a 3-digit number.
3465 if (token_2_len != 3) {
3467 * We don't have 3-character status code.
3469 return OTHER_LINE;
3471 if (!isdigit(tvb_get_guint8(tvb, token_2_start)) ||
3472 !isdigit(tvb_get_guint8(tvb, token_2_start + 1)) ||
3473 !isdigit(tvb_get_guint8(tvb, token_2_start + 2))) {
3475 * 3 characters yes, 3 digits no.
3477 return OTHER_LINE;
3479 return STATUS_LINE;
3480 } else {
3482 * No, so this is either a Request-Line or something
3483 * other than a Status-Line. To be a Request-Line, the
3484 * second token must be a URI and the third token must
3485 * be a version string.
3487 if (token_2_len < 3) {
3489 * We don't have a URI consisting of at least 3
3490 * characters.
3492 return OTHER_LINE;
3494 colon_pos = tvb_find_guint8(tvb, token_2_start + 1, -1, ':');
3495 if (colon_pos == -1) {
3497 * There is no colon after the method, so the URI
3498 * doesn't have a colon in it, so it's not valid.
3500 return OTHER_LINE;
3502 if (colon_pos >= token_3_start) {
3504 * The colon is in the version string, not the URI.
3506 return OTHER_LINE;
3508 /* XXX - Check for a proper URI prefix? */
3509 if ( (strict_sip_version && (
3510 token_3_len != SIP2_HDR_LEN
3511 || tvb_strneql(tvb, token_3_start, SIP2_HDR, SIP2_HDR_LEN) == -1)
3512 ) || (! strict_sip_version && (
3513 tvb_strncaseeql(tvb, token_3_start, "SIP/", 4) == -1)
3514 )) {
3516 * The version string isn't an SIP version 2.0 version
3517 * string.
3519 return OTHER_LINE;
3521 return REQUEST_LINE;
3525 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
3526 guint meth_len, guint *meth_idx)
3528 guint i;
3529 gchar *meth_name;
3531 meth_name = tvb_get_string(wmem_packet_scope(), tvb, meth_offset, meth_len);
3533 for (i = 1; i < array_length(sip_methods); i++) {
3534 if (meth_len == strlen(sip_methods[i]) &&
3535 strncmp(meth_name, sip_methods[i], meth_len) == 0)
3537 *meth_idx = i;
3538 return TRUE;
3542 return FALSE;
3546 * Returns index of method in sip_headers
3547 * Header namne should be in lower case
3549 static gint sip_is_known_sip_header(gchar *header_name, guint header_len)
3551 guint pos;
3553 /* Compact name is one character long */
3554 if(header_len>1){
3555 pos = GPOINTER_TO_UINT(g_hash_table_lookup(sip_headers_hash, header_name));
3556 if (pos!=0)
3557 return pos;
3560 /* Look for compact name match */
3561 for (pos = 1; pos < array_length(sip_headers); pos++) {
3562 if (sip_headers[pos].compact_name != NULL &&
3563 header_len == strlen(sip_headers[pos].compact_name) &&
3564 g_ascii_strncasecmp(header_name, sip_headers[pos].compact_name, header_len) == 0)
3565 return pos;
3568 return -1;
3572 * Display the entire message as raw text.
3574 static void
3575 tvb_raw_text_add(tvbuff_t *tvb, int offset, int length, proto_tree *tree)
3577 proto_tree *raw_tree = NULL;
3578 proto_item *ti = NULL;
3579 int next_offset, linelen, end_offset;
3580 char *str;
3582 if (tree) {
3583 ti = proto_tree_add_item(tree, proto_raw_sip, tvb, offset, length, ENC_NA);
3584 raw_tree = proto_item_add_subtree(ti, ett_raw_text);
3587 end_offset = offset + length;
3589 while (offset < end_offset) {
3590 tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
3591 linelen = next_offset - offset;
3592 if (raw_tree) {
3593 if (global_sip_raw_text_without_crlf)
3594 str = tvb_format_text_wsp(tvb, offset, linelen);
3595 else
3596 str = tvb_format_text(tvb, offset, linelen);
3597 proto_tree_add_string_format(raw_tree, hf_sip_raw_line, tvb, offset, linelen,
3598 str,
3599 "%s",
3600 str);
3602 offset = next_offset;
3606 /* Check to see if this packet is a resent request. Return value is the frame number
3607 of the original frame this packet seems to be resending (0 = no resend). */
3608 guint sip_is_packet_resend(packet_info *pinfo,
3609 gchar *cseq_method,
3610 gchar *call_id,
3611 guchar cseq_number_set,
3612 guint32 cseq_number, line_type_t line_type)
3614 guint32 cseq_to_compare = 0;
3615 sip_hash_key key;
3616 sip_hash_key *p_key = 0;
3617 sip_hash_value *p_val = 0;
3618 sip_frame_result_value *sip_frame_result = NULL;
3619 guint result = 0;
3621 /* Only consider retransmission of UDP packets */
3622 if (pinfo->ptype != PT_UDP)
3624 return 0;
3627 /* Don't consider packets that appear to be resent only because
3628 they are e.g. returned in ICMP unreachable messages. */
3629 if (pinfo->flags.in_error_pkt)
3631 return 0;
3634 /* A broken packet may have no cseq number set. Don't consider it as
3635 a resend */
3636 if (!cseq_number_set)
3638 return 0;
3641 /* Return any answer stored from previous dissection */
3642 if (pinfo->fd->flags.visited)
3644 sip_frame_result = (sip_frame_result_value*)p_get_proto_data(pinfo->fd, proto_sip, pinfo->curr_layer_num);
3645 if (sip_frame_result != NULL)
3647 return sip_frame_result->original_frame_num;
3649 else
3651 return 0;
3655 /* No packet entry found, consult global hash table */
3657 /* Prepare the key */
3658 g_strlcpy(key.call_id, call_id, MAX_CALL_ID_SIZE);
3660 /* We're only using these addresses locally (for the hash lookup) so
3661 * there is no need to make a (g_malloc'd) copy of them.
3663 SET_ADDRESS(&key.dest_address, pinfo->net_dst.type, pinfo->net_dst.len,
3664 pinfo->net_dst.data);
3665 SET_ADDRESS(&key.source_address, pinfo->net_src.type,
3666 pinfo->net_src.len, pinfo->net_src.data);
3667 key.dest_port = pinfo->destport;
3668 if (sip_retrans_the_same_sport) {
3669 key.source_port = pinfo->srcport;
3670 } else {
3671 key.source_port = MAGIC_SOURCE_PORT;
3674 /* Do the lookup */
3675 p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
3677 if (p_val)
3679 /* Table entry found, we'll use its value for comparison */
3680 cseq_to_compare = p_val->cseq;
3682 /* First time through, must update value with current details if
3683 cseq number has changed */
3684 if (cseq_number != p_val->cseq)
3686 p_val->cseq = cseq_number;
3687 g_strlcpy(p_val->method, cseq_method, MAX_CSEQ_METHOD_SIZE);
3688 p_val->transaction_state = nothing_seen;
3689 p_val->frame_number = 0;
3690 if (line_type == REQUEST_LINE)
3692 p_val->request_time = pinfo->fd->abs_ts;
3696 else
3698 /* Need to create a new table entry */
3700 /* Allocate a new key and value */
3701 p_key = wmem_new(wmem_file_scope(), sip_hash_key);
3702 p_val = wmem_new(wmem_file_scope(), sip_hash_value);
3704 /* Fill in key and value details */
3705 g_snprintf(p_key->call_id, MAX_CALL_ID_SIZE, "%s", call_id);
3706 SE_COPY_ADDRESS(&(p_key->dest_address), &pinfo->net_dst);
3707 SE_COPY_ADDRESS(&(p_key->source_address), &pinfo->net_src);
3708 p_key->dest_port = pinfo->destport;
3709 if (sip_retrans_the_same_sport) {
3710 p_key->source_port = pinfo->srcport;
3711 } else {
3712 p_key->source_port = MAGIC_SOURCE_PORT;
3715 p_val->cseq = cseq_number;
3716 g_strlcpy(p_val->method, cseq_method, MAX_CSEQ_METHOD_SIZE);
3717 p_val->transaction_state = nothing_seen;
3718 p_val->frame_number = 0;
3719 if (line_type == REQUEST_LINE)
3721 p_val->request_time = pinfo->fd->abs_ts;
3724 /* Add entry */
3725 g_hash_table_insert(sip_hash, p_key, p_val);
3727 /* Assume have seen no cseq yet */
3728 cseq_to_compare = 0;
3732 /******************************************/
3733 /* Is it a resend??? */
3735 /* Does this look like a resent request (discount ACK, CANCEL, or a
3736 different method from the original one) ? */
3738 if ((line_type == REQUEST_LINE) && (cseq_number == cseq_to_compare) &&
3739 (p_val->transaction_state == request_seen) &&
3740 (strcmp(cseq_method, p_val->method) == 0) &&
3741 (strcmp(cseq_method, "ACK") != 0) &&
3742 (strcmp(cseq_method, "CANCEL") != 0))
3744 result = p_val->frame_number;
3747 /* Does this look like a resent final response ? */
3748 if ((line_type == STATUS_LINE) && (cseq_number == cseq_to_compare) &&
3749 (p_val->transaction_state == final_response_seen) &&
3750 (strcmp(cseq_method, p_val->method) == 0) &&
3751 (stat_info->response_code >= 200) &&
3752 (stat_info->response_code == p_val->response_code))
3754 result = p_val->frame_number;
3757 /* Update state for this entry */
3758 p_val->cseq = cseq_number;
3760 switch (line_type)
3762 case REQUEST_LINE:
3763 p_val->transaction_state = request_seen;
3764 if (!result)
3766 /* This frame is the original request */
3767 p_val->frame_number = pinfo->fd->num;
3769 break;
3770 case STATUS_LINE:
3771 if (stat_info->response_code >= 200)
3773 p_val->response_code = stat_info->response_code;
3774 p_val->transaction_state = final_response_seen;
3775 if (!result)
3777 /* This frame is the original response */
3778 p_val->frame_number = pinfo->fd->num;
3781 else
3783 p_val->transaction_state = provisional_response_seen;
3785 break;
3786 default:
3787 break;
3790 sip_frame_result = (sip_frame_result_value *)p_get_proto_data(pinfo->fd, proto_sip, pinfo->curr_layer_num);
3791 if (sip_frame_result == NULL)
3793 sip_frame_result = wmem_new0(wmem_file_scope(), sip_frame_result_value);
3794 p_add_proto_data(pinfo->fd, proto_sip, pinfo->curr_layer_num, sip_frame_result);
3797 /* Store return value with this packet */
3798 sip_frame_result->original_frame_num = result;
3800 return result;
3804 /* Check to see if this packet is a resent request. Return value is the frame number
3805 of the original frame this packet seems to be resending (0 = no resend). */
3806 guint sip_find_request(packet_info *pinfo,
3807 gchar *cseq_method,
3808 gchar *call_id,
3809 guchar cseq_number_set,
3810 guint32 cseq_number,
3811 guint32 *response_time)
3813 guint32 cseq_to_compare = 0;
3814 sip_hash_key key;
3815 sip_hash_value *p_val = 0;
3816 sip_frame_result_value *sip_frame_result = NULL;
3817 guint result = 0;
3818 gint seconds_between_packets;
3819 gint nseconds_between_packets;
3821 /* Only consider UDP */
3822 if (pinfo->ptype != PT_UDP)
3824 return 0;
3827 /* Ignore error (usually ICMP) frames */
3828 if (pinfo->flags.in_error_pkt)
3830 return 0;
3833 /* A broken packet may have no cseq number set. Ignore. */
3834 if (!cseq_number_set)
3836 return 0;
3839 /* Return any answer stored from previous dissection */
3840 if (pinfo->fd->flags.visited)
3842 sip_frame_result = (sip_frame_result_value*)p_get_proto_data(pinfo->fd, proto_sip, pinfo->curr_layer_num);
3843 if (sip_frame_result != NULL)
3845 *response_time = sip_frame_result->response_time;
3846 return sip_frame_result->response_request_frame_num;
3848 else
3850 return 0;
3854 /* No packet entry found, consult global hash table */
3856 /* Prepare the key */
3857 g_strlcpy(key.call_id, call_id, MAX_CALL_ID_SIZE);
3859 /* Looking for matching request, so reverse addresses for this lookup */
3860 SET_ADDRESS(&key.dest_address, pinfo->net_src.type, pinfo->net_src.len,
3861 pinfo->net_src.data);
3862 SET_ADDRESS(&key.source_address, pinfo->net_dst.type, pinfo->net_dst.len,
3863 pinfo->net_dst.data);
3864 key.dest_port = pinfo->srcport;
3865 key.source_port = pinfo->destport;
3867 /* Do the lookup */
3868 p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
3870 if (p_val)
3872 /* Table entry found, we'll use its value for comparison */
3873 cseq_to_compare = p_val->cseq;
3875 else
3877 /* We don't have the request */
3878 return 0;
3882 /**************************************************/
3883 /* Is it a response to a request that we've seen? */
3884 if ((cseq_number == cseq_to_compare) &&
3885 (p_val->transaction_state == request_seen) &&
3886 (strcmp(cseq_method, p_val->method) == 0))
3888 result = p_val->frame_number;
3892 /* Store return value with this packet */
3893 sip_frame_result = (sip_frame_result_value *)p_get_proto_data(pinfo->fd, proto_sip, pinfo->curr_layer_num);
3894 if (sip_frame_result == NULL)
3896 /* Allocate and set all values to zero */
3897 sip_frame_result = wmem_new0(wmem_file_scope(), sip_frame_result_value);
3898 p_add_proto_data(pinfo->fd, proto_sip, pinfo->curr_layer_num, sip_frame_result);
3901 sip_frame_result->response_request_frame_num = result;
3903 /* Work out response time */
3904 seconds_between_packets = (gint)
3905 (pinfo->fd->abs_ts.secs - p_val->request_time.secs);
3906 nseconds_between_packets =
3907 pinfo->fd->abs_ts.nsecs - p_val->request_time.nsecs;
3908 sip_frame_result->response_time = (seconds_between_packets*1000) +
3909 (nseconds_between_packets / 1000000);
3910 *response_time = sip_frame_result->response_time;
3912 return result;
3916 * Find the initial INVITE to calculate the total setup time
3918 guint sip_find_invite(packet_info *pinfo,
3919 gchar *cseq_method _U_,
3920 gchar *call_id,
3921 guchar cseq_number_set,
3922 guint32 cseq_number _U_,
3923 guint32 *response_time)
3925 #if 0
3926 guint32 cseq_to_compare = 0;
3927 #endif
3928 sip_hash_key key;
3929 sip_hash_value *p_val = 0;
3930 sip_frame_result_value *sip_frame_result = NULL;
3931 guint result = 0;
3932 gint seconds_between_packets;
3933 gint nseconds_between_packets;
3935 /* Only consider UDP */
3936 if (pinfo->ptype != PT_UDP)
3938 return 0;
3941 /* Ignore error (usually ICMP) frames */
3942 if (pinfo->flags.in_error_pkt)
3944 return 0;
3947 /* A broken packet may have no cseq number set. Ignore. */
3948 if (!cseq_number_set)
3950 return 0;
3953 /* Return any answer stored from previous dissection */
3954 if (pinfo->fd->flags.visited)
3956 sip_frame_result = (sip_frame_result_value*)p_get_proto_data(pinfo->fd, proto_sip, pinfo->curr_layer_num);
3957 if (sip_frame_result != NULL)
3959 *response_time = sip_frame_result->response_time;
3960 return sip_frame_result->response_request_frame_num;
3962 else
3964 return 0;
3968 /* No packet entry found, consult global hash table */
3970 /* Prepare the key */
3971 g_strlcpy(key.call_id, call_id, MAX_CALL_ID_SIZE);
3973 /* Looking for matching INVITE */
3974 SET_ADDRESS(&key.dest_address, pinfo->net_dst.type, pinfo->net_dst.len,
3975 pinfo->net_dst.data);
3976 SET_ADDRESS(&key.source_address, pinfo->net_src.type, pinfo->net_src.len,
3977 pinfo->net_src.data);
3978 key.dest_port = pinfo->destport;
3979 key.source_port = pinfo->srcport;
3981 /* Do the lookup */
3982 p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
3984 if (p_val)
3986 #if 0
3987 /* Table entry found, we'll use its value for comparison */
3988 cseq_to_compare = p_val->cseq;
3989 #endif
3991 else
3993 /* We don't have the request */
3994 return 0;
3998 /**************************************************/
3999 /* Is it a response to a request that we've seen? */
4000 #if 0
4001 if ((cseq_number == cseq_to_compare) &&
4002 (p_val->transaction_state == request_seen) &&
4003 (strcmp(cseq_method, p_val->method) == 0))
4005 result = p_val->frame_number;
4007 #endif
4009 result = p_val->frame_number;
4011 /* Store return value with this packet */
4012 sip_frame_result = (sip_frame_result_value *)p_get_proto_data(pinfo->fd, proto_sip, pinfo->curr_layer_num);
4013 if (sip_frame_result == NULL)
4015 /* Allocate and set all values to zero */
4016 sip_frame_result = wmem_new0(wmem_file_scope(), sip_frame_result_value);
4017 p_add_proto_data(pinfo->fd, proto_sip, pinfo->curr_layer_num, sip_frame_result);
4020 sip_frame_result->response_request_frame_num = result;
4022 /* Work out response time */
4023 seconds_between_packets = (gint)
4024 (pinfo->fd->abs_ts.secs - p_val->request_time.secs);
4025 nseconds_between_packets =
4026 pinfo->fd->abs_ts.nsecs - p_val->request_time.nsecs;
4027 sip_frame_result->response_time = (seconds_between_packets*1000) +
4028 (nseconds_between_packets / 1000000);
4029 *response_time = sip_frame_result->response_time;
4032 return result;
4035 /* Register the protocol with Wireshark */
4036 void proto_register_sip(void)
4039 /* Setup list of header fields */
4040 static hf_register_info hf[] = {
4042 { &hf_sip_msg_hdr,
4043 { "Message Header", "sip.msg_hdr",
4044 FT_STRING, BASE_NONE, NULL, 0,
4045 "Message Header in SIP message", HFILL }
4047 { &hf_sip_Method,
4048 { "Method", "sip.Method",
4049 FT_STRING, BASE_NONE,NULL,0x0,
4050 "SIP Method", HFILL }
4052 { &hf_Request_Line,
4053 { "Request-Line", "sip.Request-Line",
4054 FT_STRING, BASE_NONE,NULL,0x0,
4055 "SIP Request-Line", HFILL }
4057 { &hf_sip_ruri,
4058 { "Request-URI", "sip.r-uri",
4059 FT_STRING, BASE_NONE,NULL,0x0,
4060 "RFC 3261: SIP R-URI", HFILL }
4062 { &hf_sip_ruri_user,
4063 { "Request-URI User Part", "sip.r-uri.user",
4064 FT_STRING, BASE_NONE,NULL,0x0,
4065 "RFC 3261: SIP R-URI User", HFILL }
4067 { &hf_sip_ruri_host,
4068 { "Request-URI Host Part", "sip.r-uri.host",
4069 FT_STRING, BASE_NONE,NULL,0x0,
4070 "RFC 3261: SIP R-URI Host", HFILL }
4072 { &hf_sip_ruri_port,
4073 { "Request-URI Host Port", "sip.r-uri.port",
4074 FT_STRING, BASE_NONE,NULL,0x0,
4075 "RFC 3261: SIP R-URI Port", HFILL }
4077 { &hf_sip_ruri_param,
4078 { "Request URI parameter", "sip.r-uri.param",
4079 FT_STRING, BASE_NONE,NULL,0x0,
4080 NULL, HFILL }
4082 { &hf_sip_Status_Code,
4083 { "Status-Code", "sip.Status-Code",
4084 FT_UINT32, BASE_DEC,NULL,0x0,
4085 "SIP Status Code", HFILL }
4087 { &hf_sip_Status_Line,
4088 { "Status-Line", "sip.Status-Line",
4089 FT_STRING, BASE_NONE,NULL,0x0,
4090 "SIP Status-Line", HFILL }
4092 { &hf_sip_display,
4093 { "SIP Display info", "sip.display.info",
4094 FT_STRING, BASE_NONE,NULL,0x0,
4095 "RFC 3261: Display info", HFILL }
4097 { &hf_sip_to_addr,
4098 { "SIP to address", "sip.to.addr",
4099 FT_STRING, BASE_NONE,NULL,0x0,
4100 "RFC 3261: To Address", HFILL }
4102 { &hf_sip_to_user,
4103 { "SIP to address User Part", "sip.to.user",
4104 FT_STRING, BASE_NONE,NULL,0x0,
4105 "RFC 3261: To Address User", HFILL }
4107 { &hf_sip_to_host,
4108 { "SIP to address Host Part", "sip.to.host",
4109 FT_STRING, BASE_NONE,NULL,0x0,
4110 "RFC 3261: To Address Host", HFILL }
4112 { &hf_sip_to_port,
4113 { "SIP to address Host Port", "sip.to.port",
4114 FT_STRING, BASE_NONE,NULL,0x0,
4115 "RFC 3261: To Address Port", HFILL }
4117 { &hf_sip_to_param,
4118 { "SIP To URI parameter", "sip.to.param",
4119 FT_STRING, BASE_NONE,NULL,0x0,
4120 NULL, HFILL }
4122 { &hf_sip_to_tag,
4123 { "SIP to tag", "sip.to.tag",
4124 FT_STRING, BASE_NONE,NULL,0x0,
4125 "RFC 3261: to tag", HFILL }
4127 { &hf_sip_from_addr,
4128 { "SIP from address", "sip.from.addr",
4129 FT_STRING, BASE_NONE,NULL,0x0,
4130 "RFC 3261: From Address", HFILL }
4132 { &hf_sip_from_user,
4133 { "SIP from address User Part", "sip.from.user",
4134 FT_STRING, BASE_NONE,NULL,0x0,
4135 "RFC 3261: From Address User", HFILL }
4137 { &hf_sip_from_host,
4138 { "SIP from address Host Part", "sip.from.host",
4139 FT_STRING, BASE_NONE,NULL,0x0,
4140 "RFC 3261: From Address Host", HFILL }
4142 { &hf_sip_from_port,
4143 { "SIP from address Host Port", "sip.from.port",
4144 FT_STRING, BASE_NONE,NULL,0x0,
4145 "RFC 3261: From Address Port", HFILL }
4147 { &hf_sip_from_param,
4148 { "SIP From URI parameter", "sip.from.param",
4149 FT_STRING, BASE_NONE,NULL,0x0,
4150 NULL, HFILL }
4152 { &hf_sip_from_tag,
4153 { "SIP from tag", "sip.from.tag",
4154 FT_STRING, BASE_NONE,NULL,0x0,
4155 "RFC 3261: from tag", HFILL }
4157 /* etxrab */
4158 { &hf_sip_curi,
4159 { "Contact URI", "sip.contact.uri",
4160 FT_STRING, BASE_NONE,NULL,0x0,
4161 "RFC 3261: SIP C-URI", HFILL }
4163 { &hf_sip_curi_user,
4164 { "Contact URI User Part", "sip.contact.user",
4165 FT_STRING, BASE_NONE,NULL,0x0,
4166 "RFC 3261: SIP C-URI User", HFILL }
4168 { &hf_sip_curi_host,
4169 { "Contact URI Host Part", "sip.contact.host",
4170 FT_STRING, BASE_NONE,NULL,0x0,
4171 "RFC 3261: SIP C-URI Host", HFILL }
4173 { &hf_sip_curi_port,
4174 { "Contact URI Host Port", "sip.contact.port",
4175 FT_STRING, BASE_NONE,NULL,0x0,
4176 "RFC 3261: SIP C-URI Port", HFILL }
4178 { &hf_sip_curi_param,
4179 { "Contact URI parameter", "sip.contact.param",
4180 FT_STRING, BASE_NONE,NULL,0x0,
4181 NULL, HFILL }
4183 /* etxjowa */
4184 { &hf_sip_route,
4185 { "Route URI", "sip.Route.uri",
4186 FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
4188 { &hf_sip_route_user,
4189 { "Route Userinfo", "sip.Route.user",
4190 FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
4192 { &hf_sip_route_host,
4193 { "Route Host Part", "sip.Route.host",
4194 FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
4196 { &hf_sip_route_port,
4197 { "Route Host Port", "sip.Route.port",
4198 FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
4200 { &hf_sip_route_param,
4201 { "Route URI parameter", "sip.Route.param",
4202 FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
4204 { &hf_sip_record_route,
4205 { "Record-Route URI", "sip.Record-Route.uri",
4206 FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
4208 { &hf_sip_record_route_user,
4209 { "Record-Route Userinfo", "sip.Record-Route.user",
4210 FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
4212 { &hf_sip_record_route_host,
4213 { "Record-Route Host Part", "sip.Record-Route.host",
4214 FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
4216 { &hf_sip_record_route_port,
4217 { "Record-Route Host Port", "sip.Record-Route.port",
4218 FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
4220 { &hf_sip_record_route_param,
4221 { "Record-Route URI parameter", "sip.Record-Route.param",
4222 FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
4224 /* etxjowa end */
4225 { &hf_sip_contact_param,
4226 { "Contact parameter", "sip.contact.parameter",
4227 FT_STRING, BASE_NONE,NULL,0x0,
4228 "RFC 3261: one contact parameter", HFILL }
4230 { &hf_sip_tag,
4231 { "SIP tag", "sip.tag",
4232 FT_STRING, BASE_NONE,NULL,0x0,
4233 "RFC 3261: tag", HFILL }
4235 { &hf_sip_pai_addr,
4236 { "SIP PAI Address", "sip.pai.addr",
4237 FT_STRING, BASE_NONE,NULL,0x0,
4238 "RFC 3325: P-Asserted-Identity Address", HFILL }
4240 { &hf_sip_pai_user,
4241 { "SIP PAI User Part", "sip.pai.user",
4242 FT_STRING, BASE_NONE,NULL,0x0,
4243 "RFC 3325: P-Asserted-Identity User", HFILL }
4245 { &hf_sip_pai_host,
4246 { "SIP PAI Host Part", "sip.pai.host",
4247 FT_STRING, BASE_NONE,NULL,0x0,
4248 "RFC 3325: P-Asserted-Identity Host", HFILL }
4250 { &hf_sip_pai_port,
4251 { "SIP PAI Host Port", "sip.pai.port",
4252 FT_STRING, BASE_NONE,NULL,0x0,
4253 "RFC 3325: P-Asserted-Identity Port", HFILL }
4255 { &hf_sip_pai_param,
4256 { "SIP PAI URI parameter", "sip.pai.param",
4257 FT_STRING, BASE_NONE,NULL,0x0,
4258 NULL, HFILL }
4260 { &hf_sip_pmiss_addr,
4261 { "SIP PMISS Address", "sip.pmiss.addr",
4262 FT_STRING, BASE_NONE,NULL,0x0,
4263 "RFC 3325: Permission Missing Address", HFILL }
4265 { &hf_sip_pmiss_user,
4266 { "SIP PMISS User Part", "sip.pmiss.user",
4267 FT_STRING, BASE_NONE,NULL,0x0,
4268 "RFC 3325: Permission Missing User", HFILL }
4270 { &hf_sip_pmiss_host,
4271 { "SIP PMISS Host Part", "sip.pmiss.host",
4272 FT_STRING, BASE_NONE,NULL,0x0,
4273 "RFC 3325: Permission Missing Host", HFILL }
4275 { &hf_sip_pmiss_port,
4276 { "SIP PMISS Host Port", "sip.pmiss.port",
4277 FT_STRING, BASE_NONE,NULL,0x0,
4278 "RFC 3325: Permission Missing Port", HFILL }
4280 { &hf_sip_pmiss_param,
4281 { "SIP PMISS URI parameter", "sip.pmiss.param",
4282 FT_STRING, BASE_NONE,NULL,0x0,
4283 NULL, HFILL }
4286 { &hf_sip_ppi_addr,
4287 { "SIP PPI Address", "sip.ppi.addr",
4288 FT_STRING, BASE_NONE,NULL,0x0,
4289 "RFC 3325: P-Preferred-Identity Address", HFILL }
4291 { &hf_sip_ppi_user,
4292 { "SIP PPI User Part", "sip.ppi.user",
4293 FT_STRING, BASE_NONE,NULL,0x0,
4294 "RFC 3325: P-Preferred-Identity User", HFILL }
4296 { &hf_sip_ppi_host,
4297 { "SIP PPI Host Part", "sip.ppi.host",
4298 FT_STRING, BASE_NONE,NULL,0x0,
4299 "RFC 3325: P-Preferred-Identity Host", HFILL }
4301 { &hf_sip_ppi_port,
4302 { "SIP PPI Host Port", "sip.ppi.port",
4303 FT_STRING, BASE_NONE,NULL,0x0,
4304 "RFC 3325: P-Preferred-Identity Port", HFILL }
4306 { &hf_sip_ppi_param,
4307 { "SIP PPI URI parameter", "sip.ppi.param",
4308 FT_STRING, BASE_NONE,NULL,0x0,
4309 NULL, HFILL }
4311 { &hf_sip_tc_addr,
4312 { "SIP TC Address", "sip.tc.addr",
4313 FT_STRING, BASE_NONE,NULL,0x0,
4314 "RFC 3325: Trigger Consent Address", HFILL }
4316 { &hf_sip_tc_user,
4317 { "SIP TC User Part", "sip.tc.user",
4318 FT_STRING, BASE_NONE,NULL,0x0,
4319 "RFC 3325: Trigger Consent User", HFILL }
4321 { &hf_sip_tc_host,
4322 { "SIP TC Host Part", "sip.tc.host",
4323 FT_STRING, BASE_NONE,NULL,0x0,
4324 "RFC 3325: Trigger Consent Host", HFILL }
4326 { &hf_sip_tc_port,
4327 { "SIP TC Host Port", "sip.tc.port",
4328 FT_STRING, BASE_NONE,NULL,0x0,
4329 "RFC 3325: Trigger Consent Port", HFILL }
4331 { &hf_sip_tc_param,
4332 { "SIP TC URI parameter", "sip.tc.param",
4333 FT_STRING, BASE_NONE,NULL,0x0,
4334 NULL, HFILL }
4336 { &hf_sip_tc_turi,
4337 { "SIP TC Target URI", "sip.tc.target-uri",
4338 FT_STRING, BASE_NONE,NULL,0x0,
4339 "RFC 3325: Trigger Consent Target URI", HFILL }
4341 { &hf_header_array[POS_ACCEPT],
4342 { "Accept", "sip.Accept",
4343 FT_STRING, BASE_NONE,NULL,0x0,
4344 "RFC 3261: Accept Header", HFILL }
4346 { &hf_header_array[POS_ACCEPT_CONTACT],
4347 { "Accept-Contact", "sip.Accept-Contact",
4348 FT_STRING, BASE_NONE,NULL,0x0,
4349 "RFC 3841: Accept-Contact Header", HFILL }
4351 { &hf_header_array[POS_ACCEPT_ENCODING],
4352 { "Accept-Encoding", "sip.Accept-Encoding",
4353 FT_STRING, BASE_NONE,NULL,0x0,
4354 "RFC 3841: Accept-Encoding Header", HFILL }
4356 { &hf_header_array[POS_ACCEPT_LANGUAGE],
4357 { "Accept-Language", "sip.Accept-Language",
4358 FT_STRING, BASE_NONE,NULL,0x0,
4359 "RFC 3261: Accept-Language Header", HFILL }
4361 { &hf_header_array[POS_ACCEPT_RESOURCE_PRIORITY],
4362 { "Accept-Resource-Priority", "sip.Accept-Resource-Priority",
4363 FT_STRING, BASE_NONE,NULL,0x0,
4364 "Draft: Accept-Resource-Priority Header", HFILL }
4366 { &hf_header_array[POS_ALERT_INFO],
4367 { "Alert-Info", "sip.Alert-Info",
4368 FT_STRING, BASE_NONE,NULL,0x0,
4369 "RFC 3261: Alert-Info Header", HFILL }
4371 { &hf_header_array[POS_ALLOW],
4372 { "Allow", "sip.Allow",
4373 FT_STRING, BASE_NONE,NULL,0x0,
4374 "RFC 3261: Allow Header", HFILL }
4376 { &hf_header_array[POS_ALLOW_EVENTS],
4377 { "Allow-Events", "sip.Allow-Events",
4378 FT_STRING, BASE_NONE,NULL,0x0,
4379 "RFC 3265: Allow-Events Header", HFILL }
4381 { &hf_header_array[POS_ANSWER_MODE],
4382 { "Answer-Mode", "sip.Answer-Mode",
4383 FT_STRING, BASE_NONE,NULL,0x0,
4384 "RFC 5373: Answer-Mode Header", HFILL }
4386 { &hf_header_array[POS_AUTHENTICATION_INFO],
4387 { "Authentication-Info", "sip.Authentication-Info",
4388 FT_STRING, BASE_NONE,NULL,0x0,
4389 "RFC 3261: Authentication-Info Header", HFILL }
4391 { &hf_header_array[POS_AUTHORIZATION],
4392 { "Authorization", "sip.Authorization",
4393 FT_STRING, BASE_NONE,NULL,0x0,
4394 "RFC 3261: Authorization Header", HFILL }
4396 { &hf_header_array[POS_CALL_ID],
4397 { "Call-ID", "sip.Call-ID",
4398 FT_STRING, BASE_NONE,NULL,0x0,
4399 "RFC 3261: Call-ID Header", HFILL }
4401 { &hf_header_array[POS_CALL_INFO],
4402 { "Call-Info", "sip.Call-Info",
4403 FT_STRING, BASE_NONE,NULL,0x0,
4404 "RFC 3261: Call-Info Header", HFILL }
4406 { &hf_header_array[POS_CONTACT],
4407 { "Contact", "sip.Contact",
4408 FT_STRING, BASE_NONE,NULL,0x0,
4409 "RFC 3261: Contact Header", HFILL }
4411 { &hf_header_array[POS_CONTENT_DISPOSITION],
4412 { "Content-Disposition", "sip.Content-Disposition",
4413 FT_STRING, BASE_NONE,NULL,0x0,
4414 "RFC 3261: Content-Disposition Header", HFILL }
4416 { &hf_header_array[POS_CONTENT_ENCODING],
4417 { "Content-Encoding", "sip.Content-Encoding",
4418 FT_STRING, BASE_NONE,NULL,0x0,
4419 "RFC 3261: Content-Encoding Header", HFILL }
4421 { &hf_header_array[POS_CONTENT_LANGUAGE],
4422 { "Content-Language", "sip.Content-Language",
4423 FT_STRING, BASE_NONE,NULL,0x0,
4424 "RFC 3261: Content-Language Header", HFILL }
4426 { &hf_header_array[POS_CONTENT_LENGTH],
4427 { "Content-Length", "sip.Content-Length",
4428 FT_UINT32, BASE_DEC,NULL,0x0,
4429 "RFC 3261: Content-Length Header", HFILL }
4431 { &hf_header_array[POS_CONTENT_TYPE],
4432 { "Content-Type", "sip.Content-Type",
4433 FT_STRING, BASE_NONE,NULL,0x0,
4434 "RFC 3261: Content-Type Header", HFILL }
4436 { &hf_header_array[POS_CSEQ],
4437 { "CSeq", "sip.CSeq",
4438 FT_STRING, BASE_NONE,NULL,0x0,
4439 "RFC 3261: CSeq Header", HFILL }
4441 { &hf_header_array[POS_DATE],
4442 { "Date", "sip.Date",
4443 FT_STRING, BASE_NONE,NULL,0x0,
4444 "RFC 3261: Date Header", HFILL }
4446 { &hf_header_array[POS_ERROR_INFO],
4447 { "Error-Info", "sip.Error-Info",
4448 FT_STRING, BASE_NONE,NULL,0x0,
4449 "RFC 3261: Error-Info Header", HFILL }
4451 { &hf_header_array[POS_EVENT],
4452 { "Event", "sip.Event",
4453 FT_STRING, BASE_NONE,NULL,0x0,
4454 "RFC 3265: Event Header", HFILL }
4456 { &hf_header_array[POS_EXPIRES],
4457 { "Expires", "sip.Expires",
4458 FT_UINT32, BASE_DEC,NULL,0x0,
4459 "RFC 3261: Expires Header", HFILL }
4461 { &hf_header_array[POS_FEATURE_CAPS],
4462 { "Feature-Caps", "sip.feature_caps",
4463 FT_STRING, BASE_NONE,NULL,0x0,
4464 "RFC 6809: Feature-Caps", HFILL }
4466 { &hf_header_array[POS_FLOW_TIMER],
4467 { "Flow-Timer", "sip.Flow-Timer",
4468 FT_STRING, BASE_NONE,NULL,0x0,
4469 "RFC 5626: Flow-Timer", HFILL }
4471 { &hf_header_array[POS_FROM],
4472 { "From", "sip.From",
4473 FT_STRING, BASE_NONE,NULL,0x0,
4474 "RFC 3261: From Header", HFILL }
4476 { &hf_header_array[POS_GEOLOCATION],
4477 { "Geolocation", "sip.Geolocation",
4478 FT_STRING, BASE_NONE,NULL,0x0,
4479 NULL, HFILL }
4481 { &hf_header_array[POS_GEOLOCATION_ERROR],
4482 { "Geolocation-Error", "sip.Geolocation",
4483 FT_STRING, BASE_NONE,NULL,0x0,
4484 NULL, HFILL }
4486 { &hf_header_array[POS_GEOLOCATION_ROUTING],
4487 { "Geolocation-Routing", "sip.Geolocation_Routing",
4488 FT_STRING, BASE_NONE,NULL,0x0,
4489 NULL, HFILL }
4491 { &hf_header_array[POS_HISTORY_INFO],
4492 { "History-Info", "sip.History-Info",
4493 FT_STRING, BASE_NONE,NULL,0x0,
4494 "RFC 4244: Request History Information", HFILL }
4496 { &hf_header_array[POS_IDENTITY],
4497 { "Identity", "sip.Identity",
4498 FT_STRING, BASE_NONE,NULL,0x0,
4499 "RFC 4474: Request Identity", HFILL }
4501 { &hf_header_array[POS_IDENTITY_INFO],
4502 { "Identity-info", "sip.Identity-info",
4503 FT_STRING, BASE_NONE,NULL,0x0,
4504 "RFC 4474: Request Identity-info", HFILL }
4506 { &hf_header_array[POS_INFO_PKG],
4507 { "Info-Package", "sip.Info-Package",
4508 FT_STRING, BASE_NONE,NULL,0x0,
4509 NULL, HFILL }
4511 { &hf_header_array[POS_IN_REPLY_TO],
4512 { "In-Reply-To", "sip.In-Reply-To",
4513 FT_STRING, BASE_NONE,NULL,0x0,
4514 "RFC 3261: In-Reply-To Header", HFILL }
4516 { &hf_header_array[POS_JOIN],
4517 { "Join", "sip.Join",
4518 FT_STRING, BASE_NONE,NULL,0x0,
4519 "Draft: Join Header", HFILL }
4521 { &hf_header_array[POS_MAX_BREADTH],
4522 { "Max-Breadth", "sip.Max-Breadth",
4523 FT_UINT32, BASE_DEC,NULL,0x0,
4524 "RFC 5393: Max-Breadth Header", HFILL }
4526 { &hf_header_array[POS_MAX_FORWARDS],
4527 { "Max-Forwards", "sip.Max-Forwards",
4528 FT_UINT32, BASE_DEC,NULL,0x0,
4529 "RFC 3261: Max-Forwards Header", HFILL }
4531 { &hf_header_array[POS_MIME_VERSION],
4532 { "MIME-Version", "sip.MIME-Version",
4533 FT_STRING, BASE_NONE,NULL,0x0,
4534 "RFC 3261: MIME-Version Header", HFILL }
4536 { &hf_header_array[POS_MIN_EXPIRES],
4537 { "Min-Expires", "sip.Min-Expires",
4538 FT_STRING, BASE_NONE,NULL,0x0,
4539 "RFC 3261: Min-Expires Header", HFILL }
4541 { &hf_header_array[POS_MIN_SE],
4542 { "Min-SE", "sip.Min-SE",
4543 FT_STRING, BASE_NONE,NULL,0x0,
4544 "Draft: Min-SE Header", HFILL }
4546 { &hf_header_array[POS_ORGANIZATION],
4547 { "Organization", "sip.Organization",
4548 FT_STRING, BASE_NONE,NULL,0x0,
4549 "RFC 3261: Organization Header", HFILL }
4551 { &hf_header_array[POS_P_ACCESS_NETWORK_INFO],
4552 { "P-Access-Network-Info", "sip.P-Access-Network-Info",
4553 FT_STRING, BASE_NONE,NULL,0x0,
4554 "P-Access-Network-Info Header", HFILL }
4556 { &hf_header_array[POS_P_ANSWER_STATE],
4557 { "P-Answer-State", "sip.P-Answer-State",
4558 FT_STRING, BASE_NONE,NULL,0x0,
4559 "RFC 4964: P-Answer-State Header", HFILL }
4561 { &hf_header_array[POS_P_ASSERTED_IDENTITY],
4562 { "P-Asserted-Identity", "sip.P-Asserted-Identity",
4563 FT_STRING, BASE_NONE,NULL,0x0,
4564 "RFC 3325: P-Asserted-Identity Header", HFILL }
4566 { &hf_header_array[POS_P_ASSERTED_SERV],
4567 { "P-Asserted-Service", "sip.P-Asserted-Service",
4568 FT_STRING, BASE_NONE,NULL,0x0,
4569 NULL, HFILL }
4571 { &hf_header_array[POS_P_ASSOCIATED_URI],
4572 { "P-Associated-URI", "sip.P-Associated-URI",
4573 FT_STRING, BASE_NONE,NULL,0x0,
4574 "RFC 3455: P-Associated-URI Header", HFILL }
4577 { &hf_header_array[POS_P_CALLED_PARTY_ID],
4578 { "P-Called-Party-ID", "sip.P-Called-Party-ID",
4579 FT_STRING, BASE_NONE,NULL,0x0,
4580 "RFC 3455: P-Called-Party-ID Header", HFILL }
4583 { &hf_header_array[POS_P_CHARGING_FUNC_ADDRESSES],
4584 { "P-Charging-Function-Addresses","sip.P-Charging-Function-Addresses",
4585 FT_STRING, BASE_NONE,NULL,0x0,
4586 NULL, HFILL }
4589 { &hf_header_array[POS_P_CHARGING_VECTOR],
4590 { "P-Charging-Vector", "sip.P-Charging-Vector",
4591 FT_STRING, BASE_NONE,NULL,0x0,
4592 "P-Charging-Vector Header", HFILL }
4595 { &hf_header_array[POS_P_DCS_TRACE_PARTY_ID],
4596 { "P-DCS-Trace-Party-ID", "sip.P-DCS-Trace-Party-ID",
4597 FT_STRING, BASE_NONE,NULL,0x0,
4598 "P-DCS-Trace-Party-ID Header", HFILL }
4601 { &hf_header_array[POS_P_DCS_OSPS],
4602 { "P-DCS-OSPS", "sip.P-DCS-OSPS",
4603 FT_STRING, BASE_NONE,NULL,0x0,
4604 "P-DCS-OSPS Header", HFILL }
4607 { &hf_header_array[POS_P_DCS_BILLING_INFO],
4608 { "P-DCS-Billing-Info", "sip.P-DCS-Billing-Info",
4609 FT_STRING, BASE_NONE,NULL,0x0,
4610 "P-DCS-Billing-Info Header", HFILL }
4613 { &hf_header_array[POS_P_DCS_LAES],
4614 { "P-DCS-LAES", "sip.P-DCS-LAES",
4615 FT_STRING, BASE_NONE,NULL,0x0,
4616 "P-DCS-LAES Header", HFILL }
4619 { &hf_header_array[POS_P_DCS_REDIRECT],
4620 { "P-DCS-Redirect", "sip.P-DCS-Redirect",
4621 FT_STRING, BASE_NONE,NULL,0x0,
4622 "P-DCS-Redirect Header", HFILL }
4625 { &hf_header_array[POS_P_EARLY_MEDIA],
4626 { "P-Early-Media", "sip.P-Early-Media",
4627 FT_STRING, BASE_NONE,NULL,0x0,
4628 "P-Early-Media Header", HFILL }
4631 { &hf_header_array[POS_P_MEDIA_AUTHORIZATION],
4632 { "P-Media-Authorization", "sip.P-Media-Authorization",
4633 FT_STRING, BASE_NONE,NULL,0x0,
4634 "RFC 3313: P-Media-Authorization Header", HFILL }
4637 { &hf_header_array[POS_P_PREFERRED_IDENTITY],
4638 { "P-Preferred-Identity", "sip.P-Preferred-Identity",
4639 FT_STRING, BASE_NONE,NULL,0x0,
4640 "RFC 3325: P-Preferred-Identity Header", HFILL }
4642 { &hf_header_array[POS_P_PREFERRED_SERV],
4643 { "P-Preferred-Service", "sip.P-Preferred-Service",
4644 FT_STRING, BASE_NONE,NULL,0x0,
4645 NULL, HFILL }
4647 { &hf_header_array[POS_P_PROFILE_KEY],
4648 { "P-Profile-Key", "sip.P-Profile-Key",
4649 FT_STRING, BASE_NONE,NULL,0x0,
4650 "P-Profile-Key Header", HFILL }
4652 { &hf_header_array[POS_P_REFUSED_URI_LST],
4653 { "P-Refused-URI-List", "sip.P-Refused-URI-List",
4654 FT_STRING, BASE_NONE,NULL,0x0,
4655 "P-Refused-URI-List Header", HFILL }
4657 { &hf_header_array[POS_P_SERVED_USER],
4658 { "P-Served-User", "sip.P-Served-User",
4659 FT_STRING, BASE_NONE,NULL,0x0,
4660 NULL, HFILL }
4662 { &hf_header_array[POS_P_USER_DATABASE],
4663 { "P-User-Database", "sip.P-User-Database",
4664 FT_STRING, BASE_NONE,NULL,0x0,
4665 "P-User-Database Header", HFILL }
4668 { &hf_header_array[POS_P_VISITED_NETWORK_ID],
4669 { "P-Visited-Network-ID", "sip.P-Visited-Network-ID",
4670 FT_STRING, BASE_NONE,NULL,0x0,
4671 "RFC 3455: P-Visited-Network-ID Header", HFILL }
4674 { &hf_header_array[POS_PATH],
4675 { "Path", "sip.Path",
4676 FT_STRING, BASE_NONE,NULL,0x0,
4677 "RFC 3327: Path Header", HFILL }
4680 { &hf_header_array[POS_PERMISSION_MISSING],
4681 { "Permission-Missing", "sip.Permission-Missing",
4682 FT_STRING, BASE_NONE,NULL,0x0,
4683 "RFC 5360: Permission Missing Header", HFILL }
4685 { &hf_header_array[POS_POLICY_CONTACT],
4686 { "Policy-Contact", "sip.Policy_Contact",
4687 FT_STRING, BASE_NONE,NULL,0x0,
4688 NULL, HFILL }
4690 { &hf_header_array[POS_POLICY_ID],
4691 { "Policy-ID", "sip.Policy_ID",
4692 FT_STRING, BASE_NONE,NULL,0x0,
4693 NULL, HFILL }
4695 { &hf_header_array[POS_PRIORITY],
4696 { "Priority", "sip.Priority",
4697 FT_STRING, BASE_NONE,NULL,0x0,
4698 "RFC 3261: Priority Header", HFILL }
4700 { &hf_header_array[POS_PRIV_ANSWER_MODE],
4701 { "Priv-Answer-mode", "sip.Priv-Answer-mode",
4702 FT_STRING, BASE_NONE,NULL,0x0,
4703 NULL, HFILL }
4705 { &hf_header_array[POS_PRIVACY],
4706 { "Privacy", "sip.Privacy",
4707 FT_STRING, BASE_NONE,NULL,0x0,
4708 "Privacy Header", HFILL }
4711 { &hf_header_array[POS_PROXY_AUTHENTICATE],
4712 { "Proxy-Authenticate", "sip.Proxy-Authenticate",
4713 FT_STRING, BASE_NONE,NULL,0x0,
4714 "RFC 3261: Proxy-Authenticate Header", HFILL }
4716 { &hf_header_array[POS_PROXY_AUTHORIZATION],
4717 { "Proxy-Authorization", "sip.Proxy-Authorization",
4718 FT_STRING, BASE_NONE,NULL,0x0,
4719 "RFC 3261: Proxy-Authorization Header", HFILL }
4722 { &hf_header_array[POS_PROXY_REQUIRE],
4723 { "Proxy-Require", "sip.Proxy-Require",
4724 FT_STRING, BASE_NONE,NULL,0x0,
4725 "RFC 3261: Proxy-Require Header", HFILL }
4727 { &hf_header_array[POS_RACK],
4728 { "RAck", "sip.RAck",
4729 FT_STRING, BASE_NONE,NULL,0x0,
4730 "RFC 3262: RAck Header", HFILL }
4732 { &hf_header_array[POS_REASON],
4733 { "Reason", "sip.Reason",
4734 FT_STRING, BASE_NONE,NULL,0x0,
4735 "RFC 3326 Reason Header", HFILL }
4737 { &hf_header_array[POS_REASON_PHRASE],
4738 { "Reason-Phrase", "sip.Reason-Phrase",
4739 FT_STRING, BASE_NONE,NULL,0x0,
4740 NULL, HFILL }
4742 { &hf_header_array[POS_RECORD_ROUTE],
4743 { "Record-Route", "sip.Record-Route",
4744 FT_STRING, BASE_NONE,NULL,0x0,
4745 "RFC 3261: Record-Route Header", HFILL }
4747 { &hf_header_array[POS_RECV_INFO],
4748 { "Recv-Info", "sip.Recv-Info",
4749 FT_STRING, BASE_NONE,NULL,0x0,
4750 NULL, HFILL }
4752 { &hf_header_array[POS_REFER_SUB],
4753 { "Refer-Sub", "sip.Refer-Sub",
4754 FT_STRING, BASE_NONE,NULL,0x0,
4755 "RFC 4488: Refer-Sub Header", HFILL }
4757 { &hf_header_array[POS_REFER_TO],
4758 { "Refer-To", "sip.Refer-To",
4759 FT_STRING, BASE_NONE,NULL,0x0,
4760 "RFC 3515: Refer-To Header", HFILL }
4762 { &hf_header_array[POS_REFERED_BY],
4763 { "Refered By", "sip.Refered-by",
4764 FT_STRING, BASE_NONE,NULL,0x0,
4765 "RFC 3892: Refered-by Header", HFILL }
4767 { &hf_header_array[POS_REJECT_CONTACT],
4768 { "Reject-Contact", "sip.Reject-Contact",
4769 FT_STRING, BASE_NONE,NULL,0x0,
4770 "RFC 3841: Reject-Contact Header", HFILL }
4772 { &hf_header_array[POS_REPLACES],
4773 { "Replaces", "sip.Replaces",
4774 FT_STRING, BASE_NONE,NULL,0x0,
4775 "RFC 3891: Replaces Header", HFILL }
4777 { &hf_header_array[POS_REPLY_TO],
4778 { "Reply-To", "sip.Reply-To",
4779 FT_STRING, BASE_NONE,NULL,0x0,
4780 "RFC 3261: Reply-To Header", HFILL }
4782 { &hf_header_array[POS_REQUEST_DISPOSITION],
4783 { "Request-Disposition", "sip.Request-Disposition",
4784 FT_STRING, BASE_NONE,NULL,0x0,
4785 "RFC 3841: Request-Disposition Header", HFILL }
4787 { &hf_header_array[POS_REQUIRE],
4788 { "Require", "sip.Require",
4789 FT_STRING, BASE_NONE,NULL,0x0,
4790 "RFC 3261: Require Header", HFILL }
4792 { &hf_header_array[POS_RESOURCE_PRIORITY],
4793 { "Resource-Priority", "sip.Resource-Priority",
4794 FT_STRING, BASE_NONE,NULL,0x0,
4795 "Draft: Resource-Priority Header", HFILL }
4797 { &hf_header_array[POS_RETRY_AFTER],
4798 { "Retry-After", "sip.Retry-After",
4799 FT_STRING, BASE_NONE,NULL,0x0,
4800 "RFC 3261: Retry-After Header", HFILL }
4802 { &hf_header_array[POS_ROUTE],
4803 { "Route", "sip.Route",
4804 FT_STRING, BASE_NONE,NULL,0x0,
4805 "RFC 3261: Route Header", HFILL }
4807 { &hf_header_array[POS_RSEQ],
4808 { "RSeq", "sip.RSeq",
4809 FT_UINT32, BASE_DEC,NULL,0x0,
4810 "RFC 3262: RSeq Header", HFILL }
4812 { &hf_header_array[ POS_SECURITY_CLIENT],
4813 { "Security-Client", "sip.Security-Client",
4814 FT_STRING, BASE_NONE,NULL,0x0,
4815 "RFC 3329 Security-Client Header", HFILL }
4817 { &hf_header_array[ POS_SECURITY_SERVER],
4818 { "Security-Server", "sip.Security-Server",
4819 FT_STRING, BASE_NONE,NULL,0x0,
4820 "RFC 3329 Security-Server Header", HFILL }
4822 { &hf_header_array[ POS_SECURITY_VERIFY],
4823 { "Security-Verify", "sip.Security-Verify",
4824 FT_STRING, BASE_NONE,NULL,0x0,
4825 "RFC 3329 Security-Verify Header", HFILL }
4827 { &hf_header_array[POS_SERVER],
4828 { "Server", "sip.Server",
4829 FT_STRING, BASE_NONE,NULL,0x0,
4830 "RFC 3261: Server Header", HFILL }
4832 { &hf_header_array[POS_SERVICE_ROUTE],
4833 { "Service-Route", "sip.Service-Route",
4834 FT_STRING, BASE_NONE,NULL,0x0,
4835 "RFC 3608: Service-Route Header", HFILL }
4837 { &hf_header_array[POS_SESSION_EXPIRES],
4838 { "Session-Expires", "sip.Session-Expires",
4839 FT_STRING, BASE_NONE,NULL,0x0,
4840 "RFC 4028: Session-Expires Header", HFILL }
4842 { &hf_header_array[POS_SIP_ETAG],
4843 { "ETag", "sip.ETag",
4844 FT_STRING, BASE_NONE,NULL,0x0,
4845 "RFC 3903: SIP-ETag Header", HFILL }
4847 { &hf_header_array[POS_SIP_IF_MATCH],
4848 { "If_Match", "sip.If_Match",
4849 FT_STRING, BASE_NONE,NULL,0x0,
4850 "RFC 3903: SIP-If-Match Header", HFILL }
4852 { &hf_header_array[POS_SUBJECT],
4853 { "Subject", "sip.Subject",
4854 FT_STRING, BASE_NONE,NULL,0x0,
4855 "RFC 3261: Subject Header", HFILL }
4857 { &hf_header_array[POS_SUBSCRIPTION_STATE],
4858 { "Subscription-State", "sip.Subscription-State",
4859 FT_STRING, BASE_NONE,NULL,0x0,
4860 "RFC 3265: Subscription-State Header", HFILL }
4862 { &hf_header_array[POS_SUPPORTED],
4863 { "Supported", "sip.Supported",
4864 FT_STRING, BASE_NONE,NULL,0x0,
4865 "RFC 3261: Supported Header", HFILL }
4867 { &hf_header_array[POS_SUPPRESS_IF_MATCH],
4868 { "Suppress-If-Match", "sip.Suppress_If_Match",
4869 FT_STRING, BASE_NONE,NULL,0x0,
4870 NULL, HFILL }
4872 { &hf_header_array[POS_TARGET_DIALOG],
4873 { "Target-Dialog", "sip.Target-Dialog",
4874 FT_STRING, BASE_NONE,NULL,0x0,
4875 "RFC 4538: Target-Dialog Header", HFILL }
4877 { &hf_header_array[POS_TIMESTAMP],
4878 { "Timestamp", "sip.Timestamp",
4879 FT_STRING, BASE_NONE,NULL,0x0,
4880 "RFC 3261: Timestamp Header", HFILL }
4882 { &hf_header_array[POS_TO],
4883 { "To", "sip.To",
4884 FT_STRING, BASE_NONE,NULL,0x0,
4885 "RFC 3261: To Header", HFILL }
4888 { &hf_header_array[POS_TRIGGER_CONSENT],
4889 { "Trigger-Consent", "sip.Trigger-Consent",
4890 FT_STRING, BASE_NONE,NULL,0x0,
4891 "RFC 5380: Trigger Consent", HFILL }
4894 { &hf_header_array[POS_UNSUPPORTED],
4895 { "Unsupported", "sip.Unsupported",
4896 FT_STRING, BASE_NONE,NULL,0x0,
4897 "RFC 3261: Unsupported Header", HFILL }
4899 { &hf_header_array[POS_USER_AGENT],
4900 { "User-Agent", "sip.User-Agent",
4901 FT_STRING, BASE_NONE,NULL,0x0,
4902 "RFC 3261: User-Agent Header", HFILL }
4904 { &hf_header_array[POS_VIA],
4905 { "Via", "sip.Via",
4906 FT_STRING, BASE_NONE,NULL,0x0,
4907 "RFC 3261: Via Header", HFILL }
4909 { &hf_header_array[POS_WARNING],
4910 { "Warning", "sip.Warning",
4911 FT_STRING, BASE_NONE,NULL,0x0,
4912 "RFC 3261: Warning Header", HFILL }
4915 { &hf_header_array[POS_WWW_AUTHENTICATE],
4916 { "WWW-Authenticate", "sip.WWW-Authenticate",
4917 FT_STRING, BASE_NONE,NULL,0x0,
4918 "RFC 3261: WWW-Authenticate Header", HFILL }
4920 { &hf_header_array[POS_DIVERSION],
4921 { "Diversion", "sip.Diversion",
4922 FT_STRING, BASE_NONE,NULL,0x0,
4923 "RFC 5806: Diversion Header", HFILL }
4925 { &hf_header_array[POS_USER_TO_USER],
4926 { "User-to-User", "sip.uui",
4927 FT_STRING, BASE_NONE,NULL,0x0,
4928 "draft-johnston-sipping-cc-uui-09: User-to-User header", HFILL }
4930 { &hf_sip_resend,
4931 { "Resent Packet", "sip.resend",
4932 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4933 NULL, HFILL }
4935 { &hf_sip_original_frame,
4936 { "Suspected resend of frame", "sip.resend-original",
4937 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4938 "Original transmission of frame", HFILL}
4940 { &hf_sip_matching_request_frame,
4941 { "Request Frame", "sip.response-request",
4942 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4943 NULL, HFILL}
4945 { &hf_sip_response_time,
4946 { "Response Time (ms)", "sip.response-time",
4947 FT_UINT32, BASE_DEC, NULL, 0x0,
4948 "Response time since original request (in milliseconds)", HFILL}
4950 { &hf_sip_release_time,
4951 { "Release Time (ms)", "sip.release-time",
4952 FT_UINT32, BASE_DEC, NULL, 0x0,
4953 "release time since original BYE (in milliseconds)", HFILL}
4955 { &hf_sip_auth,
4956 { "Authentication", "sip.auth",
4957 FT_STRING, BASE_NONE, NULL, 0x0,
4958 "SIP Authentication", HFILL}
4960 { &hf_sip_auth_scheme,
4961 { "Authentication Scheme", "sip.auth.scheme",
4962 FT_STRING, BASE_NONE, NULL, 0x0,
4963 "SIP Authentication Scheme", HFILL}
4965 { &hf_sip_auth_digest_response,
4966 { "Digest Authentication Response", "sip.auth.digest.response",
4967 FT_STRING, BASE_NONE, NULL, 0x0,
4968 "SIP Digest Authentication Response Value", HFILL}
4970 { &hf_sip_auth_nc,
4971 { "Nonce Count", "sip.auth.nc",
4972 FT_STRING, BASE_NONE, NULL, 0x0,
4973 "SIP Authentication Nonce count", HFILL}
4975 { &hf_sip_auth_username,
4976 { "Username", "sip.auth.username",
4977 FT_STRING, BASE_NONE, NULL, 0x0,
4978 "SIP Authentication Username", HFILL}
4980 { &hf_sip_auth_realm,
4981 { "Realm", "sip.auth.realm",
4982 FT_STRING, BASE_NONE, NULL, 0x0,
4983 "SIP Authentication Realm", HFILL}
4985 { &hf_sip_auth_nonce,
4986 { "Nonce Value", "sip.auth.nonce",
4987 FT_STRING, BASE_NONE, NULL, 0x0,
4988 "SIP Authentication Nonce", HFILL}
4990 { &hf_sip_auth_algorithm,
4991 { "Algorithm", "sip.auth.algorithm",
4992 FT_STRING, BASE_NONE, NULL, 0x0,
4993 "SIP Authentication Algorithm", HFILL}
4995 { &hf_sip_auth_opaque,
4996 { "Opaque Value", "sip.auth.opaque",
4997 FT_STRING, BASE_NONE, NULL, 0x0,
4998 "SIP Authentication Opaque value", HFILL}
5000 { &hf_sip_auth_qop,
5001 { "QOP", "sip.auth.qop",
5002 FT_STRING, BASE_NONE, NULL, 0x0,
5003 "SIP Authentication QOP", HFILL}
5005 { &hf_sip_auth_cnonce,
5006 { "CNonce Value", "sip.auth.cnonce",
5007 FT_STRING, BASE_NONE, NULL, 0x0,
5008 "SIP Authentication Client Nonce", HFILL}
5010 { &hf_sip_auth_uri,
5011 { "Authentication URI", "sip.auth.uri",
5012 FT_STRING, BASE_NONE, NULL, 0x0,
5013 "SIP Authentication URI", HFILL}
5015 { &hf_sip_auth_domain,
5016 { "Authentication Domain", "sip.auth.domain",
5017 FT_STRING, BASE_NONE, NULL, 0x0,
5018 "SIP Authentication Domain", HFILL}
5020 { &hf_sip_auth_stale,
5021 { "Stale Flag", "sip.auth.stale",
5022 FT_STRING, BASE_NONE, NULL, 0x0,
5023 "SIP Authentication Stale Flag", HFILL}
5025 { &hf_sip_auth_auts,
5026 { "Authentication Token", "sip.auth.auts",
5027 FT_STRING, BASE_NONE, NULL, 0x0,
5028 "SIP Authentication Token", HFILL}
5030 { &hf_sip_auth_rspauth,
5031 { "Response auth", "sip.auth.rspauth",
5032 FT_STRING, BASE_NONE, NULL, 0x0,
5033 "SIP Authentication Response auth", HFILL}
5035 { &hf_sip_auth_nextnonce,
5036 { "Next Nonce", "sip.auth.nextnonce",
5037 FT_STRING, BASE_NONE, NULL, 0x0,
5038 "SIP Authentication Next Nonce", HFILL}
5040 { &hf_sip_auth_ik,
5041 { "Integrity Key", "sip.auth.ik",
5042 FT_STRING, BASE_NONE, NULL, 0x0,
5043 "SIP Authentication Integrity Key", HFILL}
5045 { &hf_sip_auth_ck,
5046 { "Cyphering Key", "sip.auth.ck",
5047 FT_STRING, BASE_NONE, NULL, 0x0,
5048 "SIP Authentication Cyphering Key", HFILL}
5050 { &hf_sip_cseq_seq_no,
5051 { "Sequence Number", "sip.CSeq.seq",
5052 FT_UINT32, BASE_DEC, NULL, 0x0,
5053 "CSeq header sequence number", HFILL}
5055 { &hf_sip_cseq_method,
5056 { "Method", "sip.CSeq.method",
5057 FT_STRING, BASE_NONE, NULL, 0x0,
5058 "CSeq header method", HFILL}
5060 { &hf_sip_via_transport,
5061 { "Transport", "sip.Via.transport",
5062 FT_STRING, BASE_NONE, NULL, 0x0,
5063 "Via header Transport", HFILL}
5065 { &hf_sip_via_sent_by_address,
5066 { "Sent-by Address", "sip.Via.sent-by.address",
5067 FT_STRING, BASE_NONE, NULL, 0x0,
5068 "Via header Sent-by Address", HFILL}
5070 { &hf_sip_via_sent_by_port,
5071 { "Sent-by port", "sip.Via.sent-by.port",
5072 FT_UINT16, BASE_DEC, NULL, 0x0,
5073 "Via header Sent-by Port", HFILL}
5075 { &hf_sip_via_branch,
5076 { "Branch", "sip.Via.branch",
5077 FT_STRING, BASE_NONE, NULL, 0x0,
5078 "SIP Via Branch", HFILL},
5080 { &hf_sip_via_maddr,
5081 { "Maddr", "sip.Via.maddr",
5082 FT_STRING, BASE_NONE, NULL, 0x0,
5083 "SIP Via Maddr", HFILL},
5085 { &hf_sip_via_rport,
5086 { "RPort", "sip.Via.rport",
5087 FT_STRING, BASE_NONE, NULL, 0x0,
5088 "SIP Via RPort", HFILL},
5090 { &hf_sip_via_received,
5091 { "Received", "sip.Via.received",
5092 FT_STRING, BASE_NONE, NULL, 0x0,
5093 "SIP Via Received", HFILL},
5095 { &hf_sip_via_ttl,
5096 { "TTL", "sip.Via.ttl",
5097 FT_STRING, BASE_NONE, NULL, 0x0,
5098 "SIP Via TTL", HFILL}
5100 { &hf_sip_via_comp,
5101 { "Comp", "sip.Via.comp",
5102 FT_STRING, BASE_NONE, NULL, 0x0,
5103 "SIP Via comp", HFILL}
5105 { &hf_sip_via_sigcomp_id,
5106 { "Sigcomp identifier", "sip.Via.sigcomp-id",
5107 FT_STRING, BASE_NONE, NULL, 0x0,
5108 "SIP Via sigcomp identifier", HFILL}
5110 { &hf_sip_rack_rseq_no,
5111 { "RSeq Sequence Number", "sip.RAck.RSeq.seq",
5112 FT_UINT32, BASE_DEC, NULL, 0x0,
5113 "RAck RSeq header sequence number (from prov response)", HFILL}
5115 { &hf_sip_rack_cseq_no,
5116 { "CSeq Sequence Number", "sip.RAck.CSeq.seq",
5117 FT_UINT32, BASE_DEC, NULL, 0x0,
5118 "RAck CSeq header sequence number (from prov response)", HFILL}
5120 { &hf_sip_rack_cseq_method,
5121 { "CSeq Method", "sip.RAck.CSeq.method",
5122 FT_STRING, BASE_NONE, NULL, 0x0,
5123 "RAck CSeq header method (from prov response)", HFILL}
5125 { &hf_sip_msg_body,
5126 { "Message Body", "sip.msg_body",
5127 FT_NONE, BASE_NONE, NULL, 0x0,
5128 "Message Body in SIP message", HFILL }
5132 /* raw_sip header field(s) */
5133 static hf_register_info raw_hf[] = {
5135 { &hf_sip_raw_line,
5136 { "Raw SIP Line", "raw_sip.line",
5137 FT_STRING, BASE_NONE,NULL,0x0,
5138 NULL, HFILL }
5141 /* Setup protocol subtree array */
5142 static gint *ett[] = {
5143 &ett_sip,
5144 &ett_sip_reqresp,
5145 &ett_sip_hdr,
5146 &ett_sip_ext_hdr,
5147 &ett_sip_element,
5148 &ett_sip_hist,
5149 &ett_sip_uri,
5150 &ett_sip_contact_item,
5151 &ett_sip_message_body,
5152 &ett_sip_cseq,
5153 &ett_sip_via,
5154 &ett_sip_reason,
5155 &ett_sip_rack,
5156 &ett_sip_record_route,
5157 &ett_sip_route,
5158 &ett_sip_ruri,
5159 &ett_sip_pai_uri,
5160 &ett_sip_pmiss_uri,
5161 &ett_sip_ppi_uri,
5162 &ett_sip_tc_uri,
5163 &ett_sip_to_uri,
5164 &ett_sip_from_uri,
5165 &ett_sip_curi
5167 static gint *ett_raw[] = {
5168 &ett_raw_text,
5171 static ei_register_info ei[] = {
5172 { &ei_sip_unrecognized_header, { "sip.unrecognized_header", PI_UNDECODED, PI_NOTE, "Unrecognised SIP header", EXPFILL }},
5173 { &ei_sip_header_not_terminated, { "sip.header_not_terminated", PI_MALFORMED, PI_WARN, "Header not terminated by empty line (CRLF)", EXPFILL }},
5176 module_t *sip_module;
5177 expert_module_t* expert_sip;
5179 /* Register the protocol name and description */
5180 proto_sip = proto_register_protocol("Session Initiation Protocol",
5181 "SIP", "sip");
5182 proto_raw_sip = proto_register_protocol("Session Initiation Protocol (SIP as raw text)",
5183 "Raw_SIP", "raw_sip");
5184 new_register_dissector("sip", dissect_sip, proto_sip);
5185 register_dissector("sip.tcp", dissect_sip_tcp, proto_sip);
5187 /* Required function calls to register the header fields and subtrees used */
5188 proto_register_field_array(proto_sip, hf, array_length(hf));
5189 proto_register_subtree_array(ett, array_length(ett));
5190 expert_sip = expert_register_protocol(proto_sip);
5191 expert_register_field_array(expert_sip, ei, array_length(ei));
5192 proto_register_subtree_array(ett_raw, array_length(ett_raw));
5194 /* Register raw_sip field(s) */
5195 proto_register_field_array(proto_raw_sip, raw_hf, array_length(raw_hf));
5197 sip_module = prefs_register_protocol(proto_sip, proto_reg_handoff_sip);
5198 range_convert_str(&global_sip_tcp_port_range, DEFAULT_SIP_PORT_RANGE, MAX_UDP_PORT);
5201 prefs_register_range_preference(sip_module, "tcp.ports", "SIP TCP ports",
5202 "TCP ports to be decoded as SIP (default: "
5203 DEFAULT_SIP_PORT_RANGE ")",
5204 &global_sip_tcp_port_range, MAX_UDP_PORT);
5206 prefs_register_uint_preference(sip_module, "tls.port",
5207 "SIP TLS Port",
5208 "SIP Server TLS Port",
5209 10, &sip_tls_port);
5211 prefs_register_bool_preference(sip_module, "display_raw_text",
5212 "Display raw text for SIP message",
5213 "Specifies that the raw text of the "
5214 "SIP message should be displayed "
5215 "in addition to the dissection tree",
5216 &global_sip_raw_text);
5217 prefs_register_bool_preference(sip_module, "display_raw_text_without_crlf",
5218 "Don't show '\\r\\n' in raw SIP messages",
5219 "If the raw text of the SIP message "
5220 "is displayed, the trailing carriage "
5221 "return and line feed are not shown",
5222 &global_sip_raw_text_without_crlf);
5223 prefs_register_bool_preference(sip_module, "strict_sip_version",
5224 "Enforce strict SIP version check (" SIP2_HDR ")",
5225 "If enabled, only " SIP2_HDR " traffic will be dissected as SIP. "
5226 "Disable it to allow SIP traffic with a different version "
5227 "to be dissected as SIP.",
5228 &strict_sip_version);
5229 prefs_register_bool_preference(sip_module, "desegment_headers",
5230 "Reassemble SIP headers spanning multiple TCP segments",
5231 "Whether the SIP dissector should reassemble headers "
5232 "of a request spanning multiple TCP segments. "
5233 "To use this option, you must also enable "
5234 "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
5235 &sip_desegment_headers);
5236 prefs_register_bool_preference(sip_module, "desegment_body",
5237 "Reassemble SIP bodies spanning multiple TCP segments",
5238 "Whether the SIP dissector should use the "
5239 "\"Content-length:\" value, if present, to reassemble "
5240 "the body of a request spanning multiple TCP segments, "
5241 "and reassemble chunked data spanning multiple TCP segments. "
5242 "To use this option, you must also enable "
5243 "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
5244 &sip_desegment_body);
5245 prefs_register_bool_preference(sip_module, "retrans_the_same_sport",
5246 "Retransmissions always use the same source port",
5247 "Whether retransmissions are detected coming from the same source port only.",
5248 &sip_retrans_the_same_sport);
5250 prefs_register_obsolete_preference(sip_module, "tcp.port");
5252 register_init_routine(&sip_init_protocol);
5253 register_heur_dissector_list("sip", &heur_subdissector_list);
5254 /* Register for tapping */
5255 sip_tap = register_tap("sip");
5257 ext_hdr_subdissector_table = register_dissector_table("sip.hdr", "SIP Extension header", FT_STRING, BASE_NONE);
5261 void
5262 proto_reg_handoff_sip(void)
5264 static range_t *sip_tcp_port_range;
5266 static guint saved_sip_tls_port;
5267 static gboolean sip_prefs_initialized = FALSE;
5269 if (!sip_prefs_initialized) {
5270 dissector_handle_t sip_handle;
5271 sip_handle = find_dissector("sip");
5272 sip_tcp_handle = find_dissector("sip.tcp");
5273 sigcomp_handle = find_dissector("sigcomp");
5274 sip_diag_handle = find_dissector("sip.diagnostic");
5275 /* SIP content type and internet media type used by other dissectors are the same */
5276 media_type_dissector_table = find_dissector_table("media_type");
5278 dissector_add_uint("udp.port", UDP_PORT_SIP, sip_handle);
5279 dissector_add_string("media_type", "message/sip", sip_handle);
5281 heur_dissector_add("udp", dissect_sip_heur, proto_sip);
5282 heur_dissector_add("tcp", dissect_sip_tcp_heur, proto_sip);
5283 heur_dissector_add("sctp", dissect_sip_heur, proto_sip);
5284 heur_dissector_add("stun", dissect_sip_heur, proto_sip);
5285 sip_prefs_initialized = TRUE;
5286 } else {
5287 dissector_delete_uint_range("tcp.port", sip_tcp_port_range, sip_tcp_handle);
5288 g_free(sip_tcp_port_range);
5289 ssl_dissector_delete(saved_sip_tls_port, "sip.tcp", TRUE);
5291 /* Set our port number for future use */
5292 sip_tcp_port_range = range_copy(global_sip_tcp_port_range);
5293 dissector_add_uint_range("tcp.port", sip_tcp_port_range, sip_tcp_handle);
5294 saved_sip_tls_port = sip_tls_port;
5295 ssl_dissector_add(saved_sip_tls_port, "sip.tcp", TRUE);
5297 exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_7);