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>
14 * Wireshark - Network traffic analyzer
15 * By Gerald Combs <gerald@wireshark.org>
16 * Copyright 1998 Gerald Combs
18 * Copied from packet-cops.c
20 * This program is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU General Public License
22 * as published by the Free Software Foundation; either version 2
23 * of the License, or (at your option) any later version.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
43 #include <epan/prefs.h>
47 #include <wsutil/str_util.h>
49 #include <epan/packet.h>
50 #include <epan/req_resp_hdrs.h>
51 #include <epan/emem.h>
52 #include <epan/strutil.h>
54 #include <wsutil/str_util.h>
56 #include "packet-isup.h"
57 #include "packet-sip.h"
59 #include <epan/expert.h>
61 #include "packet-tcp.h"
62 #include "packet-ssl.h"
64 #define TCP_PORT_SIP 5060
65 #define UDP_PORT_SIP 5060
66 #define TLS_PORT_SIP 5061
68 static gint sip_tap = -1;
69 static dissector_handle_t sigcomp_handle;
71 /* Initialize the protocol and registered fields */
72 static gint proto_sip = -1;
73 static gint proto_raw_sip = -1;
74 static gint hf_raw_sip_line = -1;
75 static gint hf_msg_hdr = -1;
76 static gint hf_sip_Method = -1;
77 static gint hf_Request_Line = -1;
78 static gint hf_sip_ruri = -1;
79 static gint hf_sip_ruri_user = -1;
80 static gint hf_sip_ruri_host = -1;
81 static gint hf_sip_ruri_port = -1;
82 static gint hf_Status_Code = -1;
83 static gint hf_Status_Line = -1;
84 static gint hf_sip_display = -1;
85 static gint hf_sip_to_addr = -1;
86 static gint hf_sip_to_user = -1;
87 static gint hf_sip_to_host = -1;
88 static gint hf_sip_to_port = -1;
89 static gint hf_sip_from_addr = -1;
90 static gint hf_sip_from_user = -1;
91 static gint hf_sip_from_host = -1;
92 static gint hf_sip_from_port = -1;
93 static gint hf_sip_tag = -1;
94 static gint hf_sip_pai_addr = -1;
95 static gint hf_sip_pai_user = -1;
96 static gint hf_sip_pai_host = -1;
97 static gint hf_sip_pai_port = -1;
98 static gint hf_sip_pmiss_addr = -1;
99 static gint hf_sip_pmiss_user = -1;
100 static gint hf_sip_pmiss_host = -1;
101 static gint hf_sip_pmiss_port = -1;
102 static gint hf_sip_ppi_addr = -1;
103 static gint hf_sip_ppi_user = -1;
104 static gint hf_sip_ppi_host = -1;
105 static gint hf_sip_ppi_port = -1;
106 static gint hf_sip_tc_addr = -1;
107 static gint hf_sip_tc_user = -1;
108 static gint hf_sip_tc_host = -1;
109 static gint hf_sip_tc_port = -1;
110 static gint hf_sip_tc_turi = -1;
111 static gint hf_sip_contact_param = -1;
112 static gint hf_sip_resend = -1;
113 static gint hf_sip_original_frame = -1;
114 static gint hf_sip_matching_request_frame = -1;
115 static gint hf_sip_response_time = -1;
116 static gint hf_sip_release_time = -1;
117 static gint hf_sip_curi = -1;
118 static gint hf_sip_curi_user = -1;
119 static gint hf_sip_curi_host = -1;
120 static gint hf_sip_curi_port = -1;
122 static gint hf_sip_auth = -1;
123 static gint hf_sip_auth_scheme = -1;
124 static gint hf_sip_auth_digest_response = -1;
125 static gint hf_sip_auth_nc = -1;
126 static gint hf_sip_auth_username = -1;
127 static gint hf_sip_auth_realm = -1;
128 static gint hf_sip_auth_nonce = -1;
129 static gint hf_sip_auth_algorithm = -1;
130 static gint hf_sip_auth_opaque = -1;
131 static gint hf_sip_auth_qop = -1;
132 static gint hf_sip_auth_cnonce = -1;
133 static gint hf_sip_auth_uri = -1;
134 static gint hf_sip_auth_domain = -1;
135 static gint hf_sip_auth_stale = -1;
136 static gint hf_sip_auth_auts = -1;
137 static gint hf_sip_auth_rspauth = -1;
138 static gint hf_sip_auth_nextnonce = -1;
139 static gint hf_sip_auth_ik = -1;
140 static gint hf_sip_auth_ck = -1;
142 static gint hf_sip_cseq_seq_no = -1;
143 static gint hf_sip_cseq_method = -1;
145 static gint hf_sip_via_transport = -1;
146 static gint hf_sip_via_sent_by_address = -1;
147 static gint hf_sip_via_sent_by_port = -1;
148 static gint hf_sip_via_branch = -1;
149 static gint hf_sip_via_maddr = -1;
150 static gint hf_sip_via_rport = -1;
151 static gint hf_sip_via_received = -1;
152 static gint hf_sip_via_ttl = -1;
153 static gint hf_sip_via_comp = -1;
154 static gint hf_sip_via_sigcomp_id = -1;
156 static gint hf_sip_rack_rseq_no = -1;
157 static gint hf_sip_rack_cseq_no = -1;
158 static gint hf_sip_rack_cseq_method = -1;
160 static gint hf_sip_msg_body = -1;
162 /* Initialize the subtree pointers */
163 static gint ett_sip = -1;
164 static gint ett_sip_reqresp = -1;
165 static gint ett_sip_hdr = -1;
166 static gint ett_sip_ext_hdr = -1;
167 static gint ett_raw_text = -1;
168 static gint ett_sip_element = -1;
169 static gint ett_sip_uri = -1;
170 static gint ett_sip_contact_item = -1;
171 static gint ett_sip_message_body = -1;
172 static gint ett_sip_cseq = -1;
173 static gint ett_sip_via = -1;
174 static gint ett_sip_reason = -1;
175 static gint ett_sip_rack = -1;
176 static gint ett_sip_ruri = -1;
177 static gint ett_sip_to_uri = -1;
178 static gint ett_sip_curi = -1;
179 static gint ett_sip_from_uri = -1;
180 static gint ett_sip_pai_uri = -1;
181 static gint ett_sip_pmiss_uri = -1;
182 static gint ett_sip_ppi_uri = -1;
183 static gint ett_sip_tc_uri = -1;
185 /* PUBLISH method added as per http://www.ietf.org/internet-drafts/draft-ietf-sip-publish-01.txt */
186 static const char *sip_methods[] = {
187 #define SIP_METHOD_INVALID 0
188 "<Invalid method>", /* Pad so that the real methods start at index 1 */
189 #define SIP_METHOD_ACK 1
191 #define SIP_METHOD_BYE 2
193 #define SIP_METHOD_CANCEL 3
195 #define SIP_METHOD_DO 4
197 #define SIP_METHOD_INFO 5
199 #define SIP_METHOD_INVITE 6
201 #define SIP_METHOD_MESSAGE 7
203 #define SIP_METHOD_NOTIFY 8
205 #define SIP_METHOD_OPTIONS 9
207 #define SIP_METHOD_PRACK 10
209 #define SIP_METHOD_QAUTH 11
211 #define SIP_METHOD_REFER 12
213 #define SIP_METHOD_REGISTER 13
215 #define SIP_METHOD_SPRACK 14
217 #define SIP_METHOD_SUBSCRIBE 15
219 #define SIP_METHOD_UPDATE 16
221 #define SIP_METHOD_PUBLISH 17
226 * Updated with info from http://www.iana.org/assignments/sip-parameters
227 * (last updated 2009-11-11)
228 * Updated with: http://www.ietf.org/internet-drafts/draft-ietf-sip-resource-priority-05.txt
232 const char *compact_name;
234 static const sip_header_t sip_headers[] = {
235 { "Unknown-header", NULL }, /* 0 Pad so that the real headers start at index 1 */
236 { "Accept", NULL }, /* 1 */
237 { "Accept-Contact", "a" }, /* 2 RFC3841 */
238 { "Accept-Encoding", NULL }, /* 3 */
239 { "Accept-Language", NULL }, /* 4 */
240 { "Accept-Resource-Priority", NULL }, /* 5 RFC4412 */
241 { "Alert-Info", NULL },
243 { "Allow-Events", "u" }, /* 8 RFC3265 */
244 { "Answer-Mode", NULL }, /* 9 RFC5373 */
245 { "Authentication-Info", NULL },
246 { "Authorization", NULL }, /* 11 */
248 { "Call-Info", NULL },
250 { "Content-Disposition", NULL },
251 { "Content-Encoding", "e" }, /* 16 */
252 { "Content-Language", NULL },
253 { "Content-Length", "l" },
254 { "Content-Type", "c" },
256 { "Date", NULL }, /* 21 */
257 /* Encryption (Deprecated) [RFC3261] */
258 { "Error-Info", NULL },
261 /* Flow-Timer [RFC5626]*/
262 { "From", "f" }, /* 25 */
263 /* Hide [RFC3261] (deprecated)*/
264 { "History-Info", NULL }, /* 26 RFC4244 */
265 { "Identity", "y" }, /* 27 RFC4474 */
266 { "Identity-Info", "n" }, /* 28 RFC4474 */
267 { "In-Reply-To", NULL }, /* 29 RFC3261 */
268 { "Join", NULL }, /* 30 RFC3911 */
269 { "Max-Breadth", NULL }, /* 31 RFC5393*/
270 { "Max-Forwards", NULL }, /* 32 */
271 { "MIME-Version", NULL }, /* 33 */
272 { "Min-Expires", NULL }, /* 34 */
273 { "Min-SE", NULL }, /* 35 RFC4028 */
274 { "Organization", NULL }, /* 36 RFC3261 */
275 { "P-Access-Network-Info", NULL }, /* 37 RFC3455 */
276 { "P-Answer-State", NULL }, /* 38 RFC4964 */
277 { "P-Asserted-Identity", NULL }, /* 39 RFC3325 */
278 { "P-Associated-URI", NULL }, /* 40 RFC3455 */
279 { "P-Called-Party-ID", NULL }, /* 41 RFC3455 */
280 { "P-Charging-Function-Addresses", NULL },/* 42 RFC3455 */
281 { "P-Charging-Vector", NULL }, /* 43 RFC3455 */
282 { "P-DCS-Trace-Party-ID", NULL }, /* 44 RFC5503 */
283 { "P-DCS-OSPS", NULL }, /* 45 RFC5503 */
284 { "P-DCS-Billing-Info", NULL }, /* 46 RFC5503 */
285 { "P-DCS-LAES", NULL }, /* 47 RFC5503 */
286 { "P-DCS-Redirect", NULL }, /* 48 RFC5503 */
287 { "P-Early-Media", NULL }, /* 49 RFC5009 */
288 { "P-Media-Authorization", NULL }, /* 50 RFC3313 */
289 { "P-Preferred-Identity", NULL }, /* 51 RFC3325 */
290 { "P-Profile-Key", NULL }, /* 52 RFC5002 */
291 { "P-Refused-URI-List", NULL }, /* 53 RFC5318 */
292 { "P-Served-User", NULL }, /* 54 RFC5502 */
293 { "P-User-Database", NULL }, /* 55 RFC4457 */
294 { "P-Visited-Network-ID", NULL }, /* 56 RFC3455 */
295 { "Path", NULL }, /* 57 RFC3327 */
296 { "Permission-Missing", NULL }, /* 58 RFC5360 */
297 { "Priority", NULL }, /* 59 RFC3261 */
298 { "Priv-Answer-Mode", NULL }, /* 60 RFC5373 */
299 { "Privacy", NULL }, /* 61 RFC3323 */
300 { "Proxy-Authenticate", NULL }, /* 62 */
301 { "Proxy-Authorization", NULL }, /* 63 */
302 { "Proxy-Require", NULL }, /* 64 */
303 { "RAck", NULL }, /* 65 RFC3262 */
304 { "Reason", NULL }, /* 66 RFC3326 */
305 { "Record-Route", NULL }, /* 67 */
306 { "Refer-Sub", NULL }, /* 68 RFC4488 */
307 { "Refer-To", "r" }, /* 69 RFC3515 */
308 { "Referred-By", "b" }, /* 70 RFC3892 */
309 { "Reject-Contact", "j" }, /* 71 RFC3841 */
310 { "Replaces", NULL }, /* 72 RFC3891 */
311 { "Reply-To", NULL }, /* 73 RFC3261 */
312 { "Request-Disposition", "d" }, /* 74 RFC3841 */
313 { "Require", NULL }, /* 75 RFC3261 */
314 { "Resource-Priority", NULL }, /* 76 RFC4412 */
316 { "Response-Key (Deprecated) [RFC3261]
318 { "Retry-After", NULL }, /* 77 RFC3261 */
319 { "Route", NULL }, /* 78 RFC3261 */
320 { "RSeq", NULL }, /* 79 RFC3262 */
321 { "Security-Client", NULL }, /* 80 RFC3329 */
322 { "Security-Server", NULL }, /* 81 RFC3329 */
323 { "Security-Verify", NULL }, /* 82 RFC3329 */
324 { "Server", NULL }, /* 83 RFC3261 */
325 { "Service-Route", NULL }, /* 84 RFC3608 */
326 { "Session-Expires", "x" }, /* 85 RFC4028 */
327 { "SIP-ETag", NULL }, /* 86 RFC3903 */
328 { "SIP-If-Match", NULL }, /* 87 RFC3903 */
329 { "Subject", "s" }, /* 88 RFC3261 */
330 { "Subscription-State", NULL }, /* 89 RFC3265 */
331 { "Supported", "k" }, /* 90 RFC3261 */
332 { "Target-Dialog", NULL }, /* 81 RFC4538 */
333 { "Timestamp", NULL }, /* 92 RFC3261 */
334 { "To", "t" }, /* 93 RFC3261 */
335 { "Trigger-Consent", NULL }, /* 94 RFC5360 */
336 { "Unsupported", NULL }, /* 95 RFC3261 */
337 { "User-Agent", NULL }, /* 96 RFC3261 */
338 { "Via", "v" }, /* 97 RFC3261 */
339 { "Warning", NULL }, /* 98 RFC3261 */
340 { "WWW-Authenticate", NULL }, /* 99 RFC3261 */
345 #define POS_ACCEPT_CONTACT 2
346 #define POS_ACCEPT_ENCODING 3
347 #define POS_ACCEPT_LANGUAGE 4
348 #define POS_ACCEPT_RESOURCE_PRIORITY 5
349 #define POS_ALERT_INFO 6
351 #define POS_ALLOW_EVENTS 8
352 #define POS_ANSWER_MODE 9
353 #define POS_AUTHENTICATION_INFO 10
354 #define POS_AUTHORIZATION 11
355 #define POS_CALL_ID 12
356 #define POS_CALL_INFO 13
357 #define POS_CONTACT 14
358 #define POS_CONTENT_DISPOSITION 15
359 #define POS_CONTENT_ENCODING 16
360 #define POS_CONTENT_LANGUAGE 17
361 #define POS_CONTENT_LENGTH 18
362 #define POS_CONTENT_TYPE 19
365 #define POS_ERROR_INFO 22
367 #define POS_EXPIRES 24
369 #define POS_HISTORY_INFO 26
370 #define POS_IDENTITY 27
371 #define POS_IDENTITY_INFO 28
372 #define POS_IN_REPLY_TO 29
374 #define POS_MAX_BREADTH 31
375 #define POS_MAX_FORWARDS 32
376 #define POS_MIME_VERSION 33
377 #define POS_MIN_EXPIRES 34
378 #define POS_MIN_SE 35
379 #define POS_ORGANIZATION 36
380 #define POS_P_ACCESS_NETWORK_INFO 37
381 #define POS_P_ANSWER_STATE 38
382 #define POS_P_ASSERTED_IDENTITY 39
383 #define POS_P_ASSOCIATED_URI 40
384 #define POS_P_CALLED_PARTY_ID 41
385 #define POS_P_CHARGING_FUNCTION_ADDRESSES 42
386 #define POS_P_CHARGING_VECTOR 43
387 #define POS_P_DCS_TRACE_PARTY_ID 44
388 #define POS_P_DCS_OSPS 45
389 #define POS_P_DCS_BILLING_INFO 46
390 #define POS_P_DCS_LAES 47
391 #define POS_P_DCS_REDIRECT 48
392 #define POS_P_EARLY_MEDIA 49
393 #define POS_P_MEDIA_AUTHORIZATION 50
394 #define POS_P_PREFERRED_IDENTITY 51
395 #define POS_P_PROFILE_KEY 52
396 #define POS_P_REFUSED_URI_LST 53
397 #define POS_P_SERVED_USER 54
398 #define POS_P_USER_DATABASE 55
399 #define POS_P_VISITED_NETWORK_ID 56
401 #define POS_PERMISSION_MISSING 58
402 #define POS_PRIORITY 59
403 #define POS_PRIV_ANSWER_MODE 60
404 #define POS_PRIVACY 61
405 #define POS_PROXY_AUTHENTICATE 62
406 #define POS_PROXY_AUTHORIZATION 63
407 #define POS_PROXY_REQUIRE 64
409 #define POS_REASON 66
410 #define POS_RECORD_ROUTE 67
411 #define POS_REFER_SUB 68
412 #define POS_REFER_TO 69
413 #define POS_REFERED_BY 70
414 #define POS_REJECT_CONTACT 71
415 #define POS_REPLACES 72
416 #define POS_REPLY_TO 73
417 #define POS_REQUEST_DISPOSITION 74
418 #define POS_REQUIRE 75
419 #define POS_RESOURCE_PRIORITY 76
420 #define POS_RETRY_AFTER 77
423 #define POS_SECURITY_CLIENT 80
424 #define POS_SECURITY_SERVER 81
425 #define POS_SECURITY_VERIFY 82
426 #define POS_SERVER 83
427 #define POS_SERVICE_ROUTE 84
428 #define POS_SESSION_EXPIRES 85
429 #define POS_SIP_ETAG 86
430 #define POS_SIP_IF_MATCH 87
431 #define POS_SUBJECT 88
432 #define POS_SUBSCRIPTION_STATE 89
433 #define POS_SUPPORTED 90
434 #define POS_TARGET_DALOG 91
435 #define POS_TIMESTAMP 92
437 #define POS_TRIGGER_CONSENT 94
438 #define POS_UNSUPPORTED 95
439 #define POS_USER_AGENT 96
441 #define POS_WARNING 98
442 #define POS_WWW_AUTHENTICATE 99
445 static gint hf_header_array[] = {
446 -1, /* 0"Unknown-header" - Pad so that the real headers start at index 1 */
448 -1, /* 2"Accept-Contact" RFC3841 */
449 -1, /* 3"Accept-Encoding" */
450 -1, /* 4"Accept-Language" */
451 -1, /* 5"Accept-Resource-Priority" RFC4412 */
452 -1, /* 6"Alert-Info", */
454 -1, /* 8"Allow-Events", RFC3265 */
455 -1, /* 9"Answer-Mode" RFC5373 */
456 -1, /* 10"Authentication-Info" */
457 -1, /* 11"Authorization", */
458 -1, /* 12"Call-ID", */
459 -1, /* 13"Call-Info" */
460 -1, /* 14"Contact", */
461 -1, /* 15"Content-Disposition", */
462 -1, /* 16"Content-Encoding", */
463 -1, /* 17"Content-Language", */
464 -1, /* 18"Content-Length", */
465 -1, /* 19"Content-Type", */
468 -1, /* 22"Error-Info", */
470 -1, /* 24"Expires", */
472 -1, /* 26"History-Info", RFC4244 */
473 -1, /* 27"Identity", */
474 -1, /* 28"Identity-Info", RFC4474 */
475 -1, /* 29"In-Reply-To", RFC3261 */
476 -1, /* 30"Join", RFC3911 */
477 -1, /* 31"Max-Breadth" RFC5393 */
478 -1, /* 32"Max-Forwards", */
479 -1, /* 33"MIME-Version", */
480 -1, /* 34"Min-Expires", */
481 -1, /* 35"Min-SE", RFC4028 */
482 -1, /* 36"Organization", */
483 -1, /* 37"P-Access-Network-Info", RFC3455 */
484 -1, /* 38"P-Answer-State", RFC4964 */
485 -1, /* 39"P-Asserted-Identity", RFC3325 */
486 -1, /* 40"P-Associated-URI", RFC3455 */
487 -1, /* 41"P-Called-Party-ID", RFC3455 */
488 -1, /* 42"P-Charging-Function-Addresses", RFC3455 */
489 -1, /* 43"P-Charging-Vector", RFC3455 */
490 -1, /* 44"P-DCS-Trace-Party-ID", RFC3603 */
491 -1, /* 45"P-DCS-OSPS", RFC3603 */
492 -1, /* 46"P-DCS-Billing-Info", RFC3603 */
493 -1, /* 47"P-DCS-LAES", RFC3603 */
494 -1, /* 48"P-DCS-Redirect", RFC3603 */
495 -1, /* 49"P-Early-Media", */
496 -1, /* 50"P-Media-Authorization", RFC3313 */
497 -1, /* 51"P-Preferred-Identity", RFC3325 */
498 -1, /* 52"P-Profile-Key", */
499 -1, /* 53"P-Refused-URI-List", RFC5318 */
500 -1, /* 54"P-Served-User", RFC5502 */
501 -1, /* 55"P-User-Database RFC4457 */
502 -1, /* 56"P-Visited-Network-ID", RFC3455 */
503 -1, /* 57"Path", RFC3327 */
504 -1, /* 58"Permission-Missing" RFC5360 */
505 -1, /* 59"Priority" */
506 -1, /* 60"Priv-Answer-mode" RFC5373 */
507 -1, /* 61"Privacy", RFC3323 */
508 -1, /* 62"Proxy-Authenticate", */
509 -1, /* 63"Proxy-Authorization", */
510 -1, /* 64"Proxy-Require", */
511 -1, /* 65"RAck", RFC3262 */
512 -1, /* 66"Reason", RFC3326 */
513 -1, /* 67"Record-Route", */
514 -1, /* 68"Refer-Sub",", RFC4488 */
515 -1, /* 69"Refer-To", RFC3515 */
516 -1, /* 70"Referred-By", */
517 -1, /* 71"Reject-Contact", RFC3841 */
518 -1, /* 72"Replaces", RFC3891 */
519 -1, /* 73"Reply-To", RFC3261 */
520 -1, /* 74"Request-Disposition", RFC3841 */
521 -1, /* 75"Require", RFC3261 */
522 -1, /* 76"Resource-Priority", RFC4412 */
523 -1, /* 77"Retry-After", RFC3261 */
524 -1, /* 78"Route", RFC3261 */
525 -1, /* 79"RSeq", RFC3262 */
526 -1, /* 80"Security-Client", RFC3329 */
527 -1, /* 81"Security-Server", RFC3329 */
528 -1, /* 82"Security-Verify", RFC3329 */
529 -1, /* 83"Server", RFC3261 */
530 -1, /* 84"Service-Route", RFC3608 */
531 -1, /* 85"Session-Expires", RFC4028 */
532 -1, /* 86"SIP-ETag", RFC3903 */
533 -1, /* 87"SIP-If-Match", RFC3903 */
534 -1, /* 88"Subject", RFC3261 */
535 -1, /* 89"Subscription-State", RFC3265 */
536 -1, /* 90"Supported", RFC3261 */
537 -1, /* 91"Target-Dialog", RFC4538 */
538 -1, /* 92"Timestamp", RFC3261 */
539 -1, /* 93"To", RFC3261 */
540 -1, /* 94"Trigger-Consent" RFC5380 */
541 -1, /* 95"Unsupported", RFC3261 */
542 -1, /* 96"User-Agent", RFC3261 */
543 -1, /* 97"Via", RFC3261 */
544 -1, /* 98"Warning", RFC3261 */
545 -1, /* 99"WWW-Authenticate", RFC3261 */
549 /* Track associations between parameter name and hf item */
551 const char *param_name;
553 } header_parameter_t;
555 static header_parameter_t auth_parameters_hf_array[] =
557 {"response", &hf_sip_auth_digest_response},
558 {"nc", &hf_sip_auth_nc},
559 {"username", &hf_sip_auth_username},
560 {"realm", &hf_sip_auth_realm},
561 {"nonce", &hf_sip_auth_nonce},
562 {"algorithm", &hf_sip_auth_algorithm},
563 {"opaque", &hf_sip_auth_opaque},
564 {"qop", &hf_sip_auth_qop},
565 {"cnonce", &hf_sip_auth_cnonce},
566 {"uri", &hf_sip_auth_uri},
567 {"domain", &hf_sip_auth_domain},
568 {"stale", &hf_sip_auth_stale},
569 {"auts", &hf_sip_auth_auts},
570 {"rspauth", &hf_sip_auth_rspauth},
571 {"nextnonce", &hf_sip_auth_nextnonce},
572 {"ik", &hf_sip_auth_ik},
573 {"ck", &hf_sip_auth_ck}
576 static header_parameter_t via_parameters_hf_array[] =
578 {"branch", &hf_sip_via_branch},
579 {"maddr", &hf_sip_via_maddr},
580 {"rport", &hf_sip_via_rport},
581 {"received", &hf_sip_via_received},
582 {"ttl", &hf_sip_via_ttl},
583 {"comp", &hf_sip_via_comp},
584 {"sigcomp-id", &hf_sip_via_sigcomp_id}
596 static hf_sip_uri_t sip_pai_uri = {
604 static hf_sip_uri_t sip_ppi_uri = {
612 static hf_sip_uri_t sip_pmiss_uri = {
621 static hf_sip_uri_t sip_tc_uri = {
629 static hf_sip_uri_t sip_to_uri = {
637 static hf_sip_uri_t sip_from_uri = {
645 static hf_sip_uri_t sip_req_uri = {
653 static hf_sip_uri_t sip_contact_uri = {
662 * Type of line. It's either a SIP Request-Line, a SIP Status-Line, or
663 * another type of line.
672 static guint sip_tcp_port = TCP_PORT_SIP;
673 static guint sip_tls_port = TLS_PORT_SIP;
675 /* global_sip_raw_text determines whether we are going to display */
676 /* the raw text of the SIP message, much like the MEGACO dissector does. */
677 static gboolean global_sip_raw_text = FALSE;
678 /* strict_sip_version determines whether the SIP dissector enforces
679 * the SIP version to be "SIP/2.0". */
680 static gboolean strict_sip_version = TRUE;
683 * desegmentation of SIP headers
684 * (when we are over TCP or another protocol providing the desegmentation API)
686 static gboolean sip_desegment_headers = TRUE;
689 * desegmentation of SIP bodies
690 * (when we are over TCP or another protocol providing the desegmentation API)
692 static gboolean sip_desegment_body = TRUE;
695 * same source port for retransmissions
697 static gboolean sip_retrans_the_same_sport = TRUE;
699 /* Extension header subdissectors */
700 static dissector_table_t ext_hdr_subdissector_table;
702 /* Forward declaration we need below */
703 void proto_reg_handoff_sip(void);
704 static gboolean dissect_sip_common(tvbuff_t *tvb, int offset, packet_info *pinfo,
705 proto_tree *tree, gboolean is_heur, gboolean use_reassembly);
706 static line_type_t sip_parse_line(tvbuff_t *tvb, int offset, gint linelen,
708 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
709 guint meth_len, guint *meth_idx);
710 static gint sip_is_known_sip_header(gchar *header_name, guint header_len);
711 static void dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint offset,
712 guint meth_len, gint linelen);
713 static void dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree);
714 static void tvb_raw_text_add(tvbuff_t *tvb, int offset, int length, proto_tree *tree);
715 static guint sip_is_packet_resend(packet_info *pinfo,
718 guchar cseq_number_set, guint32 cseq_number,
719 line_type_t line_type);
721 static guint sip_find_request(packet_info *pinfo,
724 guchar cseq_number_set, guint32 cseq_number,
725 guint32 *response_time);
727 static guint sip_find_invite(packet_info *pinfo,
730 guchar cseq_number_set, guint32 cseq_number,
731 guint32 *response_time);
733 /* SIP content type and internet media type used by other dissectors
734 * are the same. List of media types from IANA at:
735 * http://www.iana.org/assignments/media-types/index.html */
736 static dissector_table_t media_type_dissector_table;
738 static heur_dissector_list_t heur_subdissector_list;
740 #define SIP2_HDR "SIP/2.0"
741 #define SIP2_HDR_LEN ((gint)strlen (SIP2_HDR))
743 /* Store the info needed by the SIP tap for one packet */
744 static sip_info_value_t *stat_info;
746 /* The buffer size for the cseq_method name */
747 #define MAX_CSEQ_METHOD_SIZE 16
749 /****************************************************************************
750 * Conversation-type definitions
752 * For each call, keep track of the current cseq number and state of
753 * transaction, in order to be able to detect retransmissions.
755 * Don't use the conservation mechanism, but instead:
756 * - store with each dissected packet original frame (if any)
757 * - maintain a global hash table of
758 * (call_id, source_addr, dest_addr) -> (cseq, transaction_state, frame)
760 * N.B. This is broken for a couple of reasons:
761 * - it won't cope properly with overlapping transactions within the
763 * - request response mapping won't work where the response uses a different
764 * address pair from the request
766 * TODO: proper transaction matching uses RFC fields (use Max-forwards or
767 * maybe Via count as extra key to limit view to one hop)
768 ****************************************************************************/
770 static GHashTable *sip_hash = NULL; /* Hash table */
771 static GHashTable *sip_headers_hash = NULL; /* Hash table */
773 /* Types for hash table keys and values */
774 #define MAX_CALL_ID_SIZE 128
775 #define MAGIC_SOURCE_PORT 0
777 /* Conversation-type key */
780 char call_id[MAX_CALL_ID_SIZE];
781 address source_address;
783 address dest_address;
792 provisional_response_seen,
794 } transaction_state_t;
796 /* Current conversation-type value */
800 transaction_state_t transaction_state;
801 gchar method[MAX_CSEQ_METHOD_SIZE];
802 nstime_t request_time;
803 guint32 response_code;
807 /* Result to be stored in per-packet info */
810 gint original_frame_num;
811 gint response_request_frame_num;
813 } sip_frame_result_value;
816 /************************/
817 /* Hash table functions */
820 static gint sip_equal(gconstpointer v, gconstpointer v2)
822 const sip_hash_key* val1 = v;
823 const sip_hash_key* val2 = v2;
825 /* Call id must match */
826 if (strcmp(val1->call_id, val2->call_id) != 0)
831 /* Addresses must match */
832 return (ADDRESSES_EQUAL(&(val1->source_address), &(val2->source_address))) &&
833 (val1->source_port == val2->source_port) &&
834 (ADDRESSES_EQUAL(&(val1->dest_address), &(val2->dest_address))) &&
835 (val1->dest_port == val2->dest_port);
839 /* Initializes the hash table and the mem_chunk area each time a new
840 * file is loaded or re-loaded in wireshark */
842 sip_init_protocol(void)
847 /* Destroy any existing hashes. */
849 g_hash_table_destroy(sip_hash);
851 /* Now create them over */
852 sip_hash = g_hash_table_new(g_str_hash , sip_equal);
853 /* Create a hastable with the SIP headers it will be used to find the related hf entry (POS_x)
854 * this is faster than the previously used for loop
855 * There is no g_hash_table_destroy as the liftime is the same as the lifetime of Wireshark
857 if(!sip_headers_hash){
858 sip_headers_hash = g_hash_table_new(g_str_hash , g_str_equal);
859 for (i = 1; i < array_length(sip_headers); i++){
860 value_copy = g_strdup (sip_headers[i].name);
861 /* Store (and compare) the string in lower case) */
862 ascii_strdown_inplace(value_copy);
863 g_hash_table_insert(sip_headers_hash, (gpointer)value_copy, GINT_TO_POINTER(i));
868 /* Structure to collect info about a sip uri */
869 typedef struct _uri_offset_info
871 gint display_name_start;
872 gint display_name_end;
875 gint uri_parameters_start;
876 gint uri_parameters_end;
877 gint name_addr_start;
883 gint uri_host_port_start;
884 gint uri_host_port_end;
888 sip_uri_offset_init(uri_offset_info *uri_offsets){
890 /* Initialize the uri_offsets */
891 uri_offsets->display_name_start = -1;
892 uri_offsets->display_name_end = -1;
893 uri_offsets->uri_start = -1;
894 uri_offsets->uri_end = -1;
895 uri_offsets->uri_parameters_start = -1;
896 uri_offsets->uri_parameters_end = -1;
897 uri_offsets->name_addr_start = -1;
898 uri_offsets->name_addr_end = -1;
899 uri_offsets->uri_user_start = -1;
900 uri_offsets->uri_user_end = -1;
901 uri_offsets->uri_host_start = -1;
902 uri_offsets->uri_host_end = -1;
903 uri_offsets->uri_host_port_start = -1;
904 uri_offsets->uri_host_port_end = -1;
907 /* Code to parse a sip uri.
908 * Returns Offset end off parsing or -1 for unsuccessful parsing
909 * - sip_uri_offset_init() must have been called first.
912 dissect_sip_uri(tvbuff_t *tvb, packet_info *pinfo _U_, gint start_offset,
913 gint line_end_offset, uri_offset_info *uri_offsets)
919 gint semicolon_offset;
920 gint parameter_end_offset;
921 gboolean in_ipv6 = FALSE;
923 /* skip Spaces and Tabs */
924 current_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
926 if(current_offset >= line_end_offset) {
927 /* Nothing to parse */
930 /* Set uri start offset in case this was called directly */
931 uri_offsets->uri_start = current_offset;
933 /* Check if it's realy a sip uri ( it might be a tel uri, parse that?) */
934 queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ':');
935 if (tvb_strneql(tvb, current_offset, "sip", 3) != 0)
938 if(uri_offsets->uri_end == -1)
940 /* name-addr form was NOT used e.g no closing ">" */
941 /* look for the first ',' or ';' which will mark the end of this URI
942 * In this case a semicolon indicates a header field parameter, and not an uri parameter.
944 comma_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ',');
945 semicolon_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ';');
947 if (semicolon_offset != -1 && comma_offset != -1)
949 if(semicolon_offset < comma_offset)
951 uri_offsets->uri_end = semicolon_offset - 1;
955 uri_offsets->uri_end = comma_offset - 1;
960 if (semicolon_offset != -1)
962 uri_offsets->uri_end = semicolon_offset - 1;
964 else if (comma_offset != -1)
966 uri_offsets->uri_end = comma_offset - 1;
969 /* If both offsets are equal to -1, we don't have a semicolon or a comma.
970 * In that case, we assume that the end of the URI is at the line end
972 uri_offsets->uri_end = line_end_offset - 3; /* remove '\r\n' */
975 uri_offsets->name_addr_end = uri_offsets->uri_end;
978 /* Look for URI address parts (user, host, host-port) */
980 /* Look for '@' within URI */
981 queried_offset = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, '@');
982 if(queried_offset == -1)
984 /* no '@' = no user part */
985 uri_offsets->uri_host_start = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, ':')+1;
989 /* with '@' = with user part */
990 uri_offsets->uri_user_start = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, ':')+1;
991 uri_offsets->uri_user_end = tvb_find_guint8(tvb, uri_offsets->uri_user_start, uri_offsets->uri_end - uri_offsets->uri_start, '@')-1;
992 uri_offsets->uri_host_start = uri_offsets->uri_user_end + 2;
995 /* find URI-Host end*/
996 parameter_end_offset = uri_offsets->uri_host_start;
998 in_ipv6 = (tvb_get_guint8(tvb, parameter_end_offset) == '[');
999 while (parameter_end_offset < line_end_offset)
1001 parameter_end_offset++;
1002 c = tvb_get_guint8(tvb, parameter_end_offset);
1010 goto uri_host_end_found;
1013 goto uri_host_end_found;
1028 uri_offsets->uri_host_end = parameter_end_offset - 1;
1032 uri_offsets->uri_host_port_start = parameter_end_offset + 1;
1033 parameter_end_offset = uri_offsets->uri_host_port_start;
1034 while (parameter_end_offset < line_end_offset)
1036 parameter_end_offset++;
1037 c = tvb_get_guint8(tvb, parameter_end_offset);
1045 goto uri_host_port_end_found;
1051 uri_host_port_end_found:
1053 uri_offsets->uri_host_port_end = parameter_end_offset -1;
1055 return uri_offsets->name_addr_end;
1058 * token = 1*(alphanum / "-" / "." / "!" / "%" / "*"
1059 * / "_" / "+" / "`" / "'" / "~" )
1060 * LWS = [*WSP CRLF] 1*WSP ; linear whitespace
1061 * name-addr = [ display-name ] LAQUOT addr-spec RAQUOT
1062 * addr-spec = SIP-URI / SIPS-URI / absoluteURI
1063 * display-name = *(token LWS)/ quoted-string
1067 dissect_sip_name_addr_or_addr_spec(tvbuff_t *tvb, packet_info *pinfo _U_, gint start_offset,
1068 gint line_end_offset, uri_offset_info *uri_offsets)
1072 gint current_offset;
1073 gint queried_offset;
1075 gboolean uri_without_angle_quotes = FALSE;
1077 /* skip Spaces and Tabs */
1078 current_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1080 if(current_offset >= line_end_offset) {
1081 /* Nothing to parse */
1085 uri_offsets->name_addr_start = current_offset;
1087 /* First look, if we have a display name */
1088 c=tvb_get_guint8(tvb, current_offset);
1092 /* We have a display name, look for the next unescaped '"' */
1093 uri_offsets->display_name_start = current_offset;
1096 queried_offset = tvb_find_guint8(tvb, current_offset + 1, line_end_offset - (current_offset + 1), '"');
1097 if(queried_offset == -1)
1102 current_offset = queried_offset;
1104 /* Is it escaped? */
1105 /* count back slashes before '"' */
1106 for(i=1;tvb_get_guint8(tvb, queried_offset - i) == '\\';i++);
1114 } while (current_offset < line_end_offset);
1115 if(current_offset >= line_end_offset)
1121 uri_offsets->display_name_end = current_offset;
1123 /* find start of the URI */
1124 queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, '<');
1125 if(queried_offset == -1)
1130 current_offset = queried_offset + 1;
1134 /* We don't have a display name */
1139 /* We have either an URI without angles or a display name with a limited character set */
1140 /* Look for the right angle quote or colon */
1141 queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, '<');
1142 colon_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ':');
1143 if(queried_offset != -1 && colon_offset != -1)
1145 if(queried_offset < colon_offset)
1147 /* we have an URI with angle quotes */
1148 uri_offsets->display_name_start = current_offset;
1149 uri_offsets->display_name_end = queried_offset - 1;
1150 current_offset = queried_offset + 1;
1154 /* we have an URI without angle quotes */
1155 uri_without_angle_quotes = TRUE;
1160 if(queried_offset != -1)
1162 /* we have an URI with angle quotes */
1163 uri_offsets->display_name_start = current_offset;
1164 uri_offsets->display_name_end = queried_offset - 1;
1165 current_offset = queried_offset + 1;
1168 if(colon_offset != -1)
1170 /* we have an URI without angle quotes */
1171 uri_without_angle_quotes = TRUE;
1174 /* If this point is reached, we can't parse the URI */
1180 uri_offsets->uri_start = current_offset;
1181 if(uri_without_angle_quotes==FALSE){
1182 /* name-addr form was used */
1183 /* look for closing angle quote */
1184 queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, '>');
1185 if(queried_offset == -1)
1190 uri_offsets->name_addr_end = queried_offset;
1191 uri_offsets->uri_end = queried_offset - 1;
1193 return dissect_sip_uri(tvb, pinfo, current_offset, line_end_offset, uri_offsets);
1198 * Code to add dissected SIP URI Information to proto tree
1202 display_sip_uri (tvbuff_t *tvb, proto_tree *sip_element_tree, uri_offset_info* uri_offsets, hf_sip_uri_t* uri)
1206 proto_tree *uri_item_tree = NULL;
1208 if(uri_offsets->display_name_end != uri_offsets->display_name_start) {
1209 proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, uri_offsets->display_name_start,
1210 uri_offsets->display_name_end - uri_offsets->display_name_start + 1, FALSE);
1213 ti = proto_tree_add_item(sip_element_tree, *(uri->hf_sip_addr), tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start + 1, FALSE);
1214 uri_item_tree = proto_item_add_subtree(ti, *(uri->ett_uri));
1216 if(uri_offsets->uri_user_end > uri_offsets->uri_user_start) {
1217 proto_tree_add_item(uri_item_tree, *(uri->hf_sip_user), tvb, uri_offsets->uri_user_start,
1218 uri_offsets->uri_user_end - uri_offsets->uri_user_start + 1, FALSE);
1221 proto_tree_add_item(uri_item_tree, *(uri->hf_sip_host), tvb, uri_offsets->uri_host_start,
1222 uri_offsets->uri_host_end - uri_offsets->uri_host_start + 1, FALSE);
1224 if(uri_offsets->uri_host_port_end > uri_offsets->uri_host_port_start) {
1225 proto_tree_add_item(uri_item_tree, *(uri->hf_sip_port), tvb, uri_offsets->uri_host_port_start,
1226 uri_offsets->uri_host_port_end - uri_offsets->uri_host_port_start + 1, FALSE);
1229 return uri_item_tree;
1235 /* Code to parse a contact header item
1236 * Returns Offset end off parsing or -1 for unsuccessful parsing
1237 * * contact-param = (name-addr / addr-spec) *(SEMI contact-params)
1240 dissect_sip_contact_item(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint start_offset, gint line_end_offset)
1243 gint current_offset;
1244 gint queried_offset;
1245 gint contact_params_start_offset = -1;
1246 gint contact_param_end_offset = -1;
1247 uri_offset_info uri_offsets;
1249 /* skip Spaces and Tabs */
1250 start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1252 if(start_offset >= line_end_offset) {
1253 /* Nothing to parse */
1256 queried_offset = tvb_find_guint8(tvb, start_offset , line_end_offset - start_offset, ';');
1257 if(queried_offset == -1){
1258 queried_offset = line_end_offset;
1260 /* skip Spaces and Tabs */
1261 contact_params_start_offset = tvb_skip_wsp(tvb, queried_offset+1, line_end_offset - queried_offset+1);
1263 /* Initialize the uri_offsets */
1264 sip_uri_offset_init(&uri_offsets);
1265 /* contact-param = (name-addr / addr-spec) *(SEMI contact-params) */
1266 current_offset = dissect_sip_name_addr_or_addr_spec(tvb, pinfo, start_offset, line_end_offset, &uri_offsets);
1267 display_sip_uri(tvb, tree, &uri_offsets, &sip_contact_uri);
1268 if(current_offset == -1)
1270 /* Parsing failed */
1273 /* check if contact-params is present */
1274 if(contact_params_start_offset == -1)
1275 return line_end_offset;
1277 /* Move current offset to the start of the first param */
1278 current_offset = contact_params_start_offset;
1280 /* Put the contact parameters in the tree */
1282 while(current_offset< line_end_offset){
1283 queried_offset = tvb_pbrk_guint8(tvb, current_offset, line_end_offset - current_offset, ",;", &c);
1284 if(queried_offset == -1){
1285 /* Reached line end */
1286 contact_param_end_offset = line_end_offset - 3;
1287 current_offset = line_end_offset;
1289 /* More contacts, make this the line end for this contact */
1290 line_end_offset = queried_offset;
1291 contact_param_end_offset = queried_offset;
1292 current_offset = queried_offset;
1294 /* More parameters */
1295 contact_param_end_offset = queried_offset-1;
1296 current_offset = tvb_skip_wsp(tvb, queried_offset+1, line_end_offset - queried_offset+1);
1298 proto_tree_add_item(tree, hf_sip_contact_param, tvb, contact_params_start_offset ,
1299 contact_param_end_offset - contact_params_start_offset +1, FALSE);
1300 /* In case there are more parameters, point to the start of it */
1301 contact_params_start_offset = current_offset;
1305 return current_offset;
1308 /* Code to parse an authorization header item
1309 * Returns offset at end of parsing, or -1 for unsuccessful parsing
1312 dissect_sip_authorization_item(tvbuff_t *tvb, proto_tree *tree, gint start_offset, gint line_end_offset)
1314 gint current_offset, par_name_end_offset;
1315 gint equals_offset = 0;
1317 header_parameter_t *auth_parameter;
1320 /* skip Spaces and Tabs */
1321 start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1323 if (start_offset >= line_end_offset)
1325 /* Nothing to parse */
1329 current_offset = start_offset;
1330 equals_offset = tvb_find_guint8(tvb, current_offset + 1, line_end_offset - (current_offset + 1), '=');
1331 if(current_offset == -1){
1332 /* malformed parameter */
1335 par_name_end_offset = equals_offset - 1;
1336 par_name_end_offset = tvb_skip_wsp_return(tvb,par_name_end_offset);
1338 /* Extract the parameter name */
1339 name = tvb_get_ephemeral_string(tvb, start_offset, par_name_end_offset-start_offset+1);
1340 current_offset = tvb_find_guint8(tvb, par_name_end_offset, line_end_offset - par_name_end_offset, ',');
1341 if(current_offset==-1)
1342 /* Last parameter, line end */
1343 current_offset = line_end_offset;
1345 /* Try to add parameter as a filterable item */
1346 for (auth_parameter = &auth_parameters_hf_array[i];
1347 i < array_length(auth_parameters_hf_array);
1348 i++, auth_parameter++)
1350 if (g_ascii_strcasecmp(name, auth_parameter->param_name) == 0)
1352 proto_tree_add_item(tree, *(auth_parameter->hf_item), tvb,
1353 equals_offset+1, current_offset-equals_offset-1,
1359 /* If not matched, just add as text... */
1360 if (i == array_length(auth_parameters_hf_array))
1362 proto_tree_add_text(tree, tvb, start_offset, current_offset-start_offset,
1363 "%s", tvb_format_text(tvb, start_offset,
1364 current_offset-start_offset));
1367 return current_offset;
1370 /* Dissect the details of a Reason header */
1372 dissect_sip_reason_header(tvbuff_t *tvb, proto_tree *tree, gint start_offset, gint line_end_offset){
1374 gint current_offset, semi_colon_offset, length;
1375 gchar *param_name = NULL;
1378 /* skip Spaces and Tabs */
1379 start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1381 if (start_offset >= line_end_offset)
1383 /* Nothing to parse */
1387 current_offset = start_offset;
1388 semi_colon_offset = tvb_find_guint8(tvb, current_offset, line_end_offset-current_offset, ';');
1389 length = semi_colon_offset - current_offset;
1390 proto_tree_add_text(tree, tvb, start_offset, length,
1391 "Reason Protocols: %s", tvb_format_text(tvb, start_offset, length));
1393 param_name = tvb_get_ephemeral_string(tvb, start_offset, length);
1394 if (g_ascii_strcasecmp(param_name, "Q.850") == 0){
1395 current_offset = tvb_find_guint8(tvb, semi_colon_offset, line_end_offset-semi_colon_offset, '=')+1;
1396 length = line_end_offset - current_offset;
1398 /* q850_cause_code_vals */
1399 cause_value = atoi(tvb_get_ephemeral_string(tvb, current_offset, length));
1400 proto_tree_add_text(tree, tvb, current_offset, length,
1401 "Cause: %u(0x%x)[%s]", cause_value,cause_value,
1402 val_to_str(cause_value, q850_cause_code_vals, "Unknown (%d)" ));
1409 /* Dissect the details of a Via header */
1410 static void dissect_sip_via_header(tvbuff_t *tvb, proto_tree *tree, gint start_offset, gint line_end_offset)
1412 gint current_offset;
1413 gint transport_start_offset;
1414 gint address_start_offset;
1415 gint semicolon_offset;
1416 guint transport_slash_count;
1417 gboolean transport_name_started;
1418 gboolean colon_seen;
1419 gboolean ipv6_reference;
1420 gboolean ipv6_address;
1422 gchar *param_name = NULL;
1425 current_offset = start_offset;
1429 /* Reset flags and counters */
1430 transport_start_offset = 0;
1431 semicolon_offset = 0;
1432 transport_name_started = FALSE;
1433 transport_slash_count = 0;
1434 ipv6_reference = FALSE;
1435 ipv6_address = FALSE;
1438 /* skip Spaces and Tabs */
1439 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1441 if (current_offset >= line_end_offset)
1443 /* Nothing more to parse */
1447 /* Now look for the end of the SIP/2.0/transport parameter.
1448 There may be spaces between the slashes */
1449 while (current_offset < line_end_offset)
1451 c = tvb_get_guint8(tvb, current_offset);
1454 transport_slash_count++;
1457 if (!transport_name_started && (transport_slash_count == 2) && isalpha(c))
1459 transport_name_started = TRUE;
1460 transport_start_offset = current_offset;
1463 if (transport_name_started && ((c == ' ') || (c == '\t')))
1465 proto_tree_add_item(tree, hf_sip_via_transport, tvb, transport_start_offset,
1466 current_offset - transport_start_offset, FALSE);
1474 /* skip Spaces and Tabs */
1475 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1477 /* Now read the address part */
1478 address_start_offset = current_offset;
1479 while (current_offset < line_end_offset)
1481 c = tvb_get_guint8(tvb, current_offset);
1484 ipv6_reference = TRUE;
1485 ipv6_address = TRUE;
1489 ipv6_reference = FALSE;
1492 if (colon_seen || (c == ' ') || (c == '\t') || ((c == ':') && (ipv6_reference == FALSE)) || (c == ';'))
1499 /* Add address to tree */
1500 if (ipv6_address == TRUE) {
1501 proto_tree_add_item(tree, hf_sip_via_sent_by_address, tvb, address_start_offset + 1,
1502 current_offset - address_start_offset - 2, FALSE);
1504 proto_tree_add_item(tree, hf_sip_via_sent_by_address, tvb, address_start_offset,
1505 current_offset - address_start_offset, FALSE);
1508 /* Transport port number may follow ([space] : [space])*/
1509 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1510 c = tvb_get_guint8(tvb, current_offset);
1514 /* Port number will follow any space after : */
1519 /* Skip optional space after colon */
1520 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1522 port_offset = current_offset;
1524 /* Find digits of port number */
1525 while (current_offset < line_end_offset)
1527 c = tvb_get_guint8(tvb, current_offset);
1531 if (current_offset > port_offset)
1533 /* Add address port number to tree */
1534 proto_tree_add_uint(tree, hf_sip_via_sent_by_port, tvb, port_offset,
1535 current_offset - port_offset,
1536 atoi(tvb_get_ephemeral_string(tvb, port_offset,
1537 current_offset - port_offset)));
1541 /* Shouldn't see a colon without a port number given */
1551 /* skip Spaces and Tabs */
1552 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1555 /* Dissect any parameters found */
1556 while (current_offset < line_end_offset)
1558 gboolean equals_found = FALSE;
1559 gboolean found_end_of_parameters = FALSE;
1560 gint parameter_name_end = 0;
1561 gint parameter_value_end;
1562 header_parameter_t *via_parameter;
1565 /* Look for the semicolon that signals the start of a parameter */
1566 while (current_offset < line_end_offset)
1568 c = tvb_get_guint8(tvb, current_offset);
1571 semicolon_offset = current_offset;
1576 if ((c != ' ') && (c != '\t'))
1578 found_end_of_parameters = TRUE;
1584 if (found_end_of_parameters)
1589 if (current_offset == line_end_offset)
1594 /* Look for end of parameter name */
1595 while (current_offset < line_end_offset)
1597 c = tvb_get_guint8(tvb, current_offset);
1598 if (!isalpha(c) && (c != '-'))
1605 /* Not all params have an = */
1608 equals_found = TRUE;
1610 parameter_name_end = current_offset;
1612 /* Read until end of parameter value */
1613 while (current_offset < line_end_offset)
1615 c = tvb_get_guint8(tvb, current_offset);
1616 if ((c == ' ') || (c == '\t') || (c == ';') || (c == ','))
1623 /* Note parameter name */
1624 parameter_value_end = current_offset;
1625 param_name = tvb_get_ephemeral_string(tvb, semicolon_offset+1,
1626 parameter_name_end - semicolon_offset - 1);
1628 /* Try to add parameter as a filterable item */
1629 for (via_parameter = &via_parameters_hf_array[i];
1630 i < array_length(via_parameters_hf_array);
1631 i++, via_parameter++)
1633 if (g_ascii_strcasecmp(param_name, via_parameter->param_name) == 0)
1637 proto_tree_add_item(tree, *(via_parameter->hf_item), tvb,
1638 parameter_name_end+1, current_offset-parameter_name_end-1,
1643 proto_tree_add_item(tree, *(via_parameter->hf_item), tvb,
1644 semicolon_offset+1, current_offset-semicolon_offset-1,
1651 /* If not matched, just add as text... */
1652 if (i == array_length(via_parameters_hf_array))
1654 proto_tree_add_text(tree, tvb, semicolon_offset+1, current_offset-semicolon_offset-1,
1655 "%s", tvb_format_text(tvb, semicolon_offset+1,
1656 current_offset-semicolon_offset-1));
1659 /* skip Spaces and Tabs */
1660 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1662 /* There may be a comma, followed by more Via entries... */
1663 if (current_offset < line_end_offset)
1665 c = tvb_get_guint8(tvb, current_offset);
1668 /* Skip it and get out of parameter loop */
1678 /* Code to actually dissect the packets */
1680 dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1685 octet = tvb_get_guint8(tvb,0);
1686 if ((octet & 0xf8) == 0xf8){
1687 call_dissector(sigcomp_handle, tvb, pinfo, tree);
1688 return tvb_length(tvb);
1691 len = dissect_sip_common(tvb, 0, pinfo, tree, FALSE, FALSE);
1693 return 0; /* not SIP */
1699 dissect_sip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1705 octet = tvb_get_guint8(tvb,0);
1706 if ((octet & 0xf8) == 0xf8){
1707 call_dissector(sigcomp_handle, tvb, pinfo, tree);
1711 while (tvb_reported_length_remaining(tvb, offset) != 0) {
1712 len = dissect_sip_common(tvb, offset, pinfo, tree, TRUE, TRUE);
1720 dissect_sip_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1724 gboolean first = TRUE;
1726 while (tvb_reported_length_remaining(tvb, offset) != 0) {
1727 len = dissect_sip_common(tvb, offset, pinfo, tree, !first, TRUE);
1731 * If the first packet doesn't start with
1732 * a valid SIP request or response, don't
1733 * treat this as SIP.
1740 break; /* need more data */
1747 dissect_sip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1749 return dissect_sip_common(tvb, 0, pinfo, tree, FALSE, FALSE) > 0;
1753 dissect_sip_common(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
1754 gboolean dissect_other_as_continuation, gboolean use_reassembly)
1757 gint next_offset, linelen;
1758 int content_length, datalen, reported_datalen;
1759 line_type_t line_type;
1761 gboolean is_known_request;
1762 gboolean found_match = FALSE;
1764 guint token_1_len = 0;
1765 guint current_method_idx = SIP_METHOD_INVALID;
1766 proto_item *ts = NULL, *ti_a = NULL, *th = NULL, *sip_element_item = NULL;
1767 proto_tree *sip_tree = NULL, *reqresp_tree = NULL , *hdr_tree = NULL,
1768 *sip_element_tree = NULL, *message_body_tree = NULL, *cseq_tree = NULL,
1769 *via_tree = NULL, *reason_tree = NULL, *rack_tree = NULL;
1770 guchar contacts = 0, contact_is_star = 0, expires_is_0 = 0;
1771 guint32 cseq_number = 0;
1772 guchar cseq_number_set = 0;
1773 char cseq_method[MAX_CSEQ_METHOD_SIZE] = "";
1774 char call_id[MAX_CALL_ID_SIZE] = "";
1775 gchar *media_type_str_lower_case = NULL;
1776 char *content_type_parameter_str = NULL;
1777 guint resend_for_packet = 0;
1778 guint request_for_response = 0;
1779 guint32 response_time = 0;
1784 * Note that "tvb_find_line_end()" will return a value that
1785 * is not longer than what's in the buffer, so the
1786 * "tvb_get_ptr()" calls below won't throw exceptions.
1788 * Note that "tvb_strneql()" doesn't throw exceptions, so
1789 * "sip_parse_line()" won't throw an exception.
1791 orig_offset = offset;
1792 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
1793 if (tvb_strnlen(tvb, offset, linelen) > -1)
1796 * There's a NULL in the line,
1797 * this may be SIP within another protocol.
1798 * This heuristic still needs to improve.
1802 line_type = sip_parse_line(tvb, offset, linelen, &token_1_len);
1804 if (line_type == OTHER_LINE) {
1806 * This is neither a SIP request nor response.
1808 if (!dissect_other_as_continuation) {
1810 * We were asked to reject this.
1816 * Just dissect it as a continuation.
1818 } else if (use_reassembly) {
1820 * Yes, it's a request or response.
1821 * Do header desegmentation if we've been told to,
1822 * and do body desegmentation if we've been told to and
1823 * we find a Content-Length header.
1825 if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo,
1826 sip_desegment_headers, sip_desegment_body)) {
1828 * More data needed for desegmentation.
1834 /* Initialise stat info for passing to tap */
1835 stat_info = ep_alloc0(sizeof(sip_info_value_t));
1837 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIP");
1839 switch (line_type) {
1842 is_known_request = sip_is_known_request(tvb, offset, token_1_len, ¤t_method_idx);
1843 descr = is_known_request ? "Request" : "Unknown request";
1844 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
1846 tvb_format_text(tvb, offset, linelen - SIP2_HDR_LEN - 1));
1851 col_add_fstr(pinfo->cinfo, COL_INFO, "Status: %s",
1852 tvb_format_text(tvb, offset + SIP2_HDR_LEN + 1, linelen - SIP2_HDR_LEN - 1));
1853 stat_info->reason_phrase = tvb_get_ephemeral_string(tvb, offset + SIP2_HDR_LEN + 5, linelen - (SIP2_HDR_LEN + 5));
1857 default: /* Squelch compiler complaints */
1858 descr = "Continuation";
1859 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
1864 ts = proto_tree_add_item(tree, proto_sip, tvb, offset, -1, FALSE);
1865 sip_tree = proto_item_add_subtree(ts, ett_sip);
1868 switch (line_type) {
1872 ti_a = proto_tree_add_item(sip_tree, hf_Request_Line, tvb,
1873 offset, linelen, FALSE);
1875 reqresp_tree = proto_item_add_subtree(ti_a, ett_sip_reqresp);
1877 dfilter_sip_request_line(tvb, reqresp_tree, pinfo, offset, token_1_len, linelen);
1882 ti_a = proto_tree_add_item(sip_tree, hf_Status_Line, tvb,
1883 offset, linelen, FALSE);
1884 reqresp_tree = proto_item_add_subtree(ti_a, ett_sip_reqresp);
1886 dfilter_sip_status_line(tvb, reqresp_tree);
1891 ti_a = proto_tree_add_text(sip_tree, tvb, offset, next_offset,
1892 "%s line: %s", descr,
1893 tvb_format_text(tvb, offset, linelen));
1894 reqresp_tree = proto_item_add_subtree(ti_a, ett_sip_reqresp);
1895 proto_tree_add_text(sip_tree, tvb, offset, -1,
1896 "Continuation data");
1898 return tvb_length_remaining(tvb, offset);
1901 offset = next_offset;
1903 th = proto_tree_add_item(sip_tree, hf_msg_hdr, tvb, offset,
1904 tvb_length_remaining(tvb, offset), FALSE);
1905 proto_item_set_text(th, "Message Header");
1906 hdr_tree = proto_item_add_subtree(th, ett_sip_hdr);
1910 * Process the headers - if we're not building a protocol tree,
1911 * we just do this to find the blank line separating the
1912 * headers from the message body.
1914 next_offset = offset;
1915 content_length = -1;
1916 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1917 gint line_end_offset;
1919 gint semi_colon_offset;
1920 gint parameter_offset;
1921 gint parameter_end_offset;
1923 gint content_type_len, content_type_parameter_str_len;
1926 dissector_handle_t ext_hdr_handle;
1929 gint sub_value_offset;
1934 gboolean is_no_header_termination = FALSE;
1936 proto_tree *pai_uri_item_tree = NULL;
1937 proto_tree *pmiss_uri_item_tree = NULL;
1938 proto_tree *ppi_uri_item_tree = NULL;
1939 proto_tree *tc_uri_item_tree = NULL;
1940 uri_offset_info uri_offsets;
1946 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
1949 * This is a blank line separating the
1950 * message header from the message body.
1952 offset = next_offset;
1956 line_end_offset = offset + linelen;
1957 if(tvb_reported_length_remaining(tvb, next_offset) == 0){
1958 is_no_header_termination = TRUE;
1960 while ((c = tvb_get_guint8(tvb, next_offset)) == ' ' || c == '\t')
1963 * This line end is not a header seperator.
1964 * It just extends the header with another line.
1965 * Look for next line end:
1967 linelen += (next_offset - line_end_offset);
1968 linelen += tvb_find_line_end(tvb, next_offset, -1, &next_offset, FALSE);
1969 line_end_offset = offset + linelen;
1972 colon_offset = tvb_find_guint8(tvb, offset, linelen, ':');
1973 if (colon_offset == -1) {
1975 * Malformed header - no colon after the name.
1978 proto_tree_add_text(hdr_tree, tvb, offset,
1979 next_offset - offset, "%s",
1980 tvb_format_text(tvb, offset, linelen));
1983 header_len = colon_offset - offset;
1984 header_name = (gchar*)tvb_get_ephemeral_string(tvb, offset, header_len);
1985 ascii_strdown_inplace(header_name);
1986 hf_index = sip_is_known_sip_header(header_name, header_len);
1989 * Skip whitespace after the colon.
1991 value_offset = tvb_skip_wsp(tvb, colon_offset + 1, line_end_offset - (colon_offset + 1));
1996 value_len = (gint) (line_end_offset - value_offset);
1997 value = tvb_get_ephemeral_string(tvb, value_offset, value_len);
1999 if (hf_index == -1) {
2000 proto_item *ti_c = proto_tree_add_text(hdr_tree, tvb,
2001 offset, next_offset - offset, "%s",
2002 tvb_format_text(tvb, offset, linelen));
2003 ext_hdr_handle = dissector_get_string_handle(ext_hdr_subdissector_table, header_name);
2004 if (ext_hdr_handle != NULL) {
2005 tvbuff_t *next_tvb2;
2006 next_tvb2 = tvb_new_subset(tvb, value_offset, value_len, value_len);
2007 dissector_try_string(ext_hdr_subdissector_table, header_name, next_tvb2, pinfo, proto_item_add_subtree(ti_c, ett_sip_ext_hdr));
2009 expert_add_info_format(pinfo, ti_c,
2010 PI_UNDECODED, PI_NOTE,
2011 "Unrecognised SIP header (%s)",
2012 tvb_format_text(tvb, offset, header_len));
2016 * Add it to the protocol tree,
2017 * but display the line as is.
2019 switch ( hf_index ) {
2024 sip_element_item = proto_tree_add_string_format(hdr_tree,
2025 hf_header_array[hf_index], tvb,
2026 offset, next_offset - offset,
2028 tvb_format_text(tvb, offset, linelen));
2029 sip_element_tree = proto_item_add_subtree( sip_element_item,
2031 /* To = ( "To" / "t" ) HCOLON ( name-addr
2032 * / addr-spec ) *( SEMI to-param )
2035 sip_uri_offset_init(&uri_offsets);
2036 if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1){
2037 display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_to_uri);
2038 if((uri_offsets.name_addr_start != -1) && (uri_offsets.name_addr_end != -1)){
2039 stat_info->tap_to_addr=tvb_get_ephemeral_string(tvb, uri_offsets.name_addr_start,
2040 uri_offsets.name_addr_end - uri_offsets.name_addr_start);
2042 offset = uri_offsets.name_addr_end +1;
2046 /* Find parameter tag if present.
2047 * TODO make this generic to find any interesting parameter
2048 * use the same method as for SIP headers ?
2051 parameter_offset = offset;
2052 while (parameter_offset < line_end_offset
2053 && (tvb_strneql(tvb, parameter_offset, "tag=", 4) != 0))
2056 if ( parameter_offset < line_end_offset ){ /* Tag found */
2057 parameter_offset = parameter_offset + 4;
2058 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
2059 (line_end_offset - parameter_offset), ';');
2060 if ( parameter_end_offset == -1)
2061 parameter_end_offset = line_end_offset;
2062 parameter_len = parameter_end_offset - parameter_offset;
2063 proto_tree_add_item(sip_element_tree, hf_sip_tag, tvb, parameter_offset,
2064 parameter_len, FALSE);
2065 /* Tag indicates in-dialog messages, in case we have a INVITE, SUBSCRIBE or REFER, mark it */
2066 switch (current_method_idx) {
2068 case SIP_METHOD_INVITE:
2069 case SIP_METHOD_SUBSCRIBE:
2070 case SIP_METHOD_REFER:
2071 col_append_str(pinfo->cinfo, COL_INFO, ", in-dialog");
2080 sip_element_item = proto_tree_add_string_format(hdr_tree,
2081 hf_header_array[hf_index], tvb,
2082 offset, next_offset - offset,
2084 tvb_format_text(tvb, offset, linelen));
2085 sip_element_tree = proto_item_add_subtree( sip_element_item, ett_sip_element);
2088 * From = ( "From" / "f" ) HCOLON from-spec
2089 * from-spec = ( name-addr / addr-spec )
2090 * *( SEMI from-param )
2093 sip_uri_offset_init(&uri_offsets);
2094 if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1){
2095 display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_from_uri);
2096 if((uri_offsets.name_addr_start != -1) && (uri_offsets.name_addr_end != -1)){
2097 stat_info->tap_from_addr=tvb_get_ephemeral_string(tvb, uri_offsets.name_addr_start,
2098 uri_offsets.name_addr_end - uri_offsets.name_addr_start);
2100 offset = uri_offsets.name_addr_end +1;
2103 /* Find parameter tag if present.
2104 * TODO make this generic to find any interesting parameter
2105 * use the same method as for SIP headers ?
2108 parameter_offset = offset;
2109 while (parameter_offset < line_end_offset
2110 && (tvb_strneql(tvb, parameter_offset, "tag=", 4) != 0))
2112 if ( parameter_offset < line_end_offset ){ /* Tag found */
2113 parameter_offset = parameter_offset + 4;
2114 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
2115 (line_end_offset - parameter_offset), ';');
2116 if ( parameter_end_offset == -1)
2117 parameter_end_offset = line_end_offset;
2118 parameter_len = parameter_end_offset - parameter_offset;
2119 proto_tree_add_item(sip_element_tree, hf_sip_tag, tvb, parameter_offset,
2120 parameter_len, FALSE);
2126 case POS_P_ASSERTED_IDENTITY :
2129 sip_element_item = proto_tree_add_string_format(hdr_tree,
2130 hf_header_array[hf_index], tvb,
2131 offset, next_offset - offset,
2133 tvb_format_text(tvb, offset, linelen));
2134 sip_element_tree = proto_item_add_subtree( sip_element_item,
2138 * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value
2139 * *(COMMA PAssertedID-value)
2140 * PAssertedID-value = name-addr / addr-spec
2142 * Initialize the uri_offsets
2144 sip_uri_offset_init(&uri_offsets);
2145 if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
2146 pai_uri_item_tree = display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_pai_uri);
2150 case POS_P_CHARGING_FUNCTION_ADDRESSES:
2153 sip_element_item = proto_tree_add_string_format(hdr_tree,
2154 hf_header_array[hf_index], tvb,
2155 offset, next_offset - offset,
2157 tvb_format_text(tvb, offset, linelen));
2158 sip_element_tree = proto_item_add_subtree( sip_element_item,
2163 case POS_P_PREFERRED_IDENTITY :
2166 sip_element_item = proto_tree_add_string_format(hdr_tree,
2167 hf_header_array[hf_index], tvb,
2168 offset, next_offset - offset,
2170 tvb_format_text(tvb, offset, linelen));
2171 sip_element_tree = proto_item_add_subtree( sip_element_item,
2174 * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value
2175 * *(COMMA PPreferredID-value)
2176 * PPreferredID-value = name-addr / addr-spec
2178 * Initialize the uri_offsets
2180 sip_uri_offset_init(&uri_offsets);
2181 if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
2182 ppi_uri_item_tree = display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_ppi_uri);
2186 case POS_PERMISSION_MISSING :
2189 sip_element_item = proto_tree_add_string_format(hdr_tree,
2190 hf_header_array[hf_index], tvb,
2191 offset, next_offset - offset,
2193 tvb_format_text(tvb, offset, linelen));
2195 sip_element_tree = proto_item_add_subtree( sip_element_item,
2198 * Permission-Missing = "Permission-Missing" HCOLON per-miss-spec
2199 * *( COMMA per-miss-spec )
2200 * per-miss-spec = ( name-addr / addr-spec )
2201 * *( SEMI generic-param )
2202 * Initialize the uri_offsets
2204 sip_uri_offset_init(&uri_offsets);
2205 if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
2206 pmiss_uri_item_tree = display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_pmiss_uri);
2211 case POS_TRIGGER_CONSENT :
2214 sip_element_item = proto_tree_add_string_format(hdr_tree,
2215 hf_header_array[hf_index], tvb,
2216 offset, next_offset - offset,
2218 tvb_format_text(tvb, offset, linelen));
2220 sip_element_tree = proto_item_add_subtree( sip_element_item,
2224 * Trigger-Consent = "Trigger-Consent" HCOLON trigger-cons-spec
2225 * *( COMMA trigger-cons-spec )
2226 * trigger-cons-spec = ( SIP-URI / SIPS-URI )
2227 * *( SEMI trigger-param )
2228 * trigger-param = target-uri / generic-param
2229 * target-uri = "target-uri" EQUAL
2230 * LDQUOT *( qdtext / quoted-pair ) RDQUOT
2231 * Initialize the uri_offsets
2233 sip_uri_offset_init(&uri_offsets);
2234 if((dissect_sip_uri(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1) {
2236 tc_uri_item_tree = display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_tc_uri);
2237 if (line_end_offset > uri_offsets.uri_end) {
2238 gint hparam_offset = uri_offsets.uri_end + 1;
2239 /* Is there a header parameter */
2240 if (tvb_find_guint8(tvb, hparam_offset, 1,';')) {
2241 while ((hparam_offset != -1 && hparam_offset < line_end_offset) ) {
2242 /* Is this a target-uri ? */
2243 hparam_offset = hparam_offset + 1;
2244 if (tvb_strncaseeql(tvb, hparam_offset, "target-uri=\"", 12) == 0) {
2245 gint turi_start_offset = hparam_offset + 12;
2246 gint turi_end_offset = tvb_find_guint8(tvb, turi_start_offset, -1,'\"');
2247 if (turi_end_offset != -1)
2248 proto_tree_add_item(tc_uri_item_tree, hf_sip_tc_turi, tvb, turi_start_offset,(turi_end_offset - turi_start_offset),FALSE);
2250 break; /* malformed */
2252 hparam_offset = tvb_find_guint8(tvb, hparam_offset, -1,';');
2260 /* Store the sequence number */
2261 cseq_number = atoi(value);
2262 cseq_number_set = 1;
2263 stat_info->tap_cseq_number=cseq_number;
2267 sip_element_item = proto_tree_add_string_format(hdr_tree,
2268 hf_header_array[hf_index], tvb,
2269 offset, next_offset - offset,
2271 tvb_format_text(tvb, offset, linelen));
2272 cseq_tree = proto_item_add_subtree(sip_element_item, ett_sip_cseq);
2275 /* Walk past number and spaces characters to get to start
2277 for (sub_value_offset=0; sub_value_offset < linelen; sub_value_offset++)
2279 if (!isdigit((guchar)value[sub_value_offset]))
2281 proto_tree_add_uint(cseq_tree, hf_sip_cseq_seq_no,
2282 tvb, value_offset, sub_value_offset,
2288 for (; sub_value_offset < linelen; sub_value_offset++)
2290 if (isalpha((guchar)value[sub_value_offset]))
2292 /* Have reached start of method name */
2297 if (sub_value_offset == linelen)
2299 /* Didn't find method name */
2300 THROW(ReportedBoundsError);
2301 return offset - orig_offset;
2304 /* Extract method name from value */
2305 strlen_to_copy = (int)linelen-sub_value_offset;
2306 if (strlen_to_copy > MAX_CSEQ_METHOD_SIZE) {
2307 /* Note the error in the protocol tree */
2309 proto_tree_add_string_format(hdr_tree,
2310 hf_header_array[hf_index], tvb,
2311 offset, next_offset - offset,
2312 value+sub_value_offset, "%s String too big: %d bytes",
2313 sip_headers[POS_CSEQ].name,
2316 THROW(ReportedBoundsError);
2317 return offset - orig_offset;
2320 g_strlcpy(cseq_method, value+sub_value_offset, MAX_CSEQ_METHOD_SIZE);
2322 /* Add CSeq method to the tree */
2325 proto_tree_add_item(cseq_tree, hf_sip_cseq_method, tvb,
2326 value_offset + sub_value_offset, strlen_to_copy, FALSE);
2334 int cseq_method_offset;
2338 sip_element_item = proto_tree_add_string_format(hdr_tree,
2339 hf_header_array[hf_index], tvb,
2340 offset, next_offset - offset,
2342 tvb_format_text(tvb, offset, linelen));
2343 rack_tree = proto_item_add_subtree(sip_element_item, ett_sip_rack);
2347 for (sub_value_offset=0; sub_value_offset < linelen; sub_value_offset++)
2349 if (!isdigit((guchar)value[sub_value_offset]))
2351 proto_tree_add_uint(rack_tree, hf_sip_rack_rseq_no,
2352 tvb, value_offset, sub_value_offset,
2358 /* Get to start of CSeq number */
2359 for ( ; sub_value_offset < linelen; sub_value_offset++)
2361 if (value[sub_value_offset] != ' ' &&
2362 value[sub_value_offset] != '\t')
2367 cseq_no_offset = sub_value_offset;
2370 for ( ; sub_value_offset < linelen; sub_value_offset++)
2372 if (!isdigit((guchar)value[sub_value_offset]))
2374 proto_tree_add_uint(rack_tree, hf_sip_rack_cseq_no,
2375 tvb, value_offset+cseq_no_offset,
2376 sub_value_offset-cseq_no_offset,
2377 atoi(value+cseq_no_offset));
2382 /* Get to start of CSeq method name */
2383 for ( ; sub_value_offset < linelen; sub_value_offset++)
2385 if (isalpha((guchar)value[sub_value_offset]))
2387 /* Have reached start of method name */
2391 cseq_method_offset = sub_value_offset;
2393 if (sub_value_offset == linelen)
2395 /* Didn't find method name */
2396 THROW(ReportedBoundsError);
2397 return offset - orig_offset;
2400 /* Add CSeq method to the tree */
2403 proto_tree_add_item(rack_tree, hf_sip_rack_cseq_method, tvb,
2404 value_offset + sub_value_offset,
2405 (int)linelen-sub_value_offset, FALSE);
2412 /* Store the Call-id */
2413 g_strlcpy(call_id, value, MAX_CALL_ID_SIZE);
2414 stat_info->tap_call_id = ep_strdup(call_id);
2416 /* Add 'Call-id' string item to tree */
2418 sip_element_item = proto_tree_add_string_format(hdr_tree,
2419 hf_header_array[hf_index], tvb,
2420 offset, next_offset - offset,
2422 tvb_format_text(tvb, offset, linelen));
2427 if (strcmp(value, "0") == 0)
2431 /* Add 'Expires' string item to tree */
2433 sip_element_item = proto_tree_add_uint(hdr_tree,
2434 hf_header_array[hf_index], tvb,
2435 offset, next_offset - offset,
2441 * Content-Type is the same as Internet
2442 * media type used by other dissectors,
2443 * appropriate dissector found by
2444 * lookup in "media_type" dissector table.
2446 case POS_CONTENT_TYPE :
2448 sip_element_item = proto_tree_add_string_format(hdr_tree,
2449 hf_header_array[hf_index], tvb,
2450 offset, next_offset - offset,
2452 tvb_format_text(tvb, offset, linelen));
2454 content_type_len = value_len;
2455 semi_colon_offset = tvb_find_guint8(tvb, value_offset, value_len, ';');
2456 /* Content-Type = ( "Content-Type" / "c" ) HCOLON media-type
2457 * media-type = m-type SLASH m-subtype *(SEMI m-parameter)
2458 * SEMI = SWS ";" SWS ; semicolon
2459 * LWS = [*WSP CRLF] 1*WSP ; linear whitespace
2460 * SWS = [LWS] ; sep whitespace
2462 if ( semi_colon_offset != -1) {
2463 gint content_type_end;
2465 * Skip whitespace after the semicolon.
2467 parameter_offset = tvb_skip_wsp(tvb, semi_colon_offset +1, value_offset + value_len - (semi_colon_offset +1));
2468 content_type_end = tvb_skip_wsp_return(tvb, semi_colon_offset-1);
2469 content_type_len = content_type_end - value_offset;
2470 content_type_parameter_str_len = value_offset + value_len - parameter_offset;
2471 content_type_parameter_str = tvb_get_ephemeral_string(tvb, parameter_offset,
2472 content_type_parameter_str_len);
2474 media_type_str_lower_case = ascii_strdown_inplace(
2475 (gchar *)tvb_get_ephemeral_string(tvb, value_offset, content_type_len));
2478 proto_tree_add_text(hdr_tree, tvb, value_offset,content_type_len,
2479 "media_type_str(lower cased)=%s",media_type_str_lower_case);
2483 case POS_CONTENT_LENGTH :
2484 content_length = atoi(value);
2486 sip_element_item = proto_tree_add_uint_format(hdr_tree,
2487 hf_header_array[hf_index], tvb,
2488 offset, next_offset - offset,
2489 content_length, "%s",
2490 tvb_format_text(tvb, offset, linelen));
2494 case POS_MAX_BREADTH :
2495 case POS_MAX_FORWARDS :
2498 sip_element_item = proto_tree_add_uint(hdr_tree,
2499 hf_header_array[hf_index], tvb,
2500 offset, next_offset - offset,
2507 * Contact = ("Contact" / "m" ) HCOLON
2508 * ( STAR / (contact-param *(COMMA contact-param)))
2509 * contact-param = (name-addr / addr-spec) *(SEMI contact-params)
2512 sip_element_item = proto_tree_add_string_format(hdr_tree,
2513 hf_header_array[hf_index], tvb,
2514 offset, next_offset - offset,
2516 tvb_format_text(tvb, offset, linelen));
2517 sip_element_tree = proto_item_add_subtree( sip_element_item,
2520 /* value_offset points to the first non SWS character after ':' */
2521 c = tvb_get_guint8(tvb, value_offset);
2523 contact_is_star = 1;
2527 comma_offset = value_offset;
2528 while((comma_offset = dissect_sip_contact_item(tvb, pinfo, sip_element_tree, comma_offset, next_offset)) != -1)
2531 if(comma_offset == next_offset)
2533 /* Line End reached: Stop Parsing */
2537 if(tvb_get_guint8(tvb, comma_offset) != ',')
2539 /* Undefined value reached: Stop Parsing */
2542 comma_offset++; /* skip comma */
2546 case POS_AUTHORIZATION:
2547 /* Authorization = "Authorization" HCOLON credentials
2548 * credentials = ("Digest" LWS digest-response)
2550 * digest-response = dig-resp *(COMMA dig-resp)
2551 * other-response = auth-scheme LWS auth-param
2552 * *(COMMA auth-param)
2554 case POS_WWW_AUTHENTICATE:
2555 /* Proxy-Authenticate = "Proxy-Authenticate" HCOLON challenge
2556 * challenge = ("Digest" LWS digest-cln *(COMMA digest-cln))
2558 * other-challenge = auth-scheme LWS auth-param
2559 * *(COMMA auth-param)
2560 * auth-scheme = token
2562 case POS_PROXY_AUTHENTICATE:
2563 /* Proxy-Authenticate = "Proxy-Authenticate" HCOLON challenge
2565 case POS_PROXY_AUTHORIZATION:
2566 /* Proxy-Authorization = "Proxy-Authorization" HCOLON credentials
2568 case POS_AUTHENTICATION_INFO:
2569 /* Authentication-Info = "Authentication-Info" HCOLON ainfo
2571 * ainfo = nextnonce / message-qop
2572 * / response-auth / cnonce
2575 /* Add tree using whole text of line */
2578 /* Add whole line as header tree */
2579 sip_element_item = proto_tree_add_string_format(hdr_tree,
2580 hf_header_array[hf_index], tvb,
2581 offset, next_offset - offset,
2583 tvb_format_text(tvb, offset, linelen));
2584 sip_element_tree = proto_item_add_subtree( sip_element_item,
2587 /* Set sip.auth as a hidden field/filter */
2588 ti_c = proto_tree_add_item(hdr_tree, hf_sip_auth, tvb,
2589 offset, next_offset-offset,
2591 PROTO_ITEM_SET_HIDDEN(ti_c);
2593 /* Authentication-Info does not begin with the scheme name */
2594 if (hf_index != POS_AUTHENTICATION_INFO)
2596 /* The first time comma_offset is "start of parameters" */
2597 comma_offset = tvb_pbrk_guint8(tvb, value_offset, line_end_offset - value_offset, " \t\r\n", NULL);
2598 proto_tree_add_item(sip_element_tree, hf_sip_auth_scheme,
2599 tvb, value_offset, comma_offset - value_offset,
2602 /* The first time comma_offset is "start of parameters" */
2603 comma_offset = value_offset;
2606 /* Parse each individual parameter in the line */
2607 while ((comma_offset = dissect_sip_authorization_item(tvb, sip_element_tree, comma_offset, line_end_offset)) != -1)
2609 if(comma_offset == line_end_offset)
2611 /* Line End reached: Stop Parsing */
2615 if(tvb_get_guint8(tvb, comma_offset) != ',')
2617 /* Undefined value reached: Stop Parsing */
2620 comma_offset++; /* skip comma */
2626 /* Add Via subtree */
2628 sip_element_item = proto_tree_add_string_format(hdr_tree,
2629 hf_header_array[hf_index], tvb,
2630 offset, next_offset - offset,
2632 tvb_format_text(tvb, offset, linelen));
2633 via_tree = proto_item_add_subtree(sip_element_item, ett_sip_via);
2634 dissect_sip_via_header(tvb, via_tree, value_offset, line_end_offset);
2639 sip_element_item = proto_tree_add_string_format(hdr_tree,
2640 hf_header_array[hf_index], tvb,
2641 offset, next_offset - offset,
2643 tvb_format_text(tvb, offset, linelen));
2644 reason_tree = proto_item_add_subtree(sip_element_item, ett_sip_reason);
2645 dissect_sip_reason_header(tvb, reason_tree, value_offset, line_end_offset);
2649 /* Default case is to assume its an FT_STRING field */
2651 sip_element_item = proto_tree_add_string_format(hdr_tree,
2652 hf_header_array[hf_index], tvb,
2653 offset, next_offset - offset,
2655 tvb_format_text(tvb, offset, linelen));
2660 }/* if colon_offset */
2661 if (is_no_header_termination == TRUE){
2662 /* Header not terminated by empty line CRLF */
2663 cause=proto_tree_add_text(hdr_tree, tvb, line_end_offset, -1,
2664 "[Header not terminated by empty line (CRLF)]");
2666 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
2667 expert_add_info_format(pinfo, sip_element_item,
2668 PI_MALFORMED, PI_WARN,
2669 "Header not terminated by empty line (CRLF)");
2671 offset = next_offset;
2674 datalen = tvb_length_remaining(tvb, offset);
2675 reported_datalen = tvb_reported_length_remaining(tvb, offset);
2676 if (content_length != -1) {
2677 if (datalen > content_length)
2678 datalen = content_length;
2679 if (reported_datalen > content_length)
2680 reported_datalen = content_length;
2685 * There's a message body starting at "offset".
2686 * Set the length of the header item.
2688 proto_item_set_end(th, tvb, offset);
2689 next_tvb = tvb_new_subset(tvb, offset, datalen, reported_datalen);
2691 ti_a = proto_tree_add_item(sip_tree, hf_sip_msg_body, next_tvb, 0, -1,
2693 message_body_tree = proto_item_add_subtree(ti_a, ett_sip_message_body);
2696 /* give the content type parameters to sub dissectors */
2698 if ( media_type_str_lower_case != NULL ) {
2699 void *save_private_data = pinfo->private_data;
2700 pinfo->private_data = content_type_parameter_str;
2701 found_match = dissector_try_string(media_type_dissector_table,
2702 media_type_str_lower_case,
2705 pinfo->private_data = save_private_data;
2706 /* If no match dump as text */
2708 if ( found_match != TRUE )
2710 if (!(dissector_try_heuristic(heur_subdissector_list,
2711 next_tvb, pinfo, message_body_tree))) {
2713 while (tvb_offset_exists(next_tvb, tmp_offset)) {
2714 tvb_find_line_end(next_tvb, tmp_offset, -1, &next_offset, FALSE);
2715 linelen = next_offset - tmp_offset;
2716 if(message_body_tree) {
2717 proto_tree_add_text(message_body_tree, next_tvb,
2718 tmp_offset, linelen, "%s",
2719 tvb_format_text(next_tvb, tmp_offset, linelen));
2721 tmp_offset = next_offset;
2729 /* Add to info column interesting things learned from header fields. */
2730 /* Registration requests */
2731 if (current_method_idx == SIP_METHOD_REGISTER)
2733 if (contact_is_star && expires_is_0)
2735 col_append_str(pinfo->cinfo, COL_INFO, " (remove all bindings)");
2740 col_append_str(pinfo->cinfo, COL_INFO, " (fetch bindings)");
2744 /* Registration responses */
2745 if (line_type == STATUS_LINE && (strcmp(cseq_method, "REGISTER") == 0))
2747 col_append_fstr(pinfo->cinfo, COL_INFO, " (%d bindings)", contacts);
2749 /* Find the total setup time, Must be done before checking for resend
2750 * As that will overwrite the "Request packet no".
2752 if ((line_type == REQUEST_LINE)&&(strcmp(cseq_method, "ACK") == 0))
2754 request_for_response = sip_find_invite(pinfo, cseq_method, call_id,
2755 cseq_number_set, cseq_number,
2757 stat_info->setup_time = response_time;
2760 /* Check if this packet is a resend. */
2761 resend_for_packet = sip_is_packet_resend(pinfo, cseq_method, call_id,
2762 cseq_number_set, cseq_number,
2764 /* Mark whether this is a resend for the tap */
2765 stat_info->resend = (resend_for_packet > 0);
2767 /* And add the filterable field to the request/response line */
2771 item = proto_tree_add_boolean(reqresp_tree, hf_sip_resend, tvb, orig_offset, 0,
2772 resend_for_packet > 0);
2773 PROTO_ITEM_SET_GENERATED(item);
2774 if (resend_for_packet > 0)
2776 item = proto_tree_add_uint(reqresp_tree, hf_sip_original_frame,
2777 tvb, orig_offset, 0, resend_for_packet);
2778 PROTO_ITEM_SET_GENERATED(item);
2782 /* For responses, try to link back to request frame */
2783 if (line_type == STATUS_LINE)
2785 request_for_response = sip_find_request(pinfo, cseq_method, call_id,
2786 cseq_number_set, cseq_number,
2793 if (request_for_response > 0)
2795 item = proto_tree_add_uint(reqresp_tree, hf_sip_matching_request_frame,
2796 tvb, orig_offset, 0, request_for_response);
2797 PROTO_ITEM_SET_GENERATED(item);
2798 item = proto_tree_add_uint(reqresp_tree, hf_sip_response_time,
2799 tvb, orig_offset, 0, response_time);
2800 PROTO_ITEM_SET_GENERATED(item);
2801 if ((line_type == STATUS_LINE)&&(strcmp(cseq_method, "BYE") == 0)){
2802 item = proto_tree_add_uint(reqresp_tree, hf_sip_release_time,
2803 tvb, orig_offset, 0, response_time);
2804 PROTO_ITEM_SET_GENERATED(item);
2810 proto_item_set_len(ts, offset - orig_offset);
2812 if (global_sip_raw_text)
2813 tvb_raw_text_add(tvb, orig_offset, offset - orig_offset, tree);
2815 /* Report this packet to the tap */
2816 if (!pinfo->in_error_pkt)
2818 tap_queue_packet(sip_tap, pinfo, stat_info);
2821 return offset - orig_offset;
2824 /* Display filter for SIP Request-Line */
2826 dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, gint offset, guint meth_len, gint linelen)
2829 guint parameter_len = meth_len;
2830 uri_offset_info uri_offsets;
2833 * We know we have the entire method; otherwise, "sip_parse_line()"
2834 * would have returned OTHER_LINE.
2835 * Request-Line = Method SP Request-URI SP SIP-Version CRLF
2837 * Request-URI = SIP-URI / SIPS-URI / absoluteURI
2840 /* get method string*/
2841 value = tvb_get_ephemeral_string(tvb, offset, parameter_len);
2843 /* Copy request method for telling tap */
2844 stat_info->request_method = value;
2847 proto_tree_add_string(tree, hf_sip_Method, tvb, offset, parameter_len, value);
2849 /* build Request-URI tree*/
2850 offset=offset + parameter_len+1;
2851 sip_uri_offset_init(&uri_offsets);
2853 uri_offsets.uri_end = tvb_find_guint8(tvb, offset, linelen, ' ')-1;
2854 dissect_sip_uri(tvb, pinfo, offset, offset + linelen, &uri_offsets);
2855 display_sip_uri(tvb, tree, &uri_offsets, &sip_req_uri);
2859 /* Display filter for SIP Status-Line */
2861 dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree)
2864 gint response_code = 0;
2867 * We know we have the entire status code; otherwise,
2868 * "sip_parse_line()" would have returned OTHER_LINE.
2869 * We also know that we have a version string followed by a
2870 * space at the beginning of the line, for the same reason.
2872 tvb_memcpy(tvb, (guint8 *)string, SIP2_HDR_LEN + 1, 3);
2874 response_code = atoi(string);
2876 /* Add numerical response code to tree */
2878 proto_tree_add_uint(tree, hf_Status_Code, tvb, SIP2_HDR_LEN + 1,
2882 /* Add response code for sending to tap */
2883 stat_info->response_code = response_code;
2886 /* From section 4.1 of RFC 2543:
2888 * Request-Line = Method SP Request-URI SP SIP-Version CRLF
2890 * From section 5.1 of RFC 2543:
2892 * Status-Line = SIP-version SP Status-Code SP Reason-Phrase CRLF
2894 * From section 7.1 of RFC 3261:
2896 * Unlike HTTP, SIP treats the version number as a literal string.
2897 * In practice, this should make no difference.
2900 sip_parse_line(tvbuff_t *tvb, int offset, gint linelen, guint *token_1_lenp)
2911 token_1_start = offset;
2912 space_offset = tvb_find_guint8(tvb, token_1_start, -1, ' ');
2913 if ((space_offset == -1) || (space_offset == token_1_start)) {
2915 * Either there's no space in the line (which means
2916 * the line is empty or doesn't have a token followed
2917 * by a space; neither is valid for a request or status), or
2918 * the first character in the line is a space (meaning
2919 * the method is empty, which isn't valid for a request,
2920 * or the SIP version is empty, which isn't valid for a
2925 token_1_len = space_offset - token_1_start;
2926 token_2_start = space_offset + 1;
2927 space_offset = tvb_find_guint8(tvb, token_2_start, -1, ' ');
2928 if (space_offset == -1) {
2930 * There's no space after the second token, so we don't
2931 * have a third token.
2935 token_2_len = space_offset - token_2_start;
2936 token_3_start = space_offset + 1;
2937 token_3_len = token_1_start + linelen - token_3_start;
2939 *token_1_lenp = token_1_len;
2942 * Is the first token a version string?
2944 if ( (strict_sip_version && (
2945 token_1_len == SIP2_HDR_LEN
2946 && tvb_strneql(tvb, token_1_start, SIP2_HDR, SIP2_HDR_LEN) == 0)
2947 ) || (! strict_sip_version && (
2948 tvb_strncaseeql(tvb, token_1_start, "SIP/", 4) == 0)
2951 * Yes, so this is either a Status-Line or something
2952 * else other than a Request-Line. To be a Status-Line,
2953 * the second token must be a 3-digit number.
2955 if (token_2_len != 3) {
2957 * We don't have 3-character status code.
2961 if (!isdigit(tvb_get_guint8(tvb, token_2_start)) ||
2962 !isdigit(tvb_get_guint8(tvb, token_2_start + 1)) ||
2963 !isdigit(tvb_get_guint8(tvb, token_2_start + 2))) {
2965 * 3 characters yes, 3 digits no.
2972 * No, so this is either a Request-Line or something
2973 * other than a Status-Line. To be a Request-Line, the
2974 * second token must be a URI and the third token must
2975 * be a version string.
2977 if (token_2_len < 3) {
2979 * We don't have a URI consisting of at least 3
2984 colon_pos = tvb_find_guint8(tvb, token_2_start + 1, -1, ':');
2985 if (colon_pos == -1) {
2987 * There is no colon after the method, so the URI
2988 * doesn't have a colon in it, so it's not valid.
2992 if (colon_pos >= token_3_start) {
2994 * The colon is in the version string, not the URI.
2998 /* XXX - Check for a proper URI prefix? */
2999 if ( (strict_sip_version && (
3000 token_3_len != SIP2_HDR_LEN
3001 || tvb_strneql(tvb, token_3_start, SIP2_HDR, SIP2_HDR_LEN) == -1)
3002 ) || (! strict_sip_version && (
3003 tvb_strncaseeql(tvb, token_3_start, "SIP/", 4) == -1)
3006 * The version string isn't an SIP version 2.0 version
3011 return REQUEST_LINE;
3015 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
3016 guint meth_len, guint *meth_idx)
3021 meth_name = tvb_get_ephemeral_string(tvb, meth_offset, meth_len);
3023 for (i = 1; i < array_length(sip_methods); i++) {
3024 if (meth_len == strlen(sip_methods[i]) &&
3025 strncmp(meth_name, sip_methods[i], meth_len) == 0)
3036 * Returns index of method in sip_headers
3037 * Header namne should be in lower case
3039 static gint sip_is_known_sip_header(gchar *header_name, guint header_len)
3043 /* Compact name is one character long */
3045 pos = GPOINTER_TO_INT(g_hash_table_lookup(sip_headers_hash, header_name));
3050 /* Look for compact name match */
3051 for (pos = 1; pos < array_length(sip_headers); pos++) {
3052 if (sip_headers[pos].compact_name != NULL &&
3053 header_len == strlen(sip_headers[pos].compact_name) &&
3054 g_ascii_strncasecmp(header_name, sip_headers[pos].compact_name, header_len) == 0)
3062 * Display the entire message as raw text.
3065 tvb_raw_text_add(tvbuff_t *tvb, int offset, int length, proto_tree *tree)
3067 proto_tree *raw_tree = NULL;
3068 proto_item *ti = NULL;
3069 int next_offset, linelen, end_offset;
3073 ti = proto_tree_add_item(tree, proto_raw_sip, tvb, offset, length, FALSE);
3074 raw_tree = proto_item_add_subtree(ti, ett_raw_text);
3077 end_offset = offset + length;
3079 while (offset < end_offset) {
3080 tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
3081 linelen = next_offset - offset;
3083 str = tvb_format_text(tvb, offset, linelen);
3084 proto_tree_add_string_format(raw_tree, hf_raw_sip_line, tvb, offset, linelen,
3089 offset = next_offset;
3093 /* Check to see if this packet is a resent request. Return value is the frame number
3094 of the original frame this packet seems to be resending (0 = no resend). */
3095 guint sip_is_packet_resend(packet_info *pinfo,
3098 guchar cseq_number_set,
3099 guint32 cseq_number, line_type_t line_type)
3101 guint32 cseq_to_compare = 0;
3103 sip_hash_key *p_key = 0;
3104 sip_hash_value *p_val = 0;
3105 sip_frame_result_value *sip_frame_result = NULL;
3108 /* Only consider retransmission of UDP packets */
3109 if (pinfo->ptype != PT_UDP)
3114 /* Don't consider packets that appear to be resent only because
3115 they are e.g. returned in ICMP unreachable messages. */
3116 if (pinfo->in_error_pkt)
3121 /* A broken packet may have no cseq number set. Don't consider it as
3123 if (!cseq_number_set)
3128 /* Return any answer stored from previous dissection */
3129 if (pinfo->fd->flags.visited)
3131 sip_frame_result = (sip_frame_result_value*)p_get_proto_data(pinfo->fd, proto_sip);
3132 if (sip_frame_result != NULL)
3134 return sip_frame_result->original_frame_num;
3142 /* No packet entry found, consult global hash table */
3144 /* Prepare the key */
3145 g_strlcpy(key.call_id, call_id, MAX_CALL_ID_SIZE);
3147 /* We're only using these addresses locally (for the hash lookup) so
3148 * there is no need to make a (g_malloc'd) copy of them.
3150 SET_ADDRESS(&key.dest_address, pinfo->net_dst.type, pinfo->net_dst.len,
3151 pinfo->net_dst.data);
3152 SET_ADDRESS(&key.source_address, pinfo->net_src.type,
3153 pinfo->net_src.len, pinfo->net_src.data);
3154 key.dest_port = pinfo->destport;
3155 if (sip_retrans_the_same_sport) {
3156 key.source_port = pinfo->srcport;
3158 key.source_port = MAGIC_SOURCE_PORT;
3162 p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
3166 /* Table entry found, we'll use its value for comparison */
3167 cseq_to_compare = p_val->cseq;
3169 /* First time through, must update value with current details if
3170 cseq number has changed */
3171 if (cseq_number != p_val->cseq)
3173 p_val->cseq = cseq_number;
3174 g_strlcpy(p_val->method, cseq_method, MAX_CSEQ_METHOD_SIZE);
3175 p_val->transaction_state = nothing_seen;
3176 p_val->frame_number = 0;
3177 if (line_type == REQUEST_LINE)
3179 p_val->request_time = pinfo->fd->abs_ts;
3185 /* Need to create a new table entry */
3187 /* Allocate a new key and value */
3188 p_key = se_alloc(sizeof(sip_hash_key));
3189 p_val = se_alloc(sizeof(sip_hash_value));
3191 /* Fill in key and value details */
3192 g_snprintf(p_key->call_id, MAX_CALL_ID_SIZE, "%s", call_id);
3193 SE_COPY_ADDRESS(&(p_key->dest_address), &pinfo->net_dst);
3194 SE_COPY_ADDRESS(&(p_key->source_address), &pinfo->net_src);
3195 p_key->dest_port = pinfo->destport;
3196 if (sip_retrans_the_same_sport) {
3197 p_key->source_port = pinfo->srcport;
3199 p_key->source_port = MAGIC_SOURCE_PORT;
3202 p_val->cseq = cseq_number;
3203 g_strlcpy(p_val->method, cseq_method, MAX_CSEQ_METHOD_SIZE);
3204 p_val->transaction_state = nothing_seen;
3205 p_val->frame_number = 0;
3206 if (line_type == REQUEST_LINE)
3208 p_val->request_time = pinfo->fd->abs_ts;
3212 g_hash_table_insert(sip_hash, p_key, p_val);
3214 /* Assume have seen no cseq yet */
3215 cseq_to_compare = 0;
3219 /******************************************/
3220 /* Is it a resend??? */
3222 /* Does this look like a resent request (discount ACK, CANCEL, or a
3223 different method from the original one) ? */
3225 if ((line_type == REQUEST_LINE) && (cseq_number == cseq_to_compare) &&
3226 (p_val->transaction_state == request_seen) &&
3227 (strcmp(cseq_method, p_val->method) == 0) &&
3228 (strcmp(cseq_method, "ACK") != 0) &&
3229 (strcmp(cseq_method, "CANCEL") != 0))
3231 result = p_val->frame_number;
3234 /* Does this look like a resent final response ? */
3235 if ((line_type == STATUS_LINE) && (cseq_number == cseq_to_compare) &&
3236 (p_val->transaction_state == final_response_seen) &&
3237 (strcmp(cseq_method, p_val->method) == 0) &&
3238 (stat_info->response_code >= 200) &&
3239 (stat_info->response_code == p_val->response_code))
3241 result = p_val->frame_number;
3244 /* Update state for this entry */
3245 p_val->cseq = cseq_number;
3250 p_val->transaction_state = request_seen;
3253 /* This frame is the original request */
3254 p_val->frame_number = pinfo->fd->num;
3258 if (stat_info->response_code >= 200)
3260 p_val->response_code = stat_info->response_code;
3261 p_val->transaction_state = final_response_seen;
3264 /* This frame is the original response */
3265 p_val->frame_number = pinfo->fd->num;
3270 p_val->transaction_state = provisional_response_seen;
3277 sip_frame_result = p_get_proto_data(pinfo->fd, proto_sip);
3278 if (sip_frame_result == NULL)
3280 sip_frame_result = se_alloc(sizeof(sip_frame_result_value));
3283 /* Store return value with this packet */
3284 sip_frame_result->original_frame_num = result;
3285 p_add_proto_data(pinfo->fd, proto_sip, sip_frame_result);
3291 /* Check to see if this packet is a resent request. Return value is the frame number
3292 of the original frame this packet seems to be resending (0 = no resend). */
3293 guint sip_find_request(packet_info *pinfo,
3296 guchar cseq_number_set,
3297 guint32 cseq_number,
3298 guint32 *response_time)
3300 guint32 cseq_to_compare = 0;
3302 sip_hash_value *p_val = 0;
3303 sip_frame_result_value *sip_frame_result = NULL;
3305 gint seconds_between_packets;
3306 gint nseconds_between_packets;
3308 /* Only consider UDP */
3309 if (pinfo->ptype != PT_UDP)
3314 /* Ignore error (usually ICMP) frames */
3315 if (pinfo->in_error_pkt)
3320 /* A broken packet may have no cseq number set. Ignore. */
3321 if (!cseq_number_set)
3326 /* Return any answer stored from previous dissection */
3327 if (pinfo->fd->flags.visited)
3329 sip_frame_result = (sip_frame_result_value*)p_get_proto_data(pinfo->fd, proto_sip);
3330 if (sip_frame_result != NULL)
3332 *response_time = sip_frame_result->response_time;
3333 return sip_frame_result->response_request_frame_num;
3341 /* No packet entry found, consult global hash table */
3343 /* Prepare the key */
3344 g_strlcpy(key.call_id, call_id, MAX_CALL_ID_SIZE);
3346 /* Looking for matching request, so reverse addresses for this lookup */
3347 SET_ADDRESS(&key.dest_address, pinfo->net_src.type, pinfo->net_src.len,
3348 pinfo->net_src.data);
3349 SET_ADDRESS(&key.source_address, pinfo->net_dst.type, pinfo->net_dst.len,
3350 pinfo->net_dst.data);
3351 key.dest_port = pinfo->srcport;
3352 key.source_port = pinfo->destport;
3355 p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
3359 /* Table entry found, we'll use its value for comparison */
3360 cseq_to_compare = p_val->cseq;
3364 /* We don't have the request */
3369 /**************************************************/
3370 /* Is it a response to a request that we've seen? */
3371 if ((cseq_number == cseq_to_compare) &&
3372 (p_val->transaction_state == request_seen) &&
3373 (strcmp(cseq_method, p_val->method) == 0))
3375 result = p_val->frame_number;
3379 /* Store return value with this packet */
3380 sip_frame_result = p_get_proto_data(pinfo->fd, proto_sip);
3381 if (sip_frame_result == NULL)
3383 /* Allocate and set all values to zero */
3384 sip_frame_result = se_alloc0(sizeof(sip_frame_result_value));
3387 sip_frame_result->response_request_frame_num = result;
3389 /* Work out response time */
3390 seconds_between_packets = (gint)
3391 (pinfo->fd->abs_ts.secs - p_val->request_time.secs);
3392 nseconds_between_packets =
3393 pinfo->fd->abs_ts.nsecs - p_val->request_time.nsecs;
3394 sip_frame_result->response_time = (seconds_between_packets*1000) +
3395 (nseconds_between_packets / 1000000);
3396 *response_time = sip_frame_result->response_time;
3398 p_add_proto_data(pinfo->fd, proto_sip, sip_frame_result);
3404 * Find the initial INVITE to calculate the total setup time
3406 guint sip_find_invite(packet_info *pinfo,
3407 gchar *cseq_method _U_,
3409 guchar cseq_number_set,
3410 guint32 cseq_number _U_,
3411 guint32 *response_time)
3413 guint32 cseq_to_compare = 0;
3415 sip_hash_value *p_val = 0;
3416 sip_frame_result_value *sip_frame_result = NULL;
3418 gint seconds_between_packets;
3419 gint nseconds_between_packets;
3421 /* Only consider UDP */
3422 if (pinfo->ptype != PT_UDP)
3427 /* Ignore error (usually ICMP) frames */
3428 if (pinfo->in_error_pkt)
3433 /* A broken packet may have no cseq number set. Ignore. */
3434 if (!cseq_number_set)
3439 /* Return any answer stored from previous dissection */
3440 if (pinfo->fd->flags.visited)
3442 sip_frame_result = (sip_frame_result_value*)p_get_proto_data(pinfo->fd, proto_sip);
3443 if (sip_frame_result != NULL)
3445 *response_time = sip_frame_result->response_time;
3446 return sip_frame_result->response_request_frame_num;
3454 /* No packet entry found, consult global hash table */
3456 /* Prepare the key */
3457 g_strlcpy(key.call_id, call_id, MAX_CALL_ID_SIZE);
3459 /* Looking for matching INVITE */
3460 SET_ADDRESS(&key.dest_address, pinfo->net_dst.type, pinfo->net_dst.len,
3461 pinfo->net_dst.data);
3462 SET_ADDRESS(&key.source_address, pinfo->net_src.type, pinfo->net_src.len,
3463 pinfo->net_src.data);
3464 key.dest_port = pinfo->destport;
3465 key.source_port = pinfo->srcport;
3468 p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
3472 /* Table entry found, we'll use its value for comparison */
3473 cseq_to_compare = p_val->cseq;
3477 /* We don't have the request */
3482 /**************************************************/
3483 /* Is it a response to a request that we've seen? */
3485 if ((cseq_number == cseq_to_compare) &&
3486 (p_val->transaction_state == request_seen) &&
3487 (strcmp(cseq_method, p_val->method) == 0))
3489 result = p_val->frame_number;
3493 result = p_val->frame_number;
3495 /* Store return value with this packet */
3496 sip_frame_result = p_get_proto_data(pinfo->fd, proto_sip);
3497 if (sip_frame_result == NULL)
3499 /* Allocate and set all values to zero */
3500 sip_frame_result = se_alloc0(sizeof(sip_frame_result_value));
3503 sip_frame_result->response_request_frame_num = result;
3505 /* Work out response time */
3506 seconds_between_packets = (gint)
3507 (pinfo->fd->abs_ts.secs - p_val->request_time.secs);
3508 nseconds_between_packets =
3509 pinfo->fd->abs_ts.nsecs - p_val->request_time.nsecs;
3510 sip_frame_result->response_time = (seconds_between_packets*1000) +
3511 (nseconds_between_packets / 1000000);
3512 *response_time = sip_frame_result->response_time;
3514 p_add_proto_data(pinfo->fd, proto_sip, sip_frame_result);
3520 /* Register the protocol with Wireshark */
3521 void proto_register_sip(void)
3524 /* Setup list of header fields */
3525 static hf_register_info hf[] = {
3528 { "Message Header", "sip.msg_hdr",
3529 FT_STRING, BASE_NONE, NULL, 0,
3530 "Message Header in SIP message", HFILL }
3533 { "Method", "sip.Method",
3534 FT_STRING, BASE_NONE,NULL,0x0,
3535 "SIP Method", HFILL }
3538 { "Request-Line", "sip.Request-Line",
3539 FT_STRING, BASE_NONE,NULL,0x0,
3540 "SIP Request-Line", HFILL }
3543 { "Request-URI", "sip.r-uri",
3544 FT_STRING, BASE_NONE,NULL,0x0,
3545 "RFC 3261: SIP R-URI", HFILL }
3547 { &hf_sip_ruri_user,
3548 { "Request-URI User Part", "sip.r-uri.user",
3549 FT_STRING, BASE_NONE,NULL,0x0,
3550 "RFC 3261: SIP R-URI User", HFILL }
3552 { &hf_sip_ruri_host,
3553 { "Request-URI Host Part", "sip.r-uri.host",
3554 FT_STRING, BASE_NONE,NULL,0x0,
3555 "RFC 3261: SIP R-URI Host", HFILL }
3557 { &hf_sip_ruri_port,
3558 { "Request-URI Host Port", "sip.r-uri.port",
3559 FT_STRING, BASE_NONE,NULL,0x0,
3560 "RFC 3261: SIP R-URI Port", HFILL }
3563 { "Status-Code", "sip.Status-Code",
3564 FT_UINT32, BASE_DEC,NULL,0x0,
3565 "SIP Status Code", HFILL }
3568 { "Status-Line", "sip.Status-Line",
3569 FT_STRING, BASE_NONE,NULL,0x0,
3570 "SIP Status-Line", HFILL }
3573 { "SIP Display info", "sip.display.info",
3574 FT_STRING, BASE_NONE,NULL,0x0,
3575 "RFC 3261: Display info", HFILL }
3578 { "SIP to address", "sip.to.addr",
3579 FT_STRING, BASE_NONE,NULL,0x0,
3580 "RFC 3261: To Address", HFILL }
3583 { "SIP to address User Part", "sip.to.user",
3584 FT_STRING, BASE_NONE,NULL,0x0,
3585 "RFC 3261: To Address User", HFILL }
3588 { "SIP to address Host Part", "sip.to.host",
3589 FT_STRING, BASE_NONE,NULL,0x0,
3590 "RFC 3261: To Address Host", HFILL }
3593 { "SIP to address Host Port", "sip.to.port",
3594 FT_STRING, BASE_NONE,NULL,0x0,
3595 "RFC 3261: To Address Port", HFILL }
3597 { &hf_sip_from_addr,
3598 { "SIP from address", "sip.from.addr",
3599 FT_STRING, BASE_NONE,NULL,0x0,
3600 "RFC 3261: From Address", HFILL }
3602 { &hf_sip_from_user,
3603 { "SIP from address User Part", "sip.from.user",
3604 FT_STRING, BASE_NONE,NULL,0x0,
3605 "RFC 3261: From Address User", HFILL }
3607 { &hf_sip_from_host,
3608 { "SIP from address Host Part", "sip.from.host",
3609 FT_STRING, BASE_NONE,NULL,0x0,
3610 "RFC 3261: From Address Host", HFILL }
3612 { &hf_sip_from_port,
3613 { "SIP from address Host Port", "sip.from.port",
3614 FT_STRING, BASE_NONE,NULL,0x0,
3615 "RFC 3261: From Address Port", HFILL }
3619 { "Contact-URI", "sip.contact.uri",
3620 FT_STRING, BASE_NONE,NULL,0x0,
3621 "RFC 3261: SIP C-URI", HFILL }
3623 { &hf_sip_curi_user,
3624 { "Contactt-URI User Part", "sip.contact.user",
3625 FT_STRING, BASE_NONE,NULL,0x0,
3626 "RFC 3261: SIP C-URI User", HFILL }
3628 { &hf_sip_curi_host,
3629 { "Contact-URI Host Part", "sip.contact.host",
3630 FT_STRING, BASE_NONE,NULL,0x0,
3631 "RFC 3261: SIP C-URI Host", HFILL }
3633 { &hf_sip_curi_port,
3634 { "Contact-URI Host Port", "sip.contact.port",
3635 FT_STRING, BASE_NONE,NULL,0x0,
3636 "RFC 3261: SIP C-URI Port", HFILL }
3638 { &hf_sip_contact_param,
3639 { "Contact parameter", "sip.contact.parameter",
3640 FT_STRING, BASE_NONE,NULL,0x0,
3641 "RFC 3261: one contact parameter", HFILL }
3644 { "SIP tag", "sip.tag",
3645 FT_STRING, BASE_NONE,NULL,0x0,
3646 "RFC 3261: tag", HFILL }
3649 { "SIP PAI Address", "sip.pai.addr",
3650 FT_STRING, BASE_NONE,NULL,0x0,
3651 "RFC 3325: P-Asserted-Identity Address", HFILL }
3654 { "SIP PAI User Part", "sip.pai.user",
3655 FT_STRING, BASE_NONE,NULL,0x0,
3656 "RFC 3325: P-Asserted-Identity User", HFILL }
3659 { "SIP PAI Host Part", "sip.pai.host",
3660 FT_STRING, BASE_NONE,NULL,0x0,
3661 "RFC 3325: P-Asserted-Identity Host", HFILL }
3664 { "SIP PAI Host Port", "sip.pai.port",
3665 FT_STRING, BASE_NONE,NULL,0x0,
3666 "RFC 3325: P-Asserted-Identity Port", HFILL }
3668 { &hf_sip_pmiss_addr,
3669 { "SIP PMISS Address", "sip.pmiss.addr",
3670 FT_STRING, BASE_NONE,NULL,0x0,
3671 "RFC 3325: Permission Missing Address", HFILL }
3673 { &hf_sip_pmiss_user,
3674 { "SIP PMISS User Part", "sip.pmiss.user",
3675 FT_STRING, BASE_NONE,NULL,0x0,
3676 "RFC 3325: Permission Missing User", HFILL }
3678 { &hf_sip_pmiss_host,
3679 { "SIP PMISS Host Part", "sip.pmiss.host",
3680 FT_STRING, BASE_NONE,NULL,0x0,
3681 "RFC 3325: Permission Missing Host", HFILL }
3683 { &hf_sip_pmiss_port,
3684 { "SIP PMISS Host Port", "sip.pmiss.port",
3685 FT_STRING, BASE_NONE,NULL,0x0,
3686 "RFC 3325: Permission Missing Port", HFILL }
3690 { "SIP PPI Address", "sip.ppi.addr",
3691 FT_STRING, BASE_NONE,NULL,0x0,
3692 "RFC 3325: P-Preferred-Identity Address", HFILL }
3695 { "SIP PPI User Part", "sip.ppi.user",
3696 FT_STRING, BASE_NONE,NULL,0x0,
3697 "RFC 3325: P-Preferred-Identity User", HFILL }
3700 { "SIP PPI Host Part", "sip.ppi.host",
3701 FT_STRING, BASE_NONE,NULL,0x0,
3702 "RFC 3325: P-Preferred-Identity Host", HFILL }
3705 { "SIP PPI Host Port", "sip.ppi.port",
3706 FT_STRING, BASE_NONE,NULL,0x0,
3707 "RFC 3325: P-Preferred-Identity Port", HFILL }
3710 { "SIP TC Address", "sip.tc.addr",
3711 FT_STRING, BASE_NONE,NULL,0x0,
3712 "RFC 3325: Trigger Consent Address", HFILL }
3715 { "SIP TC User Part", "sip.tc.user",
3716 FT_STRING, BASE_NONE,NULL,0x0,
3717 "RFC 3325: Trigger Consent User", HFILL }
3720 { "SIP TC Host Part", "sip.tc.host",
3721 FT_STRING, BASE_NONE,NULL,0x0,
3722 "RFC 3325: Trigger Consent Host", HFILL }
3725 { "SIP TC Host Port", "sip.tc.port",
3726 FT_STRING, BASE_NONE,NULL,0x0,
3727 "RFC 3325: Trigger Consent Port", HFILL }
3730 { "SIP TC Target URI", "sip.tc.target-uri",
3731 FT_STRING, BASE_NONE,NULL,0x0,
3732 "RFC 3325: Trigger Consent Target URI", HFILL }
3734 { &hf_header_array[POS_ACCEPT],
3735 { "Accept", "sip.Accept",
3736 FT_STRING, BASE_NONE,NULL,0x0,
3737 "RFC 3261: Accept Header", HFILL }
3739 { &hf_header_array[POS_ACCEPT_CONTACT],
3740 { "Accept-Contact", "sip.Accept-Contact",
3741 FT_STRING, BASE_NONE,NULL,0x0,
3742 "RFC 3841: Accept-Contact Header", HFILL }
3744 { &hf_header_array[POS_ACCEPT_ENCODING],
3745 { "Accept-Encoding", "sip.Accept-Encoding",
3746 FT_STRING, BASE_NONE,NULL,0x0,
3747 "RFC 3841: Accept-Encoding Header", HFILL }
3749 { &hf_header_array[POS_ACCEPT_LANGUAGE],
3750 { "Accept-Language", "sip.Accept-Language",
3751 FT_STRING, BASE_NONE,NULL,0x0,
3752 "RFC 3261: Accept-Language Header", HFILL }
3754 { &hf_header_array[POS_ACCEPT_RESOURCE_PRIORITY],
3755 { "Accept-Resource-Priority", "sip.Accept-Resource-Priority",
3756 FT_STRING, BASE_NONE,NULL,0x0,
3757 "Draft: Accept-Resource-Priority Header", HFILL }
3759 { &hf_header_array[POS_ALERT_INFO],
3760 { "Alert-Info", "sip.Alert-Info",
3761 FT_STRING, BASE_NONE,NULL,0x0,
3762 "RFC 3261: Alert-Info Header", HFILL }
3764 { &hf_header_array[POS_ALLOW],
3765 { "Allow", "sip.Allow",
3766 FT_STRING, BASE_NONE,NULL,0x0,
3767 "RFC 3261: Allow Header", HFILL }
3769 { &hf_header_array[POS_ALLOW_EVENTS],
3770 { "Allow-Events", "sip.Allow-Events",
3771 FT_STRING, BASE_NONE,NULL,0x0,
3772 "RFC 3265: Allow-Events Header", HFILL }
3774 { &hf_header_array[POS_ANSWER_MODE],
3775 { "Answer-Mode", "sip.Answer-Mode",
3776 FT_STRING, BASE_NONE,NULL,0x0,
3777 "RFC 5373: Answer-Mode Header", HFILL }
3779 { &hf_header_array[POS_AUTHENTICATION_INFO],
3780 { "Authentication-Info", "sip.Authentication-Info",
3781 FT_STRING, BASE_NONE,NULL,0x0,
3782 "RFC 3261: Authentication-Info Header", HFILL }
3784 { &hf_header_array[POS_AUTHORIZATION],
3785 { "Authorization", "sip.Authorization",
3786 FT_STRING, BASE_NONE,NULL,0x0,
3787 "RFC 3261: Authorization Header", HFILL }
3789 { &hf_header_array[POS_CALL_ID],
3790 { "Call-ID", "sip.Call-ID",
3791 FT_STRING, BASE_NONE,NULL,0x0,
3792 "RFC 3261: Call-ID Header", HFILL }
3794 { &hf_header_array[POS_CALL_INFO],
3795 { "Call-Info", "sip.Call-Info",
3796 FT_STRING, BASE_NONE,NULL,0x0,
3797 "RFC 3261: Call-Info Header", HFILL }
3799 { &hf_header_array[POS_CONTACT],
3800 { "Contact", "sip.Contact",
3801 FT_STRING, BASE_NONE,NULL,0x0,
3802 "RFC 3261: Contact Header", HFILL }
3804 { &hf_header_array[POS_CONTENT_DISPOSITION],
3805 { "Content-Disposition", "sip.Content-Disposition",
3806 FT_STRING, BASE_NONE,NULL,0x0,
3807 "RFC 3261: Content-Disposition Header", HFILL }
3809 { &hf_header_array[POS_CONTENT_ENCODING],
3810 { "Content-Encoding", "sip.Content-Encoding",
3811 FT_STRING, BASE_NONE,NULL,0x0,
3812 "RFC 3261: Content-Encoding Header", HFILL }
3814 { &hf_header_array[POS_CONTENT_LANGUAGE],
3815 { "Content-Language", "sip.Content-Language",
3816 FT_STRING, BASE_NONE,NULL,0x0,
3817 "RFC 3261: Content-Language Header", HFILL }
3819 { &hf_header_array[POS_CONTENT_LENGTH],
3820 { "Content-Length", "sip.Content-Length",
3821 FT_UINT32, BASE_DEC,NULL,0x0,
3822 "RFC 3261: Content-Length Header", HFILL }
3824 { &hf_header_array[POS_CONTENT_TYPE],
3825 { "Content-Type", "sip.Content-Type",
3826 FT_STRING, BASE_NONE,NULL,0x0,
3827 "RFC 3261: Content-Type Header", HFILL }
3829 { &hf_header_array[POS_CSEQ],
3830 { "CSeq", "sip.CSeq",
3831 FT_STRING, BASE_NONE,NULL,0x0,
3832 "RFC 3261: CSeq Header", HFILL }
3834 { &hf_header_array[POS_DATE],
3835 { "Date", "sip.Date",
3836 FT_STRING, BASE_NONE,NULL,0x0,
3837 "RFC 3261: Date Header", HFILL }
3839 { &hf_header_array[POS_ERROR_INFO],
3840 { "Error-Info", "sip.Error-Info",
3841 FT_STRING, BASE_NONE,NULL,0x0,
3842 "RFC 3261: Error-Info Header", HFILL }
3844 { &hf_header_array[POS_EVENT],
3845 { "Event", "sip.Event",
3846 FT_STRING, BASE_NONE,NULL,0x0,
3847 "RFC 3265: Event Header", HFILL }
3849 { &hf_header_array[POS_EXPIRES],
3850 { "Expires", "sip.Expires",
3851 FT_UINT32, BASE_DEC,NULL,0x0,
3852 "RFC 3261: Expires Header", HFILL }
3854 { &hf_header_array[POS_FROM],
3855 { "From", "sip.From",
3856 FT_STRING, BASE_NONE,NULL,0x0,
3857 "RFC 3261: From Header", HFILL }
3859 { &hf_header_array[POS_IN_REPLY_TO],
3860 { "In-Reply-To", "sip.In-Reply-To",
3861 FT_STRING, BASE_NONE,NULL,0x0,
3862 "RFC 3261: In-Reply-To Header", HFILL }
3864 { &hf_header_array[POS_JOIN],
3865 { "Join", "sip.Join",
3866 FT_STRING, BASE_NONE,NULL,0x0,
3867 "Draft: Join Header", HFILL }
3869 { &hf_header_array[POS_MAX_BREADTH],
3870 { "Max-Breadth", "sip.Max-Breadth",
3871 FT_UINT32, BASE_DEC,NULL,0x0,
3872 "RFC 5393: Max-Breadth Header", HFILL }
3874 { &hf_header_array[POS_MAX_FORWARDS],
3875 { "Max-Forwards", "sip.Max-Forwards",
3876 FT_UINT32, BASE_DEC,NULL,0x0,
3877 "RFC 3261: Max-Forwards Header", HFILL }
3879 { &hf_header_array[POS_MIME_VERSION],
3880 { "MIME-Version", "sip.MIME-Version",
3881 FT_STRING, BASE_NONE,NULL,0x0,
3882 "RFC 3261: MIME-Version Header", HFILL }
3884 { &hf_header_array[POS_MIN_EXPIRES],
3885 { "Min-Expires", "sip.Min-Expires",
3886 FT_STRING, BASE_NONE,NULL,0x0,
3887 "RFC 3261: Min-Expires Header", HFILL }
3889 { &hf_header_array[POS_MIN_SE],
3890 { "Min-SE", "sip.Min-SE",
3891 FT_STRING, BASE_NONE,NULL,0x0,
3892 "Draft: Min-SE Header", HFILL }
3894 { &hf_header_array[POS_ORGANIZATION],
3895 { "Organization", "sip.Organization",
3896 FT_STRING, BASE_NONE,NULL,0x0,
3897 "RFC 3261: Organization Header", HFILL }
3899 { &hf_header_array[POS_P_ACCESS_NETWORK_INFO],
3900 { "P-Access-Network-Info", "sip.P-Access-Network-Info",
3901 FT_STRING, BASE_NONE,NULL,0x0,
3902 "P-Access-Network-Info Header", HFILL }
3904 { &hf_header_array[POS_P_ANSWER_STATE],
3905 { "P-Answer-State", "sip.P-Answer-State",
3906 FT_STRING, BASE_NONE,NULL,0x0,
3907 "RFC 4964: P-Answer-State Header", HFILL }
3909 { &hf_header_array[POS_P_ASSERTED_IDENTITY],
3910 { "P-Asserted-Identity", "sip.P-Asserted-Identity",
3911 FT_STRING, BASE_NONE,NULL,0x0,
3912 "RFC 3325: P-Asserted-Identity Header", HFILL }
3914 { &hf_header_array[POS_P_ASSOCIATED_URI],
3915 { "P-Associated-URI", "sip.P-Associated-URI",
3916 FT_STRING, BASE_NONE,NULL,0x0,
3917 "RFC 3455: P-Associated-URI Header", HFILL }
3920 { &hf_header_array[POS_P_CALLED_PARTY_ID],
3921 { "P-Called-Party-ID", "sip.P-Called-Party-ID",
3922 FT_STRING, BASE_NONE,NULL,0x0,
3923 "RFC 3455: P-Called-Party-ID Header", HFILL }
3926 { &hf_header_array[POS_P_CHARGING_FUNCTION_ADDRESSES],
3927 { "P-Charging-Function-Addresses","sip.P-Charging-Function-Addresses",
3928 FT_STRING, BASE_NONE,NULL,0x0,
3932 { &hf_header_array[POS_P_CHARGING_VECTOR],
3933 { "P-Charging-Vector", "sip.P-Charging-Vector",
3934 FT_STRING, BASE_NONE,NULL,0x0,
3935 "P-Charging-Vector Header", HFILL }
3938 { &hf_header_array[POS_P_DCS_TRACE_PARTY_ID],
3939 { "P-DCS-Trace-Party-ID", "sip.P-DCS-Trace-Party-ID",
3940 FT_STRING, BASE_NONE,NULL,0x0,
3941 "P-DCS-Trace-Party-ID Header", HFILL }
3944 { &hf_header_array[POS_P_DCS_OSPS],
3945 { "P-DCS-OSPS", "sip.P-DCS-OSPS",
3946 FT_STRING, BASE_NONE,NULL,0x0,
3947 "P-DCS-OSPS Header", HFILL }
3950 { &hf_header_array[POS_P_DCS_BILLING_INFO],
3951 { "P-DCS-Billing-Info", "sip.P-DCS-Billing-Info",
3952 FT_STRING, BASE_NONE,NULL,0x0,
3953 "P-DCS-Billing-Info Header", HFILL }
3956 { &hf_header_array[POS_P_DCS_LAES],
3957 { "P-DCS-LAES", "sip.P-DCS-LAES",
3958 FT_STRING, BASE_NONE,NULL,0x0,
3959 "P-DCS-LAES Header", HFILL }
3962 { &hf_header_array[POS_P_DCS_REDIRECT],
3963 { "P-DCS-Redirect", "sip.P-DCS-Redirect",
3964 FT_STRING, BASE_NONE,NULL,0x0,
3965 "P-DCS-Redirect Header", HFILL }
3968 { &hf_header_array[POS_P_EARLY_MEDIA],
3969 { "P-Early-Media", "sip.P-Early-Media",
3970 FT_STRING, BASE_NONE,NULL,0x0,
3971 "P-Early-Media Header", HFILL }
3974 { &hf_header_array[POS_P_MEDIA_AUTHORIZATION],
3975 { "P-Media-Authorization", "sip.P-Media-Authorization",
3976 FT_STRING, BASE_NONE,NULL,0x0,
3977 "RFC 3313: P-Media-Authorization Header", HFILL }
3980 { &hf_header_array[POS_P_PREFERRED_IDENTITY],
3981 { "P-Preferred-Identity", "sip.P-Preferred-Identity",
3982 FT_STRING, BASE_NONE,NULL,0x0,
3983 "RFC 3325: P-Preferred-Identity Header", HFILL }
3986 { &hf_header_array[POS_P_PROFILE_KEY],
3987 { "P-Profile-Key", "sip.P-Profile-Key",
3988 FT_STRING, BASE_NONE,NULL,0x0,
3989 "P-Profile-Key Header", HFILL }
3991 { &hf_header_array[POS_P_REFUSED_URI_LST],
3992 { "P-Refused-URI-List", "sip.P-Refused-URI-List",
3993 FT_STRING, BASE_NONE,NULL,0x0,
3994 "P-Refused-URI-List Header", HFILL }
3996 { &hf_header_array[POS_P_SERVED_USER],
3997 { "P-Served-User", "sip.P-Served-User",
3998 FT_STRING, BASE_NONE,NULL,0x0,
3999 "P-Served-User", HFILL }
4001 { &hf_header_array[POS_P_USER_DATABASE],
4002 { "P-User-Database", "sip.P-User-Database",
4003 FT_STRING, BASE_NONE,NULL,0x0,
4004 "P-User-Database Header", HFILL }
4007 { &hf_header_array[POS_P_VISITED_NETWORK_ID],
4008 { "P-Visited-Network-ID", "sip.P-Visited-Network-ID",
4009 FT_STRING, BASE_NONE,NULL,0x0,
4010 "RFC 3455: P-Visited-Network-ID Header", HFILL }
4013 { &hf_header_array[POS_PATH],
4014 { "Path", "sip.Path",
4015 FT_STRING, BASE_NONE,NULL,0x0,
4016 "RFC 3327: Path Header", HFILL }
4019 { &hf_header_array[POS_PERMISSION_MISSING],
4020 { "Permission-Missing", "sip.Permission-Missing",
4021 FT_STRING, BASE_NONE,NULL,0x0,
4022 "RFC 5360: Permission Missing Header", HFILL }
4025 { &hf_header_array[POS_PRIORITY],
4026 { "Priority", "sip.Priority",
4027 FT_STRING, BASE_NONE,NULL,0x0,
4028 "RFC 3261: Priority Header", HFILL }
4030 { &hf_header_array[POS_PRIV_ANSWER_MODE],
4031 { "Priv-Answer-mode", "sip.Priv-Answer-mode",
4032 FT_STRING, BASE_NONE,NULL,0x0,
4035 { &hf_header_array[POS_PRIVACY],
4036 { "Privacy", "sip.Privacy",
4037 FT_STRING, BASE_NONE,NULL,0x0,
4038 "Privacy Header", HFILL }
4041 { &hf_header_array[POS_PROXY_AUTHENTICATE],
4042 { "Proxy-Authenticate", "sip.Proxy-Authenticate",
4043 FT_STRING, BASE_NONE,NULL,0x0,
4044 "RFC 3261: Proxy-Authenticate Header", HFILL }
4046 { &hf_header_array[POS_PROXY_AUTHORIZATION],
4047 { "Proxy-Authorization", "sip.Proxy-Authorization",
4048 FT_STRING, BASE_NONE,NULL,0x0,
4049 "RFC 3261: Proxy-Authorization Header", HFILL }
4052 { &hf_header_array[POS_PROXY_REQUIRE],
4053 { "Proxy-Require", "sip.Proxy-Require",
4054 FT_STRING, BASE_NONE,NULL,0x0,
4055 "RFC 3261: Proxy-Require Header", HFILL }
4057 { &hf_header_array[POS_RACK],
4058 { "RAck", "sip.RAck",
4059 FT_STRING, BASE_NONE,NULL,0x0,
4060 "RFC 3262: RAck Header", HFILL }
4062 { &hf_header_array[POS_REASON],
4063 { "Reason", "sip.Reason",
4064 FT_STRING, BASE_NONE,NULL,0x0,
4065 "RFC 3326 Reason Header", HFILL }
4067 { &hf_header_array[POS_RECORD_ROUTE],
4068 { "Record-Route", "sip.Record-Route",
4069 FT_STRING, BASE_NONE,NULL,0x0,
4070 "RFC 3261: Record-Route Header", HFILL }
4072 { &hf_header_array[POS_REFER_SUB],
4073 { "Refer-Sub", "sip.Refer-Sub",
4074 FT_STRING, BASE_NONE,NULL,0x0,
4075 "RFC 4488: Refer-Sub Header", HFILL }
4077 { &hf_header_array[POS_REFERED_BY],
4078 { "Refered By", "sip.Refered-by",
4079 FT_STRING, BASE_NONE,NULL,0x0,
4080 "RFC 3892: Refered-by Header", HFILL }
4082 { &hf_header_array[POS_REJECT_CONTACT],
4083 { "Reject-Contact", "sip.Reject-Contact",
4084 FT_STRING, BASE_NONE,NULL,0x0,
4085 "RFC 3841: Reject-Contact Header", HFILL }
4087 { &hf_header_array[POS_REPLACES],
4088 { "Replaces", "sip.Replaces",
4089 FT_STRING, BASE_NONE,NULL,0x0,
4090 "RFC 3891: Replaces Header", HFILL }
4092 { &hf_header_array[POS_REPLY_TO],
4093 { "Reply-To", "sip.Reply-To",
4094 FT_STRING, BASE_NONE,NULL,0x0,
4095 "RFC 3261: Reply-To Header", HFILL }
4097 { &hf_header_array[POS_REQUEST_DISPOSITION],
4098 { "Request-Disposition", "sip.Request-Disposition",
4099 FT_STRING, BASE_NONE,NULL,0x0,
4100 "RFC 3841: Request-Disposition Header", HFILL }
4102 { &hf_header_array[POS_REQUIRE],
4103 { "Require", "sip.Require",
4104 FT_STRING, BASE_NONE,NULL,0x0,
4105 "RFC 3261: Require Header", HFILL }
4107 { &hf_header_array[POS_RESOURCE_PRIORITY],
4108 { "Resource-Priority", "sip.Resource-Priority",
4109 FT_STRING, BASE_NONE,NULL,0x0,
4110 "Draft: Resource-Priority Header", HFILL }
4112 { &hf_header_array[POS_RETRY_AFTER],
4113 { "Retry-After", "sip.Retry-After",
4114 FT_STRING, BASE_NONE,NULL,0x0,
4115 "RFC 3261: Retry-After Header", HFILL }
4117 { &hf_header_array[POS_ROUTE],
4118 { "Route", "sip.Route",
4119 FT_STRING, BASE_NONE,NULL,0x0,
4120 "RFC 3261: Route Header", HFILL }
4122 { &hf_header_array[POS_RSEQ],
4123 { "RSeq", "sip.RSeq",
4124 FT_UINT32, BASE_DEC,NULL,0x0,
4125 "RFC 3262: RSeq Header", HFILL }
4127 { &hf_header_array[ POS_SECURITY_CLIENT],
4128 { "Security-Client", "sip.Security-Client",
4129 FT_STRING, BASE_NONE,NULL,0x0,
4130 "RFC 3329 Security-Client Header", HFILL }
4132 { &hf_header_array[ POS_SECURITY_SERVER],
4133 { "Security-Server", "sip.Security-Server",
4134 FT_STRING, BASE_NONE,NULL,0x0,
4135 "RFC 3329 Security-Server Header", HFILL }
4137 { &hf_header_array[ POS_SECURITY_VERIFY],
4138 { "Security-Verify", "sip.Security-Verify",
4139 FT_STRING, BASE_NONE,NULL,0x0,
4140 "RFC 3329 Security-Verify Header", HFILL }
4142 { &hf_header_array[POS_SERVER],
4143 { "Server", "sip.Server",
4144 FT_STRING, BASE_NONE,NULL,0x0,
4145 "RFC 3261: Server Header", HFILL }
4147 { &hf_header_array[POS_SERVICE_ROUTE],
4148 { "Service-Route", "sip.Service-Route",
4149 FT_STRING, BASE_NONE,NULL,0x0,
4150 "RFC 3608: Service-Route Header", HFILL }
4152 { &hf_header_array[POS_SESSION_EXPIRES],
4153 { "Session-Expires", "sip.Session-Expires",
4154 FT_STRING, BASE_NONE,NULL,0x0,
4155 "RFC 4028: Session-Expires Header", HFILL }
4157 { &hf_header_array[POS_SIP_ETAG],
4158 { "ETag", "sip.ETag",
4159 FT_STRING, BASE_NONE,NULL,0x0,
4160 "RFC 3903: SIP-ETag Header", HFILL }
4162 { &hf_header_array[POS_SIP_IF_MATCH],
4163 { "If_Match", "sip.If_Match",
4164 FT_STRING, BASE_NONE,NULL,0x0,
4165 "RFC 3903: SIP-If-Match Header", HFILL }
4167 { &hf_header_array[POS_SUBJECT],
4168 { "Subject", "sip.Subject",
4169 FT_STRING, BASE_NONE,NULL,0x0,
4170 "RFC 3261: Subject Header", HFILL }
4172 { &hf_header_array[POS_SUBSCRIPTION_STATE],
4173 { "Subscription-State", "sip.Subscription-State",
4174 FT_STRING, BASE_NONE,NULL,0x0,
4175 "RFC 3265: Subscription-State Header", HFILL }
4177 { &hf_header_array[POS_SUPPORTED],
4178 { "Supported", "sip.Supported",
4179 FT_STRING, BASE_NONE,NULL,0x0,
4180 "RFC 3261: Supported Header", HFILL }
4182 { &hf_header_array[POS_TARGET_DALOG],
4183 { "Target-Dialog", "sip.Target-Dialog",
4184 FT_STRING, BASE_NONE,NULL,0x0,
4185 "RFC 4538: Target-Dialog Header", HFILL }
4187 { &hf_header_array[POS_TIMESTAMP],
4188 { "Timestamp", "sip.Timestamp",
4189 FT_STRING, BASE_NONE,NULL,0x0,
4190 "RFC 3261: Timestamp Header", HFILL }
4192 { &hf_header_array[POS_TO],
4194 FT_STRING, BASE_NONE,NULL,0x0,
4195 "RFC 3261: To Header", HFILL }
4198 { &hf_header_array[POS_TRIGGER_CONSENT],
4199 { "Trigger-Consent", "sip.Trigger-Consent",
4200 FT_STRING, BASE_NONE,NULL,0x0,
4201 "RFC 5380: Trigger Consent", HFILL }
4204 { &hf_header_array[POS_UNSUPPORTED],
4205 { "Unsupported", "sip.Unsupported",
4206 FT_STRING, BASE_NONE,NULL,0x0,
4207 "RFC 3261: Unsupported Header", HFILL }
4209 { &hf_header_array[POS_USER_AGENT],
4210 { "User-Agent", "sip.User-Agent",
4211 FT_STRING, BASE_NONE,NULL,0x0,
4212 "RFC 3261: User-Agent Header", HFILL }
4214 { &hf_header_array[POS_VIA],
4216 FT_STRING, BASE_NONE,NULL,0x0,
4217 "RFC 3261: Via Header", HFILL }
4219 { &hf_header_array[POS_WARNING],
4220 { "Warning", "sip.Warning",
4221 FT_STRING, BASE_NONE,NULL,0x0,
4222 "RFC 3261: Warning Header", HFILL }
4225 { &hf_header_array[POS_WWW_AUTHENTICATE],
4226 { "WWW-Authenticate", "sip.WWW-Authenticate",
4227 FT_STRING, BASE_NONE,NULL,0x0,
4228 "RFC 3261: WWW-Authenticate Header", HFILL }
4230 { &hf_header_array[POS_REFER_TO],
4231 { "Refer-To", "sip.Refer-To",
4232 FT_STRING, BASE_NONE,NULL,0x0,
4233 "RFC 3515: Refer-To Header", HFILL }
4235 { &hf_header_array[POS_HISTORY_INFO],
4236 { "History-Info", "sip.History-Info",
4237 FT_STRING, BASE_NONE,NULL,0x0,
4238 "RFC 4244: Request History Information", HFILL }
4240 { &hf_header_array[POS_IDENTITY],
4241 { "Identity", "sip.Identity",
4242 FT_STRING, BASE_NONE,NULL,0x0,
4243 "RFC 4474: Request Identity", HFILL }
4245 { &hf_header_array[POS_IDENTITY_INFO],
4246 { "Identity-info", "sip.Identity-info",
4247 FT_STRING, BASE_NONE,NULL,0x0,
4248 "RFC 4474: Request Identity-info", HFILL }
4252 { "Resent Packet", "sip.resend",
4253 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4256 { &hf_sip_original_frame,
4257 { "Suspected resend of frame", "sip.resend-original",
4258 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4259 "Original transmission of frame", HFILL}
4261 { &hf_sip_matching_request_frame,
4262 { "Request Frame", "sip.response-request",
4263 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4266 { &hf_sip_response_time,
4267 { "Response Time (ms)", "sip.response-time",
4268 FT_UINT32, BASE_DEC, NULL, 0x0,
4269 "Response time since original request (in milliseconds)", HFILL}
4271 { &hf_sip_release_time,
4272 { "Release Time (ms)", "sip.release-time",
4273 FT_UINT32, BASE_DEC, NULL, 0x0,
4274 "release time since original BYE (in milliseconds)", HFILL}
4277 { "Authentication", "sip.auth",
4278 FT_STRING, BASE_NONE, NULL, 0x0,
4279 "SIP Authentication", HFILL}
4281 { &hf_sip_auth_scheme,
4282 { "Authentication Scheme", "sip.auth.scheme",
4283 FT_STRING, BASE_NONE, NULL, 0x0,
4284 "SIP Authentication Scheme", HFILL}
4286 { &hf_sip_auth_digest_response,
4287 { "Digest Authentication Response", "sip.auth.digest.response",
4288 FT_STRING, BASE_NONE, NULL, 0x0,
4289 "SIP Digest Authentication Response Value", HFILL}
4292 { "Nonce Count", "sip.auth.nc",
4293 FT_STRING, BASE_NONE, NULL, 0x0,
4294 "SIP Authentication Nonce count", HFILL}
4296 { &hf_sip_auth_username,
4297 { "Username", "sip.auth.username",
4298 FT_STRING, BASE_NONE, NULL, 0x0,
4299 "SIP Authentication Username", HFILL}
4301 { &hf_sip_auth_realm,
4302 { "Realm", "sip.auth.realm",
4303 FT_STRING, BASE_NONE, NULL, 0x0,
4304 "SIP Authentication Realm", HFILL}
4306 { &hf_sip_auth_nonce,
4307 { "Nonce Value", "sip.auth.nonce",
4308 FT_STRING, BASE_NONE, NULL, 0x0,
4309 "SIP Authentication Nonce", HFILL}
4311 { &hf_sip_auth_algorithm,
4312 { "Algorithm", "sip.auth.algorithm",
4313 FT_STRING, BASE_NONE, NULL, 0x0,
4314 "SIP Authentication Algorithm", HFILL}
4316 { &hf_sip_auth_opaque,
4317 { "Opaque Value", "sip.auth.opaque",
4318 FT_STRING, BASE_NONE, NULL, 0x0,
4319 "SIP Authentication Opaque value", HFILL}
4322 { "QOP", "sip.auth.qop",
4323 FT_STRING, BASE_NONE, NULL, 0x0,
4324 "SIP Authentication QOP", HFILL}
4326 { &hf_sip_auth_cnonce,
4327 { "CNonce Value", "sip.auth.cnonce",
4328 FT_STRING, BASE_NONE, NULL, 0x0,
4329 "SIP Authentication Client Nonce", HFILL}
4332 { "Authentication URI", "sip.auth.uri",
4333 FT_STRING, BASE_NONE, NULL, 0x0,
4334 "SIP Authentication URI", HFILL}
4336 { &hf_sip_auth_domain,
4337 { "Authentication Domain", "sip.auth.domain",
4338 FT_STRING, BASE_NONE, NULL, 0x0,
4339 "SIP Authentication Domain", HFILL}
4341 { &hf_sip_auth_stale,
4342 { "Stale Flag", "sip.auth.stale",
4343 FT_STRING, BASE_NONE, NULL, 0x0,
4344 "SIP Authentication Stale Flag", HFILL}
4346 { &hf_sip_auth_auts,
4347 { "Authentication Token", "sip.auth.auts",
4348 FT_STRING, BASE_NONE, NULL, 0x0,
4349 "SIP Authentication Token", HFILL}
4351 { &hf_sip_auth_rspauth,
4352 { "Response auth", "sip.auth.rspauth",
4353 FT_STRING, BASE_NONE, NULL, 0x0,
4354 "SIP Authentication Response auth", HFILL}
4356 { &hf_sip_auth_nextnonce,
4357 { "Next Nonce", "sip.auth.nextnonce",
4358 FT_STRING, BASE_NONE, NULL, 0x0,
4359 "SIP Authentication Next Nonce", HFILL}
4362 { "Integrity Key", "sip.auth.ik",
4363 FT_STRING, BASE_NONE, NULL, 0x0,
4364 "SIP Authentication Integrity Key", HFILL}
4367 { "Cyphering Key", "sip.auth.ck",
4368 FT_STRING, BASE_NONE, NULL, 0x0,
4369 "SIP Authentication Cyphering Key", HFILL}
4371 { &hf_sip_cseq_seq_no,
4372 { "Sequence Number", "sip.CSeq.seq",
4373 FT_UINT32, BASE_DEC, NULL, 0x0,
4374 "CSeq header sequence number", HFILL}
4376 { &hf_sip_cseq_method,
4377 { "Method", "sip.CSeq.method",
4378 FT_STRING, BASE_NONE, NULL, 0x0,
4379 "CSeq header method", HFILL}
4381 { &hf_sip_via_transport,
4382 { "Transport", "sip.Via.transport",
4383 FT_STRING, BASE_NONE, NULL, 0x0,
4384 "Via header Transport", HFILL}
4386 { &hf_sip_via_sent_by_address,
4387 { "Sent-by Address", "sip.Via.sent-by.address",
4388 FT_STRING, BASE_NONE, NULL, 0x0,
4389 "Via header Sent-by Address", HFILL}
4391 { &hf_sip_via_sent_by_port,
4392 { "Sent-by port", "sip.Via.sent-by.port",
4393 FT_UINT16, BASE_DEC, NULL, 0x0,
4394 "Via header Sent-by Port", HFILL}
4396 { &hf_sip_via_branch,
4397 { "Branch", "sip.Via.branch",
4398 FT_STRING, BASE_NONE, NULL, 0x0,
4399 "SIP Via Branch", HFILL},
4401 { &hf_sip_via_maddr,
4402 { "Maddr", "sip.Via.maddr",
4403 FT_STRING, BASE_NONE, NULL, 0x0,
4404 "SIP Via Maddr", HFILL},
4406 { &hf_sip_via_rport,
4407 { "RPort", "sip.Via.rport",
4408 FT_STRING, BASE_NONE, NULL, 0x0,
4409 "SIP Via RPort", HFILL},
4411 { &hf_sip_via_received,
4412 { "Received", "sip.Via.received",
4413 FT_STRING, BASE_NONE, NULL, 0x0,
4414 "SIP Via Received", HFILL},
4417 { "TTL", "sip.Via.ttl",
4418 FT_STRING, BASE_NONE, NULL, 0x0,
4419 "SIP Via TTL", HFILL}
4422 { "Comp", "sip.Via.comp",
4423 FT_STRING, BASE_NONE, NULL, 0x0,
4424 "SIP Via comp", HFILL}
4426 { &hf_sip_via_sigcomp_id,
4427 { "Sigcomp identifier", "sip.Via.sigcomp-id",
4428 FT_STRING, BASE_NONE, NULL, 0x0,
4429 "SIP Via sigcomp identifier", HFILL}
4431 { &hf_sip_rack_rseq_no,
4432 { "RSeq Sequence Number", "sip.RAck.RSeq.seq",
4433 FT_UINT32, BASE_DEC, NULL, 0x0,
4434 "RAck RSeq header sequence number (from prov response)", HFILL}
4436 { &hf_sip_rack_cseq_no,
4437 { "CSeq Sequence Number", "sip.RAck.CSeq.seq",
4438 FT_UINT32, BASE_DEC, NULL, 0x0,
4439 "RAck CSeq header sequence number (from prov response)", HFILL}
4441 { &hf_sip_rack_cseq_method,
4442 { "CSeq Method", "sip.RAck.CSeq.method",
4443 FT_STRING, BASE_NONE, NULL, 0x0,
4444 "RAck CSeq header method (from prov response)", HFILL}
4447 { "Message Body", "sip.msg_body",
4448 FT_NONE, BASE_NONE, NULL, 0x0,
4449 "Message Body in SIP message", HFILL }
4452 /* raw_sip header field(s) */
4453 static hf_register_info raw_hf[] = {
4456 { "Raw SIP Line", "raw_sip.line",
4457 FT_STRING, BASE_NONE,NULL,0x0,
4461 /* Setup protocol subtree array */
4462 static gint *ett[] = {
4469 &ett_sip_contact_item,
4470 &ett_sip_message_body,
4484 static gint *ett_raw[] = {
4488 module_t *sip_module;
4490 /* Register the protocol name and description */
4491 proto_sip = proto_register_protocol("Session Initiation Protocol",
4493 proto_raw_sip = proto_register_protocol("Session Initiation Protocol (SIP as raw text)",
4494 "Raw_SIP", "raw_sip");
4495 new_register_dissector("sip", dissect_sip, proto_sip);
4496 register_dissector("sip.tcp", dissect_sip_tcp, proto_sip);
4498 /* Required function calls to register the header fields and subtrees used */
4499 proto_register_field_array(proto_sip, hf, array_length(hf));
4500 proto_register_subtree_array(ett, array_length(ett));
4501 proto_register_subtree_array(ett_raw, array_length(ett_raw));
4503 /* Register raw_sip field(s) */
4504 proto_register_field_array(proto_raw_sip, raw_hf, array_length(raw_hf));
4506 sip_module = prefs_register_protocol(proto_sip, proto_reg_handoff_sip);
4508 prefs_register_uint_preference(sip_module, "tcp.port",
4510 "SIP Server TCP Port",
4512 prefs_register_uint_preference(sip_module, "tls.port",
4514 "SIP Server TLS Port",
4517 prefs_register_bool_preference(sip_module, "display_raw_text",
4518 "Display raw text for SIP message",
4519 "Specifies that the raw text of the "
4520 "SIP message should be displayed "
4521 "in addition to the dissection tree",
4522 &global_sip_raw_text);
4523 prefs_register_bool_preference(sip_module, "strict_sip_version",
4524 "Enforce strict SIP version check (" SIP2_HDR ")",
4525 "If enabled, only " SIP2_HDR " traffic will be dissected as SIP. "
4526 "Disable it to allow SIP traffic with a different version "
4527 "to be dissected as SIP.",
4528 &strict_sip_version);
4529 prefs_register_bool_preference(sip_module, "desegment_headers",
4530 "Reassemble SIP headers spanning multiple TCP segments",
4531 "Whether the SIP dissector should reassemble headers "
4532 "of a request spanning multiple TCP segments. "
4533 "To use this option, you must also enable "
4534 "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
4535 &sip_desegment_headers);
4536 prefs_register_bool_preference(sip_module, "desegment_body",
4537 "Reassemble SIP bodies spanning multiple TCP segments",
4538 "Whether the SIP dissector should use the "
4539 "\"Content-length:\" value, if present, to reassemble "
4540 "the body of a request spanning multiple TCP segments, "
4541 "and reassemble chunked data spanning multiple TCP segments. "
4542 "To use this option, you must also enable "
4543 "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
4544 &sip_desegment_body);
4545 prefs_register_bool_preference(sip_module, "retrans_the_same_sport",
4546 "Retransmissions always use the same source port",
4547 "Whether retransmissions are detected coming from the same source port only.",
4548 &sip_retrans_the_same_sport);
4550 register_init_routine(&sip_init_protocol);
4551 register_heur_dissector_list("sip", &heur_subdissector_list);
4552 /* Register for tapping */
4553 sip_tap = register_tap("sip");
4555 ext_hdr_subdissector_table = register_dissector_table("sip.hdr", "SIP Extension header", FT_STRING, BASE_NONE);
4560 proto_reg_handoff_sip(void)
4562 static dissector_handle_t sip_tcp_handle;
4563 static guint saved_sip_tcp_port;
4564 static guint saved_sip_tls_port;
4565 static gboolean sip_prefs_initialized = FALSE;
4567 if (!sip_prefs_initialized) {
4568 dissector_handle_t sip_handle;
4569 sip_handle = find_dissector("sip");
4570 sip_tcp_handle = find_dissector("sip.tcp");
4571 sigcomp_handle = find_dissector("sigcomp");
4572 /* SIP content type and internet media type used by other dissectors are the same */
4573 media_type_dissector_table = find_dissector_table("media_type");
4575 dissector_add("udp.port", UDP_PORT_SIP, sip_handle);
4576 dissector_add_string("media_type", "message/sip", sip_handle);
4578 heur_dissector_add("udp", dissect_sip_heur, proto_sip);
4579 heur_dissector_add("tcp", dissect_sip_tcp_heur, proto_sip);
4580 heur_dissector_add("sctp", dissect_sip_heur, proto_sip);
4581 heur_dissector_add("stun", dissect_sip_heur, proto_sip);
4582 sip_prefs_initialized = TRUE;
4584 dissector_delete("tcp.port", saved_sip_tcp_port, sip_tcp_handle);
4585 ssl_dissector_delete(saved_sip_tls_port, "sip.tcp", TRUE);
4587 /* Set our port number for future use */
4588 saved_sip_tcp_port = sip_tcp_port;
4589 saved_sip_tls_port = sip_tls_port;
4590 dissector_add("tcp.port", saved_sip_tcp_port, sip_tcp_handle);
4591 ssl_dissector_add(saved_sip_tls_port, "sip.tcp", TRUE);