Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-sip.c
blobc8928b0072f29b2b7256854e4a7b03a95a1d1b7c
1 /* packet-sip.c
2 * Routines for the Session Initiation Protocol (SIP) dissection.
3 * RFCs 3261-3264
5 * TODO:
6 * hf_ display filters for headers of SIP extension RFCs (ongoing)
8 * Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi>
9 * Copyright 2001, Jean-Francois Mule <jfm@cablelabs.com>
10 * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
11 * Copyright 2011, Anders Broman <anders.broman@ericsson.com>, Johan Wahl <johan.wahl@ericsson.com>
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
23 #include "config.h"
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>
33 #include <epan/uat.h>
34 #include <epan/follow.h>
35 #include <epan/addr_resolv.h>
36 #include <epan/epan_dissect.h>
37 #include <epan/iana_charsets.h>
38 #include <epan/tfs.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 */
79 static int proto_sip;
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 */
250 static int ett_sip;
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;
288 #if 0
289 static expert_field ei_sip_odd_register_response;
290 #endif
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
316 "ACK",
317 #define SIP_METHOD_BYE 2
318 "BYE",
319 #define SIP_METHOD_CANCEL 3
320 "CANCEL",
321 #define SIP_METHOD_DO 4
322 "DO",
323 #define SIP_METHOD_INFO 5
324 "INFO",
325 #define SIP_METHOD_INVITE 6
326 "INVITE",
327 #define SIP_METHOD_MESSAGE 7
328 "MESSAGE",
329 #define SIP_METHOD_NOTIFY 8
330 "NOTIFY",
331 #define SIP_METHOD_OPTIONS 9
332 "OPTIONS",
333 #define SIP_METHOD_PRACK 10
334 "PRACK",
335 #define SIP_METHOD_QAUTH 11
336 "QAUTH",
337 #define SIP_METHOD_REFER 12
338 "REFER",
339 #define SIP_METHOD_REGISTER 13
340 "REGISTER",
341 #define SIP_METHOD_SPRACK 14
342 "SPRACK",
343 #define SIP_METHOD_SUBSCRIBE 15
344 "SUBSCRIBE",
345 #define SIP_METHOD_UPDATE 16
346 "UPDATE",
347 #define SIP_METHOD_PUBLISH 17
348 "PUBLISH"
351 /* from RFC 3261
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
356 typedef struct {
357 const char *name;
358 const char *compact_name;
359 } sip_header_t;
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 }, /* */
363 #define POS_ACCEPT 1
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
376 { "Allow", NULL },
377 #define POS_ALLOW 8
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
388 { "Call-ID", "i" },
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
394 { "Contact", "m" },
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
406 { "CSeq", NULL },
407 #define POS_CSEQ 23
408 { "Date", NULL }, /* */
409 #define POS_DATE 24
410 /* Encryption (Deprecated) [RFC3261] */
411 { "Error-Info", NULL }, /* */
412 #define POS_ERROR_INFO 25
413 { "Event", "o" }, /* */
414 #define POS_EVENT 26
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" }, /* */
422 #define POS_FROM 30
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 */
443 #define POS_JOIN 39
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 */
505 #define POS_PATH 70
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 */
527 #define POS_RACK 81
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 */
568 #define POS_RSEQ 101
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 */
602 #define POS_TO 118
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 */
610 #define POS_VIA 122
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 */
625 typedef struct {
626 const char *param_name;
627 const int *hf_item;
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}
667 typedef enum {
668 MECH_PARA_STRING = 0,
669 MECH_PARA_UINT = 1,
670 } mech_parameter_type_t;
672 /* Track associations between parameter name and hf item for security mechanism*/
673 typedef struct {
674 const char *param_name;
675 const int para_type;
676 const int *hf_item;
677 } mech_parameter_t;
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},
690 {NULL, 0, 0}
693 typedef struct {
694 int *hf_sip_display;
695 int *hf_sip_addr;
696 int *hf_sip_user;
697 int *hf_sip_host;
698 int *hf_sip_port;
699 int *hf_sip_param;
700 int *ett_uri;
701 } hf_sip_uri_t;
703 static hf_sip_uri_t sip_pai_uri = {
704 &hf_sip_pai_display,
705 &hf_sip_pai_addr,
706 &hf_sip_pai_user,
707 &hf_sip_pai_host,
708 &hf_sip_pai_port,
709 &hf_sip_pai_param,
710 &ett_sip_pai_uri
713 static hf_sip_uri_t sip_ppi_uri = {
714 &hf_sip_ppi_display,
715 &hf_sip_ppi_addr,
716 &hf_sip_ppi_user,
717 &hf_sip_ppi_host,
718 &hf_sip_ppi_port,
719 &hf_sip_ppi_param,
720 &ett_sip_ppi_uri
723 static hf_sip_uri_t sip_pmiss_uri = {
724 &hf_sip_pmiss_display,
725 &hf_sip_pmiss_addr,
726 &hf_sip_pmiss_user,
727 &hf_sip_pmiss_host,
728 &hf_sip_pmiss_port,
729 &hf_sip_pmiss_param,
730 &ett_sip_pmiss_uri
733 static hf_sip_uri_t sip_tc_uri = {
734 &hf_sip_tc_display,
735 &hf_sip_tc_addr,
736 &hf_sip_tc_user,
737 &hf_sip_tc_host,
738 &hf_sip_tc_port,
739 &hf_sip_tc_param,
740 &ett_sip_tc_uri
743 static hf_sip_uri_t sip_to_uri = {
744 &hf_sip_to_display,
745 &hf_sip_to_addr,
746 &hf_sip_to_user,
747 &hf_sip_to_host,
748 &hf_sip_to_port,
749 &hf_sip_to_param,
750 &ett_sip_to_uri
753 static hf_sip_uri_t sip_from_uri = {
754 &hf_sip_from_display,
755 &hf_sip_from_addr,
756 &hf_sip_from_user,
757 &hf_sip_from_host,
758 &hf_sip_from_port,
759 &hf_sip_from_param,
760 &ett_sip_from_uri
763 static hf_sip_uri_t sip_req_uri = {
764 &hf_sip_ruri_display,
765 &hf_sip_ruri,
766 &hf_sip_ruri_user,
767 &hf_sip_ruri_host,
768 &hf_sip_ruri_port,
769 &hf_sip_ruri_param,
770 &ett_sip_ruri
773 static hf_sip_uri_t sip_contact_uri = {
774 &hf_sip_curi_display,
775 &hf_sip_curi,
776 &hf_sip_curi_user,
777 &hf_sip_curi_host,
778 &hf_sip_curi_port,
779 &hf_sip_curi_param,
780 &ett_sip_curi
783 static hf_sip_uri_t sip_route_uri = {
784 &hf_sip_route_display,
785 &hf_sip_route,
786 &hf_sip_route_user,
787 &hf_sip_route_host,
788 &hf_sip_route_port,
789 &hf_sip_route_param,
790 &ett_sip_route
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,
815 &hf_sip_path,
816 &hf_sip_path_user,
817 &hf_sip_path_host,
818 &hf_sip_path_port,
819 &hf_sip_path_param,
820 &ett_sip_path
824 * Type of line. It's either a SIP Request-Line, a SIP Status-Line, or
825 * another type of line.
827 typedef enum {
828 REQUEST_LINE,
829 STATUS_LINE,
830 OTHER_LINE
831 } line_type_t;
833 /* Preferences */
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 {
876 char* header_name;
877 char* header_desc;
878 } 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;
886 static bool
887 header_fields_update_cb(void *r, char **err)
889 header_field_t *rec = (header_field_t *)r;
890 char c;
892 if (rec->header_name == NULL) {
893 *err = g_strdup("Header name can't be empty");
894 return false;
897 g_strstrip(rec->header_name);
898 if (rec->header_name[0] == 0) {
899 *err = g_strdup("Header name can't be empty");
900 return false;
903 /* Check for invalid characters (to avoid asserting out when
904 * registering the field).
906 c = proto_check_field_name(rec->header_name);
907 if (c) {
908 *err = ws_strdup_printf("Header name can't contain '%c'", c);
909 return false;
912 *err = NULL;
913 return true;
916 static void *
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);
925 return new_rec;
928 static void
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);
937 static void
938 deregister_header_fields(void)
940 if (dynamic_hf) {
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);
948 dynamic_hf = NULL;
949 dynamic_hf_size = 0;
952 if (sip_custom_header_fields_hash) {
953 g_hash_table_destroy(sip_custom_header_fields_hash);
954 sip_custom_header_fields_hash = NULL;
958 static void
959 header_fields_post_update_cb(void)
961 int* hf_id;
962 char* header_name;
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);
974 *hf_id = -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);
995 static void
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 {
1008 char* username;
1009 char* realm;
1010 char* password;
1011 } authorization_user_t;
1013 static authorization_user_t* sip_authorization_users;
1014 static unsigned sip_authorization_num_users;
1016 static bool
1017 authorization_users_update_cb(void *r, char **err)
1019 authorization_user_t *rec = (authorization_user_t *)r;
1020 char c;
1022 if (rec->username == NULL) {
1023 *err = g_strdup("Username can't be empty");
1024 return false;
1027 g_strstrip(rec->username);
1028 if (rec->username[0] == 0) {
1029 *err = g_strdup("Username can't be empty");
1030 return false;
1033 /* Check for invalid characters (to avoid asserting out when
1034 * registering the field).
1036 c = proto_check_field_name(rec->username);
1037 if (c) {
1038 *err = ws_strdup_printf("Username can't contain '%c'", c);
1039 return false;
1042 *err = NULL;
1043 return true;
1046 static void *
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);
1056 return new_rec;
1059 static void
1060 authorization_users_free_cb(void*r)
1062 authorization_user_t* rec = (authorization_user_t*)r;
1064 g_free(rec->username);
1065 g_free(rec->realm);
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,
1088 char* call_id,
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,
1094 char* call_id,
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,
1100 char* call_id,
1101 unsigned char cseq_number_set, uint32_t cseq_number,
1102 uint32_t *response_time);
1104 typedef struct
1106 char * username;
1107 char * realm;
1108 char * uri;
1109 char * nonce;
1110 char * cnonce;
1111 char * nonce_count;
1112 char * response;
1113 char * qop;
1114 char * algorithm;
1115 char * method;
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)
1123 unsigned i;
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];
1130 return NULL;
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
1162 * same dialog
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 */
1178 typedef struct
1180 char call_id[MAX_CALL_ID_SIZE];
1181 address source_address;
1182 uint32_t source_port;
1183 address dest_address;
1184 uint32_t dest_port;
1185 port_type ptype;
1186 } sip_hash_key;
1189 typedef enum
1191 nothing_seen,
1192 request_seen,
1193 provisional_response_seen,
1194 final_response_seen
1195 } transaction_state_t;
1197 /* Current conversation-type value */
1198 typedef struct
1200 uint32_t cseq;
1201 transaction_state_t transaction_state;
1202 const char *method;
1203 nstime_t request_time;
1204 uint32_t response_code;
1205 int frame_number;
1206 } sip_hash_value;
1208 /* Result to be stored in per-packet info */
1209 typedef struct
1211 int original_frame_num;
1212 int response_request_frame_num;
1213 int response_time;
1214 } sip_frame_result_value;
1217 /************************/
1218 /* Hash table functions */
1220 /* Equal keys */
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)
1229 return 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 */
1243 static void
1244 sip_init_protocol(void)
1246 unsigned i;
1247 char *value_copy;
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));
1259 static void
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 */
1267 static void
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);
1280 typedef enum
1282 SIP_URI_TYPE_ABSOLUTE_URI,
1283 SIP_URI_TYPE_SIP,
1284 SIP_URI_TYPE_TEL
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;
1294 int uri_start;
1295 int uri_end;
1296 int uri_parameters_start;
1297 int uri_parameters_end;
1298 int name_addr_start;
1299 int name_addr_end;
1300 int uri_user_start;
1301 int uri_user_end;
1302 int uri_host_start;
1303 int uri_host_end;
1304 int uri_host_port_start;
1305 int uri_host_port_end;
1306 } uri_offset_info;
1308 static void
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.
1333 static int
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';
1338 int current_offset;
1339 int queried_offset;
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 */
1348 return -1;
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;
1359 return -1;
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.
1370 int end_offset;
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;
1378 else
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;
1397 else
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;
1416 break;
1419 /* after adding character to this switch() , update also pbrk_param_end_colon_brackets */
1420 switch (c) {
1421 case '>':
1422 case ',':
1423 goto uri_host_end_found;
1424 case ';':
1425 uri_offsets->uri_parameters_start = parameter_end_offset + 1;
1426 goto uri_host_end_found;
1427 case '?':
1428 case ' ':
1429 case '\r':
1430 goto uri_host_end_found;
1431 case ':':
1432 if (!in_ipv6)
1433 goto uri_host_end_found;
1434 break;
1435 case '[':
1436 in_ipv6 = true;
1437 break;
1438 case ']':
1439 in_ipv6 = false;
1440 break;
1441 default :
1442 DISSECTOR_ASSERT_NOT_REACHED();
1443 break;
1447 uri_host_end_found:
1449 uri_offsets->uri_host_end = parameter_end_offset - 1;
1451 if (c == ':')
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;
1462 break;
1465 /* after adding character to this switch(), update also pbrk_param_end */
1466 switch (c) {
1467 case '>':
1468 case ',':
1469 goto uri_host_port_end_found;
1470 case ';':
1471 uri_offsets->uri_parameters_start = parameter_end_offset + 1;
1472 goto uri_host_port_end_found;
1473 case '?':
1474 case ' ':
1475 case '\r':
1476 goto uri_host_port_end_found;
1477 default :
1478 DISSECTOR_ASSERT_NOT_REACHED();
1479 break;
1483 uri_host_port_end_found:
1485 uri_offsets->uri_host_port_end = parameter_end_offset -1;
1488 return uri_offsets->name_addr_end;
1491 void
1492 dfilter_store_sip_from_addr(tvbuff_t *tvb,proto_tree *tree,unsigned parameter_offset, unsigned parameter_len)
1494 proto_item *pi;
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);
1500 static proto_item *
1501 sip_proto_tree_add_uint(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start, int length, int value_offset, int value_len)
1503 const char *str;
1504 unsigned long val;
1506 /* don't fetch string when field is not referenced */
1507 if (!proto_field_is_referenced(tree, hfindex))
1508 return tree;
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);
1516 static proto_item *
1517 sip_proto_tree_add_string(proto_tree *tree, int hfindex, tvbuff_t *tvb, int start, int length, int value_offset, int value_len)
1519 const char *str;
1521 /* don't fetch string when field is not referenced */
1522 if (!proto_field_is_referenced(tree, hfindex))
1523 return tree;
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);
1530 static void
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.
1541 static void
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);
1572 else {
1573 proto_tree_add_format_text(tree, tvb, current_offset, length);
1576 else {
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
1599 static int
1600 dissect_sip_history_info(tvbuff_t *tvb, proto_tree* tree, packet_info *pinfo _U_, int current_offset,
1601 int line_end_offset)
1603 int comma_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;
1617 first_time = false;
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
1630 * as follows:
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
1643 static int
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), ';');
1659 else {
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), ';');
1663 }else{
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;
1675 first_time = false;
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 )
1695 static int
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)
1699 char c;
1700 int i;
1701 int current_offset;
1702 int queried_offset;
1703 int colon_offset;
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 */
1711 return -1;
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);
1718 switch(c)
1720 case '"':
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)
1728 /* malformed URI */
1729 return -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++);
1736 i--;
1738 if(i % 2 == 0)
1740 /* not escaped */
1741 break;
1743 } while (current_offset < line_end_offset);
1744 if(current_offset >= line_end_offset)
1746 /* malformed URI */
1747 return -1;
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)
1756 /* malformed Uri */
1757 return -1;
1759 current_offset = queried_offset + 1;
1760 break;
1762 case '<':
1763 /* We don't have a display name */
1764 current_offset++;
1765 break;
1767 default:
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;
1781 else
1783 /* we have an URI without angle quotes */
1784 uri_without_angle_quotes = true;
1787 else
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;
1795 break;
1797 if(colon_offset != -1)
1799 /* we have an URI without angle quotes */
1800 uri_without_angle_quotes = true;
1801 break;
1803 /* If this point is reached, we can't parse the URI */
1804 return -1;
1806 break;
1808 /* Start of 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)
1816 /* malformed Uri */
1817 return -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
1830 static 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)
1833 proto_item *ti;
1834 proto_tree *uri_item_tree = NULL;
1835 tvbuff_t *next_tvb;
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) {
1850 return ti;
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;
1881 int queried_offset;
1882 int uri_param_end_offset = -1;
1883 char c;
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);
1895 if (c == '>') {
1896 uri_param_end_offset = uri_offsets->name_addr_end - 1;
1897 } else {
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)
1928 static int
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)
1932 char c;
1933 int current_offset;
1934 int queried_offset;
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 */
1946 return -1;
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 */
1956 return -1;
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){
1988 c = '\0';
1989 queried_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)
1993 switch (c) {
1994 /* prevent tree from displaying the '\r\n' as part of the param */
1995 case '\r':
1996 case '\n':
1997 end_of_hdr = true;
1998 /* fall through */
1999 case ',':
2000 case ';':
2001 case '"':
2002 break;
2003 default :
2004 DISSECTOR_ASSERT_NOT_REACHED();
2005 break;
2009 if (queried_offset == -1) {
2010 /* Last parameter, line end */
2011 current_offset = line_end_offset;
2012 }else if(c=='"'){
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;
2018 } else {
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;
2025 }else{
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) {
2039 int32_t expire;
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,
2043 * so that's ok
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;
2049 if (expire == 0) {
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
2065 #if 0
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);
2072 #endif
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;
2079 if (end_of_hdr) {
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;
2085 if (c == ',') {
2086 /* comma separator found, stop parsing of current contact-param here */
2087 break;
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
2101 static int
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;
2106 char *name;
2107 header_parameter_t *auth_parameter;
2108 unsigned i = 0;
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 */
2116 return -1;
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 */
2123 return -1;
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) == '\"') {
2133 /* quoted value */
2134 value_search_offset = value_offset;
2135 do {
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;
2142 } else {
2143 /* Include closing quotes */
2144 current_offset = queried_offset + 1;
2146 } else {
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;
2152 } else {
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,
2166 ENC_UTF_8|ENC_NA);
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);
2194 break;
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;
2208 } else {
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
2220 * cause = 1*DIGIT
2221 * reason-text = "text" EQUAL quoted-string
2222 * reason-extension = generic-param
2224 static void
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 */
2238 return;
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)
2245 return;
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, &param_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;
2255 } else {
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;
2271 else {
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 */
2278 return;
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 */
2284 return;
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 */
2288 return;
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) {
2293 tvbuff_t *next_tvb;
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
2316 static void
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 */
2327 return;
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,
2339 ENC_UTF_8);
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);
2367 } else {
2368 return;
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,
2379 ENC_UTF_8);
2380 break;
2381 case MECH_PARA_UINT:
2382 if (!value) {
2383 proto_tree_add_expert(tree, pinfo, &ei_sip_sipsec_malformed,
2384 tvb, current_offset, -1);
2385 } else {
2386 uint32_t semi_para;
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);
2391 break;
2392 default:
2393 break;
2395 break;
2397 hf_index++;
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)
2412 int current_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) {
2421 return;
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)
2431 return;
2432 display_sip_uri(tvb, tree, pinfo, &uri_offsets, sip_route_uri_p);
2434 current_offset++;
2435 start_offset = current_offset + 1;
2437 } else {
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)
2443 return;
2444 display_sip_uri(tvb, tree, pinfo, &uri_offsets, sip_route_uri_p);
2446 return;
2449 current_offset++;
2452 return;
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
2461 * / via-extension
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
2468 * SLASH transport
2469 * protocol-name = "SIP" / token
2470 * protocol-version = token
2471 * transport = "UDP" / "TCP" / "TLS" / "SCTP"
2472 * / other-transport
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)
2479 int current_offset;
2480 int address_start_offset;
2481 int semicolon_offset;
2482 bool colon_seen;
2483 bool ipv6_reference;
2484 bool ipv6_address;
2485 unsigned char c;
2486 char *param_name = NULL;
2488 current_offset = start_offset;
2490 while (1)
2492 /* Reset flags and counters */
2493 semicolon_offset = 0;
2494 ipv6_reference = false;
2495 ipv6_address = false;
2496 colon_seen = 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 */
2504 return;
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
2510 * SLASH transport
2513 current_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, '/');
2514 if (current_offset != -1)
2516 current_offset++;
2517 current_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, '/');
2520 if (current_offset != -1)
2522 current_offset++;
2523 /* skip Spaces and Tabs */
2524 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
2525 } else
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"
2533 * / other-transport
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 */
2544 if(c=='/'){
2545 current_offset++;
2546 continue;
2548 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
2549 c = tvb_get_uint8(tvb, current_offset);
2550 if(c=='/'){
2551 current_offset++;
2552 continue;
2554 break;
2555 }else{
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;
2572 break;
2575 if (c == '[') {
2576 ipv6_reference = true;
2577 ipv6_address = true;
2579 else if (c == ']')
2581 ipv6_reference = false;
2584 if (colon_seen || (c == ' ') || (c == '\t') || ((c == ':') && (ipv6_reference == false)) || (c == ';'))
2586 break;
2589 current_offset++;
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);
2595 } else {
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);
2604 if (c == ':')
2606 /* Port number will follow any space after : */
2607 int port_offset;
2608 current_offset++;
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 */
2625 uint16_t port;
2626 bool port_valid;
2627 proto_item* pi;
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);
2632 if (!port_valid)
2633 expert_add_info(pinfo, pi, &ei_sip_via_sent_by_port);
2635 else
2637 /* Shouldn't see a colon without a port number given */
2638 return;
2640 break;
2643 current_offset++;
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;
2658 unsigned i = 0;
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);
2664 if (c == ';')
2666 semicolon_offset = current_offset;
2667 current_offset++;
2668 break;
2670 else
2671 if ((c != ' ') && (c != '\t'))
2673 found_end_of_parameters = true;
2674 break;
2676 current_offset++;
2679 if (found_end_of_parameters)
2681 break;
2684 if (current_offset == line_end_offset)
2686 return;
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 != '-'))
2695 break;
2697 current_offset++;
2700 /* Not all params have an = */
2701 if (c == '=')
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)
2723 if (equals_found)
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)
2732 tvbuff_t *next_tvb;
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) {
2738 proto_item *ti;
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) {
2747 proto_item *ti;
2748 nstime_t ts;
2749 int dec_p_off = tvb_find_uint8(tvb, parameter_name_end + 1, - 1, '.');
2750 char *value;
2752 if(dec_p_off > 0){
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) {
2764 tvbuff_t* next_tvb;
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));
2769 else
2771 proto_tree_add_item(tree, *(via_parameter->hf_item), tvb,
2772 semicolon_offset+1, current_offset-semicolon_offset-1,
2773 ENC_UTF_8|ENC_NA);
2775 break;
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);
2792 if (c == ',')
2794 /* Skip it and get out of parameter loop */
2795 current_offset++;
2796 break;
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;
2812 GByteArray *bytes;
2813 proto_item *pi;
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);
2823 if (length != 0) {
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,
2826 bytes, NULL, NULL);
2827 } else {
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,
2846 ENC_UTF_8|ENC_NA);
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
2861 * null = 32("0")
2863 e_guid_t guid;
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, ';');
2901 } else {
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);
2907 } else {
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 */
2957 return;
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)
2965 return;
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);
3001 } else {
3002 dissect_e212_mcc_mnc_in_utf8_address(tvb, pinfo, tree, equals_offset + 1);
3005 else {
3006 proto_tree_add_format_text(tree, tvb, current_offset, length);
3009 else {
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
3019 follows:
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 "."
3036 transit-ioi-index
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
3043 static void
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 */
3055 return;
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 */
3073 return;
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);
3104 /* charge-params */
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);
3109 else {
3110 proto_tree_add_format_text(tree, tvb, current_offset, length);
3113 else {
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
3128 *(COMMA 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.
3144 static void
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 */
3155 return;
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;
3166 else {
3167 length = next_offset - current_offset;
3168 next_offset += 2;
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 */
3175 static int
3176 dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
3178 uint8_t octet;
3179 int len;
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);
3190 if (len < 0)
3191 return 0; /* not SIP */
3192 else
3193 return len;
3196 static int
3197 dissect_sip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
3199 uint8_t octet;
3200 int offset = 0, linelen;
3201 int len;
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)) {
3217 return 0;
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);
3222 if (linelen == -1){
3223 pinfo->desegment_offset = offset;
3224 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
3225 return -1;
3228 len = dissect_sip_common(tvb, offset, remaining_length, pinfo, tree, true, true);
3229 if (len <= 0)
3230 return len;
3231 offset += len;
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);
3244 if (linelen == -1){
3245 pinfo->desegment_offset = offset;
3246 pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
3247 return -1;
3250 len = dissect_sip_common(tvb, offset, remaining_length, pinfo, tree, true, true);
3251 if (len <= 0)
3252 return len;
3253 offset += len;
3254 remaining_length = remaining_length - len;
3256 return offset;
3259 static bool
3260 dissect_sip_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
3262 int offset = 0;
3263 int len;
3264 bool first = true;
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);
3270 if (len == -2) {
3271 if (first) {
3273 * If the first packet doesn't start with
3274 * a valid SIP request or response, don't
3275 * treat this as SIP.
3277 return false;
3279 break;
3281 if (len == -1)
3282 break; /* need more data */
3283 offset += len;
3284 remaining_length = remaining_length - len;
3285 first = false;
3287 return true;
3290 static bool
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;
3298 static int
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;
3306 tvbuff_t *next_tvb;
3307 bool is_known_request;
3308 int found_match = 0;
3309 const char *descr;
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;
3329 int strlen_to_copy;
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))))
3342 return -2;
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);
3355 if(linelen==0){
3356 return -2;
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.
3366 return -2;
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.
3378 return -2;
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,
3395 NULL, NULL)) {
3397 * More data needed for desegmentation.
3399 return -1;
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;
3414 unsigned proto_id;
3415 const char *proto_name;
3416 void *tmp;
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) {
3434 case REQUEST_LINE:
3435 is_known_request = sip_is_known_request(tvb, offset, token_1_len, &current_method_idx);
3436 descr = is_known_request ? "Request" : "Unknown request";
3437 col_add_lstr(pinfo->cinfo, COL_INFO,
3438 descr, ": ",
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)));
3443 break;
3445 case STATUS_LINE:
3446 descr = "Status";
3447 col_add_lstr(pinfo->cinfo, COL_INFO,
3448 "Status: ",
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)));
3455 break;
3457 case OTHER_LINE:
3458 default: /* Squelch compiler complaints */
3459 descr = "Continuation";
3460 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
3461 DPRINT(("got continuation"));
3462 break;
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) {
3470 case REQUEST_LINE:
3471 if (sip_tree) {
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);
3478 break;
3480 case STATUS_LINE:
3481 if (sip_tree) {
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);
3487 break;
3489 case OTHER_LINE:
3490 if (sip_tree) {
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
3508 * length.
3510 content_length = -1;
3511 while (remaining_length > 0) {
3512 int line_end_offset;
3513 unsigned char c;
3515 linelen = tvb_find_line_end(tvb, body_offset, -1, &next_offset, false);
3516 if (linelen == 0) {
3518 * This is a blank line separating the
3519 * message header from the message body.
3521 body_offset = next_offset;
3522 break;
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;
3541 }/* End while */
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;
3560 int colon_offset;
3561 int semi_colon_offset;
3562 int parameter_offset;
3563 int parameter_end_offset;
3564 int parameter_len;
3565 int content_type_len, content_type_parameter_str_len;
3566 int header_len;
3567 char *header_name;
3568 dissector_handle_t ext_hdr_handle;
3569 int hf_index;
3570 int value_offset;
3571 int sub_value_offset;
3572 int comma_offset;
3573 unsigned char c;
3574 int value_len;
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);
3580 if (linelen == 0) {
3582 * This is a blank line separating the
3583 * message header from the message body.
3585 offset = next_offset;
3586 break;
3589 line_end_offset = offset + linelen;
3590 if(tvb_reported_length_remaining(tvb, next_offset) <= 0){
3591 is_no_header_termination = true;
3592 }else{
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);
3611 } else {
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) {
3625 int *hf_ptr = NULL;
3626 if (sip_custom_header_fields_hash) {
3627 hf_ptr = (int*)g_hash_table_lookup(sip_custom_header_fields_hash, header_name);
3629 if (hf_ptr) {
3630 sip_proto_tree_add_string(hdr_tree, *hf_ptr, tvb, offset,
3631 next_offset - offset, value_offset, value_len);
3632 } else {
3633 proto_item *ti_c;
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);
3643 } else {
3644 expert_add_info_format(pinfo, ti_c, &ei_sip_unrecognized_header,
3645 "Unrecognised SIP header (%s)",
3646 header_name);
3649 } else {
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 ) {
3659 case POS_TO :
3661 /*if(hdr_tree)*/ {
3662 proto_item *item;
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,
3671 ett_sip_element);
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))
3693 parameter_offset++;
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");
3715 break;
3718 } /* if hdr_tree */
3719 break;
3721 case POS_FROM :
3722 /*if(hdr_tree)*/ {
3723 proto_item *item;
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))
3756 parameter_offset++;
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);
3770 }/* hdr_tree */
3771 break;
3773 case POS_P_ASSERTED_IDENTITY :
3774 if(hdr_tree)
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,
3783 ett_sip_element);
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);
3796 break;
3797 case POS_P_ASSOCIATED_URI:
3798 if (hdr_tree)
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
3807 * [p-aso-uri-spec]
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,
3818 ett_sip_element);
3819 /* We have generic parameters */
3820 dissect_sip_generic_parameters(tvb, sip_element_tree, pinfo, semi_colon_offset + 1, line_end_offset);
3825 break;
3826 case POS_HISTORY_INFO:
3827 if(hdr_tree)
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,
3836 ett_sip_hist);
3837 dissect_sip_history_info(tvb, sip_element_tree, pinfo, value_offset, line_end_offset);
3839 break;
3841 case POS_P_CHARGING_FUNC_ADDRESSES:
3842 if(hdr_tree)
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,
3851 ett_sip_element);
3852 dissect_sip_p_charging_func_addresses(tvb, sip_element_tree, pinfo, value_offset, line_end_offset);
3854 break;
3856 case POS_P_PREFERRED_IDENTITY :
3857 if(hdr_tree)
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,
3866 ett_sip_element);
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);
3878 break;
3880 case POS_PERMISSION_MISSING :
3881 if(hdr_tree)
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,
3890 ett_sip_element);
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);
3902 break;
3905 case POS_TRIGGER_CONSENT :
3906 if(hdr_tree)
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,
3915 ett_sip_element);
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);
3942 else
3943 break; /* malformed */
3945 hparam_offset = tvb_find_uint8(tvb, hparam_offset, -1,';');
3950 }/* hdr_tree */
3951 break;
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);
3956 uint32_t retry;
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,
3962 retry);
3964 if (!retry_valid) {
3965 expert_add_info(pinfo, sip_element_item, &ei_sip_retry_after_invalid);
3968 break;
3969 case POS_CSEQ :
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;
3978 /* Add CSeq tree */
3979 if (hdr_tree) {
3980 sip_element_item = proto_tree_add_string(hdr_tree,
3981 hf_header_array[hf_index], tvb,
3982 offset, next_offset - offset,
3983 value);
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
3990 of method name */
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,
3997 cseq_number);
3998 break;
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 */
4007 break;
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,
4026 strlen_to_copy);
4027 return offset - orig_offset;
4029 else {
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);
4036 break;
4038 case POS_RACK :
4040 char *value = tvb_get_string_enc(pinfo->pool, tvb, value_offset, value_len, ENC_UTF_8|ENC_NA);
4041 int cseq_no_offset;
4042 /*int cseq_method_offset;*/
4044 /* Add RAck tree */
4045 if (hdr_tree) {
4046 sip_element_item = proto_tree_add_string(hdr_tree,
4047 hf_header_array[hf_index], tvb,
4048 offset, next_offset - offset,
4049 value);
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);
4055 /* RSeq number */
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));
4063 break;
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')
4073 break;
4076 cseq_no_offset = sub_value_offset;
4078 /* CSeq number */
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));
4087 break;
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 */
4097 break;
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 */
4109 if (cseq_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);
4116 break;
4119 case POS_CALL_ID :
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,
4131 call_id);
4132 gen_item = proto_tree_add_string(hdr_tree,
4133 hf_sip_call_id_gen, tvb,
4134 offset, next_offset - offset,
4135 call_id);
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);
4142 break;
4144 case POS_EXPIRES :
4145 if (tvb_strneql(tvb, value_offset, "0", value_len) == 0)
4147 expires_is_0 = 1;
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);
4155 break;
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));
4193 /* Debug code
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);
4197 break;
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,
4207 content_length);
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);
4212 break;
4215 case POS_MAX_BREADTH :
4216 case POS_MAX_FORWARDS :
4217 case POS_RSEQ :
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);
4222 break;
4224 case POS_CONTACT :
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,
4237 ett_sip_element);
4239 /* value_offset points to the first non SWS character after ':' */
4240 c = tvb_get_uint8(tvb, value_offset);
4241 if (c =='*'){
4242 contact_is_star = 1;
4243 break;
4246 /*if(hdr_tree)*/ {
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)
4251 contacts++;
4252 if(comma_offset == next_offset)
4254 /* Line End reached: Stop Parsing */
4255 break;
4258 if(tvb_get_uint8(tvb, comma_offset) != ',')
4260 /* Undefined value reached: Stop Parsing */
4261 break;
4263 comma_offset++; /* skip comma */
4266 break;
4268 case POS_AUTHORIZATION:
4269 /* Authorization = "Authorization" HCOLON credentials
4270 * credentials = ("Digest" LWS digest-response)
4271 * / other-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))
4279 * / other-challenge
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
4292 * *(COMMA ainfo)
4293 * ainfo = nextnonce / message-qop
4294 * / response-auth / cnonce
4295 * / nonce-count
4297 /* Add tree using whole text of line */
4298 if (hdr_tree) {
4299 proto_item *ti_c;
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,
4310 ett_sip_element);
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,
4315 ENC_UTF_8);
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);
4328 } else {
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 */
4339 break;
4342 if (tvb_get_uint8(tvb, comma_offset) != ',')
4344 /* Undefined value reached: Stop Parsing */
4345 break;
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 */
4360 }/*hdr_tree*/
4361 break;
4363 case POS_ROUTE:
4364 /* Add Route subtree */
4365 if (hdr_tree) {
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);
4375 break;
4376 case POS_RECORD_ROUTE:
4377 /* Add Record-Route subtree */
4378 if (hdr_tree) {
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);
4388 break;
4389 case POS_SERVICE_ROUTE:
4390 /* Add Service-Route subtree */
4391 if (hdr_tree) {
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);
4401 break;
4402 case POS_PATH:
4403 /* Add Path subtree */
4404 if (hdr_tree) {
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);
4414 break;
4415 case POS_VIA:
4416 /* Add Via subtree */
4417 if (hdr_tree) {
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);
4427 break;
4428 case POS_REASON:
4429 if(hdr_tree) {
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);
4439 break;
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));
4452 break;
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;
4474 break;
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;
4496 break;
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;
4518 break;
4519 case POS_SESSION_ID:
4520 if(hdr_tree) {
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);
4529 break;
4530 case POS_P_ACCESS_NETWORK_INFO:
4531 /* Add P-Access-Network-Info subtree */
4532 if (hdr_tree) {
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);
4541 break;
4542 case POS_P_CHARGING_VECTOR:
4543 if (hdr_tree) {
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);
4554 break;
4555 case POS_FEATURE_CAPS:
4556 if (hdr_tree) {
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);
4567 break;
4568 default :
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);
4575 break;
4576 }/* end switch */
4577 }/*if HF_index */
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;
4586 }/* End while */
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;
4597 if (!call_id) {
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
4602 * is missing.
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
4611 if (expires_is_0) {
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)");
4626 else
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");
4637 else
4638 if (!contacts)
4640 col_append_str(pinfo->cinfo, COL_INFO, " (fetch bindings)");
4642 else
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");
4667 } else {
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
4679 * way to do this.
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,
4691 &response_time);
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,
4700 &response_time);
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,
4706 line_type);
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);
4716 if (datalen > 0) {
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);
4734 if (next_tvb) {
4735 add_new_data_source(pinfo, next_tvb, "gunzipped data");
4736 if(sip_tree) {
4737 ti_a = proto_tree_add_item(sip_tree, hf_sip_msg_body, next_tvb, 0, -1,
4738 ENC_NA);
4739 message_body_tree = proto_item_add_subtree(ti_a, ett_sip_message_body);
4741 } else {
4742 next_tvb = tvb_new_subset_length_caplen(tvb, offset, datalen, reported_datalen);
4743 if(sip_tree) {
4744 ti_a = proto_tree_add_item(sip_tree, hf_sip_msg_body, next_tvb, 0, -1,
4745 ENC_NA);
4746 message_body_tree = proto_item_add_subtree(ti_a, ett_sip_message_body);
4749 }else{
4750 next_tvb = tvb_new_subset_length_caplen(tvb, offset, datalen, reported_datalen);
4751 if(sip_tree) {
4752 ti_a = proto_tree_add_item(sip_tree, hf_sip_msg_body, next_tvb, 0, -1,
4753 ENC_NA);
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",
4766 pinfo->num));
4767 DINDENT();
4768 setup_sdp_transport(next_tvb, pinfo, SDP_EXCHANGE_OFFER, pinfo->num, sip_delay_sdp_changes, &setup_info);
4769 DENDENT();
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));
4775 DINDENT();
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);
4778 DENDENT();
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));
4784 DINDENT();
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);
4787 DENDENT();
4790 } else {
4791 DPRINT(("calling setup_sdp_transport() resend_for_packet "
4792 "request_frame=%d, this=%d",
4793 request_for_response, pinfo->num));
4794 DINDENT();
4795 setup_sdp_transport_resend(pinfo->num, resend_for_packet);
4796 DENDENT();
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()"));
4803 DINDENT();
4804 found_match = dissector_try_string_with_data(media_type_dissector_table,
4805 media_type_str_lower_case,
4806 next_tvb, pinfo,
4807 message_body_tree, true, &content_info);
4808 DENDENT();
4809 DPRINT(("done calling dissector_try_string_with_data() with found_match=%u", found_match));
4811 if (!found_match &&
4812 !strncmp(media_type_str_lower_case, "multipart/", sizeof("multipart/")-1)) {
4813 DPRINT(("calling dissector_try_string_with_data() for multipart"));
4814 DINDENT();
4815 /* Try to decode the unknown multipart subtype anyway */
4816 found_match = dissector_try_string_with_data(media_type_dissector_table,
4817 "multipart/",
4818 next_tvb, pinfo,
4819 message_body_tree, true, &content_info);
4820 DENDENT();
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"));
4828 DINDENT();
4829 if (!(dissector_try_heuristic(heur_subdissector_list,
4830 next_tvb, pinfo, message_body_tree, &hdtbl_entry, NULL))) {
4831 int tmp_offset = 0;
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;
4838 }/* end while */
4840 DENDENT();
4842 offset += datalen;
4845 /* And add the filterable field to the request/response line */
4846 if (reqresp_tree)
4848 proto_item *item;
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);
4875 if (ts != NULL)
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);
4885 else {
4886 proto_item_append_text(ts, " (%u)", stat_info->response_code);
4888 return offset - orig_offset;
4891 /* Display filter for SIP Request-Line */
4892 static void
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
4903 * SP = single space
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;
4914 if (tree) {
4915 /* build Request-URI tree*/
4916 offset=offset + parameter_len+1;
4917 sip_uri_offset_init(&uri_offsets);
4918 /* calc R-URI len*/
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 */
4926 static void
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;
4931 proto_item* pi;
4932 int diag_len;
4933 tvbuff_t *next_tvb;
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);
4958 if((diag_len) <= 0)
4959 return;
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.
4981 static line_type_t
4982 sip_parse_line(tvbuff_t *tvb, int offset, int linelen, unsigned *token_1_lenp)
4984 int space_offset;
4985 int token_1_start;
4986 unsigned token_1_len;
4987 int token_2_start;
4988 unsigned token_2_len;
4989 int token_3_start;
4990 unsigned token_3_len;
4991 int colon_pos;
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
5003 * status).
5005 return OTHER_LINE;
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.
5015 return OTHER_LINE;
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)
5031 )) {
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.
5041 return OTHER_LINE;
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.
5049 return OTHER_LINE;
5051 return STATUS_LINE;
5052 } else {
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
5062 * characters.
5064 return OTHER_LINE;
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.
5072 return OTHER_LINE;
5074 if (colon_pos >= token_3_start) {
5076 * The colon is in the version string, not the URI.
5078 return OTHER_LINE;
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)
5086 )) {
5088 * The version string isn't an SIP version 2.0 version
5089 * string.
5091 return OTHER_LINE;
5093 return REQUEST_LINE;
5097 static bool sip_is_known_request(tvbuff_t *tvb, int meth_offset,
5098 unsigned meth_len, unsigned *meth_idx)
5100 unsigned i;
5101 char *meth_name;
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)
5109 *meth_idx = i;
5110 return true;
5114 return false;
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)
5123 unsigned pos;
5125 /* Compact name is one character long */
5126 if(header_len>1){
5127 pos = GPOINTER_TO_UINT(g_hash_table_lookup(sip_headers_hash, header_name));
5128 if (pos!=0)
5129 return pos;
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)
5137 return pos;
5140 return -1;
5144 * Display the entire message as raw text.
5146 static void
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;
5150 proto_item *ti;
5151 int next_offset, linelen, end_offset;
5152 char *str;
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;
5185 if (raw_tree) {
5186 if (global_sip_raw_text_without_crlf)
5187 str = tvb_format_text_wsp(pinfo->pool, tvb, offset, linelen);
5188 else
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,
5191 str,
5192 "%s",
5193 str);
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 */
5202 if (body_tvb) {
5203 offset = 0;
5204 end_offset = tvb_captured_length_remaining(body_tvb, 0);
5205 } else {
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;
5212 if (raw_tree) {
5213 if (global_sip_raw_text_without_crlf)
5214 str = tvb_format_text_wsp(pinfo->pool, body_tvb, offset, linelen);
5215 else
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,
5230 char *call_id,
5231 unsigned char cseq_number_set,
5232 uint32_t cseq_number, line_type_t line_type)
5234 uint32_t cseq_to_compare = 0;
5235 sip_hash_key key;
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)
5245 return 0;
5248 /* A broken packet may have no cseq number set. Don't consider it as
5249 a resend */
5250 if (!cseq_number_set)
5252 return 0;
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;
5263 else
5265 return 0;
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;
5284 } else {
5285 key.source_port = MAGIC_SOURCE_PORT;
5287 key.ptype = pinfo->ptype;
5289 /* Do the lookup */
5290 p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
5292 if (p_val)
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;
5311 else
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;
5326 } else {
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;
5339 /* Add entry */
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;
5375 switch (line_type)
5377 case REQUEST_LINE:
5378 p_val->transaction_state = request_seen;
5379 if (!result)
5381 /* This frame is the original request */
5382 p_val->frame_number = pinfo->num;
5383 p_val->request_time = pinfo->abs_ts;
5385 break;
5386 case STATUS_LINE:
5387 if (stat_info->response_code >= 200)
5389 p_val->response_code = stat_info->response_code;
5390 p_val->transaction_state = final_response_seen;
5391 if (!result)
5393 /* This frame is the original response */
5394 p_val->frame_number = pinfo->num;
5397 else
5399 p_val->transaction_state = provisional_response_seen;
5401 break;
5402 default:
5403 break;
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;
5416 return 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,
5424 char *call_id,
5425 unsigned char cseq_number_set,
5426 uint32_t cseq_number,
5427 uint32_t *response_time)
5429 uint32_t cseq_to_compare = 0;
5430 sip_hash_key key;
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)
5440 return 0;
5443 /* A broken packet may have no cseq number set. Ignore. */
5444 if (!cseq_number_set)
5446 return 0;
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;
5458 else
5460 return 0;
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;
5478 /* Do the lookup */
5479 p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
5481 if (p_val)
5483 /* Table entry found, we'll use its value for comparison */
5484 cseq_to_compare = p_val->cseq;
5486 else
5488 /* We don't have the request */
5489 return 0;
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;
5523 return result;
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_,
5531 char *call_id,
5532 unsigned char cseq_number_set,
5533 uint32_t cseq_number _U_,
5534 uint32_t *response_time)
5536 #if 0
5537 uint32_t cseq_to_compare = 0;
5538 #endif
5539 sip_hash_key key;
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)
5549 return 0;
5552 /* A broken packet may have no cseq number set. Ignore. */
5553 if (!cseq_number_set)
5555 return 0;
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;
5567 else
5569 return 0;
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;
5587 /* Do the lookup */
5588 p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
5590 if (p_val)
5592 #if 0
5593 /* Table entry found, we'll use its value for comparison */
5594 cseq_to_compare = p_val->cseq;
5595 #endif
5597 else
5599 /* We don't have the request */
5600 return 0;
5604 /**************************************************/
5605 /* Is it a response to a request that we've seen? */
5606 #if 0
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;
5613 #endif
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;
5638 return result;
5641 static bool sip_validate_authorization(sip_authorization_t *authorization_info, char *password) {
5642 char ha1[33] = {0};
5643 char ha2[33] = {0};
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)) {
5663 return false;
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)) {
5695 return true;
5697 return false;
5700 /* TAP STAT INFO */
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 */
5713 { 100, "Trying"},
5714 { 180, "Ringing"},
5715 { 181, "Call Is Being Forwarded"},
5716 { 182, "Queued"},
5717 { 183, "Session Progress"},
5718 { 199, "Informational - Others" },
5720 { 200, "OK"},
5721 { 202, "Accepted"},
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"},
5741 { 410, "Gone"},
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"},
5786 { 603, "Decline"},
5787 { 604, "Does Not Exist Anywhere"},
5788 { 606, "Not Acceptable"},
5789 { 607, "Unwanted"},
5790 { 608, "Rejected"},
5791 { 699, "Global Failure - Others"},
5793 { 0, NULL}
5795 #define RESPONSE_CODE_MIN 100
5796 #define RESPONSE_CODE_MAX 699
5798 typedef enum
5800 REQ_RESP_METHOD_COLUMN,
5801 COUNT_COLUMN,
5802 RESENT_COLUMN,
5803 MIN_SETUP_COLUMN,
5804 AVG_SETUP_COLUMN,
5805 MAX_SETUP_COLUMN
5806 } sip_stat_columns;
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)];
5827 unsigned i;
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);
5846 if (req_table) {
5847 if (new_stat->stat_tap_reset_table_cb)
5848 new_stat->stat_tap_reset_table_cb(req_table);
5850 else {
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);
5862 if (resp_table) {
5863 if (new_stat->stat_tap_reset_table_cb)
5864 new_stat->stat_tap_reset_table_cb(resp_table);
5866 else {
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) {
5890 /* Request table */
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;
5893 unsigned element;
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) {
5899 cur_row = element;
5900 break;
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;
5909 unsigned element;
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) {
5921 cur_row = element;
5922 break;
5926 } else {
5927 return TAP_PACKET_DONT_REDRAW;
5930 if (cur_table) {
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;
5948 unsigned count;
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 */
5954 if (count <= 1) {
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;
5958 } else {
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;
5977 static void
5978 sip_stat_reset(stat_tap_table* table)
5980 unsigned element;
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);
6010 static void
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 */
6023 if (edt != NULL) {
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);
6030 } else {
6031 filter = ws_strdup_printf("sip.Call-ID");
6034 return filter;
6037 static char *sip_follow_index_filter(unsigned stream _U_, unsigned sub_stream _U_)
6039 return NULL;
6042 static char *sip_follow_address_filter(address *src_addr _U_, address *dst_addr _U_, int src_port _U_, int dst_port _U_)
6044 return NULL;
6048 /* Register the protocol with Wireshark */
6049 void proto_register_sip(void)
6052 /* Setup list of header fields */
6053 static hf_register_info hf[] = {
6055 { &hf_sip_msg_hdr,
6056 { "Message Header", "sip.msg_hdr",
6057 FT_STRING, BASE_NONE|BASE_NO_DISPLAY_VALUE, NULL, 0,
6058 "Message Header in SIP message", HFILL }
6060 { &hf_sip_Method,
6061 { "Method", "sip.Method",
6062 FT_STRING, BASE_NONE,NULL,0x0,
6063 "SIP Method", HFILL }
6065 { &hf_Request_Line,
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 }
6075 { &hf_sip_ruri,
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,
6098 NULL, HFILL }
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 }
6110 { &hf_sip_display,
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 }
6120 { &hf_sip_to_addr,
6121 { "SIP to address", "sip.to.addr",
6122 FT_STRING, BASE_NONE,NULL,0x0,
6123 "RFC 3261: To Address", HFILL }
6125 { &hf_sip_to_user,
6126 { "SIP to address User Part", "sip.to.user",
6127 FT_STRING, BASE_NONE,NULL,0x0,
6128 "RFC 3261: To Address User", HFILL }
6130 { &hf_sip_to_host,
6131 { "SIP to address Host Part", "sip.to.host",
6132 FT_STRING, BASE_NONE,NULL,0x0,
6133 "RFC 3261: To Address Host", HFILL }
6135 { &hf_sip_to_port,
6136 { "SIP to address Host Port", "sip.to.port",
6137 FT_STRING, BASE_NONE,NULL,0x0,
6138 "RFC 3261: To Address Port", HFILL }
6140 { &hf_sip_to_param,
6141 { "SIP To URI parameter", "sip.to.param",
6142 FT_STRING, BASE_NONE,NULL,0x0,
6143 NULL, HFILL }
6145 { &hf_sip_to_tag,
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,
6178 NULL, HFILL }
6180 { &hf_sip_from_tag,
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 }
6190 { &hf_sip_curi,
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,
6213 NULL, HFILL }
6215 { &hf_sip_route_display,
6216 { "Route display info", "sip.Route.display.info",
6217 FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6219 { &hf_sip_route,
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 }
6291 { &hf_sip_path,
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 }
6316 { &hf_sip_tag,
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 }
6326 { &hf_sip_pai_addr,
6327 { "SIP PAI Address", "sip.pai.addr",
6328 FT_STRING, BASE_NONE,NULL,0x0,
6329 "RFC 3325: P-Asserted-Identity Address", HFILL }
6331 { &hf_sip_pai_user,
6332 { "SIP PAI User Part", "sip.pai.user",
6333 FT_STRING, BASE_NONE,NULL,0x0,
6334 "RFC 3325: P-Asserted-Identity User", HFILL }
6336 { &hf_sip_pai_host,
6337 { "SIP PAI Host Part", "sip.pai.host",
6338 FT_STRING, BASE_NONE,NULL,0x0,
6339 "RFC 3325: P-Asserted-Identity Host", HFILL }
6341 { &hf_sip_pai_port,
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,
6349 NULL, HFILL }
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,
6379 NULL, HFILL }
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 }
6386 { &hf_sip_ppi_addr,
6387 { "SIP PPI Address", "sip.ppi.addr",
6388 FT_STRING, BASE_NONE,NULL,0x0,
6389 "RFC 3325: P-Preferred-Identity Address", HFILL }
6391 { &hf_sip_ppi_user,
6392 { "SIP PPI User Part", "sip.ppi.user",
6393 FT_STRING, BASE_NONE,NULL,0x0,
6394 "RFC 3325: P-Preferred-Identity User", HFILL }
6396 { &hf_sip_ppi_host,
6397 { "SIP PPI Host Part", "sip.ppi.host",
6398 FT_STRING, BASE_NONE,NULL,0x0,
6399 "RFC 3325: P-Preferred-Identity Host", HFILL }
6401 { &hf_sip_ppi_port,
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,
6409 NULL, HFILL }
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 }
6416 { &hf_sip_tc_addr,
6417 { "SIP TC Address", "sip.tc.addr",
6418 FT_STRING, BASE_NONE,NULL,0x0,
6419 "RFC 3325: Trigger Consent Address", HFILL }
6421 { &hf_sip_tc_user,
6422 { "SIP TC User Part", "sip.tc.user",
6423 FT_STRING, BASE_NONE,NULL,0x0,
6424 "RFC 3325: Trigger Consent User", HFILL }
6426 { &hf_sip_tc_host,
6427 { "SIP TC Host Part", "sip.tc.host",
6428 FT_STRING, BASE_NONE,NULL,0x0,
6429 "RFC 3325: Trigger Consent Host", HFILL }
6431 { &hf_sip_tc_port,
6432 { "SIP TC Host Port", "sip.tc.port",
6433 FT_STRING, BASE_NONE,NULL,0x0,
6434 "RFC 3325: Trigger Consent Port", HFILL }
6436 { &hf_sip_tc_param,
6437 { "SIP TC URI parameter", "sip.tc.param",
6438 FT_STRING, BASE_NONE,NULL,0x0,
6439 NULL, HFILL }
6441 { &hf_sip_tc_turi,
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,
6474 NULL, HFILL }
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,
6499 NULL, HFILL }
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,
6524 NULL, HFILL }
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,
6599 NULL, HFILL }
6601 { &hf_header_array[POS_GEOLOCATION_ERROR],
6602 { "Geolocation-Error", "sip.Geolocation-Error",
6603 FT_STRING, BASE_NONE,NULL,0x0,
6604 NULL, HFILL }
6606 { &hf_header_array[POS_GEOLOCATION_ROUTING],
6607 { "Geolocation-Routing", "sip.Geolocation-Routing",
6608 FT_STRING, BASE_NONE,NULL,0x0,
6609 NULL, HFILL }
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,
6629 NULL, HFILL }
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,
6674 NULL, HFILL }
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,
6694 NULL, HFILL }
6696 { &hf_header_array[POS_P_CHARGE_INFO],
6697 { "P-Charge-Info", "sip.P-Charge-Info",
6698 FT_STRING, BASE_NONE,NULL,0x0,
6699 NULL, HFILL }
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,
6716 NULL, HFILL }
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,
6775 NULL, HFILL }
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,
6790 NULL, HFILL }
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,
6818 NULL, HFILL }
6820 { &hf_header_array[POS_POLICY_ID],
6821 { "Policy-ID", "sip.Policy_ID",
6822 FT_STRING, BASE_NONE,NULL,0x0,
6823 NULL, HFILL }
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,
6833 NULL, HFILL }
6835 { &hf_header_array[POS_PRIV_ANSWER_MODE],
6836 { "Priv-Answer-mode", "sip.Priv-Answer-mode",
6837 FT_STRING, BASE_NONE,NULL,0x0,
6838 NULL, HFILL }
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,
6875 NULL, HFILL }
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,
6885 NULL, HFILL }
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,
6910 NULL, HFILL }
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,
6940 NULL, HFILL }
6942 { &hf_header_array[POS_RESPONSE_SOURCE],
6943 { "Response-Source", "sip.Response-Source",
6944 FT_STRING, BASE_NONE,NULL,0x0,
6945 NULL, HFILL }
6947 { &hf_header_array[POS_RESTORATION_INFO],
6948 { "Restoration-Info", "sip.Restoration-Info",
6949 FT_STRING, BASE_NONE,NULL,0x0,
6950 NULL, HFILL }
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,
6990 NULL, HFILL }
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,
7005 NULL, HFILL }
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,
7035 NULL, HFILL }
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],
7048 { "To", "sip.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],
7070 { "Via", "sip.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 }
7095 { &hf_sip_resend,
7096 { "Resent Packet", "sip.resend",
7097 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7098 NULL, HFILL }
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,
7108 NULL, HFILL}
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}
7120 { &hf_sip_auth,
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}
7135 { &hf_sip_auth_nc,
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}
7165 { &hf_sip_auth_qop,
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}
7175 { &hf_sip_auth_uri,
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}
7205 { &hf_sip_auth_ik,
7206 { "Integrity Key", "sip.auth.ik",
7207 FT_STRING, BASE_NONE, NULL, 0x0,
7208 "SIP Authentication Integrity Key", HFILL}
7210 { &hf_sip_auth_ck,
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},
7260 { &hf_sip_via_ttl,
7261 { "TTL", "sip.Via.ttl",
7262 FT_STRING, BASE_NONE, NULL, 0x0,
7263 "SIP Via TTL", HFILL}
7265 { &hf_sip_via_comp,
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}
7275 { &hf_sip_via_oc,
7276 { "Overload Control", "sip.Via.oc",
7277 FT_STRING, BASE_NONE, NULL, 0x0,
7278 NULL, HFILL }
7280 { &hf_sip_via_oc_val,
7281 { "Overload Control Value", "sip.Via.oc_val",
7282 FT_UINT32, BASE_DEC, NULL, 0x0,
7283 NULL, HFILL }
7285 { &hf_sip_via_oc_validity,
7286 { "Overload Control Validity", "sip.Via.oc_validity",
7287 FT_STRING, BASE_NONE, NULL, 0x0,
7288 NULL, HFILL }
7290 { &hf_sip_via_oc_seq,
7291 { "Overload Control Sequence", "sip.Via.oc_seq",
7292 FT_STRING, BASE_NONE, NULL, 0x0,
7293 NULL, HFILL }
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,
7299 NULL, HFILL }
7301 { &hf_sip_via_oc_algo,
7302 { "Overload Control Algorithm", "sip.Via.oc_algo",
7303 FT_STRING, BASE_NONE, NULL, 0x0,
7304 NULL, HFILL }
7306 { &hf_sip_via_be_route,
7307 { "be-route", "sip.Via.be_route",
7308 FT_STRING, BASE_NONE, NULL, 0x0,
7309 NULL, HFILL }
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,
7339 NULL, HFILL}
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,
7344 NULL, HFILL}
7346 { &hf_sip_reason_cause_sip,
7347 { "Cause", "sip.reason_cause_sip",
7348 FT_UINT32, BASE_DEC, VALS(sip_response_code_vals), 0x0,
7349 NULL, HFILL }
7351 { &hf_sip_reason_cause_other,
7352 { "Cause", "sip.reason_cause_other",
7353 FT_UINT32, BASE_DEC, NULL, 0x0,
7354 NULL, HFILL }
7356 { &hf_sip_reason_text,
7357 { "Text", "sip.reason_text",
7358 FT_STRING, BASE_NONE, NULL, 0x0,
7359 NULL, HFILL }
7361 { &hf_sip_msg_body,
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,
7369 NULL, HFILL}
7371 { &hf_sip_sec_mechanism_alg,
7372 { "alg", "sip.sec_mechanism.alg",
7373 FT_STRING, BASE_NONE, NULL, 0x0,
7374 NULL, HFILL}
7376 { &hf_sip_sec_mechanism_ealg,
7377 { "ealg", "sip.sec_mechanism.ealg",
7378 FT_STRING, BASE_NONE, NULL, 0x0,
7379 NULL, HFILL}
7381 { &hf_sip_sec_mechanism_prot,
7382 { "prot", "sip.sec_mechanism.prot",
7383 FT_STRING, BASE_NONE, NULL, 0x0,
7384 NULL, HFILL}
7386 { &hf_sip_sec_mechanism_spi_c,
7387 { "spi-c", "sip.sec_mechanism.spi_c",
7388 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
7389 NULL, HFILL}
7391 { &hf_sip_sec_mechanism_spi_s,
7392 { "spi-s", "sip.sec_mechanism.spi_s",
7393 FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
7394 NULL, HFILL}
7396 { &hf_sip_sec_mechanism_port1,
7397 { "port1", "sip.sec_mechanism.port1",
7398 FT_UINT16, BASE_DEC, NULL, 0x0,
7399 NULL, HFILL}
7401 { &hf_sip_sec_mechanism_port_c,
7402 { "port-c", "sip.sec_mechanism.port_c",
7403 FT_UINT16, BASE_DEC, NULL, 0x0,
7404 NULL, HFILL}
7406 { &hf_sip_sec_mechanism_port2,
7407 { "port2", "sip.sec_mechanism.port2",
7408 FT_UINT16, BASE_DEC, NULL, 0x0,
7409 NULL, HFILL}
7411 { &hf_sip_sec_mechanism_port_s,
7412 { "port-s", "sip.sec_mechanism.port_s",
7413 FT_UINT16, BASE_DEC, NULL, 0x0,
7414 NULL, HFILL}
7416 { &hf_sip_session_id_sess_id,
7417 { "sess-id", "sip.Session-ID.sess_id",
7418 FT_BYTES, BASE_NONE, NULL, 0x0,
7419 NULL, HFILL}
7421 { &hf_sip_session_id_param,
7422 { "param", "sip.Session-ID.param",
7423 FT_STRING, BASE_NONE, NULL, 0x0,
7424 NULL, HFILL}
7426 { &hf_sip_session_id_local_uuid,
7427 { "local-uuid", "sip.Session-ID.local_uuid",
7428 FT_GUID, BASE_NONE, NULL, 0x0,
7429 NULL, HFILL}
7431 { &hf_sip_session_id_remote_uuid,
7432 { "remote-uuid", "sip.Session-ID.remote_uuid",
7433 FT_GUID, BASE_NONE, NULL, 0x0,
7434 NULL, HFILL}
7436 { &hf_sip_session_id_logme,
7437 { "logme", "sip.Session-ID.logme",
7438 FT_BOOLEAN, BASE_NONE, TFS(&tfs_set_notset), 0x0,
7439 NULL, HFILL}
7441 { &hf_sip_continuation,
7442 { "Continuation data", "sip.continuation",
7443 FT_BYTES, BASE_NONE, NULL, 0x0,
7444 NULL, HFILL}
7446 { &hf_sip_feature_cap,
7447 { "Feature Cap", "sip.feature_cap",
7448 FT_STRING, BASE_NONE, NULL, 0x0,
7449 NULL, HFILL }
7451 { &hf_sip_service_priority,
7452 { "Service Priority", "sip.service_priority",
7453 FT_STRING, BASE_NONE, NULL, 0x0,
7454 NULL, HFILL }
7456 { &hf_sip_icid_value,
7457 { "icid-value", "sip.icid_value",
7458 FT_STRING, BASE_NONE, NULL, 0x0,
7459 NULL, HFILL }
7461 { &hf_sip_icid_gen_addr,
7462 { "icid-gen-addr", "sip.icid_gen_addr",
7463 FT_STRING, BASE_NONE, NULL, 0x0,
7464 NULL, HFILL }
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[] = {
7477 { &hf_sip_raw_line,
7478 { "Raw SIP Line", "raw_sip.line",
7479 FT_STRING, BASE_NONE,NULL,0x0,
7480 NULL, HFILL }
7483 /* Setup protocol subtree array */
7484 static int *ett[] = {
7485 &ett_sip,
7486 &ett_sip_reqresp,
7487 &ett_sip_hdr,
7488 &ett_sip_ext_hdr,
7489 &ett_sip_element,
7490 &ett_sip_hist,
7491 &ett_sip_uri,
7492 &ett_sip_contact_item,
7493 &ett_sip_message_body,
7494 &ett_sip_cseq,
7495 &ett_sip_via,
7496 &ett_sip_reason,
7497 &ett_sip_security_client,
7498 &ett_sip_security_server,
7499 &ett_sip_security_verify,
7500 &ett_sip_rack,
7501 &ett_sip_record_route,
7502 &ett_sip_service_route,
7503 &ett_sip_route,
7504 &ett_sip_path,
7505 &ett_sip_ruri,
7506 &ett_sip_pai_uri,
7507 &ett_sip_pmiss_uri,
7508 &ett_sip_ppi_uri,
7509 &ett_sip_tc_uri,
7510 &ett_sip_to_uri,
7511 &ett_sip_from_uri,
7512 &ett_sip_curi,
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[] = {
7520 &ett_raw_text,
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 }},
7527 #if 0
7528 { &ei_sip_odd_register_response, { "sip.response.unusual", PI_RESPONSE_CODE, PI_WARN, "SIP Response is unusual", EXPFILL }},
7529 #endif
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,
7551 "SIP Statistics",
7552 "sip",
7553 "sip,stat",
7554 sip_stat_init,
7555 sip_stat_packet,
7556 sip_stat_reset,
7557 sip_stat_free_table_item,
7558 NULL,
7559 array_length(sip_stat_fields), sip_stat_fields,
7560 array_length(sip_stat_params), sip_stat_params,
7561 NULL,
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"),
7569 UAT_END_FIELDS
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"),
7576 UAT_END_FIELDS
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",
7599 "SIP TLS Port",
7600 "SIP Server TLS Port",
7601 10, &sip_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);
7666 /* UAT */
7667 sip_custom_headers_uat = uat_new("Custom SIP Header Fields",
7668 sizeof(header_field_t),
7669 "custom_sip_header_fields",
7670 true,
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,
7676 NULL,
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",
7697 true,
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,
7703 NULL,
7704 authorization_users_copy_cb,
7705 authorization_users_update_cb,
7706 authorization_users_free_cb,
7707 NULL,
7708 NULL,
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);
7741 void
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;
7777 } else {
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
7789 * Local variables:
7790 * c-basic-offset: 4
7791 * tab-width: 8
7792 * indent-tabs-mode: nil
7793 * End:
7795 * vi: set shiftwidth=4 tabstop=8 expandtab:
7796 * :indentSize=4:tabSize=8:noTabs=true: