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