2 * Routines for the Session Initiation Protocol (SIP) dissection.
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>
12 * Copyright 2018, Anders Broman <anders.broman@ericsson.com>
13 * Copyright 2020, Atul Sharma <asharm37@ncsu.edu>
15 * Wireshark - Network traffic analyzer
16 * By Gerald Combs <gerald@wireshark.org>
17 * Copyright 1998 Gerald Combs
19 * SPDX-License-Identifier: GPL-2.0-or-later
25 #include <epan/packet.h>
27 #include <epan/exported_pdu.h>
28 #include <epan/expert.h>
29 #include <epan/prefs.h>
30 #include <epan/req_resp_hdrs.h>
31 #include <epan/stat_tap_ui.h>
32 #include <epan/proto_data.h>
34 #include <epan/follow.h>
35 #include <epan/addr_resolv.h>
36 #include <epan/epan_dissect.h>
37 #include <epan/iana_charsets.h>
40 #include <wsutil/array.h>
41 #include <wsutil/str_util.h>
42 #include <wsutil/wsgcrypt.h>
44 #include "packet-tls.h"
46 #include "packet-isup.h"
47 #include "packet-e164.h"
48 #include "packet-e212.h"
49 #include "packet-sip.h"
51 #include "packet-media-type.h"
52 #include "packet-acdr.h"
54 #include "packet-sdp.h" /* SDP needs a transport layer to determine request/response */
56 /* un-comment the following as well as this line in conversation.c, to enable debug printing */
57 /* #define DEBUG_CONVERSATION */
58 #include "conversation_debug.h"
60 #define TLS_PORT_SIP 5061
61 #define DEFAULT_SIP_PORT_RANGE "5060"
63 void proto_register_sip(void);
65 static int sip_tap
= -1;
66 static int sip_follow_tap
= -1;
67 static int exported_pdu_tap
= -1;
68 static dissector_handle_t sip_handle
;
69 static dissector_handle_t sip_tcp_handle
;
70 static dissector_handle_t sigcomp_handle
;
71 static dissector_handle_t sip_diag_handle
;
72 static dissector_handle_t sip_uri_userinfo_handle
;
73 static dissector_handle_t sip_via_branch_handle
;
74 static dissector_handle_t sip_via_be_route_handle
;
75 /* Dissector to dissect the text part of an reason code */
76 static dissector_handle_t sip_reason_code_handle
;
78 /* Initialize the protocol and registered fields */
80 static int proto_raw_sip
;
81 static int hf_sip_raw_line
;
82 static int hf_sip_msg_hdr
;
83 static int hf_sip_Method
;
84 static int hf_Request_Line
;
85 static int hf_sip_ruri_display
;
86 static int hf_sip_ruri
;
87 static int hf_sip_ruri_user
;
88 static int hf_sip_ruri_host
;
89 static int hf_sip_ruri_port
;
90 static int hf_sip_ruri_param
;
91 static int hf_sip_Status_Code
;
92 static int hf_sip_Status_Line
;
93 static int hf_sip_display
;
94 static int hf_sip_to_display
;
95 static int hf_sip_to_addr
;
96 static int hf_sip_to_user
;
97 static int hf_sip_to_host
;
98 static int hf_sip_to_port
;
99 static int hf_sip_to_param
;
100 static int hf_sip_to_tag
;
101 static int hf_sip_from_display
;
102 static int hf_sip_from_addr
;
103 static int hf_sip_from_user
;
104 static int hf_sip_from_host
;
105 static int hf_sip_from_port
;
106 static int hf_sip_from_param
;
107 static int hf_sip_from_tag
;
108 static int hf_sip_tag
;
109 static int hf_sip_pai_display
;
110 static int hf_sip_pai_addr
;
111 static int hf_sip_pai_user
;
112 static int hf_sip_pai_host
;
113 static int hf_sip_pai_port
;
114 static int hf_sip_pai_param
;
115 static int hf_sip_pmiss_display
;
116 static int hf_sip_pmiss_addr
;
117 static int hf_sip_pmiss_user
;
118 static int hf_sip_pmiss_host
;
119 static int hf_sip_pmiss_port
;
120 static int hf_sip_pmiss_param
;
121 static int hf_sip_ppi_display
;
122 static int hf_sip_ppi_addr
;
123 static int hf_sip_ppi_user
;
124 static int hf_sip_ppi_host
;
125 static int hf_sip_ppi_port
;
126 static int hf_sip_ppi_param
;
127 static int hf_sip_tc_display
;
128 static int hf_sip_tc_addr
;
129 static int hf_sip_tc_user
;
130 static int hf_sip_tc_host
;
131 static int hf_sip_tc_port
;
132 static int hf_sip_tc_param
;
133 static int hf_sip_tc_turi
;
134 static int hf_sip_contact_param
;
135 static int hf_sip_resend
;
136 static int hf_sip_original_frame
;
137 static int hf_sip_matching_request_frame
;
138 static int hf_sip_response_time
;
139 static int hf_sip_release_time
;
140 static int hf_sip_curi_display
;
141 static int hf_sip_curi
;
142 static int hf_sip_curi_user
;
143 static int hf_sip_curi_host
;
144 static int hf_sip_curi_port
;
145 static int hf_sip_curi_param
;
146 static int hf_sip_route_display
;
147 static int hf_sip_route
;
148 static int hf_sip_route_user
;
149 static int hf_sip_route_host
;
150 static int hf_sip_route_port
;
151 static int hf_sip_route_param
;
152 static int hf_sip_record_route_display
;
153 static int hf_sip_record_route
;
154 static int hf_sip_record_route_user
;
155 static int hf_sip_record_route_host
;
156 static int hf_sip_record_route_port
;
157 static int hf_sip_record_route_param
;
158 static int hf_sip_service_route_display
;
159 static int hf_sip_service_route
;
160 static int hf_sip_service_route_user
;
161 static int hf_sip_service_route_host
;
162 static int hf_sip_service_route_port
;
163 static int hf_sip_service_route_param
;
164 static int hf_sip_path_display
;
165 static int hf_sip_path
;
166 static int hf_sip_path_user
;
167 static int hf_sip_path_host
;
168 static int hf_sip_path_port
;
169 static int hf_sip_path_param
;
171 static int hf_sip_auth
;
172 static int hf_sip_auth_scheme
;
173 static int hf_sip_auth_digest_response
;
174 static int hf_sip_auth_nc
;
175 static int hf_sip_auth_username
;
176 static int hf_sip_auth_realm
;
177 static int hf_sip_auth_nonce
;
178 static int hf_sip_auth_algorithm
;
179 static int hf_sip_auth_opaque
;
180 static int hf_sip_auth_qop
;
181 static int hf_sip_auth_cnonce
;
182 static int hf_sip_auth_uri
;
183 static int hf_sip_auth_domain
;
184 static int hf_sip_auth_stale
;
185 static int hf_sip_auth_auts
;
186 static int hf_sip_auth_rspauth
;
187 static int hf_sip_auth_nextnonce
;
188 static int hf_sip_auth_ik
;
189 static int hf_sip_auth_ck
;
191 static int hf_sip_cseq_seq_no
;
192 static int hf_sip_cseq_method
;
194 static int hf_sip_via_transport
;
195 static int hf_sip_via_sent_by_address
;
196 static int hf_sip_via_sent_by_port
;
197 static int hf_sip_via_branch
;
198 static int hf_sip_via_maddr
;
199 static int hf_sip_via_rport
;
200 static int hf_sip_via_received
;
201 static int hf_sip_via_ttl
;
202 static int hf_sip_via_comp
;
203 static int hf_sip_via_sigcomp_id
;
204 static int hf_sip_via_oc
;
205 static int hf_sip_via_oc_val
;
206 static int hf_sip_via_oc_algo
;
207 static int hf_sip_via_oc_validity
;
208 static int hf_sip_via_oc_seq
;
209 static int hf_sip_oc_seq_timestamp
;
210 static int hf_sip_via_be_route
;
212 static int hf_sip_rack_rseq_no
;
213 static int hf_sip_rack_cseq_no
;
214 static int hf_sip_rack_cseq_method
;
216 static int hf_sip_reason_protocols
;
217 static int hf_sip_reason_cause_q850
;
218 static int hf_sip_reason_cause_sip
;
219 static int hf_sip_reason_cause_other
;
220 static int hf_sip_reason_text
;
222 static int hf_sip_msg_body
;
223 static int hf_sip_sec_mechanism
;
224 static int hf_sip_sec_mechanism_alg
;
225 static int hf_sip_sec_mechanism_ealg
;
226 static int hf_sip_sec_mechanism_prot
;
227 static int hf_sip_sec_mechanism_spi_c
;
228 static int hf_sip_sec_mechanism_spi_s
;
229 static int hf_sip_sec_mechanism_port1
;
230 static int hf_sip_sec_mechanism_port_c
;
231 static int hf_sip_sec_mechanism_port2
;
232 static int hf_sip_sec_mechanism_port_s
;
233 static int hf_sip_session_id_sess_id
;
234 static int hf_sip_session_id_param
;
235 static int hf_sip_session_id_local_uuid
;
236 static int hf_sip_session_id_remote_uuid
;
237 static int hf_sip_session_id_logme
;
238 static int hf_sip_continuation
;
239 static int hf_sip_feature_cap
;
241 static int hf_sip_p_acc_net_i_acc_type
;
242 static int hf_sip_p_acc_net_i_ucid_3gpp
;
244 static int hf_sip_service_priority
;
245 static int hf_sip_icid_value
;
246 static int hf_sip_icid_gen_addr
;
247 static int hf_sip_call_id_gen
;
249 /* Initialize the subtree pointers */
251 static int ett_sip_reqresp
;
252 static int ett_sip_hdr
;
253 static int ett_sip_ext_hdr
;
254 static int ett_raw_text
;
255 static int ett_sip_element
;
256 static int ett_sip_hist
;
257 static int ett_sip_uri
;
258 static int ett_sip_contact_item
;
259 static int ett_sip_message_body
;
260 static int ett_sip_cseq
;
261 static int ett_sip_via
;
262 static int ett_sip_reason
;
263 static int ett_sip_security_client
;
264 static int ett_sip_security_server
;
265 static int ett_sip_security_verify
;
266 static int ett_sip_rack
;
267 static int ett_sip_route
;
268 static int ett_sip_record_route
;
269 static int ett_sip_service_route
;
270 static int ett_sip_path
;
271 static int ett_sip_ruri
;
272 static int ett_sip_to_uri
;
273 static int ett_sip_curi
;
274 static int ett_sip_from_uri
;
275 static int ett_sip_pai_uri
;
276 static int ett_sip_pmiss_uri
;
277 static int ett_sip_ppi_uri
;
278 static int ett_sip_tc_uri
;
279 static int ett_sip_session_id
;
280 static int ett_sip_p_access_net_info
;
281 static int ett_sip_p_charging_vector
;
282 static int ett_sip_feature_caps
;
283 static int ett_sip_via_be_route
;
285 static expert_field ei_sip_unrecognized_header
;
286 static expert_field ei_sip_header_no_colon
;
287 static expert_field ei_sip_header_not_terminated
;
289 static expert_field ei_sip_odd_register_response
;
291 static expert_field ei_sip_call_id_invalid
;
292 static expert_field ei_sip_sipsec_malformed
;
293 static expert_field ei_sip_via_sent_by_port
;
294 static expert_field ei_sip_content_length_invalid
;
295 static expert_field ei_sip_retry_after_invalid
;
296 static expert_field ei_sip_Status_Code_invalid
;
297 static expert_field ei_sip_authorization_invalid
;
298 static expert_field ei_sip_session_id_sess_id
;
300 /* patterns used for tvb_ws_mempbrk_pattern_uint8 */
301 static ws_mempbrk_pattern pbrk_comma_semi
;
302 static ws_mempbrk_pattern pbrk_whitespace
;
303 static ws_mempbrk_pattern pbrk_param_end
;
304 static ws_mempbrk_pattern pbrk_param_end_colon_brackets
;
305 static ws_mempbrk_pattern pbrk_header_end_dquote
;
306 static ws_mempbrk_pattern pbrk_tab_sp_fslash
;
307 static ws_mempbrk_pattern pbrk_addr_end
;
308 static ws_mempbrk_pattern pbrk_via_param_end
;
311 /* PUBLISH method added as per https://tools.ietf.org/html/draft-ietf-sip-publish-01 */
312 static const char *sip_methods
[] = {
313 #define SIP_METHOD_INVALID 0
314 "<Invalid method>", /* Pad so that the real methods start at index 1 */
315 #define SIP_METHOD_ACK 1
317 #define SIP_METHOD_BYE 2
319 #define SIP_METHOD_CANCEL 3
321 #define SIP_METHOD_DO 4
323 #define SIP_METHOD_INFO 5
325 #define SIP_METHOD_INVITE 6
327 #define SIP_METHOD_MESSAGE 7
329 #define SIP_METHOD_NOTIFY 8
331 #define SIP_METHOD_OPTIONS 9
333 #define SIP_METHOD_PRACK 10
335 #define SIP_METHOD_QAUTH 11
337 #define SIP_METHOD_REFER 12
339 #define SIP_METHOD_REGISTER 13
341 #define SIP_METHOD_SPRACK 14
343 #define SIP_METHOD_SUBSCRIBE 15
345 #define SIP_METHOD_UPDATE 16
347 #define SIP_METHOD_PUBLISH 17
352 * Updated with info from https://www.iana.org/assignments/sip-parameters
353 * (last updated 2009-11-11)
354 * Updated with: https://tools.ietf.org/html/draft-ietf-sip-resource-priority-05
358 const char *compact_name
;
360 static const sip_header_t sip_headers
[] = {
361 { "Unknown-header", NULL
}, /* 0 Pad so that the real headers start at index 1 */
362 { "Accept", NULL
}, /* */
364 { "Accept-Contact", "a" }, /* RFC3841 */
365 #define POS_ACCEPT_CONTACT 2
366 { "Accept-Encoding", NULL
}, /* */
367 #define POS_ACCEPT_ENCODING 3
368 { "Accept-Language", NULL
}, /* */
369 #define POS_ACCEPT_LANGUAGE 4
370 { "Accept-Resource-Priority", NULL
}, /* RFC4412 */
371 #define POS_ACCEPT_RESOURCE_PRIORITY 5
372 { "Additional-Identity", NULL
}, /* 3GPP TS 24.229 v16.7.0 */
373 #define POS_ADDITIONAL_IDENTITY 6
374 { "Alert-Info", NULL
},
375 #define POS_ALERT_INFO 7
378 { "Allow-Events", "u" }, /* RFC3265 */
379 #define POS_ALLOW_EVENTS 9
380 { "Answer-Mode", NULL
}, /* RFC5373 */
381 #define POS_ANSWER_MODE 10
382 { "Attestation-Info", NULL
}, /* [3GPP TS 24.229 v15.11.0] */
383 #define POS_ATTESTATION_INFO 11
384 { "Authentication-Info", NULL
},
385 #define POS_AUTHENTICATION_INFO 12
386 { "Authorization", NULL
}, /* */
387 #define POS_AUTHORIZATION 13
389 #define POS_CALL_ID 14
390 { "Call-Info", NULL
},
391 #define POS_CALL_INFO 15
392 { "Cellular-Network-Info", NULL
}, /* [3GPP TS 24.229 v13.9.0] */
393 #define POS_CELLULAR_NETWORK_INFO 16
395 #define POS_CONTACT 17
396 { "Content-Disposition", NULL
},
397 #define POS_CONTENT_DISPOSITION 18
398 { "Content-Encoding", "e" }, /* */
399 #define POS_CONTENT_ENCODING 19
400 { "Content-Language", NULL
},
401 #define POS_CONTENT_LANGUAGE 20
402 { "Content-Length", "l" },
403 #define POS_CONTENT_LENGTH 21
404 { "Content-Type", "c" },
405 #define POS_CONTENT_TYPE 22
408 { "Date", NULL
}, /* */
410 /* Encryption (Deprecated) [RFC3261] */
411 { "Error-Info", NULL
}, /* */
412 #define POS_ERROR_INFO 25
413 { "Event", "o" }, /* */
415 { "Expires", NULL
}, /* */
416 #define POS_EXPIRES 27
417 { "Feature-Caps", NULL
}, /* RFC6809 */
418 #define POS_FEATURE_CAPS 28
419 { "Flow-Timer", NULL
}, /* RFC5626 */
420 #define POS_FLOW_TIMER 29
421 { "From", "f" }, /* */
424 { "Geolocation", NULL
}, /* */
425 #define POS_GEOLOCATION 31
426 { "Geolocation-Error", NULL
}, /* */
427 #define POS_GEOLOCATION_ERROR 32
428 { "Geolocation-Routing", NULL
}, /* */
429 #define POS_GEOLOCATION_ROUTING 33
431 /* Hide RFC3261 (deprecated)*/
432 { "History-Info", NULL
}, /* RFC4244 */
433 #define POS_HISTORY_INFO 34
434 { "Identity", "y" }, /* RFC4474 */
435 #define POS_IDENTITY 35
436 { "Identity-Info", "n" }, /* RFC4474 */
437 #define POS_IDENTITY_INFO 36
438 { "Info-Package", NULL
}, /* RFC-ietf-sipcore-info-events-10.txt */
439 #define POS_INFO_PKG 37
440 { "In-Reply-To", NULL
}, /* RFC3261 */
441 #define POS_IN_REPLY_TO 38
442 { "Join", NULL
}, /* RFC3911 */
444 { "Max-Breadth", NULL
}, /* RFC5393*/
445 #define POS_MAX_BREADTH 40
446 { "Max-Forwards", NULL
}, /* */
447 #define POS_MAX_FORWARDS 41
448 { "MIME-Version", NULL
}, /* */
449 #define POS_MIME_VERSION 42
450 { "Min-Expires", NULL
}, /* */
451 #define POS_MIN_EXPIRES 43
452 { "Min-SE", NULL
}, /* RFC4028 */
453 #define POS_MIN_SE 44
454 { "Organization", NULL
}, /* RFC3261 */
455 #define POS_ORGANIZATION 45
456 { "Origination-Id", NULL
}, /* [3GPP TS 24.229 v15.11.0] */
457 #define POS_ORIGINATION_ID 46
458 { "P-Access-Network-Info", NULL
}, /* RFC3455 */
459 #define POS_P_ACCESS_NETWORK_INFO 47
460 { "P-Answer-State", NULL
}, /* RFC4964 */
461 #define POS_P_ANSWER_STATE 48
462 { "P-Asserted-Identity", NULL
}, /* RFC3325 */
463 #define POS_P_ASSERTED_IDENTITY 49
464 { "P-Asserted-Service", NULL
}, /* RFC6050 */
465 #define POS_P_ASSERTED_SERV 50
466 { "P-Associated-URI", NULL
}, /* RFC3455 */
467 #define POS_P_ASSOCIATED_URI 51
468 { "P-Called-Party-ID", NULL
}, /* RFC3455 */
469 #define POS_P_CALLED_PARTY_ID 52
470 { "P-Charge-Info", NULL
}, /* RFC8496 */
471 #define POS_P_CHARGE_INFO 53
472 { "P-Charging-Function-Addresses", NULL
}, /* RFC3455 */
473 #define POS_P_CHARGING_FUNC_ADDRESSES 54
474 { "P-Charging-Vector", NULL
}, /* RFC3455 */
475 #define POS_P_CHARGING_VECTOR 55
476 { "P-DCS-Trace-Party-ID", NULL
}, /* RFC5503 */
477 #define POS_P_DCS_TRACE_PARTY_ID 56
478 { "P-DCS-OSPS", NULL
}, /* RFC5503 */
479 #define POS_P_DCS_OSPS 57
480 { "P-DCS-Billing-Info", NULL
}, /* RFC5503 */
481 #define POS_P_DCS_BILLING_INFO 58
482 { "P-DCS-LAES", NULL
}, /* RFC5503 */
483 #define POS_P_DCS_LAES 59
484 { "P-DCS-Redirect", NULL
}, /* RFC5503 */
485 #define POS_P_DCS_REDIRECT 60
486 { "P-Early-Media", NULL
}, /* RFC5009 */
487 #define POS_P_EARLY_MEDIA 61
488 { "P-Media-Authorization", NULL
}, /* RFC3313 */
489 #define POS_P_MEDIA_AUTHORIZATION 62
490 { "P-Preferred-Identity", NULL
}, /* RFC3325 */
491 #define POS_P_PREFERRED_IDENTITY 63
492 { "P-Preferred-Service", NULL
}, /* RFC6050 */
493 #define POS_P_PREFERRED_SERV 64
494 { "P-Profile-Key", NULL
}, /* RFC5002 */
495 #define POS_P_PROFILE_KEY 65
496 { "P-Refused-URI-List", NULL
}, /* RFC5318 */
497 #define POS_P_REFUSED_URI_LST 66
498 { "P-Served-User", NULL
}, /* RFC5502 */
499 #define POS_P_SERVED_USER 67
500 { "P-User-Database", NULL
}, /* RFC4457 */
501 #define POS_P_USER_DATABASE 68
502 { "P-Visited-Network-ID", NULL
}, /* RFC3455 */
503 #define POS_P_VISITED_NETWORK_ID 69
504 { "Path", NULL
}, /* RFC3327 */
506 { "Permission-Missing", NULL
}, /* RFC5360 */
507 #define POS_PERMISSION_MISSING 71
508 { "Policy-Contact", NULL
}, /* RFC3261 */
509 #define POS_POLICY_CONTACT 72
510 { "Policy-ID", NULL
}, /* RFC3261 */
511 #define POS_POLICY_ID 73
512 { "Priority", NULL
}, /* RFC3261 */
513 #define POS_PRIORITY 74
514 { "Priority-Share", NULL
}, /* [3GPP TS 24.229 v13.16.0] */
515 #define POS_PRIORITY_SHARE 75
516 { "Priv-Answer-Mode", NULL
}, /* RFC5373 */
517 #define POS_PRIV_ANSWER_MODE 76
518 { "Privacy", NULL
}, /* RFC3323 */
519 #define POS_PRIVACY 77
520 { "Proxy-Authenticate", NULL
}, /* */
521 #define POS_PROXY_AUTHENTICATE 78
522 { "Proxy-Authorization", NULL
}, /* */
523 #define POS_PROXY_AUTHORIZATION 79
524 { "Proxy-Require", NULL
}, /* */
525 #define POS_PROXY_REQUIRE 80
526 { "RAck", NULL
}, /* RFC3262 */
528 { "Reason", NULL
}, /* RFC3326 */
529 #define POS_REASON 82
530 { "Reason-Phrase", NULL
}, /* RFC3326 */
531 #define POS_REASON_PHRASE 83
532 { "Record-Route", NULL
}, /* */
533 #define POS_RECORD_ROUTE 84
534 { "Recv-Info", NULL
}, /* RFC6086 */
535 #define POS_RECV_INFO 85
536 { "Refer-Sub", NULL
}, /* RFC4488 */
537 #define POS_REFER_SUB 86
538 { "Refer-To", "r" }, /* RFC3515 */
539 #define POS_REFER_TO 87
540 { "Referred-By", "b" }, /* RFC3892 */
541 #define POS_REFERRED_BY 88
542 { "Reject-Contact", "j" }, /* RFC3841 */
543 #define POS_REJECT_CONTACT 89
544 { "Relayed-Charge", NULL
}, /* [3GPP TS 24.229 v12.14.0] */
545 #define POS_RELAYED_CHARGE 90
546 { "Replaces", NULL
}, /* RFC3891 */
547 #define POS_REPLACES 91
548 { "Reply-To", NULL
}, /* RFC3261 */
549 #define POS_REPLY_TO 92
550 { "Request-Disposition", "d" }, /* RFC3841 */
551 #define POS_REQUEST_DISPOSITION 93
552 { "Require", NULL
}, /* RFC3261 */
553 #define POS_REQUIRE 94
554 { "Resource-Priority", NULL
}, /* RFC4412 */
555 #define POS_RESOURCE_PRIORITY 95
556 { "Resource-Share", NULL
}, /* [3GPP TS 24.229 v13.7.0] */
557 #define POS_RESOURCE_SHARE 96
558 /*{ "Response-Key (Deprecated) [RFC3261]*/
559 { "Response-Source", NULL
}, /* [3GPP TS 24.229 v15.11.0] */
560 #define POS_RESPONSE_SOURCE 97
561 { "Restoration-Info", NULL
}, /* [3GPP TS 24.229 v12.14.0] */
562 #define POS_RESTORATION_INFO 98
563 { "Retry-After", NULL
}, /* RFC3261 */
564 #define POS_RETRY_AFTER 99
565 { "Route", NULL
}, /* RFC3261 */
566 #define POS_ROUTE 100
567 { "RSeq", NULL
}, /* RFC3262 */
569 { "Security-Client", NULL
}, /* RFC3329 */
570 #define POS_SECURITY_CLIENT 102
571 { "Security-Server", NULL
}, /* RFC3329 */
572 #define POS_SECURITY_SERVER 103
573 { "Security-Verify", NULL
}, /* RFC3329 */
574 #define POS_SECURITY_VERIFY 104
575 { "Server", NULL
}, /* RFC3261 */
576 #define POS_SERVER 105
577 { "Service-Interact-Info", NULL
}, /* [3GPP TS 24.229 v13.18.0] */
578 #define POS_SERVICE_INTERACT_INFO 106
579 { "Service-Route", NULL
}, /* RFC3608 */
580 #define POS_SERVICE_ROUTE 107
581 { "Session-Expires", "x" }, /* RFC4028 */
582 #define POS_SESSION_EXPIRES 108
583 { "Session-ID", NULL
}, /* RFC7329 */
584 #define POS_SESSION_ID 109
585 { "SIP-ETag", NULL
}, /* RFC3903 */
586 #define POS_SIP_ETAG 110
587 { "SIP-If-Match", NULL
}, /* RFC3903 */
588 #define POS_SIP_IF_MATCH 111
589 { "Subject", "s" }, /* RFC3261 */
590 #define POS_SUBJECT 112
591 { "Subscription-State", NULL
}, /* RFC3265 */
592 #define POS_SUBSCRIPTION_STATE 113
593 { "Supported", "k" }, /* RFC3261 */
594 #define POS_SUPPORTED 114
595 { "Suppress-If-Match", NULL
}, /* RFC5839 */
596 #define POS_SUPPRESS_IF_MATCH 115
597 { "Target-Dialog", NULL
}, /* RFC4538 */
598 #define POS_TARGET_DIALOG 116
599 { "Timestamp", NULL
}, /* RFC3261 */
600 #define POS_TIMESTAMP 117
601 { "To", "t" }, /* RFC3261 */
603 { "Trigger-Consent", NULL
}, /* RFC5360 */
604 #define POS_TRIGGER_CONSENT 119
605 { "Unsupported", NULL
}, /* RFC3261 */
606 #define POS_UNSUPPORTED 120
607 { "User-Agent", NULL
}, /* RFC3261 */
608 #define POS_USER_AGENT 121
609 { "Via", "v" }, /* RFC3261 */
611 { "Warning", NULL
}, /* RFC3261 */
612 #define POS_WARNING 123
613 { "WWW-Authenticate", NULL
}, /* RFC3261 */
614 #define POS_WWW_AUTHENTICATE 124
615 { "Diversion", NULL
}, /* RFC5806 */
616 #define POS_DIVERSION 125
617 { "User-to-User", NULL
}, /* RFC7433 */
618 #define POS_USER_TO_USER 126
622 static int hf_header_array
[array_length(sip_headers
)];
624 /* Track associations between parameter name and hf item */
626 const char *param_name
;
628 } header_parameter_t
;
630 static header_parameter_t auth_parameters_hf_array
[] =
632 {"response", &hf_sip_auth_digest_response
},
633 {"nc", &hf_sip_auth_nc
},
634 {"username", &hf_sip_auth_username
},
635 {"realm", &hf_sip_auth_realm
},
636 {"nonce", &hf_sip_auth_nonce
},
637 {"algorithm", &hf_sip_auth_algorithm
},
638 {"opaque", &hf_sip_auth_opaque
},
639 {"qop", &hf_sip_auth_qop
},
640 {"cnonce", &hf_sip_auth_cnonce
},
641 {"uri", &hf_sip_auth_uri
},
642 {"domain", &hf_sip_auth_domain
},
643 {"stale", &hf_sip_auth_stale
},
644 {"auts", &hf_sip_auth_auts
},
645 {"rspauth", &hf_sip_auth_rspauth
},
646 {"nextnonce", &hf_sip_auth_nextnonce
},
647 {"ik", &hf_sip_auth_ik
},
648 {"ck", &hf_sip_auth_ck
}
651 static header_parameter_t via_parameters_hf_array
[] =
653 {"branch", &hf_sip_via_branch
},
654 {"maddr", &hf_sip_via_maddr
},
655 {"rport", &hf_sip_via_rport
},
656 {"received", &hf_sip_via_received
},
657 {"ttl", &hf_sip_via_ttl
},
658 {"comp", &hf_sip_via_comp
},
659 {"sigcomp-id", &hf_sip_via_sigcomp_id
},
660 {"oc", &hf_sip_via_oc
},
661 {"oc-validity", &hf_sip_via_oc_validity
},
662 {"oc-seq", &hf_sip_via_oc_seq
},
663 {"oc-algo", &hf_sip_via_oc_algo
},
664 {"be-route", &hf_sip_via_be_route
}
668 MECH_PARA_STRING
= 0,
670 } mech_parameter_type_t
;
672 /* Track associations between parameter name and hf item for security mechanism*/
674 const char *param_name
;
679 static mech_parameter_t sec_mechanism_parameters_hf_array
[] =
681 {"alg", MECH_PARA_STRING
, &hf_sip_sec_mechanism_alg
},
682 {"ealg", MECH_PARA_STRING
, &hf_sip_sec_mechanism_ealg
},
683 {"prot", MECH_PARA_STRING
, &hf_sip_sec_mechanism_prot
},
684 {"spi-c", MECH_PARA_UINT
, &hf_sip_sec_mechanism_spi_c
},
685 {"spi-s", MECH_PARA_UINT
, &hf_sip_sec_mechanism_spi_s
},
686 {"port1", MECH_PARA_UINT
, &hf_sip_sec_mechanism_port1
},
687 {"port-c", MECH_PARA_UINT
, &hf_sip_sec_mechanism_port_c
},
688 {"port2", MECH_PARA_UINT
, &hf_sip_sec_mechanism_port2
},
689 {"port-s", MECH_PARA_UINT
, &hf_sip_sec_mechanism_port_s
},
703 static hf_sip_uri_t sip_pai_uri
= {
713 static hf_sip_uri_t sip_ppi_uri
= {
723 static hf_sip_uri_t sip_pmiss_uri
= {
724 &hf_sip_pmiss_display
,
733 static hf_sip_uri_t sip_tc_uri
= {
743 static hf_sip_uri_t sip_to_uri
= {
753 static hf_sip_uri_t sip_from_uri
= {
754 &hf_sip_from_display
,
763 static hf_sip_uri_t sip_req_uri
= {
764 &hf_sip_ruri_display
,
773 static hf_sip_uri_t sip_contact_uri
= {
774 &hf_sip_curi_display
,
783 static hf_sip_uri_t sip_route_uri
= {
784 &hf_sip_route_display
,
793 static hf_sip_uri_t sip_record_route_uri
= {
794 &hf_sip_record_route_display
,
795 &hf_sip_record_route
,
796 &hf_sip_record_route_user
,
797 &hf_sip_record_route_host
,
798 &hf_sip_record_route_port
,
799 &hf_sip_record_route_param
,
800 &ett_sip_record_route
803 static hf_sip_uri_t sip_service_route_uri
= {
804 &hf_sip_service_route_display
,
805 &hf_sip_service_route
,
806 &hf_sip_service_route_user
,
807 &hf_sip_service_route_host
,
808 &hf_sip_service_route_port
,
809 &hf_sip_service_route_param
,
810 &ett_sip_service_route
813 static hf_sip_uri_t sip_path_uri
= {
814 &hf_sip_path_display
,
824 * Type of line. It's either a SIP Request-Line, a SIP Status-Line, or
825 * another type of line.
834 static unsigned sip_tls_port
= TLS_PORT_SIP
;
836 /* global_sip_raw_text determines whether we are going to display */
837 /* the raw text of the SIP message, much like the MEGACO dissector does. */
838 static bool global_sip_raw_text
;
839 /* global_sip_raw_text_without_crlf determines whether we are going to display */
840 /* the raw text of the SIP message with or without the '\r\n'. */
841 static bool global_sip_raw_text_without_crlf
;
842 /* global_sip_raw_text_body_default_encoding determines what charset we are going to display the body */
843 static int global_sip_raw_text_body_default_encoding
= IANA_CS_UTF_8
;
844 /* strict_sip_version determines whether the SIP dissector enforces
845 * the SIP version to be "SIP/2.0". */
846 static bool strict_sip_version
= true;
849 * desegmentation of SIP headers
850 * (when we are over TCP or another protocol providing the desegmentation API)
852 static bool sip_desegment_headers
= true;
855 * desegmentation of SIP bodies
856 * (when we are over TCP or another protocol providing the desegmentation API)
858 static bool sip_desegment_body
= true;
861 * same source port for retransmissions
863 static bool sip_retrans_the_same_sport
= true;
865 /* whether we hold off tracking RTP conversations until an SDP answer is received */
866 static bool sip_delay_sdp_changes
;
868 /* Hide the generated Call IDs or not */
869 static bool sip_hide_generatd_call_ids
;
871 /* Extension header subdissectors */
872 static dissector_table_t ext_hdr_subdissector_table
;
874 /* Custom SIP headers */
875 typedef struct _header_field_t
{
880 static header_field_t
* sip_custom_header_fields
;
881 static unsigned sip_custom_num_header_fields
;
882 static GHashTable
*sip_custom_header_fields_hash
;
883 static hf_register_info
*dynamic_hf
;
884 static unsigned dynamic_hf_size
;
887 header_fields_update_cb(void *r
, char **err
)
889 header_field_t
*rec
= (header_field_t
*)r
;
892 if (rec
->header_name
== NULL
) {
893 *err
= g_strdup("Header name can't be empty");
897 g_strstrip(rec
->header_name
);
898 if (rec
->header_name
[0] == 0) {
899 *err
= g_strdup("Header name can't be empty");
903 /* Check for invalid characters (to avoid asserting out when
904 * registering the field).
906 c
= proto_check_field_name(rec
->header_name
);
908 *err
= ws_strdup_printf("Header name can't contain '%c'", c
);
917 header_fields_copy_cb(void* n
, const void* o
, size_t siz _U_
)
919 header_field_t
* new_rec
= (header_field_t
*)n
;
920 const header_field_t
* old_rec
= (const header_field_t
*)o
;
922 new_rec
->header_name
= g_strdup(old_rec
->header_name
);
923 new_rec
->header_desc
= g_strdup(old_rec
->header_desc
);
929 header_fields_free_cb(void*r
)
931 header_field_t
* rec
= (header_field_t
*)r
;
933 g_free(rec
->header_name
);
934 g_free(rec
->header_desc
);
938 deregister_header_fields(void)
941 /* Deregister all fields */
942 for (unsigned i
= 0; i
< dynamic_hf_size
; i
++) {
943 proto_deregister_field(proto_sip
, *(dynamic_hf
[i
].p_id
));
944 g_free(dynamic_hf
[i
].p_id
);
947 proto_add_deregistered_data(dynamic_hf
);
952 if (sip_custom_header_fields_hash
) {
953 g_hash_table_destroy(sip_custom_header_fields_hash
);
954 sip_custom_header_fields_hash
= NULL
;
959 header_fields_post_update_cb(void)
963 char* header_name_key
;
965 deregister_header_fields();
967 if (sip_custom_num_header_fields
) {
968 sip_custom_header_fields_hash
= g_hash_table_new_full(g_str_hash
, g_str_equal
, g_free
, NULL
);
969 dynamic_hf
= g_new0(hf_register_info
, sip_custom_num_header_fields
);
970 dynamic_hf_size
= sip_custom_num_header_fields
;
972 for (unsigned i
= 0; i
< dynamic_hf_size
; i
++) {
973 hf_id
= g_new(int, 1);
975 header_name
= g_strdup(sip_custom_header_fields
[i
].header_name
);
976 header_name_key
= g_ascii_strdown(header_name
, -1);
978 dynamic_hf
[i
].p_id
= hf_id
;
979 dynamic_hf
[i
].hfinfo
.name
= header_name
;
980 dynamic_hf
[i
].hfinfo
.abbrev
= ws_strdup_printf("sip.%s", header_name
);
981 dynamic_hf
[i
].hfinfo
.type
= FT_STRING
;
982 dynamic_hf
[i
].hfinfo
.display
= BASE_NONE
;
983 dynamic_hf
[i
].hfinfo
.strings
= NULL
;
984 dynamic_hf
[i
].hfinfo
.bitmask
= 0;
985 dynamic_hf
[i
].hfinfo
.blurb
= g_strdup(sip_custom_header_fields
[i
].header_desc
);
986 HFILL_INIT(dynamic_hf
[i
]);
988 g_hash_table_insert(sip_custom_header_fields_hash
, header_name_key
, hf_id
);
991 proto_register_field_array(proto_sip
, dynamic_hf
, dynamic_hf_size
);
996 header_fields_reset_cb(void)
998 deregister_header_fields();
1001 UAT_CSTRING_CB_DEF(sip_custom_header_fields
, header_name
, header_field_t
)
1002 UAT_CSTRING_CB_DEF(sip_custom_header_fields
, header_desc
, header_field_t
)
1004 /* SIP authorization parameters */
1005 static bool global_sip_validate_authorization
;
1007 typedef struct _authorization_user_t
{
1011 } authorization_user_t
;
1013 static authorization_user_t
* sip_authorization_users
;
1014 static unsigned sip_authorization_num_users
;
1017 authorization_users_update_cb(void *r
, char **err
)
1019 authorization_user_t
*rec
= (authorization_user_t
*)r
;
1022 if (rec
->username
== NULL
) {
1023 *err
= g_strdup("Username can't be empty");
1027 g_strstrip(rec
->username
);
1028 if (rec
->username
[0] == 0) {
1029 *err
= g_strdup("Username can't be empty");
1033 /* Check for invalid characters (to avoid asserting out when
1034 * registering the field).
1036 c
= proto_check_field_name(rec
->username
);
1038 *err
= ws_strdup_printf("Username can't contain '%c'", c
);
1047 authorization_users_copy_cb(void* n
, const void* o
, size_t siz _U_
)
1049 authorization_user_t
* new_rec
= (authorization_user_t
*)n
;
1050 const authorization_user_t
* old_rec
= (const authorization_user_t
*)o
;
1052 new_rec
->username
= g_strdup(old_rec
->username
);
1053 new_rec
->realm
= g_strdup(old_rec
->realm
);
1054 new_rec
->password
= g_strdup(old_rec
->password
);
1060 authorization_users_free_cb(void*r
)
1062 authorization_user_t
* rec
= (authorization_user_t
*)r
;
1064 g_free(rec
->username
);
1066 g_free(rec
->password
);
1069 UAT_CSTRING_CB_DEF(sip_authorization_users
, username
, authorization_user_t
)
1070 UAT_CSTRING_CB_DEF(sip_authorization_users
, realm
, authorization_user_t
)
1071 UAT_CSTRING_CB_DEF(sip_authorization_users
, password
, authorization_user_t
)
1073 /* Forward declaration we need below */
1074 void proto_reg_handoff_sip(void);
1075 static int dissect_sip_common(tvbuff_t
*tvb
, int offset
, int remaining_length
, packet_info
*pinfo
,
1076 proto_tree
*tree
, bool is_heur
, bool use_reassembly
);
1077 static line_type_t
sip_parse_line(tvbuff_t
*tvb
, int offset
, int linelen
,
1078 unsigned *token_1_len
);
1079 static bool sip_is_known_request(tvbuff_t
*tvb
, int meth_offset
,
1080 unsigned meth_len
, unsigned *meth_idx
);
1081 static int sip_is_known_sip_header(char *header_name
, unsigned header_len
);
1082 static void dfilter_sip_request_line(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, int offset
,
1083 unsigned meth_len
, int linelen
);
1084 static void dfilter_sip_status_line(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, int line_end
, int offset
);
1085 static void tvb_raw_text_add(tvbuff_t
*tvb
, int offset
, int length
, int body_offset
, packet_info
* pinfo
, proto_tree
*tree
);
1086 static unsigned sip_is_packet_resend(packet_info
*pinfo
,
1087 const char *cseq_method
,
1089 unsigned char cseq_number_set
, uint32_t cseq_number
,
1090 line_type_t line_type
);
1092 static unsigned sip_find_request(packet_info
*pinfo
,
1093 const char *cseq_method
,
1095 unsigned char cseq_number_set
, uint32_t cseq_number
,
1096 uint32_t *response_time
);
1098 static unsigned sip_find_invite(packet_info
*pinfo
,
1099 const char *cseq_method
,
1101 unsigned char cseq_number_set
, uint32_t cseq_number
,
1102 uint32_t *response_time
);
1116 } sip_authorization_t
;
1118 static authorization_user_t
* sip_get_authorization(sip_authorization_t
*authorization_info
);
1119 static bool sip_validate_authorization(sip_authorization_t
*authorization_info
, char *password
);
1121 static authorization_user_t
* sip_get_authorization(sip_authorization_t
*authorization_info
)
1124 for (i
= 0; i
< sip_authorization_num_users
; i
++) {
1125 if ((!strcmp(sip_authorization_users
[i
].username
, authorization_info
->username
)) &&
1126 (!strcmp(sip_authorization_users
[i
].realm
, authorization_info
->realm
))) {
1127 return &sip_authorization_users
[i
];
1133 /* SIP content type and internet media type used by other dissectors
1134 * are the same. List of media types from IANA at:
1135 * http://www.iana.org/assignments/media-types/index.html */
1136 static dissector_table_t media_type_dissector_table
;
1138 static heur_dissector_list_t heur_subdissector_list
;
1140 #define SIP2_HDR "SIP/2.0"
1141 #define SIP2_HDR_LEN 7
1143 /* Store the info needed by the SIP tap for one packet */
1144 static sip_info_value_t
*stat_info
;
1146 /* The buffer size for the cseq_method name */
1147 #define MAX_CSEQ_METHOD_SIZE 16
1149 /****************************************************************************
1150 * Conversation-type definitions
1152 * For each call, keep track of the current cseq number and state of
1153 * transaction, in order to be able to detect retransmissions.
1155 * Don't use the conversation mechanism, but instead:
1156 * - store with each dissected packet original frame (if any)
1157 * - maintain a global hash table of
1158 * (call_id, source_addr, dest_addr) -> (cseq, transaction_state, frame)
1160 * N.B. This is broken for a couple of reasons:
1161 * - it won't cope properly with overlapping transactions within the
1163 * - request response mapping won't work where the response uses a different
1164 * address pair from the request
1166 * TODO: proper transaction matching uses RFC fields (use Max-forwards or
1167 * maybe Via count as extra key to limit view to one hop)
1168 ****************************************************************************/
1170 static GHashTable
*sip_hash
; /* Hash table */
1171 static GHashTable
*sip_headers_hash
; /* Hash table */
1173 /* Types for hash table keys and values */
1174 #define MAX_CALL_ID_SIZE 128
1175 #define MAGIC_SOURCE_PORT 0
1177 /* Conversation-type key */
1180 char call_id
[MAX_CALL_ID_SIZE
];
1181 address source_address
;
1182 uint32_t source_port
;
1183 address dest_address
;
1193 provisional_response_seen
,
1195 } transaction_state_t
;
1197 /* Current conversation-type value */
1201 transaction_state_t transaction_state
;
1203 nstime_t request_time
;
1204 uint32_t response_code
;
1208 /* Result to be stored in per-packet info */
1211 int original_frame_num
;
1212 int response_request_frame_num
;
1214 } sip_frame_result_value
;
1217 /************************/
1218 /* Hash table functions */
1221 static int sip_equal(const void *v
, const void *v2
)
1223 const sip_hash_key
* val1
= (const sip_hash_key
*)v
;
1224 const sip_hash_key
* val2
= (const sip_hash_key
*)v2
;
1226 /* Call id must match */
1227 if (strcmp(val1
->call_id
, val2
->call_id
) != 0)
1232 /* Addresses must match */
1233 return (addresses_equal(&(val1
->source_address
), &(val2
->source_address
))) &&
1234 (val1
->source_port
== val2
->source_port
) &&
1235 (addresses_equal(&(val1
->dest_address
), &(val2
->dest_address
))) &&
1236 (val1
->dest_port
== val2
->dest_port
) &&
1237 (val1
->ptype
== val2
->ptype
);
1241 /* Initializes the hash table each time a new
1242 * file is loaded or re-loaded in wireshark */
1244 sip_init_protocol(void)
1248 sip_hash
= g_hash_table_new(g_str_hash
, sip_equal
);
1250 /* Hash table for quick lookup of SIP headers names to hf entry (POS_x) */
1251 sip_headers_hash
= g_hash_table_new(g_str_hash
, g_str_equal
);
1252 for (i
= 1; i
< array_length(sip_headers
); i
++){
1253 value_copy
= wmem_strdup(wmem_file_scope(), sip_headers
[i
].name
);
1254 ascii_strdown_inplace(value_copy
);
1255 g_hash_table_insert(sip_headers_hash
, (void *)value_copy
, GINT_TO_POINTER(i
));
1260 sip_cleanup_protocol(void)
1262 g_hash_table_destroy(sip_hash
);
1263 g_hash_table_destroy(sip_headers_hash
);
1266 /* Call the export PDU tap with relevant data */
1268 export_sip_pdu(packet_info
*pinfo
, tvbuff_t
*tvb
)
1270 exp_pdu_data_t
*exp_pdu_data
= export_pdu_create_common_tags(pinfo
, "sip", EXP_PDU_TAG_DISSECTOR_NAME
);
1272 exp_pdu_data
->tvb_captured_length
= tvb_captured_length(tvb
);
1273 exp_pdu_data
->tvb_reported_length
= tvb_reported_length(tvb
);
1274 exp_pdu_data
->pdu_tvb
= tvb
;
1276 tap_queue_packet(exported_pdu_tap
, pinfo
, exp_pdu_data
);
1282 SIP_URI_TYPE_ABSOLUTE_URI
,
1286 } sip_uri_type_enum_t
;
1288 /* Structure to collect info about a sip uri */
1289 typedef struct _uri_offset_info
1291 sip_uri_type_enum_t uri_type
;
1292 int display_name_start
;
1293 int display_name_end
;
1296 int uri_parameters_start
;
1297 int uri_parameters_end
;
1298 int name_addr_start
;
1304 int uri_host_port_start
;
1305 int uri_host_port_end
;
1309 sip_uri_offset_init(uri_offset_info
*uri_offsets
){
1311 /* Initialize the uri_offsets */
1312 uri_offsets
->uri_type
= SIP_URI_TYPE_ABSOLUTE_URI
;
1313 uri_offsets
->display_name_start
= -1;
1314 uri_offsets
->display_name_end
= -1;
1315 uri_offsets
->uri_start
= -1;
1316 uri_offsets
->uri_end
= -1;
1317 uri_offsets
->uri_parameters_start
= -1;
1318 uri_offsets
->uri_parameters_end
= -1;
1319 uri_offsets
->name_addr_start
= -1;
1320 uri_offsets
->name_addr_end
= -1;
1321 uri_offsets
->uri_user_start
= -1;
1322 uri_offsets
->uri_user_end
= -1;
1323 uri_offsets
->uri_host_start
= -1;
1324 uri_offsets
->uri_host_end
= -1;
1325 uri_offsets
->uri_host_port_start
= -1;
1326 uri_offsets
->uri_host_port_end
= -1;
1329 /* Code to parse a sip uri.
1330 * Returns Offset end off parsing or -1 for unsuccessful parsing
1331 * - sip_uri_offset_init() must have been called first.
1334 dissect_sip_uri(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, int start_offset
,
1335 int line_end_offset
, uri_offset_info
*uri_offsets
)
1337 unsigned char c
= '\0';
1340 int parameter_end_offset
;
1341 bool in_ipv6
= false;
1343 /* skip Spaces and Tabs */
1344 current_offset
= tvb_skip_wsp(tvb
, start_offset
, line_end_offset
- start_offset
);
1346 if(current_offset
>= line_end_offset
) {
1347 /* Nothing to parse */
1350 /* Set uri start offset in case this was called directly */
1351 uri_offsets
->uri_start
= current_offset
;
1353 /* Check if it's really a sip uri ( it might be a tel uri, parse that?) */
1354 if (tvb_strneql(tvb
, current_offset
, "sip", 3) != 0){
1355 if (uri_offsets
->uri_end
!= -1) {
1356 /* We know where the URI ends, set the offsets*/
1357 return uri_offsets
->name_addr_end
;
1362 uri_offsets
->uri_type
= SIP_URI_TYPE_SIP
;
1364 if(uri_offsets
->uri_end
== -1)
1366 /* name-addr form was NOT used e.g no closing ">" */
1367 /* look for the first ',' or ';' which will mark the end of this URI
1368 * In this case a semicolon indicates a header field parameter, and not an uri parameter.
1372 end_offset
= tvb_ws_mempbrk_pattern_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, &pbrk_comma_semi
, NULL
);
1374 if (end_offset
!= -1)
1376 uri_offsets
->uri_end
= end_offset
- 1;
1380 /* We don't have a semicolon or a comma.
1381 * In that case, we assume that the end of the URI is at the line end
1383 uri_offsets
->uri_end
= line_end_offset
- 3; /* remove '\r\n' */
1385 uri_offsets
->name_addr_end
= uri_offsets
->uri_end
;
1388 /* Look for URI address parts (user, host, host-port) */
1390 /* Look for '@' within URI */
1391 queried_offset
= tvb_find_uint8(tvb
, uri_offsets
->uri_start
, uri_offsets
->uri_end
- uri_offsets
->uri_start
, '@');
1392 if(queried_offset
== -1)
1394 /* no '@' = no user part */
1395 uri_offsets
->uri_host_start
= tvb_find_uint8(tvb
, uri_offsets
->uri_start
, uri_offsets
->uri_end
- uri_offsets
->uri_start
, ':')+1;
1399 /* with '@' = with user part */
1400 uri_offsets
->uri_user_start
= tvb_find_uint8(tvb
, uri_offsets
->uri_start
, uri_offsets
->uri_end
- uri_offsets
->uri_start
, ':')+1;
1401 uri_offsets
->uri_user_end
= tvb_find_uint8(tvb
, uri_offsets
->uri_user_start
, uri_offsets
->uri_end
- uri_offsets
->uri_start
, '@')-1;
1402 uri_offsets
->uri_host_start
= uri_offsets
->uri_user_end
+ 2;
1405 /* find URI-Host end*/
1406 parameter_end_offset
= uri_offsets
->uri_host_start
;
1408 in_ipv6
= (tvb_get_uint8(tvb
, parameter_end_offset
) == '[');
1409 while (parameter_end_offset
< line_end_offset
)
1411 parameter_end_offset
++;
1412 parameter_end_offset
= tvb_ws_mempbrk_pattern_uint8(tvb
, parameter_end_offset
, line_end_offset
- parameter_end_offset
, &pbrk_param_end_colon_brackets
, &c
);
1413 if (parameter_end_offset
== -1)
1415 parameter_end_offset
= line_end_offset
;
1419 /* after adding character to this switch() , update also pbrk_param_end_colon_brackets */
1423 goto uri_host_end_found
;
1425 uri_offsets
->uri_parameters_start
= parameter_end_offset
+ 1;
1426 goto uri_host_end_found
;
1430 goto uri_host_end_found
;
1433 goto uri_host_end_found
;
1442 DISSECTOR_ASSERT_NOT_REACHED();
1449 uri_offsets
->uri_host_end
= parameter_end_offset
- 1;
1453 uri_offsets
->uri_host_port_start
= parameter_end_offset
+ 1;
1454 parameter_end_offset
= uri_offsets
->uri_host_port_start
;
1455 while (parameter_end_offset
< line_end_offset
)
1457 parameter_end_offset
++;
1458 parameter_end_offset
= tvb_ws_mempbrk_pattern_uint8(tvb
, parameter_end_offset
, line_end_offset
- parameter_end_offset
, &pbrk_param_end
, &c
);
1459 if (parameter_end_offset
== -1)
1461 parameter_end_offset
= line_end_offset
;
1465 /* after adding character to this switch(), update also pbrk_param_end */
1469 goto uri_host_port_end_found
;
1471 uri_offsets
->uri_parameters_start
= parameter_end_offset
+ 1;
1472 goto uri_host_port_end_found
;
1476 goto uri_host_port_end_found
;
1478 DISSECTOR_ASSERT_NOT_REACHED();
1483 uri_host_port_end_found
:
1485 uri_offsets
->uri_host_port_end
= parameter_end_offset
-1;
1488 return uri_offsets
->name_addr_end
;
1492 dfilter_store_sip_from_addr(tvbuff_t
*tvb
,proto_tree
*tree
,unsigned parameter_offset
, unsigned parameter_len
)
1496 pi
= proto_tree_add_item(tree
, hf_sip_from_addr
, tvb
, parameter_offset
, parameter_len
, ENC_UTF_8
);
1497 proto_item_set_generated(pi
);
1501 sip_proto_tree_add_uint(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
, int length
, int value_offset
, int value_len
)
1506 /* don't fetch string when field is not referenced */
1507 if (!proto_field_is_referenced(tree
, hfindex
))
1510 str
= tvb_get_string_enc(wmem_packet_scope(), tvb
, value_offset
, value_len
, ENC_UTF_8
|ENC_NA
);
1511 val
= strtoul(str
, NULL
, 10);
1513 return proto_tree_add_uint(tree
, hfindex
, tvb
, start
, length
, (uint32_t) val
);
1517 sip_proto_tree_add_string(proto_tree
*tree
, int hfindex
, tvbuff_t
*tvb
, int start
, int length
, int value_offset
, int value_len
)
1521 /* don't fetch string when field is not referenced */
1522 if (!proto_field_is_referenced(tree
, hfindex
))
1525 str
= tvb_get_string_enc(wmem_packet_scope(), tvb
, value_offset
, value_len
, ENC_UTF_8
|ENC_NA
);
1527 return proto_tree_add_string(tree
, hfindex
, tvb
, start
, length
, str
);
1531 sip_proto_set_format_text(const proto_tree
*tree
, proto_item
*item
, tvbuff_t
*tvb
, int offset
, int length
)
1533 if (tree
!= item
&& item
&& PTREE_DATA(item
)->visible
)
1534 proto_item_set_text(item
, "%s", tvb_format_text(wmem_packet_scope(), tvb
, offset
, length
));
1537 * XXXX If/when more parameters are added consider doing something similar to what's done in
1538 * packet-magaco.c for find_megaco_localParam_names() possibly adding the hf to the array and have a generic
1539 * dissection function here.
1542 dissect_sip_generic_parameters(tvbuff_t
*tvb
, proto_tree
* tree
, packet_info
*pinfo
, int current_offset
, int line_end_offset
)
1544 int semi_colon_offset
, par_name_end_offset
, equals_offset
, length
;
1545 /* Loop over the generic parameter(s)*/
1546 while (current_offset
< line_end_offset
) {
1547 char *param_name
= NULL
;
1549 /* skip Spaces and Tabs */
1550 current_offset
= tvb_skip_wsp(tvb
, current_offset
, line_end_offset
- current_offset
);
1552 semi_colon_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, ';');
1554 if (semi_colon_offset
== -1) {
1555 semi_colon_offset
= line_end_offset
;
1558 length
= semi_colon_offset
- current_offset
;
1560 /* Parse parameter and value */
1561 equals_offset
= tvb_find_uint8(tvb
, current_offset
+ 1, length
, '=');
1562 if (equals_offset
!= -1) {
1563 /* Has value part */
1564 par_name_end_offset
= equals_offset
;
1565 /* Extract the parameter name */
1566 param_name
= tvb_get_string_enc(pinfo
->pool
, tvb
, current_offset
, par_name_end_offset
- current_offset
, ENC_UTF_8
| ENC_NA
);
1567 /* Access-Info fields */
1568 if ((param_name
!= NULL
) && (g_ascii_strcasecmp(param_name
, "service-priority") == 0)) {
1569 proto_tree_add_item(tree
, hf_sip_service_priority
, tvb
,
1570 equals_offset
+ 1, semi_colon_offset
- equals_offset
- 1, ENC_UTF_8
| ENC_NA
);
1573 proto_tree_add_format_text(tree
, tvb
, current_offset
, length
);
1577 proto_tree_add_format_text(tree
, tvb
, current_offset
, length
);
1579 current_offset
= semi_colon_offset
+ 1;
1585 * History-Info = "History-Info" HCOLON
1586 * hi-entry *(COMMA hi-entry)
1588 * hi-entry = hi-targeted-to-uri *( SEMI hi-param )
1589 * hi-targeted-to-uri= name-addr
1592 * hi-param = hi-index / hi-extension
1594 * hi-index = "index" EQUAL 1*DIGIT *(DOT 1*DIGIT)
1596 * hi-extension = generic-param
1600 dissect_sip_history_info(tvbuff_t
*tvb
, proto_tree
* tree
, packet_info
*pinfo _U_
, int current_offset
,
1601 int line_end_offset
)
1604 bool first_time
= true;
1606 /* split the line at the commas */
1607 while (line_end_offset
> current_offset
){
1608 comma_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, ',');
1609 if(comma_offset
== -1){
1610 if(first_time
== true){
1611 /* It was only on parameter no need to split it up */
1612 return line_end_offset
;
1614 /* Last parameter */
1615 comma_offset
= line_end_offset
;
1618 proto_tree_add_format_text(tree
, tvb
, current_offset
, comma_offset
-current_offset
);
1620 current_offset
= comma_offset
+1;
1623 return line_end_offset
;
1629 * The syntax for the P-Charging-Function-Addresses header is described
1632 * P-Charging-Addr = "P-Charging-Function-Addresses" HCOLON
1633 * charge-addr-params
1634 * *(SEMI charge-addr-params)
1635 * charge-addr-params = ccf / ecf / generic-param
1636 * ccf = "ccf" EQUAL gen-value
1637 * ecf = "ecf" EQUAL gen-value
1638 * generic-param = token [ EQUAL gen-value ]
1639 * gen-value = token / host / quoted-string
1644 dissect_sip_p_charging_func_addresses(tvbuff_t
*tvb
, proto_tree
* tree
, packet_info
*pinfo _U_
, int current_offset
,
1645 int line_end_offset
)
1647 int semi_offset
, start_quote_offset
, end_quote_offset
;
1648 bool first_time
= true;
1650 while (line_end_offset
> current_offset
){
1651 /* Do we have a quoted string ? */
1652 start_quote_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, '"');
1653 if(start_quote_offset
>0){
1654 /* Find end of quoted string */
1655 end_quote_offset
= tvb_find_uint8(tvb
, start_quote_offset
+1, line_end_offset
- (start_quote_offset
+1), '"');
1656 /* Find parameter end */
1657 if (end_quote_offset
>0)
1658 semi_offset
= tvb_find_uint8(tvb
, end_quote_offset
+1, line_end_offset
- (end_quote_offset
+1), ';');
1660 /* XXX expert info about unterminated string */
1661 semi_offset
= tvb_find_uint8(tvb
, start_quote_offset
+1, line_end_offset
- (start_quote_offset
+1), ';');
1664 /* Find parameter end */
1665 semi_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, ';');
1667 if(semi_offset
== -1){
1668 if(first_time
== true){
1669 /* It was only one parameter no need to split it up */
1670 return line_end_offset
;
1672 /* Last parameter */
1673 semi_offset
= line_end_offset
;
1676 proto_tree_add_format_text(tree
, tvb
, current_offset
, semi_offset
-current_offset
);
1678 current_offset
= semi_offset
+1;
1682 return current_offset
;
1686 * token = 1*(alphanum / "-" / "." / "!" / "%" / "*"
1687 * / "_" / "+" / "`" / "'" / "~" )
1688 * LWS = [*WSP CRLF] 1*WSP ; linear whitespace
1689 * name-addr = [ display-name ] LAQUOT addr-spec RAQUOT
1690 * addr-spec = SIP-URI / SIPS-URI / absoluteURI
1691 * display-name = *(token LWS)/ quoted-string
1692 * absoluteURI = scheme ":" ( hier-part / opaque-part )
1696 dissect_sip_name_addr_or_addr_spec(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, int start_offset
,
1697 int line_end_offset
, uri_offset_info
*uri_offsets
)
1704 bool uri_without_angle_quotes
= false;
1706 /* skip Spaces and Tabs */
1707 current_offset
= tvb_skip_wsp(tvb
, start_offset
, line_end_offset
- start_offset
);
1709 if(current_offset
>= line_end_offset
) {
1710 /* Nothing to parse */
1714 uri_offsets
->name_addr_start
= current_offset
;
1716 /* First look, if we have a display name */
1717 c
=tvb_get_uint8(tvb
, current_offset
);
1721 /* We have a display name, look for the next unescaped '"' */
1722 uri_offsets
->display_name_start
= current_offset
;
1725 queried_offset
= tvb_find_uint8(tvb
, current_offset
+ 1, line_end_offset
- (current_offset
+ 1), '"');
1726 if(queried_offset
== -1)
1731 current_offset
= queried_offset
;
1733 /* Is it escaped? */
1734 /* count back slashes before '"' */
1735 for(i
=1;tvb_get_uint8(tvb
, queried_offset
- i
) == '\\';i
++);
1743 } while (current_offset
< line_end_offset
);
1744 if(current_offset
>= line_end_offset
)
1750 uri_offsets
->display_name_end
= current_offset
;
1752 /* find start of the URI */
1753 queried_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, '<');
1754 if(queried_offset
== -1)
1759 current_offset
= queried_offset
+ 1;
1763 /* We don't have a display name */
1768 /* We have either an URI without angles or a display name with a limited character set */
1769 /* Look for the right angle quote or colon */
1770 queried_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, '<');
1771 colon_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, ':');
1772 if(queried_offset
!= -1 && colon_offset
!= -1)
1774 if(queried_offset
< colon_offset
)
1776 /* we have an URI with angle quotes */
1777 uri_offsets
->display_name_start
= current_offset
;
1778 uri_offsets
->display_name_end
= queried_offset
- 1;
1779 current_offset
= queried_offset
+ 1;
1783 /* we have an URI without angle quotes */
1784 uri_without_angle_quotes
= true;
1789 if(queried_offset
!= -1)
1791 /* we have an URI with angle quotes */
1792 uri_offsets
->display_name_start
= current_offset
;
1793 uri_offsets
->display_name_end
= queried_offset
- 1;
1794 current_offset
= queried_offset
+ 1;
1797 if(colon_offset
!= -1)
1799 /* we have an URI without angle quotes */
1800 uri_without_angle_quotes
= true;
1803 /* If this point is reached, we can't parse the URI */
1809 uri_offsets
->uri_start
= current_offset
;
1810 if(uri_without_angle_quotes
==false){
1811 /* name-addr form was used */
1812 /* look for closing angle quote */
1813 queried_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, '>');
1814 if(queried_offset
== -1)
1819 uri_offsets
->name_addr_end
= queried_offset
;
1820 uri_offsets
->uri_end
= queried_offset
- 1;
1822 return dissect_sip_uri(tvb
, pinfo
, current_offset
, line_end_offset
, uri_offsets
);
1827 * Code to add dissected SIP URI Information to proto tree
1831 display_sip_uri (tvbuff_t
*tvb
, proto_tree
*sip_element_tree
, packet_info
*pinfo
, uri_offset_info
* uri_offsets
, hf_sip_uri_t
* uri
)
1834 proto_tree
*uri_item_tree
= NULL
;
1837 if(uri_offsets
->display_name_end
!= uri_offsets
->display_name_start
) {
1838 proto_tree_add_item(sip_element_tree
, *(uri
->hf_sip_display
), tvb
, uri_offsets
->display_name_start
,
1839 uri_offsets
->display_name_end
- uri_offsets
->display_name_start
+ 1, ENC_UTF_8
|ENC_NA
);
1840 ti
= proto_tree_add_item(sip_element_tree
, hf_sip_display
, tvb
, uri_offsets
->display_name_start
,
1841 uri_offsets
->display_name_end
- uri_offsets
->display_name_start
+ 1, ENC_UTF_8
);
1842 proto_item_set_hidden(ti
);
1845 ti
= proto_tree_add_item(sip_element_tree
, *(uri
->hf_sip_addr
),
1846 tvb
, uri_offsets
->uri_start
, uri_offsets
->uri_end
- uri_offsets
->uri_start
+ 1, ENC_UTF_8
|ENC_NA
);
1847 uri_item_tree
= proto_item_add_subtree(ti
, *(uri
->ett_uri
));
1849 if (uri_offsets
->uri_type
!= SIP_URI_TYPE_SIP
) {
1853 if(uri_offsets
->uri_user_end
> uri_offsets
->uri_user_start
) {
1854 proto_tree_add_item(uri_item_tree
, *(uri
->hf_sip_user
), tvb
, uri_offsets
->uri_user_start
,
1855 uri_offsets
->uri_user_end
- uri_offsets
->uri_user_start
+ 1, ENC_UTF_8
|ENC_NA
);
1856 if (tvb_get_uint8(tvb
, uri_offsets
->uri_user_start
) == '+') {
1857 dissect_e164_msisdn(tvb
, uri_item_tree
, uri_offsets
->uri_user_start
+ 1, uri_offsets
->uri_user_end
- uri_offsets
->uri_user_start
, E164_ENC_UTF8
);
1860 /* If we have a SIP diagnostics sub dissector call it */
1861 if (sip_uri_userinfo_handle
) {
1862 next_tvb
= tvb_new_subset_length(tvb
, uri_offsets
->uri_user_start
,
1863 uri_offsets
->uri_user_end
- uri_offsets
->uri_user_start
+ 1);
1864 call_dissector(sip_uri_userinfo_handle
, next_tvb
, pinfo
, uri_item_tree
);
1869 proto_tree_add_item(uri_item_tree
, *(uri
->hf_sip_host
), tvb
, uri_offsets
->uri_host_start
,
1870 uri_offsets
->uri_host_end
- uri_offsets
->uri_host_start
+ 1, ENC_UTF_8
|ENC_NA
);
1872 if(uri_offsets
->uri_host_port_end
> uri_offsets
->uri_host_port_start
) {
1873 proto_tree_add_item(uri_item_tree
, *(uri
->hf_sip_port
), tvb
, uri_offsets
->uri_host_port_start
,
1874 uri_offsets
->uri_host_port_end
- uri_offsets
->uri_host_port_start
+ 1, ENC_UTF_8
|ENC_NA
);
1877 if (uri_offsets
->uri_parameters_start
!= -1) {
1878 /* Move current offset to the start of the first param */
1879 int current_offset
= uri_offsets
->uri_parameters_start
;
1880 int uri_params_start_offset
= current_offset
;
1882 int uri_param_end_offset
= -1;
1885 /* Put the contact parameters in the tree */
1887 while (current_offset
< uri_offsets
->name_addr_end
) {
1888 queried_offset
= tvb_ws_mempbrk_pattern_uint8(tvb
, current_offset
, uri_offsets
->name_addr_end
- current_offset
, &pbrk_comma_semi
, &c
);
1890 if (queried_offset
== -1) {
1891 /* Reached line end */
1892 /* Check if the line ends with a ">", if so decrement end offset. */
1893 c
= tvb_get_uint8(tvb
, uri_offsets
->name_addr_end
);
1896 uri_param_end_offset
= uri_offsets
->name_addr_end
- 1;
1898 uri_param_end_offset
= uri_offsets
->name_addr_end
;
1900 current_offset
= uri_offsets
->name_addr_end
;
1901 } else if (c
==',') {
1902 uri_param_end_offset
= queried_offset
;
1903 current_offset
= queried_offset
+1; /* must move forward */
1904 } else if (c
==';') {
1905 /* More parameters */
1906 uri_param_end_offset
= queried_offset
-1;
1907 current_offset
= tvb_skip_wsp(tvb
, queried_offset
+1, uri_offsets
->name_addr_end
- queried_offset
+ 1);
1910 proto_tree_add_item(uri_item_tree
, *(uri
->hf_sip_param
), tvb
, uri_params_start_offset
,
1911 uri_param_end_offset
- uri_params_start_offset
+1, ENC_UTF_8
|ENC_NA
);
1913 /* In case there are more parameters, point to the start of it */
1914 uri_params_start_offset
= current_offset
;
1918 return uri_item_tree
;
1924 /* Code to parse a contact header item
1925 * Returns Offset end off parsing or -1 for unsuccessful parsing
1926 * * contact-param = (name-addr / addr-spec) *(SEMI contact-params)
1929 dissect_sip_contact_item(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int start_offset
, int line_end_offset
,
1930 unsigned char* contacts_expires_0
, unsigned char* contacts_expires_unknown
)
1935 int contact_params_start_offset
= -1;
1936 /*int contact_param_end_offset = -1;*/
1937 uri_offset_info uri_offsets
;
1938 bool end_of_hdr
= false;
1939 bool has_expires_param
= false;
1941 /* skip Spaces and Tabs */
1942 start_offset
= tvb_skip_wsp(tvb
, start_offset
, line_end_offset
- start_offset
);
1944 if(start_offset
>= line_end_offset
) {
1945 /* Nothing to parse */
1949 /* Initialize the uri_offsets */
1950 sip_uri_offset_init(&uri_offsets
);
1951 /* contact-param = (name-addr / addr-spec) *(SEMI contact-params) */
1952 current_offset
= dissect_sip_name_addr_or_addr_spec(tvb
, pinfo
, start_offset
, line_end_offset
, &uri_offsets
);
1953 if(current_offset
== -1)
1955 /* Parsing failed */
1958 display_sip_uri(tvb
, tree
, pinfo
, &uri_offsets
, &sip_contact_uri
);
1960 /* check if there's a comma before a ';', in which case we stop parsing this item at the comma */
1961 queried_offset
= tvb_find_uint8(tvb
, uri_offsets
.uri_end
, line_end_offset
- uri_offsets
.uri_end
, ',');
1963 /* Check if we have contact parameters, the uri should be followed by a ';' */
1964 contact_params_start_offset
= tvb_find_uint8(tvb
, uri_offsets
.uri_end
, line_end_offset
- uri_offsets
.uri_end
, ';');
1966 if (queried_offset
!= -1 && (queried_offset
< contact_params_start_offset
|| contact_params_start_offset
== -1)) {
1967 /* no expires param */
1968 (*contacts_expires_unknown
)++;
1969 return queried_offset
;
1972 /* check if contact-params is present */
1973 if(contact_params_start_offset
== -1) {
1974 /* no expires param */
1975 (*contacts_expires_unknown
)++;
1976 return line_end_offset
;
1979 /* Move current offset to the start of the first param */
1980 contact_params_start_offset
++;
1981 current_offset
= contact_params_start_offset
;
1983 /* Put the contact parameters in the tree */
1985 queried_offset
= current_offset
;
1987 while(current_offset
< line_end_offset
){
1990 queried_offset
= (queried_offset
< line_end_offset
) ? tvb_ws_mempbrk_pattern_uint8(tvb
, queried_offset
, line_end_offset
- queried_offset
, &pbrk_header_end_dquote
, &c
) : -1;
1991 if (queried_offset
!= -1)
1994 /* prevent tree from displaying the '\r\n' as part of the param */
2004 DISSECTOR_ASSERT_NOT_REACHED();
2009 if (queried_offset
== -1) {
2010 /* Last parameter, line end */
2011 current_offset
= line_end_offset
;
2013 /* Do we have a quoted string ? */
2014 queried_offset
= tvb_find_uint8(tvb
, queried_offset
+1, line_end_offset
- queried_offset
, '"');
2015 if(queried_offset
==-1){
2016 /* We have an opening quote but no closing quote. */
2017 current_offset
= line_end_offset
;
2019 current_offset
= tvb_ws_mempbrk_pattern_uint8(tvb
, queried_offset
+1, line_end_offset
- queried_offset
, &pbrk_comma_semi
, &c
);
2020 if(current_offset
==-1){
2021 /* Last parameter, line end */
2022 current_offset
= line_end_offset
;
2026 current_offset
= queried_offset
;
2028 proto_tree_add_item(tree
, hf_sip_contact_param
, tvb
, contact_params_start_offset
,
2029 current_offset
- contact_params_start_offset
, ENC_UTF_8
);
2031 /* need to check for an 'expires' parameter
2032 * TODO: this should be done in a common way for all headers,
2033 * but To/From/etc do their own right now so doing the same here
2035 /* also, this is a bad way of checking param names, but it's what To/From
2036 * etc, do. But legally "exPiRes = value" is also legit.
2038 if (tvb_strncaseeql(tvb
, contact_params_start_offset
, "expires=", 8) == 0) {
2040 /* if the expires param value is 0, then it's de-registering
2041 * this assumes the message is a REGISTER request/response, but these
2042 * contacts_expires_0/contacts_expires_unknown variables only get used then,
2045 if (!ws_strtoi32(tvb_get_string_enc(pinfo
->pool
, tvb
, contact_params_start_offset
+8,
2046 current_offset
- (contact_params_start_offset
+8), ENC_UTF_8
|ENC_NA
), NULL
, &expire
))
2047 return contact_params_start_offset
+8;
2048 has_expires_param
= true;
2050 (*contacts_expires_0
)++;
2051 /* RFC 3261 10.3 "Processing REGISTER requests":
2052 * "The registrar returns a 200 (OK) response. The response
2053 * MUST contain Contact header field values enumerating all
2054 * current bindings."
2055 * This implies it is invalid for the response to contain the
2056 * deregistered, no longer current, Contacts with expires=0.
2057 * However, this warning was removed due to 3GPP usage.
2058 * Cf. 3GPP TS 24.229 "5.4.1.4 User-initiated deregistration":
2059 * "send a 200 (OK) response to a REGISTER request that
2060 * contains a list of Contact header fields enumerating all
2061 * contacts and flows that are currently registered, and all
2062 * contacts that have been deregistered."
2063 * https://gitlab.com/wireshark/wireshark/-/issues/10364
2066 if (stat_info
&& stat_info
->response_code
> 199 && stat_info
->response_code
< 300) {
2067 proto_tree_add_expert_format(tree
, pinfo
, &ei_sip_odd_register_response
,
2068 tvb
, contact_params_start_offset
, current_offset
- contact_params_start_offset
,
2069 "SIP REGISTER %d response contains Contact with expires=0",
2070 stat_info
->response_code
);
2076 /* In case there are more parameters, point to the start of it */
2077 contact_params_start_offset
= current_offset
+1;
2078 queried_offset
= contact_params_start_offset
;
2080 /* '\r' or '\n' found, stop parsing and also set current offset to end
2081 * so the return value indicates we reached line end
2083 current_offset
= line_end_offset
;
2086 /* comma separator found, stop parsing of current contact-param here */
2091 if (!has_expires_param
) {
2092 (*contacts_expires_unknown
)++;
2095 return current_offset
;
2098 /* Code to parse an authorization header item
2099 * Returns offset at end of parsing, or -1 for unsuccessful parsing
2102 dissect_sip_authorization_item(tvbuff_t
*tvb
, proto_tree
*tree
, int start_offset
, int line_end_offset
, sip_authorization_t
*authorization_info
)
2104 int current_offset
, par_name_end_offset
, queried_offset
, value_offset
, value_search_offset
;
2105 int equals_offset
= 0;
2107 header_parameter_t
*auth_parameter
;
2110 /* skip Spaces and Tabs */
2111 start_offset
= tvb_skip_wsp(tvb
, start_offset
, line_end_offset
- start_offset
);
2113 if (start_offset
>= line_end_offset
)
2115 /* Nothing to parse */
2119 current_offset
= start_offset
;
2120 equals_offset
= tvb_find_uint8(tvb
, current_offset
+ 1, line_end_offset
- (current_offset
+ 1), '=');
2121 if(equals_offset
== -1){
2122 /* malformed parameter */
2125 par_name_end_offset
= equals_offset
- 1;
2126 par_name_end_offset
= tvb_skip_wsp_return(tvb
,par_name_end_offset
);
2128 /* Extract the parameter name */
2129 name
= tvb_get_string_enc(wmem_packet_scope(), tvb
, start_offset
, par_name_end_offset
-start_offset
, ENC_UTF_8
|ENC_NA
);
2131 value_offset
= tvb_skip_wsp(tvb
, equals_offset
+ 1, line_end_offset
- (equals_offset
+ 1));
2132 if (tvb_get_uint8(tvb
, value_offset
) == '\"') {
2134 value_search_offset
= value_offset
;
2136 value_search_offset
++;
2137 queried_offset
= tvb_find_uint8 (tvb
, value_search_offset
, line_end_offset
- value_search_offset
, '\"');
2138 } while ((queried_offset
!= -1) && (tvb_get_uint8(tvb
, queried_offset
- 1) == '\\'));
2139 if (queried_offset
== -1) {
2140 /* Closing quote not found, return line end */
2141 current_offset
= line_end_offset
;
2143 /* Include closing quotes */
2144 current_offset
= queried_offset
+ 1;
2147 /* unquoted value */
2148 queried_offset
= tvb_find_uint8 (tvb
, value_offset
, line_end_offset
- value_offset
, ',');
2149 if (queried_offset
== -1) {
2150 /* Last parameter, line end */
2151 current_offset
= line_end_offset
;
2153 current_offset
= queried_offset
;
2157 /* Try to add parameter as a filterable item */
2158 for (auth_parameter
= &auth_parameters_hf_array
[i
];
2159 i
< array_length(auth_parameters_hf_array
);
2160 i
++, auth_parameter
++)
2162 if (g_ascii_strcasecmp(name
, auth_parameter
->param_name
) == 0)
2164 proto_tree_add_item(tree
, *(auth_parameter
->hf_item
), tvb
,
2165 value_offset
, current_offset
- value_offset
,
2167 if (global_sip_validate_authorization
) {
2168 int real_value_offset
= value_offset
;
2169 int real_value_length
= current_offset
- value_offset
;
2170 if ((tvb_get_uint8(tvb
, value_offset
) == '\"') && (tvb_get_uint8(tvb
, current_offset
- 1) == '\"') && (real_value_length
> 1)) {
2171 real_value_offset
++;
2172 real_value_length
-= 2;
2174 if (g_ascii_strcasecmp(name
, "response") == 0) {
2175 authorization_info
->response
= tvb_get_string_enc(wmem_packet_scope(), tvb
, real_value_offset
, real_value_length
, ENC_ASCII
);
2176 } else if (g_ascii_strcasecmp(name
, "nc") == 0) {
2177 authorization_info
->nonce_count
= tvb_get_string_enc(wmem_packet_scope(), tvb
, real_value_offset
, real_value_length
, ENC_ASCII
);
2178 } else if (g_ascii_strcasecmp(name
, "username") == 0) {
2179 authorization_info
->username
= tvb_get_string_enc(wmem_packet_scope(), tvb
, real_value_offset
, real_value_length
, ENC_ASCII
);
2180 } else if (g_ascii_strcasecmp(name
, "realm") == 0) {
2181 authorization_info
->realm
= tvb_get_string_enc(wmem_packet_scope(), tvb
, real_value_offset
, real_value_length
, ENC_ASCII
);
2182 } else if (g_ascii_strcasecmp(name
, "algorithm") == 0) {
2183 authorization_info
->algorithm
= tvb_get_string_enc(wmem_packet_scope(), tvb
, real_value_offset
, real_value_length
, ENC_ASCII
);
2184 } else if (g_ascii_strcasecmp(name
, "nonce") == 0) {
2185 authorization_info
->nonce
= tvb_get_string_enc(wmem_packet_scope(), tvb
, real_value_offset
, real_value_length
, ENC_ASCII
);
2186 } else if (g_ascii_strcasecmp(name
, "qop") == 0) {
2187 authorization_info
->qop
= tvb_get_string_enc(wmem_packet_scope(), tvb
, real_value_offset
, real_value_length
, ENC_ASCII
);
2188 } else if (g_ascii_strcasecmp(name
, "cnonce") == 0) {
2189 authorization_info
->cnonce
= tvb_get_string_enc(wmem_packet_scope(), tvb
, real_value_offset
, real_value_length
, ENC_ASCII
);
2190 } else if (g_ascii_strcasecmp(name
, "uri") == 0) {
2191 authorization_info
->uri
= tvb_get_string_enc(wmem_packet_scope(), tvb
, real_value_offset
, real_value_length
, ENC_ASCII
);
2198 /* If not matched, just add as text... */
2199 if (i
== array_length(auth_parameters_hf_array
))
2201 proto_tree_add_format_text(tree
, tvb
, start_offset
, current_offset
-start_offset
);
2204 /* Find comma/end of line */
2205 queried_offset
= tvb_find_uint8 (tvb
, current_offset
, line_end_offset
- current_offset
, ',');
2206 if (queried_offset
== -1) {
2207 current_offset
= line_end_offset
;
2209 current_offset
= queried_offset
;
2211 return current_offset
;
2214 /* Dissect the details of a Reason header
2215 * Reason = "Reason" HCOLON reason-value *(COMMA reason-value)
2216 * reason-value = protocol *(SEMI reason-params)
2217 * protocol = "SIP" / "Q.850" / token
2218 * reason-params = protocol-cause / reason-text / reason-extension
2219 * protocol-cause = "cause" EQUAL cause
2221 * reason-text = "text" EQUAL quoted-string
2222 * reason-extension = generic-param
2225 dissect_sip_reason_header(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, int start_offset
, int line_end_offset
){
2227 int current_offset
, semi_colon_offset
, length
, end_quote_offset
;
2228 const uint8_t *param_name
= NULL
;
2229 unsigned cause_value
;
2230 sip_reason_code_info_t sip_reason_code_info
;
2232 /* skip Spaces and Tabs */
2233 start_offset
= tvb_skip_wsp(tvb
, start_offset
, line_end_offset
- start_offset
);
2235 if (start_offset
>= line_end_offset
)
2237 /* Nothing to parse */
2241 current_offset
= start_offset
;
2242 semi_colon_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
-current_offset
, ';');
2244 if(semi_colon_offset
== -1)
2247 length
= semi_colon_offset
- current_offset
;
2248 proto_tree_add_item_ret_string(tree
, hf_sip_reason_protocols
, tvb
, start_offset
, length
, ENC_UTF_8
|ENC_NA
, pinfo
->pool
, ¶m_name
);
2249 current_offset
= tvb_find_uint8(tvb
, semi_colon_offset
, line_end_offset
- semi_colon_offset
, '=') + 1;
2250 /* Do we have a text parameter too? */
2251 semi_colon_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, ';');
2253 if (semi_colon_offset
== -1){
2254 length
= line_end_offset
- current_offset
;
2256 /* Text parameter exist, set length accordingly */
2257 length
= semi_colon_offset
- current_offset
;
2260 /* Get cause value */
2261 cause_value
= (unsigned)strtoul(tvb_get_string_enc(pinfo
->pool
, tvb
, current_offset
, length
, ENC_UTF_8
| ENC_NA
), NULL
, 10);
2263 if (g_ascii_strcasecmp(param_name
, "Q.850") == 0){
2264 proto_tree_add_uint(tree
, hf_sip_reason_cause_q850
, tvb
, current_offset
, length
, cause_value
);
2265 sip_reason_code_info
.protocol_type_num
= SIP_PROTO_Q850
;
2267 else if (g_ascii_strcasecmp(param_name
, "SIP") == 0) {
2268 proto_tree_add_uint(tree
, hf_sip_reason_cause_sip
, tvb
, current_offset
, length
, cause_value
);
2269 sip_reason_code_info
.protocol_type_num
= SIP_PROTO_SIP
;
2272 proto_tree_add_uint(tree
, hf_sip_reason_cause_other
, tvb
, current_offset
, length
, cause_value
);
2273 sip_reason_code_info
.protocol_type_num
= SIP_PROTO_OTHER
;
2276 if (semi_colon_offset
== -1)
2277 /* Nothing to parse */
2280 /* reason-text = "text" EQUAL quoted-string */
2281 current_offset
= tvb_find_uint8(tvb
, semi_colon_offset
, line_end_offset
- semi_colon_offset
, '"') + 1;
2282 if (current_offset
== -1)
2283 /* Nothing to parse */
2285 end_quote_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, '"');
2286 if (end_quote_offset
== -1)
2287 /* Nothing to parse */
2289 length
= end_quote_offset
- current_offset
;
2290 proto_tree_add_item(tree
, hf_sip_reason_text
, tvb
, current_offset
, length
, ENC_UTF_8
| ENC_NA
);
2292 if (sip_reason_code_handle
) {
2295 sip_reason_code_info
.cause_value
= cause_value
;
2297 next_tvb
= tvb_new_subset_length(tvb
, current_offset
, length
);
2298 call_dissector_with_data(sip_reason_code_handle
, next_tvb
, pinfo
, tree
, &sip_reason_code_info
);
2302 /* Dissect the details of a security client header
2303 * sec-mechanism = mechanism-name *(SEMI mech-parameters)
2304 * mech-parameters = ( preference / digest-algorithm /
2305 * digest-qop / digest-verify / extension )
2306 * preference = "q" EQUAL qvalue
2307 * qvalue = ( "0" [ "." 0*3DIGIT ] )
2308 * / ( "1" [ "." 0*3("0") ] )
2309 * digest-algorithm = "d-alg" EQUAL token
2310 * digest-qop = "d-qop" EQUAL token
2311 * digest-verify = "d-ver" EQUAL LDQUOT 32LHEX RDQUOT
2312 * extension = generic-param
2317 dissect_sip_sec_mechanism(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_tree
*tree
, int start_offset
, int line_end_offset
){
2319 int current_offset
, semi_colon_offset
, length
, par_name_end_offset
, equals_offset
;
2321 /* skip Spaces and Tabs */
2322 start_offset
= tvb_skip_wsp(tvb
, start_offset
, line_end_offset
- start_offset
);
2324 if (start_offset
>= line_end_offset
)
2326 /* Nothing to parse */
2330 current_offset
= start_offset
;
2331 semi_colon_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
-current_offset
, ';');
2332 if(semi_colon_offset
== -1){
2333 semi_colon_offset
= line_end_offset
;
2336 length
= semi_colon_offset
-current_offset
;
2337 proto_tree_add_item(tree
, hf_sip_sec_mechanism
, tvb
,
2338 start_offset
, length
,
2341 current_offset
= current_offset
+ length
+ 1;
2344 while(current_offset
< line_end_offset
){
2345 char *param_name
= NULL
, *value
= NULL
;
2346 uint8_t hf_index
= 0;
2347 /* skip Spaces and Tabs */
2348 current_offset
= tvb_skip_wsp(tvb
, current_offset
, line_end_offset
- current_offset
);
2350 semi_colon_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
-current_offset
, ';');
2352 if(semi_colon_offset
== -1){
2353 semi_colon_offset
= line_end_offset
;
2356 length
= semi_colon_offset
- current_offset
;
2358 /* Parse parameter and value */
2359 equals_offset
= tvb_find_uint8(tvb
, current_offset
+ 1, length
, '=');
2360 if(equals_offset
!= -1){
2361 /* Has value part */
2362 par_name_end_offset
= equals_offset
;
2363 /* Extract the parameter name */
2364 param_name
= tvb_get_string_enc(pinfo
->pool
, tvb
, current_offset
, par_name_end_offset
-current_offset
, ENC_UTF_8
|ENC_NA
);
2365 /* Extract the value */
2366 value
= tvb_get_string_enc(pinfo
->pool
, tvb
, equals_offset
+1, semi_colon_offset
-equals_offset
+1, ENC_UTF_8
|ENC_NA
);
2372 while (sec_mechanism_parameters_hf_array
[hf_index
].param_name
) {
2373 /* Protection algorithm to be used */
2374 if (g_ascii_strcasecmp(param_name
, sec_mechanism_parameters_hf_array
[hf_index
].param_name
) == 0) {
2375 switch (sec_mechanism_parameters_hf_array
[hf_index
].para_type
) {
2376 case MECH_PARA_STRING
:
2377 proto_tree_add_item(tree
, *sec_mechanism_parameters_hf_array
[hf_index
].hf_item
, tvb
,
2378 equals_offset
+1, semi_colon_offset
-equals_offset
-1,
2381 case MECH_PARA_UINT
:
2383 proto_tree_add_expert(tree
, pinfo
, &ei_sip_sipsec_malformed
,
2384 tvb
, current_offset
, -1);
2387 semi_para
= (uint32_t)strtoul(value
, NULL
, 10);
2388 proto_tree_add_uint(tree
, *sec_mechanism_parameters_hf_array
[hf_index
].hf_item
, tvb
,
2389 equals_offset
+1, semi_colon_offset
-equals_offset
-1, semi_para
);
2400 if (!sec_mechanism_parameters_hf_array
[hf_index
].param_name
) {
2401 proto_tree_add_format_text(tree
, tvb
, current_offset
, length
);
2404 current_offset
= semi_colon_offset
+1;
2409 /* Dissect the details of a Route (and Record-Route) header */
2410 static void dissect_sip_route_header(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, hf_sip_uri_t
*sip_route_uri_p
, int start_offset
, int line_end_offset
)
2413 uri_offset_info uri_offsets
;
2415 current_offset
= start_offset
;
2417 /* skip Spaces and Tabs */
2418 current_offset
= tvb_skip_wsp(tvb
, current_offset
, line_end_offset
- current_offset
);
2420 if (current_offset
>= line_end_offset
) {
2424 while (current_offset
< line_end_offset
) {
2425 current_offset
= tvb_find_uint8(tvb
, current_offset
, (line_end_offset
- 1) - current_offset
, ',');
2427 if (current_offset
!= -1) { /* found any ',' ? */
2428 sip_uri_offset_init(&uri_offsets
);
2429 current_offset
= dissect_sip_name_addr_or_addr_spec(tvb
, pinfo
, start_offset
, current_offset
, &uri_offsets
);
2430 if(current_offset
== -1)
2432 display_sip_uri(tvb
, tree
, pinfo
, &uri_offsets
, sip_route_uri_p
);
2435 start_offset
= current_offset
+ 1;
2438 /* current_offset = (line_end_offset - 1); */
2440 sip_uri_offset_init(&uri_offsets
);
2441 current_offset
= dissect_sip_name_addr_or_addr_spec(tvb
, pinfo
, start_offset
, line_end_offset
, &uri_offsets
);
2442 if(current_offset
== -1)
2444 display_sip_uri(tvb
, tree
, pinfo
, &uri_offsets
, sip_route_uri_p
);
2455 /* Dissect the details of a Via header
2457 * Via = ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm)
2458 * via-parm = sent-protocol LWS sent-by *( SEMI via-params )
2459 * via-params = via-ttl / via-maddr
2460 * / via-received / via-branch
2462 * via-ttl = "ttl" EQUAL ttl
2463 * via-maddr = "maddr" EQUAL host
2464 * via-received = "received" EQUAL (IPv4address / IPv6address)
2465 * via-branch = "branch" EQUAL token
2466 * via-extension = generic-param
2467 * sent-protocol = protocol-name SLASH protocol-version
2469 * protocol-name = "SIP" / token
2470 * protocol-version = token
2471 * transport = "UDP" / "TCP" / "TLS" / "SCTP"
2473 * sent-by = host [ COLON port ]
2474 * ttl = 1*3DIGIT ; 0 to 255
2477 static void dissect_sip_via_header(tvbuff_t
*tvb
, proto_tree
*tree
, int start_offset
, int line_end_offset
, packet_info
*pinfo
)
2480 int address_start_offset
;
2481 int semicolon_offset
;
2483 bool ipv6_reference
;
2486 char *param_name
= NULL
;
2488 current_offset
= start_offset
;
2492 /* Reset flags and counters */
2493 semicolon_offset
= 0;
2494 ipv6_reference
= false;
2495 ipv6_address
= false;
2498 /* skip Spaces and Tabs */
2499 current_offset
= tvb_skip_wsp(tvb
, current_offset
, line_end_offset
- current_offset
);
2501 if (current_offset
>= line_end_offset
)
2503 /* Nothing more to parse */
2507 /* Now look for the end of the SIP/2.0/transport parameter.
2508 * There may be spaces between the slashes
2509 * sent-protocol = protocol-name SLASH protocol-version
2513 current_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, '/');
2514 if (current_offset
!= -1)
2517 current_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, '/');
2520 if (current_offset
!= -1)
2523 /* skip Spaces and Tabs */
2524 current_offset
= tvb_skip_wsp(tvb
, current_offset
, line_end_offset
- current_offset
);
2526 current_offset
= line_end_offset
;
2529 /* We should now be at the start of the first transport name (or at the end of the line) */
2532 * transport = "UDP" / "TCP" / "TLS" / "SCTP"
2535 while (current_offset
< line_end_offset
)
2537 int transport_start_offset
= current_offset
;
2539 current_offset
= tvb_ws_mempbrk_pattern_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, &pbrk_tab_sp_fslash
, &c
);
2540 if (current_offset
!= -1){
2541 proto_tree_add_item(tree
, hf_sip_via_transport
, tvb
, transport_start_offset
,
2542 current_offset
- transport_start_offset
, ENC_UTF_8
);
2543 /* Check if we have more transport parameters */
2548 current_offset
= tvb_skip_wsp(tvb
, current_offset
, line_end_offset
- current_offset
);
2549 c
= tvb_get_uint8(tvb
, current_offset
);
2556 current_offset
= line_end_offset
;
2561 /* skip Spaces and Tabs */
2562 current_offset
= tvb_skip_wsp(tvb
, current_offset
, line_end_offset
- current_offset
);
2564 /* Now read the address part */
2565 address_start_offset
= current_offset
;
2566 while (current_offset
< line_end_offset
)
2568 current_offset
= tvb_ws_mempbrk_pattern_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, &pbrk_addr_end
, &c
);
2569 if (current_offset
== -1)
2571 current_offset
= line_end_offset
;
2576 ipv6_reference
= true;
2577 ipv6_address
= true;
2581 ipv6_reference
= false;
2584 if (colon_seen
|| (c
== ' ') || (c
== '\t') || ((c
== ':') && (ipv6_reference
== false)) || (c
== ';'))
2591 /* Add address to tree */
2592 if (ipv6_address
== true) {
2593 proto_tree_add_item(tree
, hf_sip_via_sent_by_address
, tvb
, address_start_offset
+ 1,
2594 current_offset
- address_start_offset
- 2, ENC_UTF_8
);
2596 proto_tree_add_item(tree
, hf_sip_via_sent_by_address
, tvb
, address_start_offset
,
2597 current_offset
- address_start_offset
, ENC_UTF_8
);
2600 /* Transport port number may follow ([space] : [space])*/
2601 current_offset
= tvb_skip_wsp(tvb
, current_offset
, line_end_offset
- current_offset
);
2602 c
= tvb_get_uint8(tvb
, current_offset
);
2606 /* Port number will follow any space after : */
2610 /* Skip optional space after colon */
2611 current_offset
= tvb_skip_wsp(tvb
, current_offset
, line_end_offset
- current_offset
);
2613 port_offset
= current_offset
;
2615 /* Find digits of port number */
2616 while (current_offset
< line_end_offset
)
2618 c
= tvb_get_uint8(tvb
, current_offset
);
2620 if (!g_ascii_isdigit(c
))
2622 if (current_offset
> port_offset
)
2624 /* Add address port number to tree */
2628 port_valid
= ws_strtou16(tvb_get_string_enc(pinfo
->pool
, tvb
, port_offset
,
2629 current_offset
- port_offset
, ENC_UTF_8
|ENC_NA
), NULL
, &port
);
2630 pi
= proto_tree_add_uint(tree
, hf_sip_via_sent_by_port
, tvb
, port_offset
,
2631 current_offset
- port_offset
, port
);
2633 expert_add_info(pinfo
, pi
, &ei_sip_via_sent_by_port
);
2637 /* Shouldn't see a colon without a port number given */
2647 /* skip Spaces and Tabs */
2648 current_offset
= tvb_skip_wsp(tvb
, current_offset
, line_end_offset
- current_offset
);
2651 /* Dissect any parameters found */
2652 while (current_offset
< line_end_offset
)
2654 bool equals_found
= false;
2655 bool found_end_of_parameters
= false;
2656 int parameter_name_end
= 0;
2657 header_parameter_t
*via_parameter
;
2660 /* Look for the semicolon that signals the start of a parameter */
2661 while (current_offset
< line_end_offset
)
2663 c
= tvb_get_uint8(tvb
, current_offset
);
2666 semicolon_offset
= current_offset
;
2671 if ((c
!= ' ') && (c
!= '\t'))
2673 found_end_of_parameters
= true;
2679 if (found_end_of_parameters
)
2684 if (current_offset
== line_end_offset
)
2689 /* Look for end of parameter name */
2690 while (current_offset
< line_end_offset
)
2692 c
= tvb_get_uint8(tvb
, current_offset
);
2693 if (!g_ascii_isalpha(c
) && (c
!= '-'))
2700 /* Not all params have an = */
2703 equals_found
= true;
2705 parameter_name_end
= current_offset
;
2707 /* Read until end of parameter value */
2708 current_offset
= tvb_ws_mempbrk_pattern_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, &pbrk_via_param_end
, NULL
);
2709 if (current_offset
== -1)
2710 current_offset
= line_end_offset
;
2712 /* Note parameter name */
2713 param_name
= tvb_get_string_enc(pinfo
->pool
, tvb
, semicolon_offset
+1,
2714 parameter_name_end
- semicolon_offset
- 1, ENC_UTF_8
|ENC_NA
);
2716 /* Try to add parameter as a filterable item */
2717 for (via_parameter
= &via_parameters_hf_array
[i
];
2718 i
< array_length(via_parameters_hf_array
);
2719 i
++, via_parameter
++)
2721 if (g_ascii_strcasecmp(param_name
, via_parameter
->param_name
) == 0)
2725 proto_item
* via_parameter_item
;
2726 via_parameter_item
= proto_tree_add_item(tree
, *(via_parameter
->hf_item
), tvb
,
2727 parameter_name_end
+ 1, current_offset
- parameter_name_end
- 1,
2728 ENC_UTF_8
| ENC_NA
);
2730 if (sip_via_branch_handle
&& g_ascii_strcasecmp(param_name
, "branch") == 0)
2733 next_tvb
= tvb_new_subset_length(tvb
, parameter_name_end
+ 1, current_offset
- parameter_name_end
- 1);
2735 call_dissector(sip_via_branch_handle
, next_tvb
, pinfo
, tree
);
2737 else if (g_ascii_strcasecmp(param_name
, "oc") == 0) {
2739 char *value
= tvb_get_string_enc(pinfo
->pool
, tvb
, parameter_name_end
+ 1,
2740 current_offset
- parameter_name_end
- 1, ENC_UTF_8
| ENC_NA
);
2741 ti
= proto_tree_add_uint(tree
, hf_sip_via_oc_val
, tvb
,
2742 parameter_name_end
+ 1, current_offset
- parameter_name_end
- 1,
2743 (uint32_t)strtoul(value
, NULL
, 10));
2744 proto_item_set_generated(ti
);
2746 else if (g_ascii_strcasecmp(param_name
, "oc-seq") == 0) {
2749 int dec_p_off
= tvb_find_uint8(tvb
, parameter_name_end
+ 1, - 1, '.');
2753 value
= tvb_get_string_enc(pinfo
->pool
, tvb
,
2754 parameter_name_end
+ 1, dec_p_off
- parameter_name_end
, ENC_UTF_8
| ENC_NA
);
2755 ts
.secs
= (time_t)strtoul(value
, NULL
, 10);
2756 value
= tvb_get_string_enc(pinfo
->pool
, tvb
,
2757 dec_p_off
+ 1, current_offset
- parameter_name_end
- 1, ENC_UTF_8
| ENC_NA
);
2758 ts
.nsecs
= (uint32_t)strtoul(value
, NULL
, 10) * 1000;
2759 ti
= proto_tree_add_time(tree
, hf_sip_oc_seq_timestamp
, tvb
,
2760 parameter_name_end
+ 1, current_offset
- parameter_name_end
- 1, &ts
);
2761 proto_item_set_generated(ti
);
2763 } else if (sip_via_be_route_handle
&& g_ascii_strcasecmp(param_name
, "be-route") == 0) {
2765 next_tvb
= tvb_new_subset_length(tvb
, parameter_name_end
+ 1, current_offset
- parameter_name_end
- 1);
2766 call_dissector(sip_via_be_route_handle
, next_tvb
, pinfo
, proto_item_add_subtree(via_parameter_item
, ett_sip_via_be_route
));
2771 proto_tree_add_item(tree
, *(via_parameter
->hf_item
), tvb
,
2772 semicolon_offset
+1, current_offset
-semicolon_offset
-1,
2779 /* If not matched, just add as text... */
2780 if (i
== array_length(via_parameters_hf_array
))
2782 proto_tree_add_format_text(tree
, tvb
, semicolon_offset
+1, current_offset
-semicolon_offset
-1);
2785 /* skip Spaces and Tabs */
2786 current_offset
= tvb_skip_wsp(tvb
, current_offset
, line_end_offset
- current_offset
);
2788 /* There may be a comma, followed by more Via entries... */
2789 if (current_offset
< line_end_offset
)
2791 c
= tvb_get_uint8(tvb
, current_offset
);
2794 /* Skip it and get out of parameter loop */
2803 /* Dissect the details of a Session-ID header
2805 * Session-ID = "Session-ID" HCOLON sess-id
2806 * *( SEMI generic-param )
2807 * sess-id = 32(DIGIT / %x61-66) ; 32 chars of [0-9a-f]
2809 static void dissect_sip_session_id_header(tvbuff_t
*tvb
, proto_tree
*tree
, int start_offset
, int line_end_offset
, packet_info
*pinfo
)
2811 int current_offset
, semi_colon_offset
, equals_offset
, length
, logme_end_offset
;
2815 current_offset
= start_offset
;
2816 semi_colon_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
-current_offset
, ';');
2817 if(semi_colon_offset
== -1){
2818 semi_colon_offset
= line_end_offset
;
2821 length
= semi_colon_offset
-current_offset
;
2822 bytes
= g_byte_array_sized_new(16);
2824 pi
= proto_tree_add_bytes_item(tree
, hf_sip_session_id_sess_id
, tvb
,
2825 start_offset
, length
, ENC_UTF_8
|ENC_STR_HEX
|ENC_SEP_NONE
,
2828 pi
= proto_tree_add_item(tree
, hf_sip_session_id_sess_id
, tvb
,
2829 start_offset
, length
, ENC_UTF_8
| ENC_STR_HEX
| ENC_SEP_NONE
);
2830 expert_add_info(pinfo
, pi
, &ei_sip_session_id_sess_id
);
2833 current_offset
= current_offset
+ length
+ 1;
2835 /* skip Spaces and Tabs */
2836 current_offset
= tvb_skip_wsp(tvb
, current_offset
, line_end_offset
- current_offset
);
2838 if (current_offset
< line_end_offset
) {
2839 /* Parse parameter and value */
2840 equals_offset
= tvb_find_uint8(tvb
, current_offset
+ 1, length
, '=');
2841 if (equals_offset
!= -1) {
2842 /* Extract the parameter name */
2843 GByteArray
*uuid
= g_byte_array_sized_new(16);
2844 uint8_t *param_name
= tvb_get_string_enc(pinfo
->pool
, tvb
, current_offset
,
2845 tvb_skip_wsp_return(tvb
, equals_offset
- 1) - current_offset
,
2848 if ((bytes
->len
== 16) && (g_ascii_strcasecmp(param_name
, "remote") == 0) &&
2849 tvb_get_string_bytes(tvb
, equals_offset
+ 1, line_end_offset
- equals_offset
- 1,
2850 ENC_UTF_8
|ENC_STR_HEX
|ENC_SEP_NONE
, uuid
, NULL
) &&
2851 (uuid
->len
== 16)) {
2852 /* Decode header as draft-ietf-insipid-session-id
2854 * session-id = "Session-ID" HCOLON session-id-value
2855 * session-id-value = local-uuid *(SEMI sess-id-param)
2856 * local-uuid = sess-uuid / null
2857 * remote-uuid = sess-uuid / null
2858 * sess-uuid = 32(DIGIT / %x61-66) ;32 chars of [0-9a-f]
2859 * sess-id-param = remote-param / generic-param
2860 * remote-param = "remote" EQUAL remote-uuid
2865 proto_item_set_hidden(pi
);
2866 guid
.data1
= (bytes
->data
[0] << 24) | (bytes
->data
[1] << 16) |
2867 (bytes
->data
[2] << 8) | bytes
->data
[3];
2868 guid
.data2
= (bytes
->data
[4] << 8) | bytes
->data
[5];
2869 guid
.data3
= (bytes
->data
[6] << 8) | bytes
->data
[7];
2870 memcpy(guid
.data4
, &bytes
->data
[8], 8);
2871 proto_tree_add_guid(tree
, hf_sip_session_id_local_uuid
, tvb
,
2872 start_offset
, semi_colon_offset
- start_offset
, &guid
);
2873 guid
.data1
= (uuid
->data
[0] << 24) | (uuid
->data
[1] << 16) |
2874 (uuid
->data
[2] << 8) | uuid
->data
[3];
2875 guid
.data2
= (uuid
->data
[4] << 8) | uuid
->data
[5];
2876 guid
.data3
= (uuid
->data
[6] << 8) | uuid
->data
[7];
2877 memcpy(guid
.data4
, &uuid
->data
[8], 8);
2878 proto_tree_add_guid(tree
, hf_sip_session_id_remote_uuid
, tvb
,
2879 equals_offset
+ 1, line_end_offset
- equals_offset
- 1, &guid
);
2880 /* Decode logme parameter as per https://tools.ietf.org/html/rfc8497
2882 * sess-id-param =/ logme-param
2883 * logme-param = "logme"
2885 semi_colon_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, ';');
2886 while(semi_colon_offset
!= -1){
2887 current_offset
= semi_colon_offset
+ 1;
2888 if(current_offset
!= line_end_offset
){
2889 logme_end_offset
= current_offset
+ 5;
2890 current_offset
= tvb_skip_wsp_return(tvb
,semi_colon_offset
);
2891 /* Extract logme parameter name */
2892 char *name
= tvb_get_string_enc(pinfo
->pool
, tvb
, current_offset
,logme_end_offset
- current_offset
, ENC_UTF_8
|ENC_NA
);
2893 if(g_ascii_strcasecmp(name
, "logme") == 0){
2894 proto_tree_add_boolean(tree
, hf_sip_session_id_logme
, tvb
, current_offset
, logme_end_offset
- current_offset
, 1);
2895 } else if(current_offset
!= line_end_offset
){
2896 proto_tree_add_item(tree
, hf_sip_session_id_param
, tvb
, current_offset
,line_end_offset
- current_offset
, ENC_UTF_8
);
2899 semi_colon_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, ';');
2902 /* Display generic parameter */
2903 proto_tree_add_item(tree
, hf_sip_session_id_param
, tvb
, current_offset
,
2904 line_end_offset
- current_offset
, ENC_UTF_8
);
2906 g_byte_array_free(uuid
, true);
2908 /* Display generic parameter */
2909 proto_tree_add_item(tree
, hf_sip_session_id_param
, tvb
, current_offset
,
2910 line_end_offset
- current_offset
, ENC_UTF_8
);
2914 g_byte_array_free(bytes
, true);
2917 /* Dissect the headers for P-Access-Network-Info Headers
2919 * Spec found in 3GPP 24.229 7.2A.4
2920 * P-Access-Network-Info = "P-Access-Network-Info" HCOLON
2921 * access-net-spec *(COMMA access-net-spec)
2922 * access-net-spec = (access-type / access-class) *(SEMI access-info)
2923 * access-type = "IEEE-802.11" / "IEEE-802.11a" / "IEEE-802.11b" / "IEEE-802.11g" / "IEEE-802.11n" / "3GPP-GERAN" /
2924 * "3GPP-UTRAN-FDD" / "3GPP-UTRAN-TDD" / "3GPP-E-UTRAN-FDD" / "3GPP-E-UTRAN-TDD" / "ADSL" / "ADSL2" /
2925 * "ADSL2+" / "RADSL" / "SDSL" / "HDSL" / "HDSL2" / "G.SHDSL" / "VDSL" / "IDSL" / "3GPP2-1X" /
2926 * "3GPP2-1X-Femto" / "3GPP2-1X-HRPD" / "3GPP2-UMB" / "DOCSIS" / "IEEE-802.3" / "IEEE-802.3a" /
2927 * "IEEE-802.3e" / "IEEE-802.3i" / "IEEE-802.3j" / "IEEE-802.3u" / "IEEE-802.3ab"/ "IEEE-802.3ae" /
2928 * "IEEE-802.3ak" / "IEEE-802.3aq" / "IEEE-802.3an" / "IEEE-802.3y" / "IEEE-802.3z" / "GPON" /
2929 "XGPON1" / "GSTN"/ token
2930 * access-class = "3GPP-GERAN" / "3GPP-UTRAN" / "3GPP-E-UTRAN" / "3GPP-WLAN" / "3GPP-GAN" / "3GPP-HSPA" / token
2931 * np = "network-provided"
2932 * access-info = cgi-3gpp / utran-cell-id-3gpp / dsl-location / i-wlan-node-id / ci-3gpp2 / ci-3gpp2-femto /
2933 eth-location / fiber-location / np / gstn-location / extension-access-info
2934 * extension-access-info = gen-value
2935 * cgi-3gpp = "cgi-3gpp" EQUAL (token / quoted-string)
2936 * utran-cell-id-3gpp = "utran-cell-id-3gpp" EQUAL (token / quoted-string)
2937 * i-wlan-node-id = "i-wlan-node-id" EQUAL (token / quoted-string)
2938 * dsl-location = "dsl-location" EQUAL (token / quoted-string)
2939 * eth-location = "eth-location" EQUAL (token / quoted-string)
2940 * fiber-location = "fiber-location" EQUAL (token / quoted-string)
2941 * ci-3gpp2 = "ci-3gpp2" EQUAL (token / quoted-string)
2942 * ci-3gpp2-femto = "ci-3gpp2-femto" EQUAL (token / quoted-string)
2943 * gstn-location = "gstn-location" EQUAL (token / quoted-string)
2946 void dissect_sip_p_access_network_info_header(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, int start_offset
, int line_end_offset
)
2949 int current_offset
, semi_colon_offset
, length
, par_name_end_offset
, equals_offset
;
2951 /* skip Spaces and Tabs */
2952 start_offset
= tvb_skip_wsp(tvb
, start_offset
, line_end_offset
- start_offset
);
2954 if (start_offset
>= line_end_offset
)
2956 /* Nothing to parse */
2960 /* Get the Access Type / Access Class*/
2961 current_offset
= start_offset
;
2962 semi_colon_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, ';');
2964 if (semi_colon_offset
== -1)
2967 length
= semi_colon_offset
- current_offset
;
2968 proto_tree_add_item(tree
, hf_sip_p_acc_net_i_acc_type
, tvb
, start_offset
, length
, ENC_UTF_8
| ENC_NA
);
2970 current_offset
= current_offset
+ length
+ 1;
2973 while (current_offset
< line_end_offset
){
2974 char *param_name
= NULL
;
2976 /* skip Spaces and Tabs */
2977 current_offset
= tvb_skip_wsp(tvb
, current_offset
, line_end_offset
- current_offset
);
2979 semi_colon_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, ';');
2981 if (semi_colon_offset
== -1){
2982 semi_colon_offset
= line_end_offset
;
2985 length
= semi_colon_offset
- current_offset
;
2987 /* Parse parameter and value */
2988 equals_offset
= tvb_find_uint8(tvb
, current_offset
+ 1, length
, '=');
2989 if (equals_offset
!= -1){
2990 /* Has value part */
2991 par_name_end_offset
= equals_offset
;
2992 /* Extract the parameter name */
2993 param_name
= tvb_get_string_enc(pinfo
->pool
, tvb
, current_offset
, par_name_end_offset
- current_offset
, ENC_UTF_8
| ENC_NA
);
2994 /* Access-Info fields */
2995 if ((param_name
!= NULL
)&&(g_ascii_strcasecmp(param_name
, "utran-cell-id-3gpp") == 0)) {
2996 proto_tree_add_item(tree
, hf_sip_p_acc_net_i_ucid_3gpp
, tvb
,
2997 equals_offset
+ 1, semi_colon_offset
- equals_offset
- 1, ENC_UTF_8
| ENC_NA
);
2998 /* check if value is quoted */
2999 if (tvb_get_uint8(tvb
, equals_offset
+ 1) == '"') {
3000 dissect_e212_mcc_mnc_in_utf8_address(tvb
, pinfo
, tree
, equals_offset
+ 2);
3002 dissect_e212_mcc_mnc_in_utf8_address(tvb
, pinfo
, tree
, equals_offset
+ 1);
3006 proto_tree_add_format_text(tree
, tvb
, current_offset
, length
);
3010 proto_tree_add_format_text(tree
, tvb
, current_offset
, length
);
3013 current_offset
= semi_colon_offset
+ 1;
3018 The syntax for the P-Charging-Vector header field is described as
3021 P-Charging-Vector = "P-Charging-Vector" HCOLON icid-value
3022 *(SEMI charge-params)
3023 charge-params = icid-gen-addr / orig-ioi / term-ioi /
3024 transit-ioi / related-icid /
3025 related-icid-gen-addr / generic-param
3026 icid-value = "icid-value" EQUAL gen-value
3027 icid-gen-addr = "icid-generated-at" EQUAL host
3028 orig-ioi = "orig-ioi" EQUAL gen-value
3029 term-ioi = "term-ioi" EQUAL gen-value
3030 transit-ioi = "transit-ioi" EQUAL transit-ioi-list
3031 transit-ioi-list = DQUOTE transit-ioi-param
3032 *(COMMA transit-ioi-param) DQUOTE
3033 transit-ioi-param = transit-ioi-indexed-value /
3034 transit-ioi-void-value
3035 transit-ioi-indexed-value = transit-ioi-name "."
3037 transit-ioi-name = ALPHA *(ALPHA / DIGIT)
3038 transit-ioi-index = 1*DIGIT
3039 transit-ioi-void-value = "void"
3040 related-icid = "related-icid" EQUAL gen-value
3041 related-icid-gen-addr = "related-icid-generated-at" EQUAL host
3044 dissect_sip_p_charging_vector_header(tvbuff_t
*tvb
, proto_tree
*tree
, int start_offset
, int line_end_offset
)
3047 int current_offset
, semi_colon_offset
, length
, equals_offset
;
3049 /* skip Spaces and Tabs */
3050 start_offset
= tvb_skip_wsp(tvb
, start_offset
, line_end_offset
- start_offset
);
3052 if (start_offset
>= line_end_offset
)
3054 /* Nothing to parse */
3058 /* icid-value = "icid-value" EQUAL gen-value */
3059 current_offset
= start_offset
;
3060 semi_colon_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, ';');
3062 if (semi_colon_offset
== -1) {
3063 /* No parameters, is that allowed?*/
3064 semi_colon_offset
= line_end_offset
;
3067 length
= semi_colon_offset
- current_offset
;
3069 /* Parse parameter and value */
3070 equals_offset
= tvb_find_uint8(tvb
, current_offset
+ 1, length
, '=');
3071 if (equals_offset
== -1) {
3072 /* Does not conform to ABNF */
3076 /* Get the icid-value */
3077 proto_tree_add_item(tree
, hf_sip_icid_value
, tvb
,
3078 equals_offset
+ 1, semi_colon_offset
- equals_offset
- 1, ENC_UTF_8
| ENC_NA
);
3080 current_offset
= semi_colon_offset
+ 1;
3082 /* Add the rest of the parameters to the tree */
3083 while (current_offset
< line_end_offset
) {
3084 char *param_name
= NULL
;
3085 int par_name_end_offset
;
3086 /* skip Spaces and Tabs */
3087 current_offset
= tvb_skip_wsp(tvb
, current_offset
, line_end_offset
- current_offset
);
3089 semi_colon_offset
= tvb_find_uint8(tvb
, current_offset
, line_end_offset
- current_offset
, ';');
3091 if (semi_colon_offset
== -1) {
3092 semi_colon_offset
= line_end_offset
;
3095 length
= semi_colon_offset
- current_offset
;
3097 /* Parse parameter and value */
3098 equals_offset
= tvb_find_uint8(tvb
, current_offset
+ 1, length
, '=');
3099 if (equals_offset
!= -1) {
3100 /* Has value part */
3101 par_name_end_offset
= equals_offset
;
3102 /* Extract the parameter name */
3103 param_name
= tvb_get_string_enc(wmem_packet_scope(), tvb
, current_offset
, par_name_end_offset
- current_offset
, ENC_UTF_8
| ENC_NA
);
3105 if ((param_name
!= NULL
) && (g_ascii_strcasecmp(param_name
, "icid-gen-addr") == 0)) {
3106 proto_tree_add_item(tree
, hf_sip_icid_gen_addr
, tvb
,
3107 equals_offset
+ 1, semi_colon_offset
- equals_offset
- 1, ENC_UTF_8
| ENC_NA
);
3110 proto_tree_add_format_text(tree
, tvb
, current_offset
, length
);
3114 proto_tree_add_format_text(tree
, tvb
, current_offset
, length
);
3117 current_offset
= semi_colon_offset
+ 1;
3124 https://tools.ietf.org/html/rfc6809
3125 The ABNF for the Feature-Caps header fields is:
3127 Feature-Caps = "Feature-Caps" HCOLON fc-value
3129 fc-value = "*" *(SEMI feature-cap)
3131 The ABNF for the feature-capability indicator is:
3133 feature-cap = "+" fcap-name [EQUAL LDQUOT (fcap-value-list
3134 / fcap-string-value ) RDQUOT]
3135 fcap-name = ftag-name
3136 fcap-value-list = tag-value-list
3137 fcap-string-value = string-value
3138 ;; ftag-name, tag-value-list, string-value defined in RFC 3840
3140 NOTE: In comparison with media feature tags, the "+" sign in front of
3141 the feature-capability indicator name is mandatory.
3145 dissect_sip_p_feature_caps(tvbuff_t
*tvb
, proto_tree
*tree
, int start_offset
, int line_end_offset
)
3147 int current_offset
, next_offset
, length
;
3148 uint16_t semi_plus
= 0x3b2b;
3150 /* skip Spaces and Tabs */
3151 next_offset
= tvb_skip_wsp(tvb
, start_offset
, line_end_offset
- start_offset
);
3153 if (next_offset
>= line_end_offset
) {
3154 /* Nothing to parse */
3158 while (next_offset
< line_end_offset
) {
3159 /* Find the end of feature cap or start of feature cap parameter, ";+" should indicate the start of a new feature-cap */
3160 current_offset
= next_offset
;
3161 next_offset
= tvb_find_uint16(tvb
, current_offset
, line_end_offset
- current_offset
, semi_plus
);
3162 if (next_offset
== -1) {
3163 length
= line_end_offset
- current_offset
;
3164 next_offset
= line_end_offset
;
3167 length
= next_offset
- current_offset
;
3170 proto_tree_add_item(tree
, hf_sip_feature_cap
, tvb
, current_offset
, length
, ENC_UTF_8
| ENC_NA
);
3174 /* Code to actually dissect the packets */
3176 dissect_sip(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
3180 int remaining_length
;
3182 octet
= tvb_get_uint8(tvb
,0);
3183 if ((octet
& 0xf8) == 0xf8){
3184 call_dissector(sigcomp_handle
, tvb
, pinfo
, tree
);
3185 return tvb_reported_length(tvb
);
3188 remaining_length
= tvb_reported_length(tvb
);
3189 len
= dissect_sip_common(tvb
, 0, remaining_length
, pinfo
, tree
, false, false);
3191 return 0; /* not SIP */
3197 dissect_sip_tcp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
3200 int offset
= 0, linelen
;
3202 int remaining_length
;
3204 octet
= tvb_get_uint8(tvb
,0);
3205 if ((octet
& 0xf8) == 0xf8){
3206 call_dissector(sigcomp_handle
, tvb
, pinfo
, tree
);
3207 return tvb_reported_length(tvb
);
3210 remaining_length
= tvb_reported_length(tvb
);
3211 /* If we have exactly one non printable byte of payload, this is
3212 * probably just a keep alive at the beginning of a capture. Better
3213 * to treat it as such than to mark it and everything up to the next
3214 * line end as Continuation Data.
3216 if (remaining_length
== 1 && !g_ascii_isprint(octet
)) {
3219 /* Check if we have enough data or if we need another segment, as a safety measure set a length limit*/
3220 if (remaining_length
< 1500){
3221 linelen
= tvb_find_line_end(tvb
, offset
, remaining_length
, NULL
, true);
3223 pinfo
->desegment_offset
= offset
;
3224 pinfo
->desegment_len
= DESEGMENT_ONE_MORE_SEGMENT
;
3228 len
= dissect_sip_common(tvb
, offset
, remaining_length
, pinfo
, tree
, true, true);
3232 remaining_length
= remaining_length
- len
;
3235 * This is a bit of a cludge as the TCP dissector does not call the dissectors again if not all
3236 * the data in the segment was dissected and we do not know if we need another segment or not.
3237 * so DESEGMENT_ONE_MORE_SEGMENT can't be used in all cases.
3240 while (remaining_length
> 0) {
3241 /* Check if we have enough data or if we need another segment, as a safety measure set a length limit*/
3242 if (remaining_length
< 1500){
3243 linelen
= tvb_find_line_end(tvb
, offset
, remaining_length
, NULL
, true);
3245 pinfo
->desegment_offset
= offset
;
3246 pinfo
->desegment_len
= DESEGMENT_ONE_MORE_SEGMENT
;
3250 len
= dissect_sip_common(tvb
, offset
, remaining_length
, pinfo
, tree
, true, true);
3254 remaining_length
= remaining_length
- len
;
3260 dissect_sip_tcp_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
3265 int remaining_length
;
3267 remaining_length
= tvb_captured_length(tvb
);
3268 while (remaining_length
> 0) {
3269 len
= dissect_sip_common(tvb
, offset
, remaining_length
, pinfo
, tree
, !first
, true);
3273 * If the first packet doesn't start with
3274 * a valid SIP request or response, don't
3275 * treat this as SIP.
3282 break; /* need more data */
3284 remaining_length
= remaining_length
- len
;
3291 dissect_sip_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data _U_
)
3293 int remaining_length
= tvb_captured_length(tvb
);
3295 return dissect_sip_common(tvb
, 0, remaining_length
, pinfo
, tree
, false, false) > 0;
3299 dissect_sip_common(tvbuff_t
*tvb
, int offset
, int remaining_length
, packet_info
*pinfo
, proto_tree
*tree
,
3300 bool dissect_other_as_continuation
, bool use_reassembly
)
3302 int orig_offset
, body_offset
;
3303 int next_offset
, linelen
;
3304 int content_length
, datalen
, reported_datalen
;
3305 line_type_t line_type
;
3307 bool is_known_request
;
3308 int found_match
= 0;
3310 unsigned token_1_len
= 0;
3311 unsigned current_method_idx
= SIP_METHOD_INVALID
;
3312 proto_item
*ts
, *ti_a
= NULL
, *th
= NULL
;
3313 proto_tree
*sip_tree
, *reqresp_tree
= NULL
, *hdr_tree
= NULL
,
3314 *message_body_tree
= NULL
, *cseq_tree
= NULL
,
3315 *via_tree
= NULL
, *reason_tree
= NULL
, *rack_tree
= NULL
,
3316 *route_tree
= NULL
, *security_client_tree
= NULL
, *session_id_tree
= NULL
,
3317 *p_access_net_info_tree
= NULL
;
3318 unsigned char contacts
= 0, contact_is_star
= 0, expires_is_0
= 0, contacts_expires_0
= 0, contacts_expires_unknown
= 0;
3319 uint32_t cseq_number
= 0;
3320 unsigned char cseq_number_set
= 0;
3321 const char *cseq_method
= "";
3322 char *call_id
= NULL
;
3323 char *media_type_str_lower_case
= NULL
;
3324 media_content_info_t content_info
= { MEDIA_CONTAINER_SIP_DATA
, NULL
, NULL
, NULL
};
3325 char *content_encoding_parameter_str
= NULL
;
3326 unsigned resend_for_packet
= 0;
3327 unsigned request_for_response
= 0;
3328 uint32_t response_time
= 0;
3330 heur_dtbl_entry_t
*hdtbl_entry
;
3333 * If this should be a request of response, do this quick check to see if
3334 * it begins with a string...
3335 * Otherwise, SIP heuristics are expensive...
3339 if (!dissect_other_as_continuation
&&
3340 ((remaining_length
< 1) || !g_ascii_isprint(tvb_get_uint8(tvb
, offset
))))
3346 * Note that "tvb_find_line_end()" will return a value that
3347 * is not longer than what's in the buffer, so the
3348 * "tvb_get_ptr()" calls below won't throw exceptions.
3350 * Note that "tvb_strneql()" doesn't throw exceptions, so
3351 * "sip_parse_line()" won't throw an exception.
3353 orig_offset
= offset
;
3354 linelen
= tvb_find_line_end(tvb
, offset
, remaining_length
, &next_offset
, false);
3359 if (tvb_strnlen(tvb
, offset
, linelen
) > -1)
3362 * There's a NULL in the line,
3363 * this may be SIP within another protocol.
3364 * This heuristic still needs to improve.
3368 line_type
= sip_parse_line(tvb
, offset
, linelen
, &token_1_len
);
3370 if (line_type
== OTHER_LINE
) {
3372 * This is neither a SIP request nor response.
3374 if (!dissect_other_as_continuation
) {
3376 * We were asked to reject this.
3382 * Just dissect it as a continuation.
3384 } else if ((use_reassembly
)&&( pinfo
->ptype
== PT_TCP
)) {
3386 * Yes, it's a request or response.
3387 * Do header desegmentation if we've been told to,
3388 * and do body desegmentation if we've been told to and
3389 * we find a Content-Length header.
3391 * RFC 6594, Section 20.14. requires Content-Length for TCP.
3393 if (!req_resp_hdrs_do_reassembly(tvb
, offset
, pinfo
,
3394 sip_desegment_headers
, sip_desegment_body
, false, NULL
,
3397 * More data needed for desegmentation.
3403 /* Initialise stat info for passing to tap
3404 * Note: this isn't _only_ for taps - internal code here uses it too
3405 * also store stat info in proto_data for subdissectors
3407 stat_info
= wmem_new0(pinfo
->pool
, sip_info_value_t
);
3408 p_add_proto_data(pinfo
->pool
, pinfo
, proto_sip
, pinfo
->curr_layer_num
, stat_info
);
3410 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SIP");
3412 if (!pinfo
->flags
.in_error_pkt
&& have_tap_listener(exported_pdu_tap
)) {
3413 wmem_list_frame_t
*cur
;
3415 const char *proto_name
;
3418 /* For SIP messages with other sip messages embeded in the body, don't export those individually.
3419 * E.g. if we are called from the mime_multipart dissector don't export the message.
3421 cur
= wmem_list_frame_prev(wmem_list_tail(pinfo
->layers
));
3422 tmp
= wmem_list_frame_data(cur
);
3423 proto_id
= GPOINTER_TO_UINT(tmp
);
3424 proto_name
= proto_get_protocol_filter_name(proto_id
);
3425 if (strcmp(proto_name
, "mime_multipart") != 0) {
3426 export_sip_pdu(pinfo
, tvb
);
3430 DPRINT2(("------------------------------ dissect_sip_common ------------------------------"));
3432 switch (line_type
) {
3435 is_known_request
= sip_is_known_request(tvb
, offset
, token_1_len
, ¤t_method_idx
);
3436 descr
= is_known_request
? "Request" : "Unknown request";
3437 col_add_lstr(pinfo
->cinfo
, COL_INFO
,
3439 tvb_format_text(pinfo
->pool
, tvb
, offset
, linelen
- SIP2_HDR_LEN
- 1),
3440 COL_ADD_LSTR_TERMINATOR
);
3441 DPRINT(("got %s: %s", descr
,
3442 tvb_format_text(pinfo
->pool
, tvb
, offset
, linelen
- SIP2_HDR_LEN
- 1)));
3447 col_add_lstr(pinfo
->cinfo
, COL_INFO
,
3449 tvb_format_text(pinfo
->pool
, tvb
, offset
+ SIP2_HDR_LEN
+ 1, linelen
- SIP2_HDR_LEN
- 1),
3450 COL_ADD_LSTR_TERMINATOR
);
3451 stat_info
->reason_phrase
= tvb_get_string_enc(pinfo
->pool
, tvb
, offset
+ SIP2_HDR_LEN
+ 5,
3452 linelen
- (SIP2_HDR_LEN
+ 5),ENC_UTF_8
|ENC_NA
);
3453 DPRINT(("got Response: %s",
3454 tvb_format_text(pinfo
->pool
, tvb
, offset
+ SIP2_HDR_LEN
+ 1, linelen
- SIP2_HDR_LEN
- 1)));
3458 default: /* Squelch compiler complaints */
3459 descr
= "Continuation";
3460 col_set_str(pinfo
->cinfo
, COL_INFO
, "Continuation");
3461 DPRINT(("got continuation"));
3465 ts
= proto_tree_add_item(tree
, proto_sip
, tvb
, offset
, -1, ENC_NA
);
3466 sip_tree
= proto_item_add_subtree(ts
, ett_sip
);
3468 switch (line_type
) {
3472 ti_a
= proto_tree_add_item(sip_tree
, hf_Request_Line
, tvb
,
3473 offset
, linelen
, ENC_UTF_8
);
3475 reqresp_tree
= proto_item_add_subtree(ti_a
, ett_sip_reqresp
);
3477 dfilter_sip_request_line(tvb
, reqresp_tree
, pinfo
, offset
, token_1_len
, linelen
);
3482 ti_a
= proto_tree_add_item(sip_tree
, hf_sip_Status_Line
, tvb
,
3483 offset
, linelen
, ENC_UTF_8
);
3484 reqresp_tree
= proto_item_add_subtree(ti_a
, ett_sip_reqresp
);
3486 dfilter_sip_status_line(tvb
, reqresp_tree
, pinfo
, linelen
, offset
);
3491 reqresp_tree
= proto_tree_add_subtree_format(sip_tree
, tvb
, offset
, next_offset
,
3492 ett_sip_reqresp
, NULL
, "%s line: %s", descr
,
3493 tvb_format_text(pinfo
->pool
, tvb
, offset
, linelen
));
3494 /* XXX: Is adding to 'reqresp_tree as intended ? Changed from original 'sip_tree' */
3495 proto_tree_add_item(reqresp_tree
, hf_sip_continuation
, tvb
, offset
, -1, ENC_NA
);
3497 return remaining_length
;
3500 remaining_length
= remaining_length
- (next_offset
- offset
);
3501 offset
= next_offset
;
3503 body_offset
= offset
;
3506 * Find the blank line separating the headers from the message body.
3507 * Do this now so we can add the msg_hdr FT_STRING item with the correct
3510 content_length
= -1;
3511 while (remaining_length
> 0) {
3512 int line_end_offset
;
3515 linelen
= tvb_find_line_end(tvb
, body_offset
, -1, &next_offset
, false);
3518 * This is a blank line separating the
3519 * message header from the message body.
3521 body_offset
= next_offset
;
3525 line_end_offset
= body_offset
+ linelen
;
3526 if(tvb_reported_length_remaining(tvb
, next_offset
) > 0){
3527 while (tvb_offset_exists(tvb
, next_offset
) && ((c
= tvb_get_uint8(tvb
, next_offset
)) == ' ' || c
== '\t'))
3530 * This line end is not a header seperator.
3531 * It just extends the header with another line.
3532 * Look for next line end:
3534 linelen
+= (next_offset
- line_end_offset
);
3535 linelen
+= tvb_find_line_end(tvb
, next_offset
, -1, &next_offset
, false);
3536 line_end_offset
= body_offset
+ linelen
;
3539 remaining_length
= remaining_length
- (next_offset
- body_offset
);
3540 body_offset
= next_offset
;
3543 remaining_length
+= (body_offset
- offset
);
3545 th
= proto_tree_add_item(sip_tree
, hf_sip_msg_hdr
, tvb
, offset
,
3546 body_offset
- offset
, ENC_UTF_8
);
3547 hdr_tree
= proto_item_add_subtree(th
, ett_sip_hdr
);
3549 if (have_tap_listener(sip_follow_tap
))
3550 tap_queue_packet(sip_follow_tap
, pinfo
, tvb
);
3553 * Process the headers - if we're not building a protocol tree,
3554 * we just do this to find the blank line separating the
3555 * headers from the message body.
3557 content_length
= -1;
3558 while (remaining_length
> 0) {
3559 int line_end_offset
;
3561 int semi_colon_offset
;
3562 int parameter_offset
;
3563 int parameter_end_offset
;
3565 int content_type_len
, content_type_parameter_str_len
;
3568 dissector_handle_t ext_hdr_handle
;
3571 int sub_value_offset
;
3575 bool is_no_header_termination
= false;
3576 proto_tree
*tc_uri_item_tree
= NULL
;
3577 uri_offset_info uri_offsets
;
3579 linelen
= tvb_find_line_end(tvb
, offset
, -1, &next_offset
, false);
3582 * This is a blank line separating the
3583 * message header from the message body.
3585 offset
= next_offset
;
3589 line_end_offset
= offset
+ linelen
;
3590 if(tvb_reported_length_remaining(tvb
, next_offset
) <= 0){
3591 is_no_header_termination
= true;
3593 while (tvb_offset_exists(tvb
, next_offset
) && ((c
= tvb_get_uint8(tvb
, next_offset
)) == ' ' || c
== '\t'))
3596 * This line end is not a header seperator.
3597 * It just extends the header with another line.
3598 * Look for next line end:
3600 linelen
+= (next_offset
- line_end_offset
);
3601 linelen
+= tvb_find_line_end(tvb
, next_offset
, -1, &next_offset
, false);
3602 line_end_offset
= offset
+ linelen
;
3605 colon_offset
= tvb_find_uint8(tvb
, offset
, linelen
, ':');
3606 if (colon_offset
== -1) {
3608 * Malformed header - no colon after the name.
3610 expert_add_info(pinfo
, th
, &ei_sip_header_no_colon
);
3612 header_len
= colon_offset
- offset
;
3613 header_name
= (char*)tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, header_len
, ENC_UTF_8
|ENC_NA
);
3614 ascii_strdown_inplace(header_name
);
3615 hf_index
= sip_is_known_sip_header(header_name
, header_len
);
3618 * Skip whitespace after the colon.
3620 value_offset
= tvb_skip_wsp(tvb
, colon_offset
+ 1, line_end_offset
- (colon_offset
+ 1));
3622 value_len
= (int) (line_end_offset
- value_offset
);
3624 if (hf_index
== -1) {
3626 if (sip_custom_header_fields_hash
) {
3627 hf_ptr
= (int*)g_hash_table_lookup(sip_custom_header_fields_hash
, header_name
);
3630 sip_proto_tree_add_string(hdr_tree
, *hf_ptr
, tvb
, offset
,
3631 next_offset
- offset
, value_offset
, value_len
);
3634 proto_tree
*ti_tree
= proto_tree_add_subtree(hdr_tree
, tvb
,
3635 offset
, next_offset
- offset
, ett_sip_ext_hdr
, &ti_c
,
3636 tvb_format_text(pinfo
->pool
, tvb
, offset
, linelen
));
3638 ext_hdr_handle
= dissector_get_string_handle(ext_hdr_subdissector_table
, header_name
);
3639 if (ext_hdr_handle
!= NULL
) {
3640 tvbuff_t
*next_tvb2
;
3641 next_tvb2
= tvb_new_subset_length(tvb
, value_offset
, value_len
);
3642 dissector_try_string_with_data(ext_hdr_subdissector_table
, header_name
, next_tvb2
, pinfo
, ti_tree
, true, NULL
);
3644 expert_add_info_format(pinfo
, ti_c
, &ei_sip_unrecognized_header
,
3645 "Unrecognised SIP header (%s)",
3650 proto_item
*sip_element_item
;
3651 proto_tree
*sip_element_tree
;
3654 * Add it to the protocol tree,
3655 * but display the line as is.
3657 switch ( hf_index
) {
3664 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
3665 hf_header_array
[hf_index
], tvb
,
3666 offset
, next_offset
- offset
,
3667 value_offset
, value_len
);
3668 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
3670 sip_element_tree
= proto_item_add_subtree( sip_element_item
,
3672 /* To = ( "To" / "t" ) HCOLON ( name-addr
3673 * / addr-spec ) *( SEMI to-param )
3675 sip_uri_offset_init(&uri_offsets
);
3676 if((dissect_sip_name_addr_or_addr_spec(tvb
, pinfo
, value_offset
, line_end_offset
+2, &uri_offsets
)) != -1){
3677 display_sip_uri(tvb
, sip_element_tree
, pinfo
, &uri_offsets
, &sip_to_uri
);
3678 if((uri_offsets
.name_addr_start
!= -1) && (uri_offsets
.name_addr_end
!= -1)){
3679 stat_info
->tap_to_addr
=tvb_get_string_enc(pinfo
->pool
, tvb
, uri_offsets
.name_addr_start
,
3680 uri_offsets
.name_addr_end
- uri_offsets
.name_addr_start
+ 1, ENC_UTF_8
|ENC_NA
);
3682 offset
= uri_offsets
.name_addr_end
+1;
3685 /* Find parameter tag if present.
3686 * TODO make this generic to find any interesting parameter
3687 * use the same method as for SIP headers ?
3690 parameter_offset
= offset
;
3691 while (parameter_offset
< line_end_offset
3692 && (tvb_strneql(tvb
, parameter_offset
, "tag=", 4) != 0))
3695 if ( parameter_offset
< line_end_offset
){ /* Tag found */
3696 parameter_offset
= parameter_offset
+ 4;
3697 parameter_end_offset
= tvb_find_uint8(tvb
, parameter_offset
,
3698 (line_end_offset
- parameter_offset
), ';');
3699 if ( parameter_end_offset
== -1)
3700 parameter_end_offset
= line_end_offset
;
3701 parameter_len
= parameter_end_offset
- parameter_offset
;
3702 proto_tree_add_item(sip_element_tree
, hf_sip_to_tag
, tvb
, parameter_offset
,
3703 parameter_len
, ENC_UTF_8
);
3704 item
= proto_tree_add_item(sip_element_tree
, hf_sip_tag
, tvb
, parameter_offset
,
3705 parameter_len
, ENC_UTF_8
);
3706 proto_item_set_hidden(item
);
3708 /* Tag indicates in-dialog messages, in case we have a INVITE, SUBSCRIBE or REFER, mark it */
3709 switch (current_method_idx
) {
3711 case SIP_METHOD_INVITE
:
3712 case SIP_METHOD_SUBSCRIBE
:
3713 case SIP_METHOD_REFER
:
3714 col_append_str(pinfo
->cinfo
, COL_INFO
, ", in-dialog");
3725 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
3726 hf_header_array
[hf_index
], tvb
,
3727 offset
, next_offset
- offset
,
3728 value_offset
, value_len
);
3729 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
3731 sip_element_tree
= proto_item_add_subtree( sip_element_item
, ett_sip_element
);
3733 * From = ( "From" / "f" ) HCOLON from-spec
3734 * from-spec = ( name-addr / addr-spec )
3735 * *( SEMI from-param )
3738 sip_uri_offset_init(&uri_offsets
);
3739 if((dissect_sip_name_addr_or_addr_spec(tvb
, pinfo
, value_offset
, line_end_offset
+2, &uri_offsets
)) != -1){
3740 display_sip_uri(tvb
, sip_element_tree
, pinfo
, &uri_offsets
, &sip_from_uri
);
3741 if((uri_offsets
.name_addr_start
!= -1) && (uri_offsets
.name_addr_end
!= -1)){
3742 stat_info
->tap_from_addr
=tvb_get_string_enc(pinfo
->pool
, tvb
, uri_offsets
.name_addr_start
,
3743 uri_offsets
.name_addr_end
- uri_offsets
.name_addr_start
+ 1, ENC_UTF_8
|ENC_NA
);
3745 offset
= uri_offsets
.name_addr_end
+1;
3748 /* Find parameter tag if present.
3749 * TODO make this generic to find any interesting parameter
3750 * use the same method as for SIP headers ?
3753 parameter_offset
= offset
;
3754 while (parameter_offset
< line_end_offset
3755 && (tvb_strneql(tvb
, parameter_offset
, "tag=", 4) != 0))
3757 if ( parameter_offset
< line_end_offset
){ /* Tag found */
3758 parameter_offset
= parameter_offset
+ 4;
3759 parameter_end_offset
= tvb_find_uint8(tvb
, parameter_offset
,
3760 (line_end_offset
- parameter_offset
), ';');
3761 if ( parameter_end_offset
== -1)
3762 parameter_end_offset
= line_end_offset
;
3763 parameter_len
= parameter_end_offset
- parameter_offset
;
3764 proto_tree_add_item(sip_element_tree
, hf_sip_from_tag
, tvb
, parameter_offset
,
3765 parameter_len
, ENC_UTF_8
);
3766 item
= proto_tree_add_item(sip_element_tree
, hf_sip_tag
, tvb
, parameter_offset
,
3767 parameter_len
, ENC_UTF_8
);
3768 proto_item_set_hidden(item
);
3773 case POS_P_ASSERTED_IDENTITY
:
3776 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
3777 hf_header_array
[hf_index
], tvb
,
3778 offset
, next_offset
- offset
,
3779 value_offset
, value_len
);
3780 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
3782 sip_element_tree
= proto_item_add_subtree( sip_element_item
,
3786 * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value
3787 * *(COMMA PAssertedID-value)
3788 * PAssertedID-value = name-addr / addr-spec
3790 * Initialize the uri_offsets
3792 sip_uri_offset_init(&uri_offsets
);
3793 if((dissect_sip_name_addr_or_addr_spec(tvb
, pinfo
, value_offset
, line_end_offset
+2, &uri_offsets
)) != -1)
3794 display_sip_uri(tvb
, sip_element_tree
, pinfo
, &uri_offsets
, &sip_pai_uri
);
3797 case POS_P_ASSOCIATED_URI
:
3800 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
3801 hf_header_array
[hf_index
], tvb
,
3802 offset
, next_offset
- offset
,
3803 value_offset
, value_len
);
3804 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
3806 * P-Associated-URI = "P-Associated-URI" HCOLON
3808 * *(COMMA p-aso-uri-spec)
3809 * p-aso-uri-spec = name-addr *(SEMI ai-param)
3810 * ai-param = generic-param
3812 /* Skip to the end of the URI directly */
3813 semi_colon_offset
= tvb_find_uint8(tvb
, value_offset
, line_end_offset
- value_offset
, '>');
3814 if (semi_colon_offset
!= -1) {
3815 semi_colon_offset
= tvb_find_uint8(tvb
, semi_colon_offset
, line_end_offset
- semi_colon_offset
, ';');
3816 if (semi_colon_offset
!= -1) {
3817 sip_element_tree
= proto_item_add_subtree(sip_element_item
,
3819 /* We have generic parameters */
3820 dissect_sip_generic_parameters(tvb
, sip_element_tree
, pinfo
, semi_colon_offset
+ 1, line_end_offset
);
3826 case POS_HISTORY_INFO
:
3829 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
3830 hf_header_array
[hf_index
], tvb
,
3831 offset
, next_offset
- offset
,
3832 value_offset
, value_len
);
3833 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
3835 sip_element_tree
= proto_item_add_subtree( sip_element_item
,
3837 dissect_sip_history_info(tvb
, sip_element_tree
, pinfo
, value_offset
, line_end_offset
);
3841 case POS_P_CHARGING_FUNC_ADDRESSES
:
3844 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
3845 hf_header_array
[hf_index
], tvb
,
3846 offset
, next_offset
- offset
,
3847 value_offset
, value_len
);
3848 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
3850 sip_element_tree
= proto_item_add_subtree( sip_element_item
,
3852 dissect_sip_p_charging_func_addresses(tvb
, sip_element_tree
, pinfo
, value_offset
, line_end_offset
);
3856 case POS_P_PREFERRED_IDENTITY
:
3859 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
3860 hf_header_array
[hf_index
], tvb
,
3861 offset
, next_offset
- offset
,
3862 value_offset
, value_len
);
3863 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
3865 sip_element_tree
= proto_item_add_subtree( sip_element_item
,
3868 * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value
3869 * *(COMMA PPreferredID-value)
3870 * PPreferredID-value = name-addr / addr-spec
3872 * Initialize the uri_offsets
3874 sip_uri_offset_init(&uri_offsets
);
3875 if((dissect_sip_name_addr_or_addr_spec(tvb
, pinfo
, value_offset
, line_end_offset
+2, &uri_offsets
)) != -1)
3876 display_sip_uri(tvb
, sip_element_tree
, pinfo
, &uri_offsets
, &sip_ppi_uri
);
3880 case POS_PERMISSION_MISSING
:
3883 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
3884 hf_header_array
[hf_index
], tvb
,
3885 offset
, next_offset
- offset
,
3886 value_offset
, value_len
);
3887 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
3889 sip_element_tree
= proto_item_add_subtree( sip_element_item
,
3892 * Permission-Missing = "Permission-Missing" HCOLON per-miss-spec
3893 * *( COMMA per-miss-spec )
3894 * per-miss-spec = ( name-addr / addr-spec )
3895 * *( SEMI generic-param )
3896 * Initialize the uri_offsets
3898 sip_uri_offset_init(&uri_offsets
);
3899 if((dissect_sip_name_addr_or_addr_spec(tvb
, pinfo
, value_offset
, line_end_offset
+2, &uri_offsets
)) != -1)
3900 display_sip_uri(tvb
, sip_element_tree
, pinfo
, &uri_offsets
, &sip_pmiss_uri
);
3905 case POS_TRIGGER_CONSENT
:
3908 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
3909 hf_header_array
[hf_index
], tvb
,
3910 offset
, next_offset
- offset
,
3911 value_offset
, value_len
);
3912 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
3914 sip_element_tree
= proto_item_add_subtree( sip_element_item
,
3917 * Trigger-Consent = "Trigger-Consent" HCOLON trigger-cons-spec
3918 * *( COMMA trigger-cons-spec )
3919 * trigger-cons-spec = ( SIP-URI / SIPS-URI )
3920 * *( SEMI trigger-param )
3921 * trigger-param = target-uri / generic-param
3922 * target-uri = "target-uri" EQUAL
3923 * LDQUOT *( qdtext / quoted-pair ) RDQUOT
3924 * Initialize the uri_offsets
3926 sip_uri_offset_init(&uri_offsets
);
3927 if((dissect_sip_uri(tvb
, pinfo
, value_offset
, line_end_offset
+2, &uri_offsets
)) != -1) {
3929 tc_uri_item_tree
= display_sip_uri(tvb
, sip_element_tree
, pinfo
, &uri_offsets
, &sip_tc_uri
);
3930 if (line_end_offset
> uri_offsets
.uri_end
) {
3931 int hparam_offset
= uri_offsets
.uri_end
+ 1;
3932 /* Is there a header parameter */
3933 if (tvb_find_uint8(tvb
, hparam_offset
, 1,';')) {
3934 while ((hparam_offset
!= -1 && hparam_offset
< line_end_offset
) ) {
3935 /* Is this a target-uri ? */
3936 hparam_offset
= hparam_offset
+ 1;
3937 if (tvb_strncaseeql(tvb
, hparam_offset
, "target-uri=\"", 12) == 0) {
3938 int turi_start_offset
= hparam_offset
+ 12;
3939 int turi_end_offset
= tvb_find_uint8(tvb
, turi_start_offset
, -1,'\"');
3940 if (turi_end_offset
!= -1)
3941 proto_tree_add_item(tc_uri_item_tree
, hf_sip_tc_turi
, tvb
, turi_start_offset
,(turi_end_offset
- turi_start_offset
),ENC_UTF_8
);
3943 break; /* malformed */
3945 hparam_offset
= tvb_find_uint8(tvb
, hparam_offset
, -1,';');
3952 case POS_RETRY_AFTER
:
3954 /* Store the retry number */
3955 char *value
= tvb_get_string_enc(pinfo
->pool
, tvb
, value_offset
, value_len
, ENC_UTF_8
| ENC_NA
);
3957 bool retry_valid
= ws_strtou32(value
, NULL
, &retry
);
3960 sip_element_item
= proto_tree_add_uint(hdr_tree
, hf_header_array
[hf_index
],
3961 tvb
, offset
, next_offset
- offset
,
3965 expert_add_info(pinfo
, sip_element_item
, &ei_sip_retry_after_invalid
);
3971 /* Store the sequence number */
3972 char *value
= tvb_get_string_enc(pinfo
->pool
, tvb
, value_offset
, value_len
, ENC_UTF_8
|ENC_NA
);
3974 cseq_number
= (uint32_t)strtoul(value
, NULL
, 10);
3975 cseq_number_set
= 1;
3976 stat_info
->tap_cseq_number
=cseq_number
;
3980 sip_element_item
= proto_tree_add_string(hdr_tree
,
3981 hf_header_array
[hf_index
], tvb
,
3982 offset
, next_offset
- offset
,
3984 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
3986 cseq_tree
= proto_item_add_subtree(sip_element_item
, ett_sip_cseq
);
3989 /* Walk past number and spaces characters to get to start
3991 for (sub_value_offset
=0; sub_value_offset
< value_len
; sub_value_offset
++)
3993 if (!g_ascii_isdigit(value
[sub_value_offset
]))
3995 proto_tree_add_uint(cseq_tree
, hf_sip_cseq_seq_no
,
3996 tvb
, value_offset
, sub_value_offset
,
4002 for (; sub_value_offset
< value_len
; sub_value_offset
++)
4004 if (g_ascii_isalpha(value
[sub_value_offset
]))
4006 /* Have reached start of method name */
4011 if (sub_value_offset
== value_len
)
4013 /* Didn't find method name */
4014 return offset
- orig_offset
;
4017 /* Extract method name from value */
4018 strlen_to_copy
= (int)value_len
-sub_value_offset
;
4019 if (strlen_to_copy
> MAX_CSEQ_METHOD_SIZE
) {
4020 /* Note the error in the protocol tree */
4021 proto_tree_add_string_format(hdr_tree
,
4022 hf_header_array
[hf_index
], tvb
,
4023 offset
, next_offset
- offset
,
4024 value
+sub_value_offset
, "%s String too big: %d bytes",
4025 sip_headers
[POS_CSEQ
].name
,
4027 return offset
- orig_offset
;
4030 /* Add CSeq method to the tree */
4031 proto_tree_add_item_ret_string(cseq_tree
, hf_sip_cseq_method
, tvb
,
4032 value_offset
+ sub_value_offset
, strlen_to_copy
, ENC_UTF_8
,
4033 pinfo
->pool
, (const uint8_t **)&cseq_method
);
4040 char *value
= tvb_get_string_enc(pinfo
->pool
, tvb
, value_offset
, value_len
, ENC_UTF_8
|ENC_NA
);
4042 /*int cseq_method_offset;*/
4046 sip_element_item
= proto_tree_add_string(hdr_tree
,
4047 hf_header_array
[hf_index
], tvb
,
4048 offset
, next_offset
- offset
,
4050 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4052 rack_tree
= proto_item_add_subtree(sip_element_item
, ett_sip_rack
);
4056 for (sub_value_offset
=0; sub_value_offset
< value_len
; sub_value_offset
++)
4058 if (!g_ascii_isdigit(value
[sub_value_offset
]))
4060 proto_tree_add_uint(rack_tree
, hf_sip_rack_rseq_no
,
4061 tvb
, value_offset
, sub_value_offset
,
4062 (uint32_t)strtoul(value
, NULL
, 10));
4067 /* Get to start of CSeq number */
4068 for ( ; sub_value_offset
< value_len
; sub_value_offset
++)
4070 if (value
[sub_value_offset
] != ' ' &&
4071 value
[sub_value_offset
] != '\t')
4076 cseq_no_offset
= sub_value_offset
;
4079 for ( ; sub_value_offset
< value_len
; sub_value_offset
++)
4081 if (!g_ascii_isdigit(value
[sub_value_offset
]))
4083 proto_tree_add_uint(rack_tree
, hf_sip_rack_cseq_no
,
4084 tvb
, value_offset
+cseq_no_offset
,
4085 sub_value_offset
-cseq_no_offset
,
4086 (uint32_t)strtoul(value
+cseq_no_offset
, NULL
, 10));
4091 /* Get to start of CSeq method name */
4092 for ( ; sub_value_offset
< value_len
; sub_value_offset
++)
4094 if (g_ascii_isalpha(value
[sub_value_offset
]))
4096 /* Have reached start of method name */
4100 /*cseq_method_offset = sub_value_offset;*/
4102 if (sub_value_offset
== linelen
)
4104 /* Didn't find method name */
4105 return offset
- orig_offset
;
4108 /* Add CSeq method to the tree */
4111 proto_tree_add_item(rack_tree
, hf_sip_rack_cseq_method
, tvb
,
4112 value_offset
+ sub_value_offset
,
4113 (int)value_len
-sub_value_offset
, ENC_UTF_8
);
4121 call_id
= tvb_get_string_enc(pinfo
->pool
, tvb
, value_offset
, value_len
, ENC_UTF_8
|ENC_NA
);
4122 proto_item
*gen_item
;
4124 /* Store the Call-id */
4125 stat_info
->tap_call_id
= call_id
;
4127 /* Add 'Call-id' string item to tree */
4128 sip_element_item
= proto_tree_add_string(hdr_tree
,
4129 hf_header_array
[hf_index
], tvb
,
4130 offset
, next_offset
- offset
,
4132 gen_item
= proto_tree_add_string(hdr_tree
,
4133 hf_sip_call_id_gen
, tvb
,
4134 offset
, next_offset
- offset
,
4136 proto_item_set_generated(gen_item
);
4137 if (sip_hide_generatd_call_ids
) {
4138 proto_item_set_hidden(gen_item
);
4140 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4145 if (tvb_strneql(tvb
, value_offset
, "0", value_len
) == 0)
4150 /* Add 'Expires' string item to tree */
4151 sip_proto_tree_add_uint(hdr_tree
,
4152 hf_header_array
[hf_index
], tvb
,
4153 offset
, next_offset
- offset
,
4154 value_offset
, value_len
);
4158 * Content-Type is the same as Internet
4159 * media type used by other dissectors,
4160 * appropriate dissector found by
4161 * lookup in "media_type" dissector table.
4163 case POS_CONTENT_TYPE
:
4164 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4165 hf_header_array
[hf_index
], tvb
,
4166 offset
, next_offset
- offset
,
4167 value_offset
, value_len
);
4168 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4170 content_type_len
= value_len
;
4171 semi_colon_offset
= tvb_find_uint8(tvb
, value_offset
, value_len
, ';');
4172 /* Content-Type = ( "Content-Type" / "c" ) HCOLON media-type
4173 * media-type = m-type SLASH m-subtype *(SEMI m-parameter)
4174 * SEMI = SWS ";" SWS ; semicolon
4175 * LWS = [*WSP CRLF] 1*WSP ; linear whitespace
4176 * SWS = [LWS] ; sep whitespace
4178 if ( semi_colon_offset
!= -1) {
4179 int content_type_end
;
4181 * Skip whitespace after the semicolon.
4183 parameter_offset
= tvb_skip_wsp(tvb
, semi_colon_offset
+1, value_offset
+ value_len
- (semi_colon_offset
+1));
4184 content_type_end
= tvb_skip_wsp_return(tvb
, semi_colon_offset
-1);
4185 content_type_len
= content_type_end
- value_offset
;
4186 content_type_parameter_str_len
= value_offset
+ value_len
- parameter_offset
;
4187 content_info
.media_str
= tvb_get_string_enc(pinfo
->pool
, tvb
, parameter_offset
,
4188 content_type_parameter_str_len
, ENC_UTF_8
|ENC_NA
);
4190 media_type_str_lower_case
= ascii_strdown_inplace(
4191 (char *)tvb_get_string_enc(pinfo
->pool
, tvb
, value_offset
, content_type_len
, ENC_UTF_8
|ENC_NA
));
4194 proto_tree_add_debug_text(hdr_tree, tvb, value_offset,content_type_len,
4195 "media_type_str(lower cased)=%s",media_type_str_lower_case);
4199 case POS_CONTENT_LENGTH
:
4201 char *value
= tvb_get_string_enc(pinfo
->pool
, tvb
, value_offset
, value_len
, ENC_UTF_8
|ENC_NA
);
4202 bool content_length_valid
= ws_strtou32(value
, NULL
, &content_length
);
4204 sip_element_item
= proto_tree_add_uint(hdr_tree
,
4205 hf_header_array
[hf_index
], tvb
,
4206 offset
, next_offset
- offset
,
4208 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4209 if (!content_length_valid
)
4210 expert_add_info(pinfo
, sip_element_item
, &ei_sip_content_length_invalid
);
4215 case POS_MAX_BREADTH
:
4216 case POS_MAX_FORWARDS
:
4218 sip_proto_tree_add_uint(hdr_tree
,
4219 hf_header_array
[hf_index
], tvb
,
4220 offset
, next_offset
- offset
,
4221 value_offset
, value_len
);
4226 * Contact = ("Contact" / "m" ) HCOLON
4227 * ( STAR / (contact-param *(COMMA contact-param)))
4228 * contact-param = (name-addr / addr-spec) *(SEMI contact-params)
4230 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4231 hf_header_array
[hf_index
], tvb
,
4232 offset
, next_offset
- offset
,
4233 value_offset
, value_len
);
4234 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4236 sip_element_tree
= proto_item_add_subtree( sip_element_item
,
4239 /* value_offset points to the first non SWS character after ':' */
4240 c
= tvb_get_uint8(tvb
, value_offset
);
4242 contact_is_star
= 1;
4247 comma_offset
= value_offset
;
4248 while((comma_offset
= dissect_sip_contact_item(tvb
, pinfo
, sip_element_tree
, comma_offset
,
4249 next_offset
, &contacts_expires_0
, &contacts_expires_unknown
)) != -1)
4252 if(comma_offset
== next_offset
)
4254 /* Line End reached: Stop Parsing */
4258 if(tvb_get_uint8(tvb
, comma_offset
) != ',')
4260 /* Undefined value reached: Stop Parsing */
4263 comma_offset
++; /* skip comma */
4268 case POS_AUTHORIZATION
:
4269 /* Authorization = "Authorization" HCOLON credentials
4270 * credentials = ("Digest" LWS digest-response)
4272 * digest-response = dig-resp *(COMMA dig-resp)
4273 * other-response = auth-scheme LWS auth-param
4274 * *(COMMA auth-param)
4276 case POS_WWW_AUTHENTICATE
:
4277 /* Proxy-Authenticate = "Proxy-Authenticate" HCOLON challenge
4278 * challenge = ("Digest" LWS digest-cln *(COMMA digest-cln))
4280 * other-challenge = auth-scheme LWS auth-param
4281 * *(COMMA auth-param)
4282 * auth-scheme = token
4284 case POS_PROXY_AUTHENTICATE
:
4285 /* Proxy-Authenticate = "Proxy-Authenticate" HCOLON challenge
4287 case POS_PROXY_AUTHORIZATION
:
4288 /* Proxy-Authorization = "Proxy-Authorization" HCOLON credentials
4290 case POS_AUTHENTICATION_INFO
:
4291 /* Authentication-Info = "Authentication-Info" HCOLON ainfo
4293 * ainfo = nextnonce / message-qop
4294 * / response-auth / cnonce
4297 /* Add tree using whole text of line */
4300 sip_authorization_t authorization_info
= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
4301 authorization_user_t
* authorization_user
= NULL
;
4302 /* Add whole line as header tree */
4303 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4304 hf_header_array
[hf_index
], tvb
,
4305 offset
, next_offset
- offset
,
4306 value_offset
, value_len
);
4307 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4309 sip_element_tree
= proto_item_add_subtree( sip_element_item
,
4312 /* Set sip.auth as a hidden field/filter */
4313 ti_c
= proto_tree_add_item(hdr_tree
, hf_sip_auth
, tvb
,
4314 offset
, next_offset
-offset
,
4316 proto_item_set_hidden(ti_c
);
4318 /* Check if we have any parameters */
4319 if ((line_end_offset
- value_offset
) != 0) {
4320 /* Authentication-Info does not begin with the scheme name */
4321 if (hf_index
!= POS_AUTHENTICATION_INFO
)
4323 /* The first time comma_offset is "start of parameters" */
4324 comma_offset
= tvb_ws_mempbrk_pattern_uint8(tvb
, value_offset
, line_end_offset
- value_offset
, &pbrk_whitespace
, NULL
);
4325 proto_tree_add_item(sip_element_tree
, hf_sip_auth_scheme
,
4326 tvb
, value_offset
, comma_offset
- value_offset
,
4327 ENC_UTF_8
| ENC_NA
);
4329 /* The first time comma_offset is "start of parameters" */
4330 comma_offset
= value_offset
;
4333 /* Parse each individual parameter in the line */
4334 while ((comma_offset
= dissect_sip_authorization_item(tvb
, sip_element_tree
, comma_offset
, line_end_offset
, &authorization_info
)) != -1)
4336 if (comma_offset
== line_end_offset
)
4338 /* Line End reached: Stop Parsing */
4342 if (tvb_get_uint8(tvb
, comma_offset
) != ',')
4344 /* Undefined value reached: Stop Parsing */
4347 comma_offset
++; /* skip comma */
4349 if ((authorization_info
.response
!= NULL
) && (global_sip_validate_authorization
) &&
4350 (authorization_info
.username
!= NULL
) && (authorization_info
.realm
!= NULL
)) { /* If there is a response, check for valid credentials */
4351 authorization_user
= sip_get_authorization(&authorization_info
);
4352 if (authorization_user
) {
4353 authorization_info
.method
= wmem_strdup(pinfo
->pool
, stat_info
->request_method
);
4354 if (!sip_validate_authorization(&authorization_info
, authorization_user
->password
)) {
4355 proto_tree_add_expert_format(tree
, pinfo
, &ei_sip_authorization_invalid
, tvb
, offset
, line_end_offset
- offset
, "SIP digest does not match known password %s", authorization_user
->password
);
4359 } /* Check if we have any parameters */
4364 /* Add Route subtree */
4366 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4367 hf_header_array
[hf_index
], tvb
,
4368 offset
, next_offset
- offset
,
4369 value_offset
, value_len
);
4370 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4372 route_tree
= proto_item_add_subtree(sip_element_item
, ett_sip_route
);
4373 dissect_sip_route_header(tvb
, route_tree
, pinfo
, &sip_route_uri
, value_offset
, line_end_offset
);
4376 case POS_RECORD_ROUTE
:
4377 /* Add Record-Route subtree */
4379 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4380 hf_header_array
[hf_index
], tvb
,
4381 offset
, next_offset
- offset
,
4382 value_offset
, value_len
);
4383 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4385 route_tree
= proto_item_add_subtree(sip_element_item
, ett_sip_route
);
4386 dissect_sip_route_header(tvb
, route_tree
, pinfo
, &sip_record_route_uri
, value_offset
, line_end_offset
);
4389 case POS_SERVICE_ROUTE
:
4390 /* Add Service-Route subtree */
4392 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4393 hf_header_array
[hf_index
], tvb
,
4394 offset
, next_offset
- offset
,
4395 value_offset
, value_len
);
4396 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4398 route_tree
= proto_item_add_subtree(sip_element_item
, ett_sip_route
);
4399 dissect_sip_route_header(tvb
, route_tree
, pinfo
, &sip_service_route_uri
, value_offset
, line_end_offset
);
4403 /* Add Path subtree */
4405 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4406 hf_header_array
[hf_index
], tvb
,
4407 offset
, next_offset
- offset
,
4408 value_offset
, value_len
);
4409 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4411 route_tree
= proto_item_add_subtree(sip_element_item
, ett_sip_route
);
4412 dissect_sip_route_header(tvb
, route_tree
, pinfo
, &sip_path_uri
, value_offset
, line_end_offset
);
4416 /* Add Via subtree */
4418 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4419 hf_header_array
[hf_index
], tvb
,
4420 offset
, next_offset
- offset
,
4421 value_offset
, value_len
);
4422 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4424 via_tree
= proto_item_add_subtree(sip_element_item
, ett_sip_via
);
4425 dissect_sip_via_header(tvb
, via_tree
, value_offset
, line_end_offset
, pinfo
);
4430 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4431 hf_header_array
[hf_index
], tvb
,
4432 offset
, next_offset
- offset
,
4433 value_offset
, value_len
);
4434 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4436 reason_tree
= proto_item_add_subtree(sip_element_item
, ett_sip_reason
);
4437 dissect_sip_reason_header(tvb
, reason_tree
, pinfo
, value_offset
, line_end_offset
);
4440 case POS_CONTENT_ENCODING
:
4441 /* Content-Encoding = ( "Content-Encoding" / "e" ) HCOLON
4442 * content-coding *(COMMA content-coding)
4444 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4445 hf_header_array
[hf_index
], tvb
,
4446 offset
, next_offset
- offset
,
4447 value_offset
, value_len
);
4448 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4450 content_encoding_parameter_str
= ascii_strdown_inplace(tvb_get_string_enc(pinfo
->pool
, tvb
, value_offset
,
4451 (line_end_offset
-value_offset
), ENC_UTF_8
|ENC_NA
));
4453 case POS_SECURITY_CLIENT
:
4454 /* security-client = "Security-Client" HCOLON
4455 * sec-mechanism *(COMMA sec-mechanism)
4457 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4458 hf_header_array
[hf_index
], tvb
,
4459 offset
, next_offset
- offset
,
4460 value_offset
, value_len
);
4461 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4463 comma_offset
= tvb_find_uint8(tvb
, value_offset
, line_end_offset
- value_offset
, ',');
4464 while(comma_offset
<line_end_offset
){
4465 comma_offset
= tvb_find_uint8(tvb
, value_offset
, line_end_offset
- value_offset
, ',');
4466 if(comma_offset
== -1){
4467 comma_offset
= line_end_offset
;
4469 security_client_tree
= proto_item_add_subtree(sip_element_item
, ett_sip_security_client
);
4470 dissect_sip_sec_mechanism(tvb
, pinfo
, security_client_tree
, value_offset
, comma_offset
);
4471 comma_offset
= value_offset
= comma_offset
+1;
4475 case POS_SECURITY_SERVER
:
4476 /* security-server = "Security-Server" HCOLON
4477 * sec-mechanism *(COMMA sec-mechanism)
4479 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4480 hf_header_array
[hf_index
], tvb
,
4481 offset
, next_offset
- offset
,
4482 value_offset
, value_len
);
4483 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4485 comma_offset
= tvb_find_uint8(tvb
, value_offset
, line_end_offset
- value_offset
, ',');
4486 while(comma_offset
<line_end_offset
){
4487 comma_offset
= tvb_find_uint8(tvb
, value_offset
, line_end_offset
- value_offset
, ',');
4488 if(comma_offset
== -1){
4489 comma_offset
= line_end_offset
;
4491 security_client_tree
= proto_item_add_subtree(sip_element_item
, ett_sip_security_server
);
4492 dissect_sip_sec_mechanism(tvb
, pinfo
, security_client_tree
, value_offset
, comma_offset
);
4493 comma_offset
= value_offset
= comma_offset
+1;
4497 case POS_SECURITY_VERIFY
:
4498 /* security-verify = "Security-Verify" HCOLON
4499 * sec-mechanism *(COMMA sec-mechanism)
4501 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4502 hf_header_array
[hf_index
], tvb
,
4503 offset
, next_offset
- offset
,
4504 value_offset
, value_len
);
4505 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4507 comma_offset
= tvb_find_uint8(tvb
, value_offset
, line_end_offset
- value_offset
, ',');
4508 while(comma_offset
<line_end_offset
){
4509 comma_offset
= tvb_find_uint8(tvb
, value_offset
, line_end_offset
- value_offset
, ',');
4510 if(comma_offset
== -1){
4511 comma_offset
= line_end_offset
;
4513 security_client_tree
= proto_item_add_subtree(sip_element_item
, ett_sip_security_verify
);
4514 dissect_sip_sec_mechanism(tvb
, pinfo
, security_client_tree
, value_offset
, comma_offset
);
4515 comma_offset
= value_offset
= comma_offset
+1;
4519 case POS_SESSION_ID
:
4521 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4522 hf_header_array
[hf_index
], tvb
,
4523 offset
, next_offset
- offset
,
4524 value_offset
, value_len
);
4525 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4526 session_id_tree
= proto_item_add_subtree(sip_element_item
, ett_sip_session_id
);
4527 dissect_sip_session_id_header(tvb
, session_id_tree
, value_offset
, line_end_offset
, pinfo
);
4530 case POS_P_ACCESS_NETWORK_INFO
:
4531 /* Add P-Access-Network-Info subtree */
4533 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4534 hf_header_array
[hf_index
], tvb
,
4535 offset
, next_offset
- offset
,
4536 value_offset
, value_len
);
4537 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4538 p_access_net_info_tree
= proto_item_add_subtree(sip_element_item
, ett_sip_p_access_net_info
);
4539 dissect_sip_p_access_network_info_header(tvb
, pinfo
, p_access_net_info_tree
, value_offset
, line_end_offset
);
4542 case POS_P_CHARGING_VECTOR
:
4544 proto_tree
*p_charging_vector_tree
;
4546 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4547 hf_header_array
[hf_index
], tvb
,
4548 offset
, next_offset
- offset
,
4549 value_offset
, value_len
);
4550 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4551 p_charging_vector_tree
= proto_item_add_subtree(sip_element_item
, ett_sip_p_charging_vector
);
4552 dissect_sip_p_charging_vector_header(tvb
, p_charging_vector_tree
, value_offset
, line_end_offset
);
4555 case POS_FEATURE_CAPS
:
4557 proto_tree
*feature_caps_tree
;
4559 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4560 hf_header_array
[hf_index
], tvb
,
4561 offset
, next_offset
- offset
,
4562 value_offset
, value_len
);
4563 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4564 feature_caps_tree
= proto_item_add_subtree(sip_element_item
, ett_sip_feature_caps
);
4565 dissect_sip_p_feature_caps(tvb
, feature_caps_tree
, value_offset
, line_end_offset
);
4569 /* Default case is to assume it's an FT_STRING field */
4570 sip_element_item
= sip_proto_tree_add_string(hdr_tree
,
4571 hf_header_array
[hf_index
], tvb
,
4572 offset
, next_offset
- offset
,
4573 value_offset
, value_len
);
4574 sip_proto_set_format_text(hdr_tree
, sip_element_item
, tvb
, offset
, linelen
);
4578 }/* if colon_offset */
4579 if (is_no_header_termination
== true){
4580 /* Header not terminated by empty line CRLF */
4581 proto_tree_add_expert(hdr_tree
, pinfo
, &ei_sip_header_not_terminated
,
4582 tvb
, line_end_offset
, -1);
4584 remaining_length
= remaining_length
- (next_offset
- offset
);
4585 offset
= next_offset
;
4588 datalen
= tvb_captured_length_remaining(tvb
, offset
);
4589 reported_datalen
= tvb_reported_length_remaining(tvb
, offset
);
4590 if (content_length
!= -1) {
4591 if (datalen
> content_length
)
4592 datalen
= content_length
;
4593 if (reported_datalen
> content_length
)
4594 reported_datalen
= content_length
;
4598 call_id
= wmem_strdup(pinfo
->pool
, "");
4599 expert_add_info(pinfo
, hdr_tree
, &ei_sip_call_id_invalid
);
4600 /* XXX: The hash table lookups below (setup time, request/response,
4601 * resend) are less reliable when the mandatory Call-Id header field
4606 /* Add to info column interesting things learned from header fields. */
4608 /* for either REGISTER requests or responses, any contacts without expires
4609 * parameter use the Expires header's value
4612 /* this may add nothing, but that's ok */
4613 contacts_expires_0
+= contacts_expires_unknown
;
4616 /* Registration requests */
4617 if (current_method_idx
== SIP_METHOD_REGISTER
)
4619 /* TODO: what if there's a *-contact but also non-*-contacts?
4620 * we should create expert info for that someday I guess
4622 if (contact_is_star
&& expires_is_0
)
4624 col_append_str(pinfo
->cinfo
, COL_INFO
, " (remove all bindings)");
4627 if (contacts_expires_0
> 0)
4629 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (remove %d binding%s)",
4630 contacts_expires_0
, contacts_expires_0
== 1 ? "":"s");
4631 if (contacts
> contacts_expires_0
) {
4632 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (add %d binding%s)",
4633 contacts
- contacts_expires_0
,
4634 (contacts
- contacts_expires_0
== 1) ? "":"s");
4640 col_append_str(pinfo
->cinfo
, COL_INFO
, " (fetch bindings)");
4644 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%d binding%s)",
4645 contacts
, contacts
== 1 ? "":"s");
4649 /* Registration responses - this info only makes sense in 2xx responses */
4650 if (line_type
== STATUS_LINE
&& stat_info
)
4652 if (stat_info
->response_code
== 200)
4654 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%s)", cseq_method
);
4656 if ((strcmp(cseq_method
, "REGISTER") == 0) &&
4657 stat_info
->response_code
> 199 && stat_info
->response_code
< 300)
4659 if (contacts_expires_0
> 0) {
4660 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (removed %d binding%s)",
4661 contacts_expires_0
, contacts_expires_0
== 1 ? "":"s");
4662 if (contacts
> contacts_expires_0
) {
4663 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%d binding%s kept)",
4664 contacts
- contacts_expires_0
,
4665 (contacts
- contacts_expires_0
== 1) ? "":"s");
4668 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (%d binding%s)",
4669 contacts
, contacts
== 1 ? "":"s");
4674 /* We've finished writing to the info col for this SIP message
4675 * Set fence in case there is more than one (SIP)message in the frame
4677 /* XXX: this produces ugly output, since usually there's only one SIP
4678 * message in a frame yet this '|' gets added at the end. Need a better
4681 col_append_str(pinfo
->cinfo
, COL_INFO
, " | ");
4682 col_set_fence(pinfo
->cinfo
, COL_INFO
);
4684 /* Find the total setup time, Must be done before checking for resend
4685 * As that will overwrite the "Request packet no".
4687 if ((line_type
== REQUEST_LINE
)&&(strcmp(cseq_method
, "ACK") == 0))
4689 request_for_response
= sip_find_invite(pinfo
, cseq_method
, call_id
,
4690 cseq_number_set
, cseq_number
,
4692 stat_info
->setup_time
= response_time
;
4695 /* For responses, try to link back to request frame */
4696 if (line_type
== STATUS_LINE
)
4698 request_for_response
= sip_find_request(pinfo
, cseq_method
, call_id
,
4699 cseq_number_set
, cseq_number
,
4703 /* Check if this packet is a resend. */
4704 resend_for_packet
= sip_is_packet_resend(pinfo
, cseq_method
, call_id
,
4705 cseq_number_set
, cseq_number
,
4707 /* Mark whether this is a resend for the tap */
4708 stat_info
->resend
= (resend_for_packet
> 0);
4710 /* Report this packet to the tap */
4711 if (!pinfo
->flags
.in_error_pkt
)
4713 tap_queue_packet(sip_tap
, pinfo
, stat_info
);
4718 * There's a message body starting at "offset".
4719 * Set the length of the header item.
4721 sdp_setup_info_t setup_info
= {
4722 .hf_id
= hf_sip_call_id_gen
,
4723 .add_hidden
= sip_hide_generatd_call_ids
,
4724 .hf_type
= SDP_TRACE_ID_HF_TYPE_STR
,
4725 .trace_id
.str
= wmem_strdup(wmem_file_scope(), call_id
),
4727 content_info
.data
= &setup_info
;
4729 if(content_encoding_parameter_str
!= NULL
&&
4730 (!strncmp(content_encoding_parameter_str
, "gzip", 4) ||
4731 !strncmp(content_encoding_parameter_str
,"deflate",7))){
4732 /* The body is gzip:ed */
4733 next_tvb
= tvb_child_uncompress_zlib(tvb
, tvb
, offset
, datalen
);
4735 add_new_data_source(pinfo
, next_tvb
, "gunzipped data");
4737 ti_a
= proto_tree_add_item(sip_tree
, hf_sip_msg_body
, next_tvb
, 0, -1,
4739 message_body_tree
= proto_item_add_subtree(ti_a
, ett_sip_message_body
);
4742 next_tvb
= tvb_new_subset_length_caplen(tvb
, offset
, datalen
, reported_datalen
);
4744 ti_a
= proto_tree_add_item(sip_tree
, hf_sip_msg_body
, next_tvb
, 0, -1,
4746 message_body_tree
= proto_item_add_subtree(ti_a
, ett_sip_message_body
);
4750 next_tvb
= tvb_new_subset_length_caplen(tvb
, offset
, datalen
, reported_datalen
);
4752 ti_a
= proto_tree_add_item(sip_tree
, hf_sip_msg_body
, next_tvb
, 0, -1,
4754 message_body_tree
= proto_item_add_subtree(ti_a
, ett_sip_message_body
);
4758 /* give the content type parameters to sub dissectors */
4759 if ( media_type_str_lower_case
!= NULL
) {
4760 /* SDP needs a transport layer to determine request/response */
4761 if (!strcmp(media_type_str_lower_case
, "application/sdp")) {
4762 /* Resends don't count */
4763 if (resend_for_packet
== 0) {
4764 if (line_type
== REQUEST_LINE
) {
4765 DPRINT(("calling setup_sdp_transport() SDP_EXCHANGE_OFFER frame=%d",
4768 setup_sdp_transport(next_tvb
, pinfo
, SDP_EXCHANGE_OFFER
, pinfo
->num
, sip_delay_sdp_changes
, &setup_info
);
4770 } else if (line_type
== STATUS_LINE
) {
4771 if (stat_info
->response_code
>= 400) {
4772 DPRINT(("calling setup_sdp_transport() SDP_EXCHANGE_ANSWER_REJECT "
4773 "request_frame=%d, this=%d",
4774 request_for_response
, pinfo
->num
));
4776 /* SIP client request failed, so SDP offer should fail */
4777 setup_sdp_transport(next_tvb
, pinfo
, SDP_EXCHANGE_ANSWER_REJECT
, request_for_response
, sip_delay_sdp_changes
, &setup_info
);
4780 else if ((stat_info
->response_code
>= 200) && (stat_info
->response_code
<= 299)) {
4781 DPRINT(("calling setup_sdp_transport() SDP_EXCHANGE_ANSWER_ACCEPT "
4782 "request_frame=%d, this=%d",
4783 request_for_response
, pinfo
->num
));
4785 /* SIP success request, so SDP offer should be accepted */
4786 setup_sdp_transport(next_tvb
, pinfo
, SDP_EXCHANGE_ANSWER_ACCEPT
, request_for_response
, sip_delay_sdp_changes
, &setup_info
);
4791 DPRINT(("calling setup_sdp_transport() resend_for_packet "
4792 "request_frame=%d, this=%d",
4793 request_for_response
, pinfo
->num
));
4795 setup_sdp_transport_resend(pinfo
->num
, resend_for_packet
);
4800 /* XXX: why is this called even if setup_sdp_transport() was called before? That will
4801 parse the SDP a second time, for 'application/sdp' media MIME bodies */
4802 DPRINT(("calling dissector_try_string_with_data()"));
4804 found_match
= dissector_try_string_with_data(media_type_dissector_table
,
4805 media_type_str_lower_case
,
4807 message_body_tree
, true, &content_info
);
4809 DPRINT(("done calling dissector_try_string_with_data() with found_match=%u", found_match
));
4812 !strncmp(media_type_str_lower_case
, "multipart/", sizeof("multipart/")-1)) {
4813 DPRINT(("calling dissector_try_string_with_data() for multipart"));
4815 /* Try to decode the unknown multipart subtype anyway */
4816 found_match
= dissector_try_string_with_data(media_type_dissector_table
,
4819 message_body_tree
, true, &content_info
);
4821 DPRINT(("done calling dissector_try_string_with_data() with found_match=%u", found_match
));
4823 /* If no match dump as text */
4825 if ( found_match
== 0 )
4827 DPRINT(("calling dissector_try_heuristic() with found_match=0"));
4829 if (!(dissector_try_heuristic(heur_subdissector_list
,
4830 next_tvb
, pinfo
, message_body_tree
, &hdtbl_entry
, NULL
))) {
4832 while (tvb_offset_exists(next_tvb
, tmp_offset
)) {
4833 tvb_find_line_end(next_tvb
, tmp_offset
, -1, &next_offset
, false);
4834 linelen
= next_offset
- tmp_offset
;
4835 proto_tree_add_format_text(message_body_tree
, next_tvb
,
4836 tmp_offset
, linelen
);
4837 tmp_offset
= next_offset
;
4845 /* And add the filterable field to the request/response line */
4849 item
= proto_tree_add_boolean(reqresp_tree
, hf_sip_resend
, tvb
, orig_offset
, 0,
4850 resend_for_packet
> 0);
4851 proto_item_set_generated(item
);
4852 if (resend_for_packet
> 0)
4854 item
= proto_tree_add_uint(reqresp_tree
, hf_sip_original_frame
,
4855 tvb
, orig_offset
, 0, resend_for_packet
);
4856 proto_item_set_generated(item
);
4859 if (request_for_response
> 0)
4861 item
= proto_tree_add_uint(reqresp_tree
, hf_sip_matching_request_frame
,
4862 tvb
, orig_offset
, 0, request_for_response
);
4863 proto_item_set_generated(item
);
4864 item
= proto_tree_add_uint(reqresp_tree
, hf_sip_response_time
,
4865 tvb
, orig_offset
, 0, response_time
);
4866 proto_item_set_generated(item
);
4867 if ((line_type
== STATUS_LINE
)&&(strcmp(cseq_method
, "BYE") == 0)){
4868 item
= proto_tree_add_uint(reqresp_tree
, hf_sip_release_time
,
4869 tvb
, orig_offset
, 0, response_time
);
4870 proto_item_set_generated(item
);
4876 proto_item_set_len(ts
, offset
- orig_offset
);
4878 if (global_sip_raw_text
)
4879 tvb_raw_text_add(tvb
, orig_offset
, offset
- orig_offset
, body_offset
, pinfo
, tree
);
4881 /* Append a brief summary to the SIP root item */
4882 if (stat_info
->request_method
) {
4883 proto_item_append_text(ts
, " (%s)", stat_info
->request_method
);
4886 proto_item_append_text(ts
, " (%u)", stat_info
->response_code
);
4888 return offset
- orig_offset
;
4891 /* Display filter for SIP Request-Line */
4893 dfilter_sip_request_line(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, int offset
, unsigned meth_len
, int linelen
)
4895 const uint8_t *value
;
4896 unsigned parameter_len
= meth_len
;
4897 uri_offset_info uri_offsets
;
4900 * We know we have the entire method; otherwise, "sip_parse_line()"
4901 * would have returned OTHER_LINE.
4902 * Request-Line = Method SP Request-URI SP SIP-Version CRLF
4904 * Request-URI = SIP-URI / SIPS-URI / absoluteURI
4907 /* get method string*/
4908 proto_tree_add_item_ret_string(tree
, hf_sip_Method
, tvb
, offset
, parameter_len
, ENC_ASCII
| ENC_NA
,
4909 pinfo
->pool
, &value
);
4911 /* Copy request method for telling tap */
4912 stat_info
->request_method
= value
;
4915 /* build Request-URI tree*/
4916 offset
=offset
+ parameter_len
+1;
4917 sip_uri_offset_init(&uri_offsets
);
4919 uri_offsets
.uri_end
= tvb_find_uint8(tvb
, offset
, linelen
, ' ')-1;
4920 dissect_sip_uri(tvb
, pinfo
, offset
, offset
+ linelen
, &uri_offsets
);
4921 display_sip_uri(tvb
, tree
, pinfo
, &uri_offsets
, &sip_req_uri
);
4925 /* Display filter for SIP Status-Line */
4927 dfilter_sip_status_line(tvbuff_t
*tvb
, proto_tree
*tree
, packet_info
*pinfo
, int line_end
, int offset
)
4929 int response_code
= 0;
4930 bool response_code_valid
;
4936 * We know we have the entire status code; otherwise,
4937 * "sip_parse_line()" would have returned OTHER_LINE.
4938 * We also know that we have a version string followed by a
4939 * space at the beginning of the line, for the same reason.
4941 offset
= offset
+ SIP2_HDR_LEN
+ 1;
4942 response_code_valid
= ws_strtoi32(tvb_get_string_enc(pinfo
->pool
, tvb
, offset
, 3,
4943 ENC_UTF_8
|ENC_NA
), NULL
, &response_code
);
4945 /* Add numerical response code to tree */
4946 pi
= proto_tree_add_uint(tree
, hf_sip_Status_Code
, tvb
, offset
, 3, response_code
);
4947 if (!response_code_valid
)
4948 expert_add_info(pinfo
, pi
, &ei_sip_Status_Code_invalid
);
4950 /* Add response code for sending to tap */
4951 stat_info
->response_code
= response_code
;
4953 /* Skip past the response code and possible trailing space */
4954 offset
= offset
+ 3 + 1;
4956 /* Check for diagnostics */
4957 diag_len
= line_end
- (SIP2_HDR_LEN
+ 1 + 3 + 1);
4961 /* If we have a SIP diagnostics sub dissector call it */
4962 if(sip_diag_handle
){
4963 next_tvb
= tvb_new_subset_length(tvb
, offset
, diag_len
);
4964 call_dissector_only(sip_diag_handle
, next_tvb
, pinfo
, tree
, NULL
);
4968 /* From section 4.1 of RFC 2543:
4970 * Request-Line = Method SP Request-URI SP SIP-Version CRLF
4972 * From section 5.1 of RFC 2543:
4974 * Status-Line = SIP-version SP Status-Code SP Reason-Phrase CRLF
4976 * From section 7.1 of RFC 3261:
4978 * Unlike HTTP, SIP treats the version number as a literal string.
4979 * In practice, this should make no difference.
4982 sip_parse_line(tvbuff_t
*tvb
, int offset
, int linelen
, unsigned *token_1_lenp
)
4986 unsigned token_1_len
;
4988 unsigned token_2_len
;
4990 unsigned token_3_len
;
4993 token_1_start
= offset
;
4994 space_offset
= tvb_find_uint8(tvb
, token_1_start
, -1, ' ');
4995 if ((space_offset
== -1) || (space_offset
== token_1_start
)) {
4997 * Either there's no space in the line (which means
4998 * the line is empty or doesn't have a token followed
4999 * by a space; neither is valid for a request or status), or
5000 * the first character in the line is a space (meaning
5001 * the method is empty, which isn't valid for a request,
5002 * or the SIP version is empty, which isn't valid for a
5007 token_1_len
= space_offset
- token_1_start
;
5008 token_2_start
= space_offset
+ 1;
5009 space_offset
= tvb_find_uint8(tvb
, token_2_start
, -1, ' ');
5010 if (space_offset
== -1) {
5012 * There's no space after the second token, so we don't
5013 * have a third token.
5017 token_2_len
= space_offset
- token_2_start
;
5018 token_3_start
= space_offset
+ 1;
5019 token_3_len
= token_1_start
+ linelen
- token_3_start
;
5021 *token_1_lenp
= token_1_len
;
5024 * Is the first token a version string?
5026 if ( (strict_sip_version
&& (
5027 token_1_len
== SIP2_HDR_LEN
5028 && tvb_strneql(tvb
, token_1_start
, SIP2_HDR
, SIP2_HDR_LEN
) == 0)
5029 ) || (! strict_sip_version
&& (
5030 tvb_strncaseeql(tvb
, token_1_start
, "SIP/", 4) == 0)
5033 * Yes, so this is either a Status-Line or something
5034 * else other than a Request-Line. To be a Status-Line,
5035 * the second token must be a 3-digit number.
5037 if (token_2_len
!= 3) {
5039 * We don't have 3-character status code.
5043 if (!g_ascii_isdigit(tvb_get_uint8(tvb
, token_2_start
)) ||
5044 !g_ascii_isdigit(tvb_get_uint8(tvb
, token_2_start
+ 1)) ||
5045 !g_ascii_isdigit(tvb_get_uint8(tvb
, token_2_start
+ 2))) {
5047 * 3 characters yes, 3 digits no.
5054 * No, so this is either a Request-Line or something
5055 * other than a Status-Line. To be a Request-Line, the
5056 * second token must be a URI and the third token must
5057 * be a version string.
5059 if (token_2_len
< 3) {
5061 * We don't have a URI consisting of at least 3
5066 colon_pos
= tvb_find_uint8(tvb
, token_2_start
+ 1, -1, ':');
5067 if (colon_pos
== -1) {
5069 * There is no colon after the method, so the URI
5070 * doesn't have a colon in it, so it's not valid.
5074 if (colon_pos
>= token_3_start
) {
5076 * The colon is in the version string, not the URI.
5080 /* XXX - Check for a proper URI prefix? */
5081 if ( (strict_sip_version
&& (
5082 token_3_len
!= SIP2_HDR_LEN
5083 || tvb_strneql(tvb
, token_3_start
, SIP2_HDR
, SIP2_HDR_LEN
) == -1)
5084 ) || (! strict_sip_version
&& (
5085 tvb_strncaseeql(tvb
, token_3_start
, "SIP/", 4) == -1)
5088 * The version string isn't an SIP version 2.0 version
5093 return REQUEST_LINE
;
5097 static bool sip_is_known_request(tvbuff_t
*tvb
, int meth_offset
,
5098 unsigned meth_len
, unsigned *meth_idx
)
5103 meth_name
= tvb_get_string_enc(wmem_packet_scope(), tvb
, meth_offset
, meth_len
, ENC_UTF_8
|ENC_NA
);
5105 for (i
= 1; i
< array_length(sip_methods
); i
++) {
5106 if (meth_len
== strlen(sip_methods
[i
]) &&
5107 strncmp(meth_name
, sip_methods
[i
], meth_len
) == 0)
5118 * Returns index of method in sip_headers
5119 * Header namne should be in lower case
5121 static int sip_is_known_sip_header(char *header_name
, unsigned header_len
)
5125 /* Compact name is one character long */
5127 pos
= GPOINTER_TO_UINT(g_hash_table_lookup(sip_headers_hash
, header_name
));
5132 /* Look for compact name match */
5133 for (pos
= 1; pos
< array_length(sip_headers
); pos
++) {
5134 if (sip_headers
[pos
].compact_name
!= NULL
&&
5135 header_len
== strlen(sip_headers
[pos
].compact_name
) &&
5136 g_ascii_strncasecmp(header_name
, sip_headers
[pos
].compact_name
, header_len
) == 0)
5144 * Display the entire message as raw text.
5147 tvb_raw_text_add(tvbuff_t
*tvb
, int offset
, int length
, int body_offset
, packet_info
* pinfo
, proto_tree
*tree
)
5149 proto_tree
*raw_tree
;
5151 int next_offset
, linelen
, end_offset
;
5153 tvbuff_t
* body_tvb
= NULL
;
5155 ti
= proto_tree_add_item(tree
, proto_raw_sip
, tvb
, offset
, length
, ENC_NA
);
5156 raw_tree
= proto_item_add_subtree(ti
, ett_raw_text
);
5158 end_offset
= offset
+ length
;
5160 if (body_offset
< end_offset
5161 && global_sip_raw_text_body_default_encoding
!= IANA_CS_UTF_8
5162 /* UTF-8 compatible with ASCII */
5163 && global_sip_raw_text_body_default_encoding
!= IANA_CS_US_ASCII
)
5165 /* Create body tvb with new character encoding */
5166 uint32_t iana_charset_id
= global_sip_raw_text_body_default_encoding
;
5167 unsigned ws_encoding_id
= mibenum_charset_to_encoding((unsigned)iana_charset_id
);
5169 if (ws_encoding_id
!= (ENC_NA
| ENC_ASCII
) && ws_encoding_id
!= (ENC_NA
| ENC_UTF_8
)) {
5170 /* Encoding body with the new encoding */
5171 char* encoding_name
= val_to_str_ext_wmem(pinfo
->pool
, iana_charset_id
,
5172 &mibenum_vals_character_sets_ext
, "UNKNOWN");
5173 const uint8_t* data_str
= tvb_get_string_enc(pinfo
->pool
, tvb
, body_offset
,
5174 end_offset
- body_offset
, ws_encoding_id
);
5175 size_t l
= strlen(data_str
);
5176 body_tvb
= tvb_new_child_real_data(tvb
, data_str
, (unsigned)l
, (int)l
);
5177 add_new_data_source(pinfo
, body_tvb
, wmem_strdup_printf(pinfo
->pool
, "Decoded %s text", encoding_name
));
5181 /* Display the headers of SIP message as raw text */
5182 while (offset
< body_offset
) {
5183 tvb_find_line_end(tvb
, offset
, -1, &next_offset
, false);
5184 linelen
= next_offset
- offset
;
5186 if (global_sip_raw_text_without_crlf
)
5187 str
= tvb_format_text_wsp(pinfo
->pool
, tvb
, offset
, linelen
);
5189 str
= tvb_format_text(pinfo
->pool
, tvb
, offset
, linelen
);
5190 proto_tree_add_string_format(raw_tree
, hf_sip_raw_line
, tvb
, offset
, linelen
,
5195 offset
= next_offset
;
5198 DISSECTOR_ASSERT_HINT(offset
== body_offset
, "The offset must be equal to body_offset before dissect body as raw text.");
5200 if (body_offset
< end_offset
) {
5201 /* Dissect the body of SIP message as raw text */
5204 end_offset
= tvb_captured_length_remaining(body_tvb
, 0);
5206 body_tvb
= tvb
; /* reuse old offset and end_offset */
5209 while (offset
< end_offset
) {
5210 tvb_find_line_end(body_tvb
, offset
, -1, &next_offset
, false);
5211 linelen
= next_offset
- offset
;
5213 if (global_sip_raw_text_without_crlf
)
5214 str
= tvb_format_text_wsp(pinfo
->pool
, body_tvb
, offset
, linelen
);
5216 str
= tvb_format_text(pinfo
->pool
, body_tvb
, offset
, linelen
);
5218 proto_tree_add_string_format(raw_tree
, hf_sip_raw_line
, body_tvb
, offset
,
5219 linelen
, str
, "%s", str
);
5221 offset
= next_offset
;
5226 /* Check to see if this packet is a resent request. Return value is the frame number
5227 of the original frame this packet seems to be resending (0 = no resend). */
5228 unsigned sip_is_packet_resend(packet_info
*pinfo
,
5229 const char *cseq_method
,
5231 unsigned char cseq_number_set
,
5232 uint32_t cseq_number
, line_type_t line_type
)
5234 uint32_t cseq_to_compare
= 0;
5236 sip_hash_key
*p_key
= 0;
5237 sip_hash_value
*p_val
= 0;
5238 sip_frame_result_value
*sip_frame_result
= NULL
;
5239 unsigned result
= 0;
5241 /* Don't consider packets that appear to be resent only because
5242 they are e.g. returned in ICMP unreachable messages. */
5243 if (pinfo
->flags
.in_error_pkt
)
5248 /* A broken packet may have no cseq number set. Don't consider it as
5250 if (!cseq_number_set
)
5255 /* Return any answer stored from previous dissection */
5256 if (pinfo
->fd
->visited
)
5258 sip_frame_result
= (sip_frame_result_value
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_sip
, pinfo
->curr_layer_num
);
5259 if (sip_frame_result
!= NULL
)
5261 return sip_frame_result
->original_frame_num
;
5269 /* No packet entry found, consult global hash table */
5271 /* Prepare the key */
5272 (void) g_strlcpy(key
.call_id
, call_id
, MAX_CALL_ID_SIZE
);
5274 /* We're only using these addresses locally (for the hash lookup) so
5275 * there is no need to make a (g_malloc'd) copy of them.
5277 set_address(&key
.dest_address
, pinfo
->net_dst
.type
, pinfo
->net_dst
.len
,
5278 pinfo
->net_dst
.data
);
5279 set_address(&key
.source_address
, pinfo
->net_src
.type
,
5280 pinfo
->net_src
.len
, pinfo
->net_src
.data
);
5281 key
.dest_port
= pinfo
->destport
;
5282 if (sip_retrans_the_same_sport
) {
5283 key
.source_port
= pinfo
->srcport
;
5285 key
.source_port
= MAGIC_SOURCE_PORT
;
5287 key
.ptype
= pinfo
->ptype
;
5290 p_val
= (sip_hash_value
*)g_hash_table_lookup(sip_hash
, &key
);
5294 /* Table entry found, we'll use its value for comparison */
5295 cseq_to_compare
= p_val
->cseq
;
5297 /* First time through, must update value with current details if
5298 cseq number has changed */
5299 if (cseq_number
!= p_val
->cseq
)
5301 p_val
->cseq
= cseq_number
;
5302 p_val
->method
= wmem_strdup(wmem_file_scope(), cseq_method
);
5303 p_val
->transaction_state
= nothing_seen
;
5304 p_val
->frame_number
= 0;
5305 if (line_type
== REQUEST_LINE
)
5307 p_val
->request_time
= pinfo
->abs_ts
;
5313 /* Need to create a new table entry */
5315 /* Allocate a new key and value */
5316 p_key
= wmem_new(wmem_file_scope(), sip_hash_key
);
5317 p_val
= wmem_new0(wmem_file_scope(), sip_hash_value
);
5319 /* Fill in key and value details */
5320 snprintf(p_key
->call_id
, MAX_CALL_ID_SIZE
, "%s", call_id
);
5321 copy_address_wmem(wmem_file_scope(), &(p_key
->dest_address
), &pinfo
->net_dst
);
5322 copy_address_wmem(wmem_file_scope(), &(p_key
->source_address
), &pinfo
->net_src
);
5323 p_key
->dest_port
= pinfo
->destport
;
5324 if (sip_retrans_the_same_sport
) {
5325 p_key
->source_port
= pinfo
->srcport
;
5327 p_key
->source_port
= MAGIC_SOURCE_PORT
;
5329 p_key
->ptype
= pinfo
->ptype
;
5331 p_val
->cseq
= cseq_number
;
5332 p_val
->method
= wmem_strdup(wmem_file_scope(), cseq_method
);
5333 p_val
->transaction_state
= nothing_seen
;
5334 if (line_type
== REQUEST_LINE
)
5336 p_val
->request_time
= pinfo
->abs_ts
;
5340 g_hash_table_insert(sip_hash
, p_key
, p_val
);
5342 /* Assume have seen no cseq yet */
5343 cseq_to_compare
= 0;
5347 /******************************************/
5348 /* Is it a resend??? */
5350 /* Does this look like a resent request (discount ACK, CANCEL, or a
5351 different method from the original one) ? */
5353 if ((line_type
== REQUEST_LINE
) && (cseq_number
== cseq_to_compare
) &&
5354 (p_val
->transaction_state
== request_seen
) &&
5355 (strcmp(cseq_method
, p_val
->method
) == 0) &&
5356 (strcmp(cseq_method
, "ACK") != 0) &&
5357 (strcmp(cseq_method
, "CANCEL") != 0))
5359 result
= p_val
->frame_number
;
5362 /* Does this look like a resent final response ? */
5363 if ((line_type
== STATUS_LINE
) && (cseq_number
== cseq_to_compare
) &&
5364 (p_val
->transaction_state
== final_response_seen
) &&
5365 (strcmp(cseq_method
, p_val
->method
) == 0) &&
5366 (stat_info
->response_code
>= 200) &&
5367 (stat_info
->response_code
== p_val
->response_code
))
5369 result
= p_val
->frame_number
;
5372 /* Update state for this entry */
5373 p_val
->cseq
= cseq_number
;
5378 p_val
->transaction_state
= request_seen
;
5381 /* This frame is the original request */
5382 p_val
->frame_number
= pinfo
->num
;
5383 p_val
->request_time
= pinfo
->abs_ts
;
5387 if (stat_info
->response_code
>= 200)
5389 p_val
->response_code
= stat_info
->response_code
;
5390 p_val
->transaction_state
= final_response_seen
;
5393 /* This frame is the original response */
5394 p_val
->frame_number
= pinfo
->num
;
5399 p_val
->transaction_state
= provisional_response_seen
;
5406 sip_frame_result
= (sip_frame_result_value
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_sip
, pinfo
->curr_layer_num
);
5407 if (sip_frame_result
== NULL
)
5409 sip_frame_result
= wmem_new0(wmem_file_scope(), sip_frame_result_value
);
5410 p_add_proto_data(wmem_file_scope(), pinfo
, proto_sip
, pinfo
->curr_layer_num
, sip_frame_result
);
5413 /* Store return value with this packet */
5414 sip_frame_result
->original_frame_num
= result
;
5420 /* Check to see if this packet is a resent request. Return value is the frame number
5421 of the original frame this packet seems to be resending (0 = no resend). */
5422 unsigned sip_find_request(packet_info
*pinfo
,
5423 const char *cseq_method
,
5425 unsigned char cseq_number_set
,
5426 uint32_t cseq_number
,
5427 uint32_t *response_time
)
5429 uint32_t cseq_to_compare
= 0;
5431 sip_hash_value
*p_val
= 0;
5432 sip_frame_result_value
*sip_frame_result
= NULL
;
5433 unsigned result
= 0;
5434 int seconds_between_packets
;
5435 int nseconds_between_packets
;
5437 /* Ignore error (usually ICMP) frames */
5438 if (pinfo
->flags
.in_error_pkt
)
5443 /* A broken packet may have no cseq number set. Ignore. */
5444 if (!cseq_number_set
)
5449 /* Return any answer stored from previous dissection */
5450 if (pinfo
->fd
->visited
)
5452 sip_frame_result
= (sip_frame_result_value
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_sip
, pinfo
->curr_layer_num
);
5453 if (sip_frame_result
!= NULL
)
5455 *response_time
= sip_frame_result
->response_time
;
5456 return sip_frame_result
->response_request_frame_num
;
5464 /* No packet entry found, consult global hash table */
5466 /* Prepare the key */
5467 (void) g_strlcpy(key
.call_id
, call_id
, MAX_CALL_ID_SIZE
);
5469 /* Looking for matching request, so reverse addresses for this lookup */
5470 set_address(&key
.dest_address
, pinfo
->net_src
.type
, pinfo
->net_src
.len
,
5471 pinfo
->net_src
.data
);
5472 set_address(&key
.source_address
, pinfo
->net_dst
.type
, pinfo
->net_dst
.len
,
5473 pinfo
->net_dst
.data
);
5474 key
.dest_port
= pinfo
->srcport
;
5475 key
.source_port
= pinfo
->destport
;
5476 key
.ptype
= pinfo
->ptype
;
5479 p_val
= (sip_hash_value
*)g_hash_table_lookup(sip_hash
, &key
);
5483 /* Table entry found, we'll use its value for comparison */
5484 cseq_to_compare
= p_val
->cseq
;
5488 /* We don't have the request */
5493 /**************************************************/
5494 /* Is it a response to a request that we've seen? */
5495 if ((cseq_number
== cseq_to_compare
) &&
5496 (p_val
->transaction_state
== request_seen
) &&
5497 (strcmp(cseq_method
, p_val
->method
) == 0))
5499 result
= p_val
->frame_number
;
5503 /* Store return value with this packet */
5504 sip_frame_result
= (sip_frame_result_value
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_sip
, pinfo
->curr_layer_num
);
5505 if (sip_frame_result
== NULL
)
5507 /* Allocate and set all values to zero */
5508 sip_frame_result
= wmem_new0(wmem_file_scope(), sip_frame_result_value
);
5509 p_add_proto_data(wmem_file_scope(), pinfo
, proto_sip
, pinfo
->curr_layer_num
, sip_frame_result
);
5512 sip_frame_result
->response_request_frame_num
= result
;
5514 /* Work out response time */
5515 seconds_between_packets
= (int)
5516 (pinfo
->abs_ts
.secs
- p_val
->request_time
.secs
);
5517 nseconds_between_packets
=
5518 pinfo
->abs_ts
.nsecs
- p_val
->request_time
.nsecs
;
5519 sip_frame_result
->response_time
= (seconds_between_packets
*1000) +
5520 (nseconds_between_packets
/ 1000000);
5521 *response_time
= sip_frame_result
->response_time
;
5527 * Find the initial INVITE to calculate the total setup time
5529 unsigned sip_find_invite(packet_info
*pinfo
,
5530 const char *cseq_method _U_
,
5532 unsigned char cseq_number_set
,
5533 uint32_t cseq_number _U_
,
5534 uint32_t *response_time
)
5537 uint32_t cseq_to_compare
= 0;
5540 sip_hash_value
*p_val
= 0;
5541 sip_frame_result_value
*sip_frame_result
= NULL
;
5542 unsigned result
= 0;
5543 int seconds_between_packets
;
5544 int nseconds_between_packets
;
5546 /* Ignore error (usually ICMP) frames */
5547 if (pinfo
->flags
.in_error_pkt
)
5552 /* A broken packet may have no cseq number set. Ignore. */
5553 if (!cseq_number_set
)
5558 /* Return any answer stored from previous dissection */
5559 if (pinfo
->fd
->visited
)
5561 sip_frame_result
= (sip_frame_result_value
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_sip
, pinfo
->curr_layer_num
);
5562 if (sip_frame_result
!= NULL
)
5564 *response_time
= sip_frame_result
->response_time
;
5565 return sip_frame_result
->response_request_frame_num
;
5573 /* No packet entry found, consult global hash table */
5575 /* Prepare the key */
5576 (void) g_strlcpy(key
.call_id
, call_id
, MAX_CALL_ID_SIZE
);
5578 /* Looking for matching INVITE */
5579 set_address(&key
.dest_address
, pinfo
->net_dst
.type
, pinfo
->net_dst
.len
,
5580 pinfo
->net_dst
.data
);
5581 set_address(&key
.source_address
, pinfo
->net_src
.type
, pinfo
->net_src
.len
,
5582 pinfo
->net_src
.data
);
5583 key
.dest_port
= pinfo
->destport
;
5584 key
.source_port
= pinfo
->srcport
;
5585 key
.ptype
= pinfo
->ptype
;
5588 p_val
= (sip_hash_value
*)g_hash_table_lookup(sip_hash
, &key
);
5593 /* Table entry found, we'll use its value for comparison */
5594 cseq_to_compare
= p_val
->cseq
;
5599 /* We don't have the request */
5604 /**************************************************/
5605 /* Is it a response to a request that we've seen? */
5607 if ((cseq_number
== cseq_to_compare
) &&
5608 (p_val
->transaction_state
== request_seen
) &&
5609 (strcmp(cseq_method
, p_val
->method
) == 0))
5611 result
= p_val
->frame_number
;
5615 result
= p_val
->frame_number
;
5617 /* Store return value with this packet */
5618 sip_frame_result
= (sip_frame_result_value
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_sip
, pinfo
->curr_layer_num
);
5619 if (sip_frame_result
== NULL
)
5621 /* Allocate and set all values to zero */
5622 sip_frame_result
= wmem_new0(wmem_file_scope(), sip_frame_result_value
);
5623 p_add_proto_data(wmem_file_scope(), pinfo
, proto_sip
, pinfo
->curr_layer_num
, sip_frame_result
);
5626 sip_frame_result
->response_request_frame_num
= result
;
5628 /* Work out response time */
5629 seconds_between_packets
= (int)
5630 (pinfo
->abs_ts
.secs
- p_val
->request_time
.secs
);
5631 nseconds_between_packets
=
5632 pinfo
->abs_ts
.nsecs
- p_val
->request_time
.nsecs
;
5633 sip_frame_result
->response_time
= (seconds_between_packets
*1000) +
5634 (nseconds_between_packets
/ 1000000);
5635 *response_time
= sip_frame_result
->response_time
;
5641 static bool sip_validate_authorization(sip_authorization_t
*authorization_info
, char *password
) {
5644 char response
[33] = {0};
5645 gcry_md_hd_t md5_handle
;
5646 if ( (authorization_info
->qop
== NULL
) ||
5647 (authorization_info
->username
== NULL
) ||
5648 (authorization_info
->realm
== NULL
) ||
5649 (authorization_info
->method
== NULL
) ||
5650 (authorization_info
->uri
== NULL
) ||
5651 (authorization_info
->nonce
== NULL
) ) {
5652 return true; /* If no qop, discard */
5654 if (strcmp(authorization_info
->qop
, "auth") ||
5655 (authorization_info
->nonce_count
== NULL
) ||
5656 (authorization_info
->cnonce
== NULL
) ||
5657 (authorization_info
->response
== NULL
) ||
5658 (password
== NULL
)) {
5659 return true; /* Obsolete or not enough information, discard */
5662 if (gcry_md_open(&md5_handle
, GCRY_MD_MD5
, 0)) {
5666 gcry_md_write(md5_handle
, authorization_info
->username
, strlen(authorization_info
->username
));
5667 gcry_md_putc(md5_handle
, ':');
5668 gcry_md_write(md5_handle
, authorization_info
->realm
, strlen(authorization_info
->realm
));
5669 gcry_md_putc(md5_handle
, ':');
5670 gcry_md_write(md5_handle
, password
, strlen(password
));
5671 /* Array is zeroed out so there is always a \0 at index 32 for string termination */
5672 bytes_to_hexstr(ha1
, gcry_md_read(md5_handle
, 0), HASH_MD5_LENGTH
);
5673 gcry_md_reset(md5_handle
);
5674 gcry_md_write(md5_handle
, authorization_info
->method
, strlen(authorization_info
->method
));
5675 gcry_md_putc(md5_handle
, ':');
5676 gcry_md_write(md5_handle
, authorization_info
->uri
, strlen(authorization_info
->uri
));
5677 /* Array is zeroed out so there is always a \0 at index 32 for string termination */
5678 bytes_to_hexstr(ha2
, gcry_md_read(md5_handle
, 0), HASH_MD5_LENGTH
);
5679 gcry_md_reset(md5_handle
);
5680 gcry_md_write(md5_handle
, ha1
, strlen(ha1
));
5681 gcry_md_putc(md5_handle
, ':');
5682 gcry_md_write(md5_handle
, authorization_info
->nonce
, strlen(authorization_info
->nonce
));
5683 gcry_md_putc(md5_handle
, ':');
5684 gcry_md_write(md5_handle
, authorization_info
->nonce_count
, strlen(authorization_info
->nonce_count
));
5685 gcry_md_putc(md5_handle
, ':');
5686 gcry_md_write(md5_handle
, authorization_info
->cnonce
, strlen(authorization_info
->cnonce
));
5687 gcry_md_putc(md5_handle
, ':');
5688 gcry_md_write(md5_handle
, authorization_info
->qop
, strlen(authorization_info
->qop
));
5689 gcry_md_putc(md5_handle
, ':');
5690 gcry_md_write(md5_handle
, ha2
, strlen(ha2
));
5691 /* Array is zeroed out so there is always a \0 at index 32 for string termination */
5692 bytes_to_hexstr(response
, gcry_md_read(md5_handle
, 0), HASH_MD5_LENGTH
);
5693 gcry_md_close(md5_handle
);
5694 if (!strncmp(response
, authorization_info
->response
, 32)) {
5703 * Much of this is from ui/gtk/sip_stat.c:
5704 * sip_stat 2004 Martin Mathieson
5707 /* TODO: extra codes to be added from SIP extensions?
5708 * https://www.iana.org/assignments/sip-parameters/sip-parameters.xhtml#sip-parameters-6
5710 const value_string sip_response_code_vals
[] = {
5711 { 999, "Unknown response"}, /* Must be first */
5715 { 181, "Call Is Being Forwarded"},
5717 { 183, "Session Progress"},
5718 { 199, "Informational - Others" },
5722 { 204, "No Notification"},
5723 { 299, "Success - Others"}, /* used to keep track of other Success packets */
5725 { 300, "Multiple Choices"},
5726 { 301, "Moved Permanently"},
5727 { 302, "Moved Temporarily"},
5728 { 305, "Use Proxy"},
5729 { 380, "Alternative Service"},
5730 { 399, "Redirection - Others"},
5732 { 400, "Bad Request"},
5733 { 401, "Unauthorized"},
5734 { 402, "Payment Required"},
5735 { 403, "Forbidden"},
5736 { 404, "Not Found"},
5737 { 405, "Method Not Allowed"},
5738 { 406, "Not Acceptable"},
5739 { 407, "Proxy Authentication Required"},
5740 { 408, "Request Timeout"},
5742 { 412, "Conditional Request Failed"},
5743 { 413, "Request Entity Too Large"},
5744 { 414, "Request-URI Too Long"},
5745 { 415, "Unsupported Media Type"},
5746 { 416, "Unsupported URI Scheme"},
5747 { 420, "Bad Extension"},
5748 { 421, "Extension Required"},
5749 { 422, "Session Timer Too Small"},
5750 { 423, "Interval Too Brief"},
5751 { 428, "Use Identity Header"},
5752 { 429, "Provide Referrer Identity"},
5753 { 430, "Flow Failed"},
5754 { 433, "Anonymity Disallowed"},
5755 { 436, "Bad Identity-Info"},
5756 { 437, "Unsupported Certificate"},
5757 { 438, "Invalid Identity Header"},
5758 { 439, "First Hop Lacks Outbound Support"},
5759 { 440, "Max-Breadth Exceeded"},
5760 { 470, "Consent Needed"},
5761 { 480, "Temporarily Unavailable"},
5762 { 481, "Call/Transaction Does Not Exist"},
5763 { 482, "Loop Detected"},
5764 { 483, "Too Many Hops"},
5765 { 484, "Address Incomplete"},
5766 { 485, "Ambiguous"},
5767 { 486, "Busy Here"},
5768 { 487, "Request Terminated"},
5769 { 488, "Not Acceptable Here"},
5770 { 489, "Bad Event"},
5771 { 491, "Request Pending"},
5772 { 493, "Undecipherable"},
5773 { 494, "Security Agreement Required"},
5774 { 499, "Client Error - Others"},
5776 { 500, "Server Internal Error"},
5777 { 501, "Not Implemented"},
5778 { 502, "Bad Gateway"},
5779 { 503, "Service Unavailable"},
5780 { 504, "Server Time-out"},
5781 { 505, "Version Not Supported"},
5782 { 513, "Message Too Large"},
5783 { 599, "Server Error - Others"},
5785 { 600, "Busy Everywhere"},
5787 { 604, "Does Not Exist Anywhere"},
5788 { 606, "Not Acceptable"},
5791 { 699, "Global Failure - Others"},
5795 #define RESPONSE_CODE_MIN 100
5796 #define RESPONSE_CODE_MAX 699
5800 REQ_RESP_METHOD_COLUMN
,
5808 static stat_tap_table_item sip_stat_fields
[] = {
5809 {TABLE_ITEM_STRING
, TAP_ALIGN_LEFT
, "Request Method / Response Code", "%-25s"},
5810 {TABLE_ITEM_UINT
, TAP_ALIGN_RIGHT
, "Count", "%d"},
5811 {TABLE_ITEM_UINT
, TAP_ALIGN_RIGHT
, "Resent", "%d"},
5812 {TABLE_ITEM_FLOAT
, TAP_ALIGN_RIGHT
, "Min Setup (s)", "%8.2f"},
5813 {TABLE_ITEM_FLOAT
, TAP_ALIGN_RIGHT
, "Avg Setup (s)", "%8.2f"},
5814 {TABLE_ITEM_FLOAT
, TAP_ALIGN_RIGHT
, "Max Setup (s)", "%8.2f"},
5817 static const char *req_table_name
= "SIP Requests";
5818 static const char *resp_table_name
= "SIP Responses";
5820 static void sip_stat_init(stat_tap_table_ui
* new_stat
)
5822 /* XXX Should we have a single request + response table instead? */
5823 int num_fields
= array_length(sip_stat_fields
);
5824 stat_tap_table
*req_table
;
5825 stat_tap_table
*resp_table
;
5826 stat_tap_table_item_type items
[array_length(sip_stat_fields
)];
5829 // These values are fixed for all entries.
5830 items
[REQ_RESP_METHOD_COLUMN
].type
= TABLE_ITEM_STRING
;
5831 items
[COUNT_COLUMN
].type
= TABLE_ITEM_UINT
;
5832 items
[COUNT_COLUMN
].user_data
.uint_value
= 0;
5833 items
[COUNT_COLUMN
].value
.uint_value
= 0;
5834 items
[RESENT_COLUMN
].type
= TABLE_ITEM_UINT
;
5835 items
[RESENT_COLUMN
].value
.uint_value
= 0;
5836 items
[MIN_SETUP_COLUMN
].type
= TABLE_ITEM_FLOAT
;
5837 items
[MIN_SETUP_COLUMN
].user_data
.uint_value
= 0;
5838 items
[MIN_SETUP_COLUMN
].value
.float_value
= 0.0f
;
5839 items
[AVG_SETUP_COLUMN
].type
= TABLE_ITEM_FLOAT
;
5840 items
[AVG_SETUP_COLUMN
].user_data
.float_value
= 0.0f
;
5841 items
[AVG_SETUP_COLUMN
].value
.float_value
= 0.0f
;
5842 items
[MAX_SETUP_COLUMN
].type
= TABLE_ITEM_FLOAT
;
5843 items
[MAX_SETUP_COLUMN
].value
.float_value
= 0.0f
;
5845 req_table
= stat_tap_find_table(new_stat
, req_table_name
);
5847 if (new_stat
->stat_tap_reset_table_cb
)
5848 new_stat
->stat_tap_reset_table_cb(req_table
);
5851 req_table
= stat_tap_init_table(req_table_name
, num_fields
, 0, NULL
);
5852 stat_tap_add_table(new_stat
, req_table
);
5854 // For req_table, first column value is method.
5855 for (i
= 1; i
< array_length(sip_methods
); i
++) {
5856 items
[REQ_RESP_METHOD_COLUMN
].value
.string_value
= g_strdup(sip_methods
[i
]);
5857 stat_tap_init_table_row(req_table
, i
-1, num_fields
, items
);
5861 resp_table
= stat_tap_find_table(new_stat
, resp_table_name
);
5863 if (new_stat
->stat_tap_reset_table_cb
)
5864 new_stat
->stat_tap_reset_table_cb(resp_table
);
5867 resp_table
= stat_tap_init_table(resp_table_name
, num_fields
, 0, NULL
);
5868 stat_tap_add_table(new_stat
, resp_table
);
5870 // For responses entries, first column gets code and description.
5871 for (i
= 1; sip_response_code_vals
[i
].strptr
; i
++) {
5872 unsigned response_code
= sip_response_code_vals
[i
].value
;
5873 items
[REQ_RESP_METHOD_COLUMN
].value
.string_value
=
5874 ws_strdup_printf("%u %s", response_code
, sip_response_code_vals
[i
].strptr
);
5875 items
[REQ_RESP_METHOD_COLUMN
].user_data
.uint_value
= response_code
;
5876 stat_tap_init_table_row(resp_table
, i
-1, num_fields
, items
);
5881 static tap_packet_status
5882 sip_stat_packet(void *tapdata
, packet_info
*pinfo _U_
, epan_dissect_t
*edt _U_
, const void *siv_ptr
, tap_flags_t flags _U_
)
5884 stat_data_t
* stat_data
= (stat_data_t
*) tapdata
;
5885 const sip_info_value_t
*info_value
= (const sip_info_value_t
*) siv_ptr
;
5886 stat_tap_table
*cur_table
= NULL
;
5887 unsigned cur_row
= 0; /* 0 = Unknown for both tables */
5889 if (info_value
->request_method
&& info_value
->response_code
< 1) {
5891 stat_tap_table
*req_table
= stat_tap_find_table(stat_data
->stat_tap_data
, req_table_name
);
5892 stat_tap_table_item_type
*item_data
;
5895 cur_table
= req_table
;
5896 for (element
= 0; element
< req_table
->num_elements
; element
++) {
5897 item_data
= stat_tap_get_field_data(req_table
, element
, REQ_RESP_METHOD_COLUMN
);
5898 if (g_ascii_strcasecmp(info_value
->request_method
, item_data
->value
.string_value
) == 0) {
5904 } else if (info_value
->response_code
> 0) {
5905 /* Response table */
5906 stat_tap_table
*resp_table
= stat_tap_find_table(stat_data
->stat_tap_data
, resp_table_name
);
5907 unsigned response_code
= info_value
->response_code
;
5908 stat_tap_table_item_type
*item_data
;
5911 cur_table
= resp_table
;
5912 if (response_code
< RESPONSE_CODE_MIN
|| response_code
> RESPONSE_CODE_MAX
) {
5913 response_code
= 999;
5914 } else if (!try_val_to_str(response_code
, sip_response_code_vals
)) {
5915 response_code
= ((response_code
/ 100) * 100) + 99;
5918 for (element
= 0; element
< resp_table
->num_elements
; element
++) {
5919 item_data
= stat_tap_get_field_data(resp_table
, element
, REQ_RESP_METHOD_COLUMN
);
5920 if (item_data
->user_data
.uint_value
== response_code
) {
5927 return TAP_PACKET_DONT_REDRAW
;
5931 stat_tap_table_item_type
*item_data
;
5933 item_data
= stat_tap_get_field_data(cur_table
, cur_row
, COUNT_COLUMN
);
5934 item_data
->value
.uint_value
++;
5935 stat_tap_set_field_data(cur_table
, cur_row
, COUNT_COLUMN
, item_data
);
5937 if (info_value
->resend
) {
5938 item_data
= stat_tap_get_field_data(cur_table
, cur_row
, RESENT_COLUMN
);
5939 item_data
->value
.uint_value
++;
5940 stat_tap_set_field_data(cur_table
, cur_row
, RESENT_COLUMN
, item_data
);
5943 if (info_value
->setup_time
> 0) {
5944 stat_tap_table_item_type
*min_item_data
= stat_tap_get_field_data(cur_table
, cur_row
, MIN_SETUP_COLUMN
);
5945 stat_tap_table_item_type
*avg_item_data
= stat_tap_get_field_data(cur_table
, cur_row
, AVG_SETUP_COLUMN
);
5946 stat_tap_table_item_type
*max_item_data
= stat_tap_get_field_data(cur_table
, cur_row
, MAX_SETUP_COLUMN
);
5947 double setup_time
= (double) info_value
->setup_time
/ 1000;
5950 min_item_data
->user_data
.uint_value
++; /* We store the setup count in MIN_SETUP_COLUMN */
5951 count
= min_item_data
->user_data
.uint_value
;
5952 avg_item_data
->user_data
.float_value
+= setup_time
; /* We store the total setup time in AVG_SETUP_COLUMN */
5955 min_item_data
->value
.float_value
= setup_time
;
5956 avg_item_data
->value
.float_value
= setup_time
;
5957 max_item_data
->value
.float_value
= setup_time
;
5959 if (setup_time
< min_item_data
->value
.float_value
) {
5960 min_item_data
->value
.float_value
= setup_time
;
5962 avg_item_data
->value
.float_value
= avg_item_data
->user_data
.float_value
/ count
;
5963 if (setup_time
> max_item_data
->value
.float_value
) {
5964 max_item_data
->value
.float_value
= setup_time
;
5968 stat_tap_set_field_data(cur_table
, cur_row
, MIN_SETUP_COLUMN
, min_item_data
);
5969 stat_tap_set_field_data(cur_table
, cur_row
, AVG_SETUP_COLUMN
, avg_item_data
);
5970 stat_tap_set_field_data(cur_table
, cur_row
, MAX_SETUP_COLUMN
, max_item_data
);
5974 return TAP_PACKET_REDRAW
;
5978 sip_stat_reset(stat_tap_table
* table
)
5981 stat_tap_table_item_type
* item_data
;
5983 for (element
= 0; element
< table
->num_elements
; element
++)
5985 item_data
= stat_tap_get_field_data(table
, element
, COUNT_COLUMN
);
5986 item_data
->user_data
.uint_value
= 0;
5987 item_data
->value
.uint_value
= 0;
5988 stat_tap_set_field_data(table
, element
, COUNT_COLUMN
, item_data
);
5990 item_data
= stat_tap_get_field_data(table
, element
, RESENT_COLUMN
);
5991 item_data
->value
.uint_value
= 0;
5992 stat_tap_set_field_data(table
, element
, RESENT_COLUMN
, item_data
);
5994 item_data
= stat_tap_get_field_data(table
, element
, MIN_SETUP_COLUMN
);
5995 item_data
->user_data
.uint_value
= 0;
5996 item_data
->value
.float_value
= 0.0f
;
5997 stat_tap_set_field_data(table
, element
, MIN_SETUP_COLUMN
, item_data
);
5999 item_data
= stat_tap_get_field_data(table
, element
, AVG_SETUP_COLUMN
);
6000 item_data
->user_data
.float_value
= 0.0f
;
6001 item_data
->value
.float_value
= 0.0f
;
6002 stat_tap_set_field_data(table
, element
, AVG_SETUP_COLUMN
, item_data
);
6004 item_data
= stat_tap_get_field_data(table
, element
, MAX_SETUP_COLUMN
);
6005 item_data
->value
.float_value
= 0.0f
;
6006 stat_tap_set_field_data(table
, element
, MAX_SETUP_COLUMN
, item_data
);
6011 sip_stat_free_table_item(stat_tap_table
* table _U_
, unsigned row _U_
, unsigned column
, stat_tap_table_item_type
* field_data
)
6013 if (column
!= REQ_RESP_METHOD_COLUMN
) return;
6014 g_free((char*)field_data
->value
.string_value
);
6015 field_data
->value
.string_value
= NULL
;
6018 static char *sip_follow_conv_filter(epan_dissect_t
*edt
, packet_info
*pinfo _U_
, unsigned *stream _U_
, unsigned *sub_stream _U_
)
6020 char *filter
= NULL
;
6022 /* Extract si.Call-ID from decoded tree in edt */
6024 int hfid
= proto_registrar_get_id_byname("sip.Call-ID");
6025 GPtrArray
*gp
= proto_find_first_finfo(edt
->tree
, hfid
);
6026 if (gp
!= NULL
&& gp
->len
!= 0) {
6027 filter
= ws_strdup_printf("sip.Call-ID == \"%s\"", fvalue_get_string(((field_info
*)gp
->pdata
[0])->value
));
6029 g_ptr_array_free(gp
, true);
6031 filter
= ws_strdup_printf("sip.Call-ID");
6037 static char *sip_follow_index_filter(unsigned stream _U_
, unsigned sub_stream _U_
)
6042 static char *sip_follow_address_filter(address
*src_addr _U_
, address
*dst_addr _U_
, int src_port _U_
, int dst_port _U_
)
6048 /* Register the protocol with Wireshark */
6049 void proto_register_sip(void)
6052 /* Setup list of header fields */
6053 static hf_register_info hf
[] = {
6056 { "Message Header", "sip.msg_hdr",
6057 FT_STRING
, BASE_NONE
|BASE_NO_DISPLAY_VALUE
, NULL
, 0,
6058 "Message Header in SIP message", HFILL
}
6061 { "Method", "sip.Method",
6062 FT_STRING
, BASE_NONE
,NULL
,0x0,
6063 "SIP Method", HFILL
}
6066 { "Request-Line", "sip.Request-Line",
6067 FT_STRING
, BASE_NONE
,NULL
,0x0,
6068 "SIP Request-Line", HFILL
}
6070 { &hf_sip_ruri_display
,
6071 { "Request-URI display info", "sip.r-uri.display.info",
6072 FT_STRING
, BASE_NONE
,NULL
,0x0,
6073 "RFC 3261: SIP R-URI Display Info", HFILL
}
6076 { "Request-URI", "sip.r-uri",
6077 FT_STRING
, BASE_NONE
,NULL
,0x0,
6078 "RFC 3261: SIP R-URI", HFILL
}
6080 { &hf_sip_ruri_user
,
6081 { "Request-URI User Part", "sip.r-uri.user",
6082 FT_STRING
, BASE_NONE
,NULL
,0x0,
6083 "RFC 3261: SIP R-URI User", HFILL
}
6085 { &hf_sip_ruri_host
,
6086 { "Request-URI Host Part", "sip.r-uri.host",
6087 FT_STRING
, BASE_NONE
,NULL
,0x0,
6088 "RFC 3261: SIP R-URI Host", HFILL
}
6090 { &hf_sip_ruri_port
,
6091 { "Request-URI Host Port", "sip.r-uri.port",
6092 FT_STRING
, BASE_NONE
,NULL
,0x0,
6093 "RFC 3261: SIP R-URI Port", HFILL
}
6095 { &hf_sip_ruri_param
,
6096 { "Request URI parameter", "sip.r-uri.param",
6097 FT_STRING
, BASE_NONE
,NULL
,0x0,
6100 { &hf_sip_Status_Code
,
6101 { "Status-Code", "sip.Status-Code",
6102 FT_UINT32
, BASE_DEC
,NULL
,0x0,
6103 "SIP Status Code", HFILL
}
6105 { &hf_sip_Status_Line
,
6106 { "Status-Line", "sip.Status-Line",
6107 FT_STRING
, BASE_NONE
,NULL
,0x0,
6108 "SIP Status-Line", HFILL
}
6111 { "SIP Display info", "sip.display.info",
6112 FT_STRING
, BASE_NONE
,NULL
,0x0,
6113 "RFC 3261: Display info", HFILL
}
6115 { &hf_sip_to_display
,
6116 { "SIP to display info", "sip.to.display.info",
6117 FT_STRING
, BASE_NONE
,NULL
,0x0,
6118 "RFC 3261: To Display info", HFILL
}
6121 { "SIP to address", "sip.to.addr",
6122 FT_STRING
, BASE_NONE
,NULL
,0x0,
6123 "RFC 3261: To Address", HFILL
}
6126 { "SIP to address User Part", "sip.to.user",
6127 FT_STRING
, BASE_NONE
,NULL
,0x0,
6128 "RFC 3261: To Address User", HFILL
}
6131 { "SIP to address Host Part", "sip.to.host",
6132 FT_STRING
, BASE_NONE
,NULL
,0x0,
6133 "RFC 3261: To Address Host", HFILL
}
6136 { "SIP to address Host Port", "sip.to.port",
6137 FT_STRING
, BASE_NONE
,NULL
,0x0,
6138 "RFC 3261: To Address Port", HFILL
}
6141 { "SIP To URI parameter", "sip.to.param",
6142 FT_STRING
, BASE_NONE
,NULL
,0x0,
6146 { "SIP to tag", "sip.to.tag",
6147 FT_STRING
, BASE_NONE
,NULL
,0x0,
6148 "RFC 3261: to tag", HFILL
}
6150 { &hf_sip_from_display
,
6151 { "SIP from display info", "sip.from.display.info",
6152 FT_STRING
, BASE_NONE
,NULL
,0x0,
6153 "RFC 3261: From Display info", HFILL
}
6155 { &hf_sip_from_addr
,
6156 { "SIP from address", "sip.from.addr",
6157 FT_STRING
, BASE_NONE
,NULL
,0x0,
6158 "RFC 3261: From Address", HFILL
}
6160 { &hf_sip_from_user
,
6161 { "SIP from address User Part", "sip.from.user",
6162 FT_STRING
, BASE_NONE
,NULL
,0x0,
6163 "RFC 3261: From Address User", HFILL
}
6165 { &hf_sip_from_host
,
6166 { "SIP from address Host Part", "sip.from.host",
6167 FT_STRING
, BASE_NONE
,NULL
,0x0,
6168 "RFC 3261: From Address Host", HFILL
}
6170 { &hf_sip_from_port
,
6171 { "SIP from address Host Port", "sip.from.port",
6172 FT_STRING
, BASE_NONE
,NULL
,0x0,
6173 "RFC 3261: From Address Port", HFILL
}
6175 { &hf_sip_from_param
,
6176 { "SIP From URI parameter", "sip.from.param",
6177 FT_STRING
, BASE_NONE
,NULL
,0x0,
6181 { "SIP from tag", "sip.from.tag",
6182 FT_STRING
, BASE_NONE
,NULL
,0x0,
6183 "RFC 3261: from tag", HFILL
}
6185 { &hf_sip_curi_display
,
6186 { "SIP C-URI display info", "sip.contact.display.info",
6187 FT_STRING
, BASE_NONE
,NULL
,0x0,
6188 "RFC 3261: SIP C-URI Display info", HFILL
}
6191 { "Contact URI", "sip.contact.uri",
6192 FT_STRING
, BASE_NONE
,NULL
,0x0,
6193 "RFC 3261: SIP C-URI", HFILL
}
6195 { &hf_sip_curi_user
,
6196 { "Contact URI User Part", "sip.contact.user",
6197 FT_STRING
, BASE_NONE
,NULL
,0x0,
6198 "RFC 3261: SIP C-URI User", HFILL
}
6200 { &hf_sip_curi_host
,
6201 { "Contact URI Host Part", "sip.contact.host",
6202 FT_STRING
, BASE_NONE
,NULL
,0x0,
6203 "RFC 3261: SIP C-URI Host", HFILL
}
6205 { &hf_sip_curi_port
,
6206 { "Contact URI Host Port", "sip.contact.port",
6207 FT_STRING
, BASE_NONE
,NULL
,0x0,
6208 "RFC 3261: SIP C-URI Port", HFILL
}
6210 { &hf_sip_curi_param
,
6211 { "Contact URI parameter", "sip.contact.param",
6212 FT_STRING
, BASE_NONE
,NULL
,0x0,
6215 { &hf_sip_route_display
,
6216 { "Route display info", "sip.Route.display.info",
6217 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6220 { "Route URI", "sip.Route.uri",
6221 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6223 { &hf_sip_route_user
,
6224 { "Route Userinfo", "sip.Route.user",
6225 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6227 { &hf_sip_route_host
,
6228 { "Route Host Part", "sip.Route.host",
6229 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6231 { &hf_sip_route_port
,
6232 { "Route Host Port", "sip.Route.port",
6233 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6235 { &hf_sip_route_param
,
6236 { "Route URI parameter", "sip.Route.param",
6237 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6239 { &hf_sip_record_route_display
,
6240 { "Record-Route display info", "sip.Record-Route.display.info",
6241 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6243 { &hf_sip_record_route
,
6244 { "Record-Route URI", "sip.Record-Route.uri",
6245 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6247 { &hf_sip_record_route_user
,
6248 { "Record-Route Userinfo", "sip.Record-Route.user",
6249 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6251 { &hf_sip_record_route_host
,
6252 { "Record-Route Host Part", "sip.Record-Route.host",
6253 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6255 { &hf_sip_record_route_port
,
6256 { "Record-Route Host Port", "sip.Record-Route.port",
6257 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6259 { &hf_sip_record_route_param
,
6260 { "Record-Route URI parameter", "sip.Record-Route.param",
6261 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6263 { &hf_sip_service_route_display
,
6264 { "Service-Route display info", "sip.Service-Route.display.info",
6265 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6267 { &hf_sip_service_route
,
6268 { "Service-Route URI", "sip.Service-Route.uri",
6269 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6271 { &hf_sip_service_route_user
,
6272 { "Service-Route Userinfo", "sip.Service-Route.user",
6273 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6275 { &hf_sip_service_route_host
,
6276 { "Service-Route Host Part", "sip.Service-Route.host",
6277 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6279 { &hf_sip_service_route_port
,
6280 { "Service-Route Host Port", "sip.Service-Route.port",
6281 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6283 { &hf_sip_service_route_param
,
6284 { "Service-Route URI parameter", "sip.Service-Route.param",
6285 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6287 { &hf_sip_path_display
,
6288 { "Path URI", "sip.Path.display.info",
6289 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6292 { "Path URI", "sip.Path.uri",
6293 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6295 { &hf_sip_path_user
,
6296 { "Path Userinfo", "sip.Path.user",
6297 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6299 { &hf_sip_path_host
,
6300 { "Path Host Part", "sip.Path.host",
6301 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6303 { &hf_sip_path_port
,
6304 { "Path Host Port", "sip.Path.port",
6305 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6307 { &hf_sip_path_param
,
6308 { "Path URI parameter", "sip.Path.param",
6309 FT_STRING
, BASE_NONE
,NULL
,0x0,NULL
,HFILL
}
6311 { &hf_sip_contact_param
,
6312 { "Contact parameter", "sip.contact.parameter",
6313 FT_STRING
, BASE_NONE
,NULL
,0x0,
6314 "RFC 3261: one contact parameter", HFILL
}
6317 { "SIP tag", "sip.tag",
6318 FT_STRING
, BASE_NONE
,NULL
,0x0,
6319 "RFC 3261: tag", HFILL
}
6321 { &hf_sip_pai_display
,
6322 { "SIP PAI display info", "sip.pai.display.info",
6323 FT_STRING
, BASE_NONE
,NULL
,0x0,
6324 "RFC 3325: P-Asserted-Identity Display info", HFILL
}
6327 { "SIP PAI Address", "sip.pai.addr",
6328 FT_STRING
, BASE_NONE
,NULL
,0x0,
6329 "RFC 3325: P-Asserted-Identity Address", HFILL
}
6332 { "SIP PAI User Part", "sip.pai.user",
6333 FT_STRING
, BASE_NONE
,NULL
,0x0,
6334 "RFC 3325: P-Asserted-Identity User", HFILL
}
6337 { "SIP PAI Host Part", "sip.pai.host",
6338 FT_STRING
, BASE_NONE
,NULL
,0x0,
6339 "RFC 3325: P-Asserted-Identity Host", HFILL
}
6342 { "SIP PAI Host Port", "sip.pai.port",
6343 FT_STRING
, BASE_NONE
,NULL
,0x0,
6344 "RFC 3325: P-Asserted-Identity Port", HFILL
}
6346 { &hf_sip_pai_param
,
6347 { "SIP PAI URI parameter", "sip.pai.param",
6348 FT_STRING
, BASE_NONE
,NULL
,0x0,
6351 { &hf_sip_pmiss_display
,
6352 { "SIP PMISS display info", "sip.pmiss.display.info",
6353 FT_STRING
, BASE_NONE
,NULL
,0x0,
6354 "RFC 3325: Permission Missing Display info", HFILL
}
6356 { &hf_sip_pmiss_addr
,
6357 { "SIP PMISS Address", "sip.pmiss.addr",
6358 FT_STRING
, BASE_NONE
,NULL
,0x0,
6359 "RFC 3325: Permission Missing Address", HFILL
}
6361 { &hf_sip_pmiss_user
,
6362 { "SIP PMISS User Part", "sip.pmiss.user",
6363 FT_STRING
, BASE_NONE
,NULL
,0x0,
6364 "RFC 3325: Permission Missing User", HFILL
}
6366 { &hf_sip_pmiss_host
,
6367 { "SIP PMISS Host Part", "sip.pmiss.host",
6368 FT_STRING
, BASE_NONE
,NULL
,0x0,
6369 "RFC 3325: Permission Missing Host", HFILL
}
6371 { &hf_sip_pmiss_port
,
6372 { "SIP PMISS Host Port", "sip.pmiss.port",
6373 FT_STRING
, BASE_NONE
,NULL
,0x0,
6374 "RFC 3325: Permission Missing Port", HFILL
}
6376 { &hf_sip_pmiss_param
,
6377 { "SIP PMISS URI parameter", "sip.pmiss.param",
6378 FT_STRING
, BASE_NONE
,NULL
,0x0,
6381 { &hf_sip_ppi_display
,
6382 { "SIP PPI display info", "sip.ppi.display.info",
6383 FT_STRING
, BASE_NONE
,NULL
,0x0,
6384 "RFC 3325: P-Preferred-Identity Display info", HFILL
}
6387 { "SIP PPI Address", "sip.ppi.addr",
6388 FT_STRING
, BASE_NONE
,NULL
,0x0,
6389 "RFC 3325: P-Preferred-Identity Address", HFILL
}
6392 { "SIP PPI User Part", "sip.ppi.user",
6393 FT_STRING
, BASE_NONE
,NULL
,0x0,
6394 "RFC 3325: P-Preferred-Identity User", HFILL
}
6397 { "SIP PPI Host Part", "sip.ppi.host",
6398 FT_STRING
, BASE_NONE
,NULL
,0x0,
6399 "RFC 3325: P-Preferred-Identity Host", HFILL
}
6402 { "SIP PPI Host Port", "sip.ppi.port",
6403 FT_STRING
, BASE_NONE
,NULL
,0x0,
6404 "RFC 3325: P-Preferred-Identity Port", HFILL
}
6406 { &hf_sip_ppi_param
,
6407 { "SIP PPI URI parameter", "sip.ppi.param",
6408 FT_STRING
, BASE_NONE
,NULL
,0x0,
6411 { &hf_sip_tc_display
,
6412 { "SIP TC display info", "sip.tc.display.info",
6413 FT_STRING
, BASE_NONE
,NULL
,0x0,
6414 "RFC 3325: Trigger Consent Display info", HFILL
}
6417 { "SIP TC Address", "sip.tc.addr",
6418 FT_STRING
, BASE_NONE
,NULL
,0x0,
6419 "RFC 3325: Trigger Consent Address", HFILL
}
6422 { "SIP TC User Part", "sip.tc.user",
6423 FT_STRING
, BASE_NONE
,NULL
,0x0,
6424 "RFC 3325: Trigger Consent User", HFILL
}
6427 { "SIP TC Host Part", "sip.tc.host",
6428 FT_STRING
, BASE_NONE
,NULL
,0x0,
6429 "RFC 3325: Trigger Consent Host", HFILL
}
6432 { "SIP TC Host Port", "sip.tc.port",
6433 FT_STRING
, BASE_NONE
,NULL
,0x0,
6434 "RFC 3325: Trigger Consent Port", HFILL
}
6437 { "SIP TC URI parameter", "sip.tc.param",
6438 FT_STRING
, BASE_NONE
,NULL
,0x0,
6442 { "SIP TC Target URI", "sip.tc.target-uri",
6443 FT_STRING
, BASE_NONE
,NULL
,0x0,
6444 "RFC 3325: Trigger Consent Target URI", HFILL
}
6446 { &hf_header_array
[POS_ACCEPT
],
6447 { "Accept", "sip.Accept",
6448 FT_STRING
, BASE_NONE
,NULL
,0x0,
6449 "RFC 3261: Accept Header", HFILL
}
6451 { &hf_header_array
[POS_ACCEPT_CONTACT
],
6452 { "Accept-Contact", "sip.Accept-Contact",
6453 FT_STRING
, BASE_NONE
,NULL
,0x0,
6454 "RFC 3841: Accept-Contact Header", HFILL
}
6456 { &hf_header_array
[POS_ACCEPT_ENCODING
],
6457 { "Accept-Encoding", "sip.Accept-Encoding",
6458 FT_STRING
, BASE_NONE
,NULL
,0x0,
6459 "RFC 3841: Accept-Encoding Header", HFILL
}
6461 { &hf_header_array
[POS_ACCEPT_LANGUAGE
],
6462 { "Accept-Language", "sip.Accept-Language",
6463 FT_STRING
, BASE_NONE
,NULL
,0x0,
6464 "RFC 3261: Accept-Language Header", HFILL
}
6466 { &hf_header_array
[POS_ACCEPT_RESOURCE_PRIORITY
],
6467 { "Accept-Resource-Priority", "sip.Accept-Resource-Priority",
6468 FT_STRING
, BASE_NONE
,NULL
,0x0,
6469 "Draft: Accept-Resource-Priority Header", HFILL
}
6471 { &hf_header_array
[POS_ADDITIONAL_IDENTITY
],
6472 { "Additional-Identity", "sip.Additional-Identity",
6473 FT_STRING
, BASE_NONE
,NULL
,0x0,
6476 { &hf_header_array
[POS_ALERT_INFO
],
6477 { "Alert-Info", "sip.Alert-Info",
6478 FT_STRING
, BASE_NONE
,NULL
,0x0,
6479 "RFC 3261: Alert-Info Header", HFILL
}
6481 { &hf_header_array
[POS_ALLOW
],
6482 { "Allow", "sip.Allow",
6483 FT_STRING
, BASE_NONE
,NULL
,0x0,
6484 "RFC 3261: Allow Header", HFILL
}
6486 { &hf_header_array
[POS_ALLOW_EVENTS
],
6487 { "Allow-Events", "sip.Allow-Events",
6488 FT_STRING
, BASE_NONE
,NULL
,0x0,
6489 "RFC 3265: Allow-Events Header", HFILL
}
6491 { &hf_header_array
[POS_ANSWER_MODE
],
6492 { "Answer-Mode", "sip.Answer-Mode",
6493 FT_STRING
, BASE_NONE
,NULL
,0x0,
6494 "RFC 5373: Answer-Mode Header", HFILL
}
6496 { &hf_header_array
[POS_ATTESTATION_INFO
],
6497 { "Attestation-Info", "sip.Attestation-Info",
6498 FT_STRING
, BASE_NONE
,NULL
,0x0,
6501 { &hf_header_array
[POS_AUTHENTICATION_INFO
],
6502 { "Authentication-Info", "sip.Authentication-Info",
6503 FT_STRING
, BASE_NONE
,NULL
,0x0,
6504 "RFC 3261: Authentication-Info Header", HFILL
}
6506 { &hf_header_array
[POS_AUTHORIZATION
],
6507 { "Authorization", "sip.Authorization",
6508 FT_STRING
, BASE_NONE
,NULL
,0x0,
6509 "RFC 3261: Authorization Header", HFILL
}
6511 { &hf_header_array
[POS_CALL_ID
],
6512 { "Call-ID", "sip.Call-ID",
6513 FT_STRING
, BASE_NONE
,NULL
,0x0,
6514 "RFC 3261: Call-ID Header", HFILL
}
6516 { &hf_header_array
[POS_CALL_INFO
],
6517 { "Call-Info", "sip.Call-Info",
6518 FT_STRING
, BASE_NONE
,NULL
,0x0,
6519 "RFC 3261: Call-Info Header", HFILL
}
6521 { &hf_header_array
[POS_CELLULAR_NETWORK_INFO
],
6522 { "Cellular-Network-Info", "sip.Cellular-Network-Info",
6523 FT_STRING
, BASE_NONE
,NULL
,0x0,
6526 { &hf_header_array
[POS_CONTACT
],
6527 { "Contact", "sip.Contact",
6528 FT_STRING
, BASE_NONE
,NULL
,0x0,
6529 "RFC 3261: Contact Header", HFILL
}
6531 { &hf_header_array
[POS_CONTENT_DISPOSITION
],
6532 { "Content-Disposition", "sip.Content-Disposition",
6533 FT_STRING
, BASE_NONE
,NULL
,0x0,
6534 "RFC 3261: Content-Disposition Header", HFILL
}
6536 { &hf_header_array
[POS_CONTENT_ENCODING
],
6537 { "Content-Encoding", "sip.Content-Encoding",
6538 FT_STRING
, BASE_NONE
,NULL
,0x0,
6539 "RFC 3261: Content-Encoding Header", HFILL
}
6541 { &hf_header_array
[POS_CONTENT_LANGUAGE
],
6542 { "Content-Language", "sip.Content-Language",
6543 FT_STRING
, BASE_NONE
,NULL
,0x0,
6544 "RFC 3261: Content-Language Header", HFILL
}
6546 { &hf_header_array
[POS_CONTENT_LENGTH
],
6547 { "Content-Length", "sip.Content-Length",
6548 FT_UINT32
, BASE_DEC
,NULL
,0x0,
6549 "RFC 3261: Content-Length Header", HFILL
}
6551 { &hf_header_array
[POS_CONTENT_TYPE
],
6552 { "Content-Type", "sip.Content-Type",
6553 FT_STRING
, BASE_NONE
,NULL
,0x0,
6554 "RFC 3261: Content-Type Header", HFILL
}
6556 { &hf_header_array
[POS_CSEQ
],
6557 { "CSeq", "sip.CSeq",
6558 FT_STRING
, BASE_NONE
,NULL
,0x0,
6559 "RFC 3261: CSeq Header", HFILL
}
6561 { &hf_header_array
[POS_DATE
],
6562 { "Date", "sip.Date",
6563 FT_STRING
, BASE_NONE
,NULL
,0x0,
6564 "RFC 3261: Date Header", HFILL
}
6566 { &hf_header_array
[POS_ERROR_INFO
],
6567 { "Error-Info", "sip.Error-Info",
6568 FT_STRING
, BASE_NONE
,NULL
,0x0,
6569 "RFC 3261: Error-Info Header", HFILL
}
6571 { &hf_header_array
[POS_EVENT
],
6572 { "Event", "sip.Event",
6573 FT_STRING
, BASE_NONE
,NULL
,0x0,
6574 "RFC 3265: Event Header", HFILL
}
6576 { &hf_header_array
[POS_EXPIRES
],
6577 { "Expires", "sip.Expires",
6578 FT_UINT32
, BASE_DEC
,NULL
,0x0,
6579 "RFC 3261: Expires Header", HFILL
}
6581 { &hf_header_array
[POS_FEATURE_CAPS
],
6582 { "Feature-Caps", "sip.Feature-Caps",
6583 FT_STRING
, BASE_NONE
,NULL
,0x0,
6584 "RFC 6809: Feature-Caps", HFILL
}
6586 { &hf_header_array
[POS_FLOW_TIMER
],
6587 { "Flow-Timer", "sip.Flow-Timer",
6588 FT_STRING
, BASE_NONE
,NULL
,0x0,
6589 "RFC 5626: Flow-Timer", HFILL
}
6591 { &hf_header_array
[POS_FROM
],
6592 { "From", "sip.From",
6593 FT_STRING
, BASE_NONE
,NULL
,0x0,
6594 "RFC 3261: From Header", HFILL
}
6596 { &hf_header_array
[POS_GEOLOCATION
],
6597 { "Geolocation", "sip.Geolocation",
6598 FT_STRING
, BASE_NONE
,NULL
,0x0,
6601 { &hf_header_array
[POS_GEOLOCATION_ERROR
],
6602 { "Geolocation-Error", "sip.Geolocation-Error",
6603 FT_STRING
, BASE_NONE
,NULL
,0x0,
6606 { &hf_header_array
[POS_GEOLOCATION_ROUTING
],
6607 { "Geolocation-Routing", "sip.Geolocation-Routing",
6608 FT_STRING
, BASE_NONE
,NULL
,0x0,
6611 { &hf_header_array
[POS_HISTORY_INFO
],
6612 { "History-Info", "sip.History-Info",
6613 FT_STRING
, BASE_NONE
,NULL
,0x0,
6614 "RFC 4244: Request History Information", HFILL
}
6616 { &hf_header_array
[POS_IDENTITY
],
6617 { "Identity", "sip.Identity",
6618 FT_STRING
, BASE_NONE
,NULL
,0x0,
6619 "RFC 4474: Request Identity", HFILL
}
6621 { &hf_header_array
[POS_IDENTITY_INFO
],
6622 { "Identity-info", "sip.Identity-info",
6623 FT_STRING
, BASE_NONE
,NULL
,0x0,
6624 "RFC 4474: Request Identity-info", HFILL
}
6626 { &hf_header_array
[POS_INFO_PKG
],
6627 { "Info-Package", "sip.Info-Package",
6628 FT_STRING
, BASE_NONE
,NULL
,0x0,
6631 { &hf_header_array
[POS_IN_REPLY_TO
],
6632 { "In-Reply-To", "sip.In-Reply-To",
6633 FT_STRING
, BASE_NONE
,NULL
,0x0,
6634 "RFC 3261: In-Reply-To Header", HFILL
}
6636 { &hf_header_array
[POS_JOIN
],
6637 { "Join", "sip.Join",
6638 FT_STRING
, BASE_NONE
,NULL
,0x0,
6639 "Draft: Join Header", HFILL
}
6641 { &hf_header_array
[POS_MAX_BREADTH
],
6642 { "Max-Breadth", "sip.Max-Breadth",
6643 FT_UINT32
, BASE_DEC
,NULL
,0x0,
6644 "RFC 5393: Max-Breadth Header", HFILL
}
6646 { &hf_header_array
[POS_MAX_FORWARDS
],
6647 { "Max-Forwards", "sip.Max-Forwards",
6648 FT_UINT32
, BASE_DEC
,NULL
,0x0,
6649 "RFC 3261: Max-Forwards Header", HFILL
}
6651 { &hf_header_array
[POS_MIME_VERSION
],
6652 { "MIME-Version", "sip.MIME-Version",
6653 FT_STRING
, BASE_NONE
,NULL
,0x0,
6654 "RFC 3261: MIME-Version Header", HFILL
}
6656 { &hf_header_array
[POS_MIN_EXPIRES
],
6657 { "Min-Expires", "sip.Min-Expires",
6658 FT_STRING
, BASE_NONE
,NULL
,0x0,
6659 "RFC 3261: Min-Expires Header", HFILL
}
6661 { &hf_header_array
[POS_MIN_SE
],
6662 { "Min-SE", "sip.Min-SE",
6663 FT_STRING
, BASE_NONE
,NULL
,0x0,
6664 "Draft: Min-SE Header", HFILL
}
6666 { &hf_header_array
[POS_ORGANIZATION
],
6667 { "Organization", "sip.Organization",
6668 FT_STRING
, BASE_NONE
,NULL
,0x0,
6669 "RFC 3261: Organization Header", HFILL
}
6671 { &hf_header_array
[POS_ORIGINATION_ID
],
6672 { "Origination-Id", "sip.Origination-Id",
6673 FT_STRING
, BASE_NONE
,NULL
,0x0,
6676 { &hf_header_array
[POS_P_ACCESS_NETWORK_INFO
],
6677 { "P-Access-Network-Info", "sip.P-Access-Network-Info",
6678 FT_STRING
, BASE_NONE
,NULL
,0x0,
6679 "P-Access-Network-Info Header", HFILL
}
6681 { &hf_header_array
[POS_P_ANSWER_STATE
],
6682 { "P-Answer-State", "sip.P-Answer-State",
6683 FT_STRING
, BASE_NONE
,NULL
,0x0,
6684 "RFC 4964: P-Answer-State Header", HFILL
}
6686 { &hf_header_array
[POS_P_ASSERTED_IDENTITY
],
6687 { "P-Asserted-Identity", "sip.P-Asserted-Identity",
6688 FT_STRING
, BASE_NONE
,NULL
,0x0,
6689 "RFC 3325: P-Asserted-Identity Header", HFILL
}
6691 { &hf_header_array
[POS_P_ASSERTED_SERV
],
6692 { "P-Asserted-Service", "sip.P-Asserted-Service",
6693 FT_STRING
, BASE_NONE
,NULL
,0x0,
6696 { &hf_header_array
[POS_P_CHARGE_INFO
],
6697 { "P-Charge-Info", "sip.P-Charge-Info",
6698 FT_STRING
, BASE_NONE
,NULL
,0x0,
6701 { &hf_header_array
[POS_P_ASSOCIATED_URI
],
6702 { "P-Associated-URI", "sip.P-Associated-URI",
6703 FT_STRING
, BASE_NONE
,NULL
,0x0,
6704 "RFC 3455: P-Associated-URI Header", HFILL
}
6707 { &hf_header_array
[POS_P_CALLED_PARTY_ID
],
6708 { "P-Called-Party-ID", "sip.P-Called-Party-ID",
6709 FT_STRING
, BASE_NONE
,NULL
,0x0,
6710 "RFC 3455: P-Called-Party-ID Header", HFILL
}
6713 { &hf_header_array
[POS_P_CHARGING_FUNC_ADDRESSES
],
6714 { "P-Charging-Function-Addresses","sip.P-Charging-Function-Addresses",
6715 FT_STRING
, BASE_NONE
,NULL
,0x0,
6719 { &hf_header_array
[POS_P_CHARGING_VECTOR
],
6720 { "P-Charging-Vector", "sip.P-Charging-Vector",
6721 FT_STRING
, BASE_NONE
,NULL
,0x0,
6722 "P-Charging-Vector Header", HFILL
}
6725 { &hf_header_array
[POS_P_DCS_TRACE_PARTY_ID
],
6726 { "P-DCS-Trace-Party-ID", "sip.P-DCS-Trace-Party-ID",
6727 FT_STRING
, BASE_NONE
,NULL
,0x0,
6728 "P-DCS-Trace-Party-ID Header", HFILL
}
6731 { &hf_header_array
[POS_P_DCS_OSPS
],
6732 { "P-DCS-OSPS", "sip.P-DCS-OSPS",
6733 FT_STRING
, BASE_NONE
,NULL
,0x0,
6734 "P-DCS-OSPS Header", HFILL
}
6737 { &hf_header_array
[POS_P_DCS_BILLING_INFO
],
6738 { "P-DCS-Billing-Info", "sip.P-DCS-Billing-Info",
6739 FT_STRING
, BASE_NONE
,NULL
,0x0,
6740 "P-DCS-Billing-Info Header", HFILL
}
6743 { &hf_header_array
[POS_P_DCS_LAES
],
6744 { "P-DCS-LAES", "sip.P-DCS-LAES",
6745 FT_STRING
, BASE_NONE
,NULL
,0x0,
6746 "P-DCS-LAES Header", HFILL
}
6749 { &hf_header_array
[POS_P_DCS_REDIRECT
],
6750 { "P-DCS-Redirect", "sip.P-DCS-Redirect",
6751 FT_STRING
, BASE_NONE
,NULL
,0x0,
6752 "P-DCS-Redirect Header", HFILL
}
6755 { &hf_header_array
[POS_P_EARLY_MEDIA
],
6756 { "P-Early-Media", "sip.P-Early-Media",
6757 FT_STRING
, BASE_NONE
,NULL
,0x0,
6758 "P-Early-Media Header", HFILL
}
6761 { &hf_header_array
[POS_P_MEDIA_AUTHORIZATION
],
6762 { "P-Media-Authorization", "sip.P-Media-Authorization",
6763 FT_STRING
, BASE_NONE
,NULL
,0x0,
6764 "RFC 3313: P-Media-Authorization Header", HFILL
}
6767 { &hf_header_array
[POS_P_PREFERRED_IDENTITY
],
6768 { "P-Preferred-Identity", "sip.P-Preferred-Identity",
6769 FT_STRING
, BASE_NONE
,NULL
,0x0,
6770 "RFC 3325: P-Preferred-Identity Header", HFILL
}
6772 { &hf_header_array
[POS_P_PREFERRED_SERV
],
6773 { "P-Preferred-Service", "sip.P-Preferred-Service",
6774 FT_STRING
, BASE_NONE
,NULL
,0x0,
6777 { &hf_header_array
[POS_P_PROFILE_KEY
],
6778 { "P-Profile-Key", "sip.P-Profile-Key",
6779 FT_STRING
, BASE_NONE
,NULL
,0x0,
6780 "P-Profile-Key Header", HFILL
}
6782 { &hf_header_array
[POS_P_REFUSED_URI_LST
],
6783 { "P-Refused-URI-List", "sip.P-Refused-URI-List",
6784 FT_STRING
, BASE_NONE
,NULL
,0x0,
6785 "P-Refused-URI-List Header", HFILL
}
6787 { &hf_header_array
[POS_P_SERVED_USER
],
6788 { "P-Served-User", "sip.P-Served-User",
6789 FT_STRING
, BASE_NONE
,NULL
,0x0,
6792 { &hf_header_array
[POS_P_USER_DATABASE
],
6793 { "P-User-Database", "sip.P-User-Database",
6794 FT_STRING
, BASE_NONE
,NULL
,0x0,
6795 "P-User-Database Header", HFILL
}
6798 { &hf_header_array
[POS_P_VISITED_NETWORK_ID
],
6799 { "P-Visited-Network-ID", "sip.P-Visited-Network-ID",
6800 FT_STRING
, BASE_NONE
,NULL
,0x0,
6801 "RFC 3455: P-Visited-Network-ID Header", HFILL
}
6804 { &hf_header_array
[POS_PATH
],
6805 { "Path", "sip.Path",
6806 FT_STRING
, BASE_NONE
,NULL
,0x0,
6807 "RFC 3327: Path Header", HFILL
}
6810 { &hf_header_array
[POS_PERMISSION_MISSING
],
6811 { "Permission-Missing", "sip.Permission-Missing",
6812 FT_STRING
, BASE_NONE
,NULL
,0x0,
6813 "RFC 5360: Permission Missing Header", HFILL
}
6815 { &hf_header_array
[POS_POLICY_CONTACT
],
6816 { "Policy-Contact", "sip.Policy_Contact",
6817 FT_STRING
, BASE_NONE
,NULL
,0x0,
6820 { &hf_header_array
[POS_POLICY_ID
],
6821 { "Policy-ID", "sip.Policy_ID",
6822 FT_STRING
, BASE_NONE
,NULL
,0x0,
6825 { &hf_header_array
[POS_PRIORITY
],
6826 { "Priority", "sip.Priority",
6827 FT_STRING
, BASE_NONE
,NULL
,0x0,
6828 "RFC 3261: Priority Header", HFILL
}
6830 { &hf_header_array
[POS_PRIORITY_SHARE
],
6831 { "Priority-Share", "sip.Priority-Share",
6832 FT_STRING
, BASE_NONE
,NULL
,0x0,
6835 { &hf_header_array
[POS_PRIV_ANSWER_MODE
],
6836 { "Priv-Answer-mode", "sip.Priv-Answer-mode",
6837 FT_STRING
, BASE_NONE
,NULL
,0x0,
6840 { &hf_header_array
[POS_PRIVACY
],
6841 { "Privacy", "sip.Privacy",
6842 FT_STRING
, BASE_NONE
,NULL
,0x0,
6843 "Privacy Header", HFILL
}
6846 { &hf_header_array
[POS_PROXY_AUTHENTICATE
],
6847 { "Proxy-Authenticate", "sip.Proxy-Authenticate",
6848 FT_STRING
, BASE_NONE
,NULL
,0x0,
6849 "RFC 3261: Proxy-Authenticate Header", HFILL
}
6851 { &hf_header_array
[POS_PROXY_AUTHORIZATION
],
6852 { "Proxy-Authorization", "sip.Proxy-Authorization",
6853 FT_STRING
, BASE_NONE
,NULL
,0x0,
6854 "RFC 3261: Proxy-Authorization Header", HFILL
}
6857 { &hf_header_array
[POS_PROXY_REQUIRE
],
6858 { "Proxy-Require", "sip.Proxy-Require",
6859 FT_STRING
, BASE_NONE
,NULL
,0x0,
6860 "RFC 3261: Proxy-Require Header", HFILL
}
6862 { &hf_header_array
[POS_RACK
],
6863 { "RAck", "sip.RAck",
6864 FT_STRING
, BASE_NONE
,NULL
,0x0,
6865 "RFC 3262: RAck Header", HFILL
}
6867 { &hf_header_array
[POS_REASON
],
6868 { "Reason", "sip.Reason",
6869 FT_STRING
, BASE_NONE
,NULL
,0x0,
6870 "RFC 3326 Reason Header", HFILL
}
6872 { &hf_header_array
[POS_REASON_PHRASE
],
6873 { "Reason-Phrase", "sip.Reason-Phrase",
6874 FT_STRING
, BASE_NONE
,NULL
,0x0,
6877 { &hf_header_array
[POS_RECORD_ROUTE
],
6878 { "Record-Route", "sip.Record-Route",
6879 FT_STRING
, BASE_NONE
,NULL
,0x0,
6880 "RFC 3261: Record-Route Header", HFILL
}
6882 { &hf_header_array
[POS_RECV_INFO
],
6883 { "Recv-Info", "sip.Recv-Info",
6884 FT_STRING
, BASE_NONE
,NULL
,0x0,
6887 { &hf_header_array
[POS_REFER_SUB
],
6888 { "Refer-Sub", "sip.Refer-Sub",
6889 FT_STRING
, BASE_NONE
,NULL
,0x0,
6890 "RFC 4488: Refer-Sub Header", HFILL
}
6892 { &hf_header_array
[POS_REFER_TO
],
6893 { "Refer-To", "sip.Refer-To",
6894 FT_STRING
, BASE_NONE
,NULL
,0x0,
6895 "RFC 3515: Refer-To Header", HFILL
}
6897 { &hf_header_array
[POS_REFERRED_BY
],
6898 { "Referred By", "sip.Referred-by",
6899 FT_STRING
, BASE_NONE
,NULL
,0x0,
6900 "RFC 3892: Referred-by Header", HFILL
}
6902 { &hf_header_array
[POS_REJECT_CONTACT
],
6903 { "Reject-Contact", "sip.Reject-Contact",
6904 FT_STRING
, BASE_NONE
,NULL
,0x0,
6905 "RFC 3841: Reject-Contact Header", HFILL
}
6907 { &hf_header_array
[POS_RELAYED_CHARGE
],
6908 { "Relayed-Charge", "sip.Relayed-Charge",
6909 FT_STRING
, BASE_NONE
,NULL
,0x0,
6912 { &hf_header_array
[POS_REPLACES
],
6913 { "Replaces", "sip.Replaces",
6914 FT_STRING
, BASE_NONE
,NULL
,0x0,
6915 "RFC 3891: Replaces Header", HFILL
}
6917 { &hf_header_array
[POS_REPLY_TO
],
6918 { "Reply-To", "sip.Reply-To",
6919 FT_STRING
, BASE_NONE
,NULL
,0x0,
6920 "RFC 3261: Reply-To Header", HFILL
}
6922 { &hf_header_array
[POS_REQUEST_DISPOSITION
],
6923 { "Request-Disposition", "sip.Request-Disposition",
6924 FT_STRING
, BASE_NONE
,NULL
,0x0,
6925 "RFC 3841: Request-Disposition Header", HFILL
}
6927 { &hf_header_array
[POS_REQUIRE
],
6928 { "Require", "sip.Require",
6929 FT_STRING
, BASE_NONE
,NULL
,0x0,
6930 "RFC 3261: Require Header", HFILL
}
6932 { &hf_header_array
[POS_RESOURCE_PRIORITY
],
6933 { "Resource-Priority", "sip.Resource-Priority",
6934 FT_STRING
, BASE_NONE
,NULL
,0x0,
6935 "Draft: Resource-Priority Header", HFILL
}
6937 { &hf_header_array
[POS_RESOURCE_SHARE
],
6938 { "Resource-Share", "sip.Resource-Share",
6939 FT_STRING
, BASE_NONE
,NULL
,0x0,
6942 { &hf_header_array
[POS_RESPONSE_SOURCE
],
6943 { "Response-Source", "sip.Response-Source",
6944 FT_STRING
, BASE_NONE
,NULL
,0x0,
6947 { &hf_header_array
[POS_RESTORATION_INFO
],
6948 { "Restoration-Info", "sip.Restoration-Info",
6949 FT_STRING
, BASE_NONE
,NULL
,0x0,
6952 { &hf_header_array
[POS_RETRY_AFTER
],
6953 { "Retry-After", "sip.Retry-After",
6954 FT_UINT32
, BASE_DEC
,NULL
,0x0,
6955 "RFC 3261: Retry-After Header", HFILL
}
6957 { &hf_header_array
[POS_ROUTE
],
6958 { "Route", "sip.Route",
6959 FT_STRING
, BASE_NONE
,NULL
,0x0,
6960 "RFC 3261: Route Header", HFILL
}
6962 { &hf_header_array
[POS_RSEQ
],
6963 { "RSeq", "sip.RSeq",
6964 FT_UINT32
, BASE_DEC
,NULL
,0x0,
6965 "RFC 3262: RSeq Header", HFILL
}
6967 { &hf_header_array
[ POS_SECURITY_CLIENT
],
6968 { "Security-Client", "sip.Security-Client",
6969 FT_STRING
, BASE_NONE
,NULL
,0x0,
6970 "RFC 3329 Security-Client Header", HFILL
}
6972 { &hf_header_array
[ POS_SECURITY_SERVER
],
6973 { "Security-Server", "sip.Security-Server",
6974 FT_STRING
, BASE_NONE
,NULL
,0x0,
6975 "RFC 3329 Security-Server Header", HFILL
}
6977 { &hf_header_array
[ POS_SECURITY_VERIFY
],
6978 { "Security-Verify", "sip.Security-Verify",
6979 FT_STRING
, BASE_NONE
,NULL
,0x0,
6980 "RFC 3329 Security-Verify Header", HFILL
}
6982 { &hf_header_array
[POS_SERVER
],
6983 { "Server", "sip.Server",
6984 FT_STRING
, BASE_NONE
,NULL
,0x0,
6985 "RFC 3261: Server Header", HFILL
}
6987 { &hf_header_array
[POS_SERVICE_INTERACT_INFO
],
6988 { "Service-Interact-Info", "sip.Service-Interact-Info",
6989 FT_STRING
, BASE_NONE
,NULL
,0x0,
6992 { &hf_header_array
[POS_SERVICE_ROUTE
],
6993 { "Service-Route", "sip.Service-Route",
6994 FT_STRING
, BASE_NONE
,NULL
,0x0,
6995 "RFC 3608: Service-Route Header", HFILL
}
6997 { &hf_header_array
[POS_SESSION_EXPIRES
],
6998 { "Session-Expires", "sip.Session-Expires",
6999 FT_STRING
, BASE_NONE
,NULL
,0x0,
7000 "RFC 4028: Session-Expires Header", HFILL
}
7002 { &hf_header_array
[POS_SESSION_ID
],
7003 { "Session-ID", "sip.Session-ID",
7004 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7007 { &hf_header_array
[POS_SIP_ETAG
],
7008 { "ETag", "sip.ETag",
7009 FT_STRING
, BASE_NONE
,NULL
,0x0,
7010 "RFC 3903: SIP-ETag Header", HFILL
}
7012 { &hf_header_array
[POS_SIP_IF_MATCH
],
7013 { "If_Match", "sip.If_Match",
7014 FT_STRING
, BASE_NONE
,NULL
,0x0,
7015 "RFC 3903: SIP-If-Match Header", HFILL
}
7017 { &hf_header_array
[POS_SUBJECT
],
7018 { "Subject", "sip.Subject",
7019 FT_STRING
, BASE_NONE
,NULL
,0x0,
7020 "RFC 3261: Subject Header", HFILL
}
7022 { &hf_header_array
[POS_SUBSCRIPTION_STATE
],
7023 { "Subscription-State", "sip.Subscription-State",
7024 FT_STRING
, BASE_NONE
,NULL
,0x0,
7025 "RFC 3265: Subscription-State Header", HFILL
}
7027 { &hf_header_array
[POS_SUPPORTED
],
7028 { "Supported", "sip.Supported",
7029 FT_STRING
, BASE_NONE
,NULL
,0x0,
7030 "RFC 3261: Supported Header", HFILL
}
7032 { &hf_header_array
[POS_SUPPRESS_IF_MATCH
],
7033 { "Suppress-If-Match", "sip.Suppress_If_Match",
7034 FT_STRING
, BASE_NONE
,NULL
,0x0,
7037 { &hf_header_array
[POS_TARGET_DIALOG
],
7038 { "Target-Dialog", "sip.Target-Dialog",
7039 FT_STRING
, BASE_NONE
,NULL
,0x0,
7040 "RFC 4538: Target-Dialog Header", HFILL
}
7042 { &hf_header_array
[POS_TIMESTAMP
],
7043 { "Timestamp", "sip.Timestamp",
7044 FT_STRING
, BASE_NONE
,NULL
,0x0,
7045 "RFC 3261: Timestamp Header", HFILL
}
7047 { &hf_header_array
[POS_TO
],
7049 FT_STRING
, BASE_NONE
,NULL
,0x0,
7050 "RFC 3261: To Header", HFILL
}
7053 { &hf_header_array
[POS_TRIGGER_CONSENT
],
7054 { "Trigger-Consent", "sip.Trigger-Consent",
7055 FT_STRING
, BASE_NONE
,NULL
,0x0,
7056 "RFC 5380: Trigger Consent", HFILL
}
7059 { &hf_header_array
[POS_UNSUPPORTED
],
7060 { "Unsupported", "sip.Unsupported",
7061 FT_STRING
, BASE_NONE
,NULL
,0x0,
7062 "RFC 3261: Unsupported Header", HFILL
}
7064 { &hf_header_array
[POS_USER_AGENT
],
7065 { "User-Agent", "sip.User-Agent",
7066 FT_STRING
, BASE_NONE
,NULL
,0x0,
7067 "RFC 3261: User-Agent Header", HFILL
}
7069 { &hf_header_array
[POS_VIA
],
7071 FT_STRING
, BASE_NONE
,NULL
,0x0,
7072 "RFC 3261: Via Header", HFILL
}
7074 { &hf_header_array
[POS_WARNING
],
7075 { "Warning", "sip.Warning",
7076 FT_STRING
, BASE_NONE
,NULL
,0x0,
7077 "RFC 3261: Warning Header", HFILL
}
7080 { &hf_header_array
[POS_WWW_AUTHENTICATE
],
7081 { "WWW-Authenticate", "sip.WWW-Authenticate",
7082 FT_STRING
, BASE_NONE
,NULL
,0x0,
7083 "RFC 3261: WWW-Authenticate Header", HFILL
}
7085 { &hf_header_array
[POS_DIVERSION
],
7086 { "Diversion", "sip.Diversion",
7087 FT_STRING
, BASE_NONE
,NULL
,0x0,
7088 "RFC 5806: Diversion Header", HFILL
}
7090 { &hf_header_array
[POS_USER_TO_USER
],
7091 { "User-to-User", "sip.uui",
7092 FT_STRING
, BASE_NONE
,NULL
,0x0,
7093 "draft-johnston-sipping-cc-uui-09: User-to-User header", HFILL
}
7096 { "Resent Packet", "sip.resend",
7097 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
7100 { &hf_sip_original_frame
,
7101 { "Suspected resend of frame", "sip.resend-original",
7102 FT_FRAMENUM
, BASE_NONE
, FRAMENUM_TYPE(FT_FRAMENUM_RETRANS_PREV
), 0x0,
7103 "Original transmission of frame", HFILL
}
7105 { &hf_sip_matching_request_frame
,
7106 { "Request Frame", "sip.response-request",
7107 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
7110 { &hf_sip_response_time
,
7111 { "Response Time (ms)", "sip.response-time",
7112 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
7113 "Response time since original request (in milliseconds)", HFILL
}
7115 { &hf_sip_release_time
,
7116 { "Release Time (ms)", "sip.release-time",
7117 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
7118 "release time since original BYE (in milliseconds)", HFILL
}
7121 { "Authentication", "sip.auth",
7122 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7123 "SIP Authentication", HFILL
}
7125 { &hf_sip_auth_scheme
,
7126 { "Authentication Scheme", "sip.auth.scheme",
7127 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7128 "SIP Authentication Scheme", HFILL
}
7130 { &hf_sip_auth_digest_response
,
7131 { "Digest Authentication Response", "sip.auth.digest.response",
7132 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7133 "SIP Digest Authentication Response Value", HFILL
}
7136 { "Nonce Count", "sip.auth.nc",
7137 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7138 "SIP Authentication Nonce count", HFILL
}
7140 { &hf_sip_auth_username
,
7141 { "Username", "sip.auth.username",
7142 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7143 "SIP Authentication Username", HFILL
}
7145 { &hf_sip_auth_realm
,
7146 { "Realm", "sip.auth.realm",
7147 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7148 "SIP Authentication Realm", HFILL
}
7150 { &hf_sip_auth_nonce
,
7151 { "Nonce Value", "sip.auth.nonce",
7152 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7153 "SIP Authentication Nonce", HFILL
}
7155 { &hf_sip_auth_algorithm
,
7156 { "Algorithm", "sip.auth.algorithm",
7157 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7158 "SIP Authentication Algorithm", HFILL
}
7160 { &hf_sip_auth_opaque
,
7161 { "Opaque Value", "sip.auth.opaque",
7162 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7163 "SIP Authentication Opaque value", HFILL
}
7166 { "QOP", "sip.auth.qop",
7167 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7168 "SIP Authentication QOP", HFILL
}
7170 { &hf_sip_auth_cnonce
,
7171 { "CNonce Value", "sip.auth.cnonce",
7172 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7173 "SIP Authentication Client Nonce", HFILL
}
7176 { "Authentication URI", "sip.auth.uri",
7177 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7178 "SIP Authentication URI", HFILL
}
7180 { &hf_sip_auth_domain
,
7181 { "Authentication Domain", "sip.auth.domain",
7182 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7183 "SIP Authentication Domain", HFILL
}
7185 { &hf_sip_auth_stale
,
7186 { "Stale Flag", "sip.auth.stale",
7187 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7188 "SIP Authentication Stale Flag", HFILL
}
7190 { &hf_sip_auth_auts
,
7191 { "Authentication Token", "sip.auth.auts",
7192 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7193 "SIP Authentication Token", HFILL
}
7195 { &hf_sip_auth_rspauth
,
7196 { "Response auth", "sip.auth.rspauth",
7197 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7198 "SIP Authentication Response auth", HFILL
}
7200 { &hf_sip_auth_nextnonce
,
7201 { "Next Nonce", "sip.auth.nextnonce",
7202 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7203 "SIP Authentication Next Nonce", HFILL
}
7206 { "Integrity Key", "sip.auth.ik",
7207 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7208 "SIP Authentication Integrity Key", HFILL
}
7211 { "Cyphering Key", "sip.auth.ck",
7212 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7213 "SIP Authentication Cyphering Key", HFILL
}
7215 { &hf_sip_cseq_seq_no
,
7216 { "Sequence Number", "sip.CSeq.seq",
7217 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
7218 "CSeq header sequence number", HFILL
}
7220 { &hf_sip_cseq_method
,
7221 { "Method", "sip.CSeq.method",
7222 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7223 "CSeq header method", HFILL
}
7225 { &hf_sip_via_transport
,
7226 { "Transport", "sip.Via.transport",
7227 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7228 "Via header Transport", HFILL
}
7230 { &hf_sip_via_sent_by_address
,
7231 { "Sent-by Address", "sip.Via.sent-by.address",
7232 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7233 "Via header Sent-by Address", HFILL
}
7235 { &hf_sip_via_sent_by_port
,
7236 { "Sent-by port", "sip.Via.sent-by.port",
7237 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
7238 "Via header Sent-by Port", HFILL
}
7240 { &hf_sip_via_branch
,
7241 { "Branch", "sip.Via.branch",
7242 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7243 "SIP Via Branch", HFILL
},
7245 { &hf_sip_via_maddr
,
7246 { "Maddr", "sip.Via.maddr",
7247 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7248 "SIP Via Maddr", HFILL
},
7250 { &hf_sip_via_rport
,
7251 { "RPort", "sip.Via.rport",
7252 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7253 "SIP Via RPort", HFILL
},
7255 { &hf_sip_via_received
,
7256 { "Received", "sip.Via.received",
7257 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7258 "SIP Via Received", HFILL
},
7261 { "TTL", "sip.Via.ttl",
7262 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7263 "SIP Via TTL", HFILL
}
7266 { "Comp", "sip.Via.comp",
7267 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7268 "SIP Via comp", HFILL
}
7270 { &hf_sip_via_sigcomp_id
,
7271 { "Sigcomp identifier", "sip.Via.sigcomp-id",
7272 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7273 "SIP Via sigcomp identifier", HFILL
}
7276 { "Overload Control", "sip.Via.oc",
7277 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7280 { &hf_sip_via_oc_val
,
7281 { "Overload Control Value", "sip.Via.oc_val",
7282 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
7285 { &hf_sip_via_oc_validity
,
7286 { "Overload Control Validity", "sip.Via.oc_validity",
7287 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7290 { &hf_sip_via_oc_seq
,
7291 { "Overload Control Sequence", "sip.Via.oc_seq",
7292 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7295 { &hf_sip_oc_seq_timestamp
,
7296 { "Overload Control Sequence Time Stamp",
7297 "sip.Via.oc_seq.ts",
7298 FT_ABSOLUTE_TIME
, ABSOLUTE_TIME_UTC
, NULL
, 0x0,
7301 { &hf_sip_via_oc_algo
,
7302 { "Overload Control Algorithm", "sip.Via.oc_algo",
7303 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7306 { &hf_sip_via_be_route
,
7307 { "be-route", "sip.Via.be_route",
7308 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7311 { &hf_sip_p_acc_net_i_acc_type
,
7312 { "access-type", "sip.P-Access-Network-Info.access-type",
7313 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7314 "SIP P-Access-Network-Info access-type", HFILL
}
7316 { &hf_sip_p_acc_net_i_ucid_3gpp
,
7317 { "utran-cell-id-3gpp", "sip.P-Access-Network-Info.utran-cell-id-3gpp",
7318 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7319 "SIP P-Access-Network-Info utran-cell-id-3gpp", HFILL
}
7321 { &hf_sip_rack_rseq_no
,
7322 { "RSeq Sequence Number", "sip.RAck.RSeq.seq",
7323 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
7324 "RAck RSeq header sequence number (from prov response)", HFILL
}
7326 { &hf_sip_rack_cseq_no
,
7327 { "CSeq Sequence Number", "sip.RAck.CSeq.seq",
7328 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
7329 "RAck CSeq header sequence number (from prov response)", HFILL
}
7331 { &hf_sip_rack_cseq_method
,
7332 { "CSeq Method", "sip.RAck.CSeq.method",
7333 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7334 "RAck CSeq header method (from prov response)", HFILL
}
7336 { &hf_sip_reason_protocols
,
7337 { "Reason protocols", "sip.reason_protocols",
7338 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7341 { &hf_sip_reason_cause_q850
,
7342 { "Cause", "sip.reason_cause_q850",
7343 FT_UINT32
, BASE_DEC_HEX
|BASE_EXT_STRING
, &q850_cause_code_vals_ext
, 0x0,
7346 { &hf_sip_reason_cause_sip
,
7347 { "Cause", "sip.reason_cause_sip",
7348 FT_UINT32
, BASE_DEC
, VALS(sip_response_code_vals
), 0x0,
7351 { &hf_sip_reason_cause_other
,
7352 { "Cause", "sip.reason_cause_other",
7353 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
7356 { &hf_sip_reason_text
,
7357 { "Text", "sip.reason_text",
7358 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7362 { "Message Body", "sip.msg_body",
7363 FT_BYTES
, BASE_NONE
|BASE_NO_DISPLAY_VALUE
, NULL
, 0x0,
7364 "Message Body in SIP message", HFILL
}
7366 { &hf_sip_sec_mechanism
,
7367 { "[Security-mechanism]", "sip.sec_mechanism",
7368 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7371 { &hf_sip_sec_mechanism_alg
,
7372 { "alg", "sip.sec_mechanism.alg",
7373 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7376 { &hf_sip_sec_mechanism_ealg
,
7377 { "ealg", "sip.sec_mechanism.ealg",
7378 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7381 { &hf_sip_sec_mechanism_prot
,
7382 { "prot", "sip.sec_mechanism.prot",
7383 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7386 { &hf_sip_sec_mechanism_spi_c
,
7387 { "spi-c", "sip.sec_mechanism.spi_c",
7388 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
7391 { &hf_sip_sec_mechanism_spi_s
,
7392 { "spi-s", "sip.sec_mechanism.spi_s",
7393 FT_UINT32
, BASE_DEC_HEX
, NULL
, 0x0,
7396 { &hf_sip_sec_mechanism_port1
,
7397 { "port1", "sip.sec_mechanism.port1",
7398 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
7401 { &hf_sip_sec_mechanism_port_c
,
7402 { "port-c", "sip.sec_mechanism.port_c",
7403 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
7406 { &hf_sip_sec_mechanism_port2
,
7407 { "port2", "sip.sec_mechanism.port2",
7408 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
7411 { &hf_sip_sec_mechanism_port_s
,
7412 { "port-s", "sip.sec_mechanism.port_s",
7413 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
7416 { &hf_sip_session_id_sess_id
,
7417 { "sess-id", "sip.Session-ID.sess_id",
7418 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
7421 { &hf_sip_session_id_param
,
7422 { "param", "sip.Session-ID.param",
7423 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7426 { &hf_sip_session_id_local_uuid
,
7427 { "local-uuid", "sip.Session-ID.local_uuid",
7428 FT_GUID
, BASE_NONE
, NULL
, 0x0,
7431 { &hf_sip_session_id_remote_uuid
,
7432 { "remote-uuid", "sip.Session-ID.remote_uuid",
7433 FT_GUID
, BASE_NONE
, NULL
, 0x0,
7436 { &hf_sip_session_id_logme
,
7437 { "logme", "sip.Session-ID.logme",
7438 FT_BOOLEAN
, BASE_NONE
, TFS(&tfs_set_notset
), 0x0,
7441 { &hf_sip_continuation
,
7442 { "Continuation data", "sip.continuation",
7443 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
7446 { &hf_sip_feature_cap
,
7447 { "Feature Cap", "sip.feature_cap",
7448 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7451 { &hf_sip_service_priority
,
7452 { "Service Priority", "sip.service_priority",
7453 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7456 { &hf_sip_icid_value
,
7457 { "icid-value", "sip.icid_value",
7458 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7461 { &hf_sip_icid_gen_addr
,
7462 { "icid-gen-addr", "sip.icid_gen_addr",
7463 FT_STRING
, BASE_NONE
, NULL
, 0x0,
7466 { &hf_sip_call_id_gen
,
7467 { "Generated Call-ID", "sip.call_id_generated",
7468 FT_STRING
, BASE_NONE
,NULL
,0x0,
7469 "Use to catch call id across protocols", HFILL
}
7474 /* raw_sip header field(s) */
7475 static hf_register_info raw_hf
[] = {
7478 { "Raw SIP Line", "raw_sip.line",
7479 FT_STRING
, BASE_NONE
,NULL
,0x0,
7483 /* Setup protocol subtree array */
7484 static int *ett
[] = {
7492 &ett_sip_contact_item
,
7493 &ett_sip_message_body
,
7497 &ett_sip_security_client
,
7498 &ett_sip_security_server
,
7499 &ett_sip_security_verify
,
7501 &ett_sip_record_route
,
7502 &ett_sip_service_route
,
7513 &ett_sip_session_id
,
7514 &ett_sip_p_access_net_info
,
7515 &ett_sip_p_charging_vector
,
7516 &ett_sip_feature_caps
,
7517 &ett_sip_via_be_route
7519 static int *ett_raw
[] = {
7523 static ei_register_info ei
[] = {
7524 { &ei_sip_unrecognized_header
, { "sip.unrecognized_header", PI_UNDECODED
, PI_NOTE
, "Unrecognised SIP header", EXPFILL
}},
7525 { &ei_sip_header_no_colon
, { "sip.header_no_colon", PI_MALFORMED
, PI_WARN
, "Header has no colon after the name", EXPFILL
}},
7526 { &ei_sip_header_not_terminated
, { "sip.header_not_terminated", PI_MALFORMED
, PI_WARN
, "Header not terminated by empty line (CRLF)", EXPFILL
}},
7528 { &ei_sip_odd_register_response
, { "sip.response.unusual", PI_RESPONSE_CODE
, PI_WARN
, "SIP Response is unusual", EXPFILL
}},
7530 { &ei_sip_call_id_invalid
, { "sip.Call-ID.invalid", PI_PROTOCOL
, PI_WARN
, "Call ID is mandatory", EXPFILL
}},
7531 { &ei_sip_sipsec_malformed
, { "sip.sec_mechanism.malformed", PI_MALFORMED
, PI_WARN
, "SIP Security-mechanism header malformed", EXPFILL
}},
7532 { &ei_sip_via_sent_by_port
, { "sip.Via.sent-by.port.invalid", PI_MALFORMED
, PI_NOTE
, "Invalid SIP Via sent-by-port", EXPFILL
}},
7533 { &ei_sip_content_length_invalid
, { "sip.content_length.invalid", PI_MALFORMED
, PI_NOTE
, "Invalid content_length", EXPFILL
}},
7534 { &ei_sip_retry_after_invalid
, { "sip.retry_after.invalid", PI_MALFORMED
, PI_NOTE
, "Invalid retry_after value", EXPFILL
}},
7535 { &ei_sip_Status_Code_invalid
, { "sip.Status-Code.invalid", PI_MALFORMED
, PI_NOTE
, "Invalid Status-Code", EXPFILL
}},
7536 { &ei_sip_authorization_invalid
, { "sip.authorization.invalid", PI_PROTOCOL
, PI_WARN
, "Invalid authorization response for known credentials", EXPFILL
}},
7537 { &ei_sip_session_id_sess_id
,{ "sip.Session-ID.sess_id.invalid", PI_PROTOCOL
, PI_WARN
, "Session ID cannot be empty", EXPFILL
}}
7540 module_t
*sip_module
;
7541 expert_module_t
* expert_sip
;
7542 uat_t
* sip_custom_headers_uat
;
7543 uat_t
* sip_authorization_users_uat
;
7545 static tap_param sip_stat_params
[] = {
7546 { PARAM_FILTER
, "filter", "Filter", NULL
, true }
7549 static stat_tap_table_ui sip_stat_table
= {
7550 REGISTER_TELEPHONY_GROUP_UNSORTED
,
7557 sip_stat_free_table_item
,
7559 array_length(sip_stat_fields
), sip_stat_fields
,
7560 array_length(sip_stat_params
), sip_stat_params
,
7565 /* UAT for header fields */
7566 static uat_field_t sip_custom_header_uat_fields
[] = {
7567 UAT_FLD_CSTRING(sip_custom_header_fields
, header_name
, "Header name", "SIP header name"),
7568 UAT_FLD_CSTRING(sip_custom_header_fields
, header_desc
, "Field desc", "Description of the value contained in the header"),
7572 static uat_field_t sip_authorization_users_uat_fields
[] = {
7573 UAT_FLD_CSTRING(sip_authorization_users
, username
, "Username", "SIP authorization username"),
7574 UAT_FLD_CSTRING(sip_authorization_users
, realm
, "Realm", "SIP authorization realm"),
7575 UAT_FLD_CSTRING(sip_authorization_users
, password
, "Password", "SIP authorization password"),
7579 /* Register the protocol name and description */
7580 proto_sip
= proto_register_protocol("Session Initiation Protocol", "SIP", "sip");
7581 proto_raw_sip
= proto_register_protocol("Session Initiation Protocol (SIP as raw text)",
7582 "Raw_SIP", "raw_sip");
7583 sip_handle
= register_dissector("sip", dissect_sip
, proto_sip
);
7584 sip_tcp_handle
= register_dissector("sip.tcp", dissect_sip_tcp
, proto_sip
);
7586 /* Required function calls to register the header fields and subtrees used */
7587 proto_register_field_array(proto_sip
, hf
, array_length(hf
));
7588 proto_register_subtree_array(ett
, array_length(ett
));
7589 expert_sip
= expert_register_protocol(proto_sip
);
7590 expert_register_field_array(expert_sip
, ei
, array_length(ei
));
7591 proto_register_subtree_array(ett_raw
, array_length(ett_raw
));
7593 /* Register raw_sip field(s) */
7594 proto_register_field_array(proto_raw_sip
, raw_hf
, array_length(raw_hf
));
7596 sip_module
= prefs_register_protocol(proto_sip
, proto_reg_handoff_sip
);
7598 prefs_register_uint_preference(sip_module
, "tls.port",
7600 "SIP Server TLS Port",
7603 prefs_register_bool_preference(sip_module
, "display_raw_text",
7604 "Display raw text for SIP message",
7605 "Specifies that the raw text of the "
7606 "SIP message should be displayed "
7607 "in addition to the dissection tree",
7608 &global_sip_raw_text
);
7610 prefs_register_bool_preference(sip_module
, "display_raw_text_without_crlf",
7611 "Don't show '\\r\\n' in raw SIP messages",
7612 "If the raw text of the SIP message "
7613 "is displayed, the trailing carriage "
7614 "return and line feed are not shown",
7615 &global_sip_raw_text_without_crlf
);
7617 prefs_register_enum_preference(sip_module
, "raw_text_body_default_encoding",
7618 "Default charset of raw SIP messages",
7619 "Display sip body of raw text by using this charset. The default is UTF-8.",
7620 &global_sip_raw_text_body_default_encoding
,
7621 ws_supported_mibenum_vals_character_sets_ev_array
, false);
7623 prefs_register_bool_preference(sip_module
, "strict_sip_version",
7624 "Enforce strict SIP version check (" SIP2_HDR
")",
7625 "If enabled, only " SIP2_HDR
" traffic will be dissected as SIP. "
7626 "Disable it to allow SIP traffic with a different version "
7627 "to be dissected as SIP.",
7628 &strict_sip_version
);
7630 prefs_register_bool_preference(sip_module
, "desegment_headers",
7631 "Reassemble SIP headers spanning multiple TCP segments",
7632 "Whether the SIP dissector should reassemble headers "
7633 "of a request spanning multiple TCP segments. "
7634 "To use this option, you must also enable "
7635 "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
7636 &sip_desegment_headers
);
7638 prefs_register_bool_preference(sip_module
, "desegment_body",
7639 "Reassemble SIP bodies spanning multiple TCP segments",
7640 "Whether the SIP dissector should use the "
7641 "\"Content-length:\" value, if present, to reassemble "
7642 "the body of a request spanning multiple TCP segments, "
7643 "and reassemble chunked data spanning multiple TCP segments. "
7644 "To use this option, you must also enable "
7645 "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
7646 &sip_desegment_body
);
7648 prefs_register_bool_preference(sip_module
, "retrans_the_same_sport",
7649 "Retransmissions always use the same source port",
7650 "Whether retransmissions are detected coming from the same source port only.",
7651 &sip_retrans_the_same_sport
);
7653 prefs_register_bool_preference(sip_module
, "delay_sdp_changes",
7654 "Delay SDP changes for tracking media",
7655 "Whether SIP should delay tracking the media (e.g., RTP/RTCP) until an SDP offer "
7656 "is answered. If enabled, mid-dialog changes to SDP and media state only take "
7657 "effect if and when an SDP offer is successfully answered; however enabling this "
7658 "prevents tracking media in early-media call scenarios",
7659 &sip_delay_sdp_changes
);
7661 prefs_register_bool_preference(sip_module
, "hide_generatd_call_id",
7662 "Hide the generated Call Id",
7663 "Whether the generated call id should be hidden(not displayed) in the tree or not.",
7664 &sip_hide_generatd_call_ids
);
7667 sip_custom_headers_uat
= uat_new("Custom SIP Header Fields",
7668 sizeof(header_field_t
),
7669 "custom_sip_header_fields",
7671 &sip_custom_header_fields
,
7672 &sip_custom_num_header_fields
,
7673 /* specifies named fields, so affects dissection
7674 and the set of named fields */
7675 UAT_AFFECTS_DISSECTION
|UAT_AFFECTS_FIELDS
,
7677 header_fields_copy_cb
,
7678 header_fields_update_cb
,
7679 header_fields_free_cb
,
7680 header_fields_post_update_cb
,
7681 header_fields_reset_cb
,
7682 sip_custom_header_uat_fields
7685 prefs_register_uat_preference(sip_module
, "custom_sip_header_fields", "Custom SIP header fields",
7686 "A table to define custom SIP header for which fields can be setup and used for filtering/data extraction etc.",
7687 sip_custom_headers_uat
);
7689 prefs_register_bool_preference(sip_module
, "validate_authorization",
7690 "Validate SIP authorization",
7691 "Validate SIP authorizations with known credentials",
7692 &global_sip_validate_authorization
);
7694 sip_authorization_users_uat
= uat_new("SIP authorization users",
7695 sizeof(authorization_user_t
),
7696 "authorization_users_sip",
7698 &sip_authorization_users
,
7699 &sip_authorization_num_users
,
7700 /* specifies named fields, so affects dissection
7701 and the set of named fields */
7702 UAT_AFFECTS_DISSECTION
|UAT_AFFECTS_FIELDS
,
7704 authorization_users_copy_cb
,
7705 authorization_users_update_cb
,
7706 authorization_users_free_cb
,
7709 sip_authorization_users_uat_fields
7712 prefs_register_uat_preference(sip_module
, "authorization_users_sip", "SIP authorization users",
7713 "A table to define user credentials used for validating authorization attempts",
7714 sip_authorization_users_uat
);
7716 register_init_routine(&sip_init_protocol
);
7717 register_cleanup_routine(&sip_cleanup_protocol
);
7718 heur_subdissector_list
= register_heur_dissector_list_with_description("sip", "SIP message fallback", proto_sip
);
7719 /* Register for tapping */
7720 sip_tap
= register_tap("sip");
7721 sip_follow_tap
= register_tap("sip_follow");
7723 ext_hdr_subdissector_table
= register_dissector_table("sip.hdr", "SIP Extension header", proto_sip
, FT_STRING
, STRING_CASE_SENSITIVE
);
7725 register_stat_tap_table_ui(&sip_stat_table
);
7727 /* compile patterns */
7728 ws_mempbrk_compile(&pbrk_comma_semi
, ",;");
7729 ws_mempbrk_compile(&pbrk_whitespace
, " \t\r\n");
7730 ws_mempbrk_compile(&pbrk_param_end
, ">,;? \r");
7731 ws_mempbrk_compile(&pbrk_param_end_colon_brackets
, ">,;? \r:[]");
7732 ws_mempbrk_compile(&pbrk_header_end_dquote
, "\r\n,;\"");
7733 ws_mempbrk_compile(&pbrk_tab_sp_fslash
, "\t /");
7734 ws_mempbrk_compile(&pbrk_addr_end
, "[] \t:;");
7735 ws_mempbrk_compile(&pbrk_via_param_end
, "\t;, ");
7737 register_follow_stream(proto_sip
, "sip_follow", sip_follow_conv_filter
, sip_follow_index_filter
, sip_follow_address_filter
,
7738 udp_port_to_display
, follow_tvb_tap_listener
, NULL
, NULL
);
7742 proto_reg_handoff_sip(void)
7744 static unsigned saved_sip_tls_port
;
7745 static bool sip_prefs_initialized
= false;
7747 if (!sip_prefs_initialized
) {
7748 sigcomp_handle
= find_dissector_add_dependency("sigcomp", proto_sip
);
7749 sip_diag_handle
= find_dissector("sip.diagnostic");
7750 sip_uri_userinfo_handle
= find_dissector("sip.uri_userinfo");
7751 sip_via_branch_handle
= find_dissector("sip.via_branch");
7752 sip_via_be_route_handle
= find_dissector("sip.via_be_route");
7753 /* Check for a dissector to parse Reason Code texts */
7754 sip_reason_code_handle
= find_dissector("sip.reason_code");
7755 /* SIP content type and internet media type used by other dissectors are the same */
7756 media_type_dissector_table
= find_dissector_table("media_type");
7758 dissector_add_uint_range_with_preference("udp.port", DEFAULT_SIP_PORT_RANGE
, sip_handle
);
7759 dissector_add_string("media_type", "message/sip", sip_handle
);
7760 dissector_add_string("ws.protocol", "sip", sip_handle
); /* RFC 7118 */
7762 dissector_add_uint_range_with_preference("tcp.port", DEFAULT_SIP_PORT_RANGE
, sip_tcp_handle
);
7764 heur_dissector_add("udp", dissect_sip_heur
, "SIP over UDP", "sip_udp", proto_sip
, HEURISTIC_ENABLE
);
7765 heur_dissector_add("tcp", dissect_sip_tcp_heur
, "SIP over TCP", "sip_tcp", proto_sip
, HEURISTIC_ENABLE
);
7766 heur_dissector_add("sctp", dissect_sip_heur
, "SIP over SCTP", "sip_sctp", proto_sip
, HEURISTIC_ENABLE
);
7767 heur_dissector_add("stun", dissect_sip_heur
, "SIP over TURN", "sip_stun", proto_sip
, HEURISTIC_ENABLE
);
7769 dissector_add_uint("acdr.tls_application_port", 5061, sip_handle
);
7770 dissector_add_uint("acdr.tls_application", TLS_APP_SIP
, sip_handle
);
7771 dissector_add_string("protobuf_field", "adc.sip.ResponsePDU.body", sip_handle
);
7772 dissector_add_string("protobuf_field", "adc.sip.RequestPDU.body", sip_handle
);
7774 exported_pdu_tap
= find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_7
);
7776 sip_prefs_initialized
= true;
7778 ssl_dissector_delete(saved_sip_tls_port
, sip_tcp_handle
);
7780 /* Set our port number for future use */
7781 ssl_dissector_add(sip_tls_port
, sip_tcp_handle
);
7782 saved_sip_tls_port
= sip_tls_port
;
7787 * Editor modelines - https://www.wireshark.org/tools/modelines.html
7792 * indent-tabs-mode: nil
7795 * vi: set shiftwidth=4 tabstop=8 expandtab:
7796 * :indentSize=4:tabSize=8:noTabs=true: