2 * Routines for the Session Initiation Protocol (SIP) dissection.
6 * hf_ display filters for headers of SIP extension RFCs (ongoing)
7 * Use hash table for list of headers
8 * Align SIP methods with recent Internet Drafts or RFCs
10 * Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi>
11 * Copyright 2001, Jean-Francois Mule <jfm@cablelabs.com>
12 * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
16 * Wireshark - Network traffic analyzer
17 * By Gerald Combs <gerald@wireshark.org>
18 * Copyright 1998 Gerald Combs
20 * Copied from packet-cops.c
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * as published by the Free Software Foundation; either version 2
25 * of the License, or (at your option) any later version.
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
46 #include <epan/prefs.h>
50 #include <wsutil/str_util.h>
52 #include <epan/packet.h>
53 #include <epan/req_resp_hdrs.h>
54 #include <epan/emem.h>
55 #include <epan/strutil.h>
57 #include <wsutil/str_util.h>
59 #include "packet-isup.h"
60 #include "packet-sip.h"
62 #include <epan/expert.h>
64 #include "packet-tcp.h"
65 #include "packet-ssl.h"
67 #define TCP_PORT_SIP 5060
68 #define UDP_PORT_SIP 5060
69 #define TLS_PORT_SIP 5061
71 static gint sip_tap = -1;
72 static dissector_handle_t sigcomp_handle;
74 /* Initialize the protocol and registered fields */
75 static gint proto_sip = -1;
76 static gint proto_raw_sip = -1;
77 static gint hf_raw_sip_line = -1;
78 static gint hf_msg_hdr = -1;
79 static gint hf_Method = -1;
80 static gint hf_Request_Line = -1;
81 static gint hf_sip_ruri = -1;
82 static gint hf_sip_ruri_user = -1;
83 static gint hf_sip_ruri_host = -1;
84 static gint hf_sip_ruri_port = -1;
85 static gint hf_Status_Code = -1;
86 static gint hf_Status_Line = -1;
87 static gint hf_sip_display = -1;
88 static gint hf_sip_to_addr = -1;
89 static gint hf_sip_to_user = -1;
90 static gint hf_sip_to_host = -1;
91 static gint hf_sip_to_port = -1;
92 static gint hf_sip_from_addr = -1;
93 static gint hf_sip_from_user = -1;
94 static gint hf_sip_from_host = -1;
95 static gint hf_sip_from_port = -1;
96 static gint hf_sip_tag = -1;
97 static gint hf_sip_pai_addr = -1;
98 static gint hf_sip_pai_user = -1;
99 static gint hf_sip_pai_host = -1;
100 static gint hf_sip_pai_port = -1;
101 static gint hf_sip_pmiss_addr = -1;
102 static gint hf_sip_pmiss_user = -1;
103 static gint hf_sip_pmiss_host = -1;
104 static gint hf_sip_pmiss_port = -1;
105 static gint hf_sip_ppi_addr = -1;
106 static gint hf_sip_ppi_user = -1;
107 static gint hf_sip_ppi_host = -1;
108 static gint hf_sip_ppi_port = -1;
109 static gint hf_sip_tc_addr = -1;
110 static gint hf_sip_tc_user = -1;
111 static gint hf_sip_tc_host = -1;
112 static gint hf_sip_tc_port = -1;
113 static gint hf_sip_tc_turi = -1;
114 static gint hf_sip_uri = -1;
115 static gint hf_sip_contact_addr = -1;
116 static gint hf_sip_contact_item = -1;
117 static gint hf_sip_resend = -1;
118 static gint hf_sip_original_frame = -1;
119 static gint hf_sip_matching_request_frame = -1;
120 static gint hf_sip_response_time = -1;
121 static gint hf_sip_release_time = -1;
123 static gint hf_sip_auth = -1;
124 static gint hf_sip_auth_scheme = -1;
125 static gint hf_sip_auth_digest_response = -1;
126 static gint hf_sip_auth_nc = -1;
127 static gint hf_sip_auth_username = -1;
128 static gint hf_sip_auth_realm = -1;
129 static gint hf_sip_auth_nonce = -1;
130 static gint hf_sip_auth_algorithm = -1;
131 static gint hf_sip_auth_opaque = -1;
132 static gint hf_sip_auth_qop = -1;
133 static gint hf_sip_auth_cnonce = -1;
134 static gint hf_sip_auth_uri = -1;
135 static gint hf_sip_auth_domain = -1;
136 static gint hf_sip_auth_stale = -1;
137 static gint hf_sip_auth_auts = -1;
138 static gint hf_sip_auth_rspauth = -1;
139 static gint hf_sip_auth_nextnonce = -1;
140 static gint hf_sip_auth_ik = -1;
141 static gint hf_sip_auth_ck = -1;
143 static gint hf_sip_cseq_seq_no = -1;
144 static gint hf_sip_cseq_method = -1;
146 static gint hf_sip_via_transport = -1;
147 static gint hf_sip_via_sent_by_address = -1;
148 static gint hf_sip_via_sent_by_port = -1;
149 static gint hf_sip_via_branch = -1;
150 static gint hf_sip_via_maddr = -1;
151 static gint hf_sip_via_rport = -1;
152 static gint hf_sip_via_received = -1;
153 static gint hf_sip_via_ttl = -1;
154 static gint hf_sip_via_comp = -1;
155 static gint hf_sip_via_sigcomp_id = -1;
157 static gint hf_sip_rack_rseq_no = -1;
158 static gint hf_sip_rack_cseq_no = -1;
159 static gint hf_sip_rack_cseq_method = -1;
161 static gint hf_sip_msg_body = -1;
163 /* Initialize the subtree pointers */
164 static gint ett_sip = -1;
165 static gint ett_sip_reqresp = -1;
166 static gint ett_sip_hdr = -1;
167 static gint ett_sip_ext_hdr = -1;
168 static gint ett_raw_text = -1;
169 static gint ett_sip_element = -1;
170 static gint ett_sip_uri = -1;
171 static gint ett_sip_contact_item = -1;
172 static gint ett_sip_message_body = -1;
173 static gint ett_sip_cseq = -1;
174 static gint ett_sip_via = -1;
175 static gint ett_sip_reason = -1;
176 static gint ett_sip_rack = -1;
177 static gint ett_sip_ruri = -1;
178 static gint ett_sip_to_uri = -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 "<Invalid method>", /* Pad so that the real methods start at index 1 */
208 * Updated with info from http://www.iana.org/assignments/sip-parameters
209 * (last updated 2007-12-10)
210 * Updated with: http://www.ietf.org/internet-drafts/draft-ietf-sip-resource-priority-05.txt
214 const char *compact_name;
216 static const sip_header_t sip_headers[] = {
217 { "Unknown-header", NULL }, /* 0 Pad so that the real headers start at index 1 */
218 { "Accept", NULL }, /* 1 */
219 { "Accept-Contact", "a" }, /* 2 RFC3841 */
220 { "Accept-Encoding", NULL }, /* 3 */
221 { "Accept-Language", NULL }, /* 4 */
222 { "Accept-Resource-Priority", NULL }, /* 5 RFC4412 */
223 { "Alert-Info", NULL },
225 { "Allow-Events", "u" }, /* 8 RFC3265 */
226 { "Answer-Mode", NULL }, /* 9 RFC5373 */
227 { "Authentication-Info", NULL },
228 { "Authorization", NULL }, /* 11 */
230 { "Call-Info", NULL },
232 { "Content-Disposition", NULL },
233 { "Content-Encoding", "e" }, /* 16 */
234 { "Content-Language", NULL },
235 { "Content-Length", "l" },
236 { "Content-Type", "c" },
238 { "Date", NULL }, /* 21 */
240 Encryption (Deprecated) [RFC3261]
242 { "Error-Info", NULL },
245 { "From", "f" }, /* 25 */
247 Hide [RFC3261] (deprecated)
249 { "History-Info", NULL }, /* 26 RFC4244 */
250 { "Identity", "y" }, /* 27 RFC4474 */
251 { "Identity-Info", "n" }, /* 28 RFC4474 */
252 { "In-Reply-To", NULL }, /* 29 RFC3261 */
253 { "Join", NULL }, /* 30 RFC3911 */
254 { "Max-Breadth", NULL }, /* 31 RFC5393*/
255 { "Max-Forwards", NULL }, /* 32 */
256 { "MIME-Version", NULL }, /* 33 */
257 { "Min-Expires", NULL }, /* 34 */
258 { "Min-SE", NULL }, /* 35 RFC4028 */
259 { "Organization", NULL }, /* 36 RFC3261 */
260 { "P-Access-Network-Info", NULL }, /* 37 RFC3455 */
261 { "P-Answer-State", NULL }, /* 38 RFC4964 */
262 { "P-Asserted-Identity", NULL }, /* 39 RFC3325 */
263 { "P-Associated-URI", NULL }, /* 40 RFC3455 */
264 { "P-Called-Party-ID", NULL }, /* 41 RFC3455 */
265 { "P-Charging-Function-Addresses",NULL },/* 42 RFC3455 */
266 { "P-Charging-Vector", NULL }, /* 43 RFC3455 */
267 { "P-DCS-Trace-Party-ID", NULL }, /* 44 RFC3603 */
268 { "P-DCS-OSPS", NULL }, /* 45 RFC3603 */
269 { "P-DCS-Billing-Info", NULL }, /* 46 RFC3603 */
270 { "P-DCS-LAES", NULL }, /* 47 RFC3603 */
271 { "P-DCS-Redirect", NULL }, /* 48 RFC3603 */
272 { "P-Early-Media", NULL }, /* 49 RFC5009 */
273 { "P-Media-Authorization", NULL }, /* 50 RFC3313 */
274 { "P-Preferred-Identity", NULL }, /* 51 RFC3325 */
275 { "P-Profile-Key", NULL }, /* 52 RFC5002 */
276 { "P-User-Database", NULL }, /* 53 RFC4457 */
277 { "P-Visited-Network-ID", NULL }, /* 54 RFC3455 */
278 { "Path", NULL }, /* 55 RFC3327 */
279 { "Permission-Missing", NULL }, /* 56 RFC5360 */
280 { "Priority", NULL }, /* 57 RFC3261 */
281 { "Priv-Answer-Mode", NULL }, /* 58 RFC5373 */
282 { "Privacy", NULL }, /* 59 RFC3323 */
283 { "Proxy-Authenticate", NULL }, /* 60 */
284 { "Proxy-Authorization", NULL }, /* 61 */
285 { "Proxy-Require", NULL }, /* 62 */
286 { "RAck", NULL }, /* 63 RFC3262 */
287 { "Reason", NULL }, /* 64 RFC3326 */
288 { "Record-Route", NULL }, /* 65 */
289 { "Refer-Sub", NULL }, /* 66 RFC4488 */
290 { "Refer-To", "r" }, /* 67 RFC3515 */
291 { "Referred-By", "b" }, /* 68 RFC3892 */
292 { "Reject-Contact", "j" }, /* 69 RFC3841 */
293 { "Replaces", NULL }, /* 70 RFC3891 */
294 { "Reply-To", NULL }, /* 71 RFC3261 */
295 { "Request-Disposition", "d" }, /* 72 RFC3841 */
296 { "Require", NULL }, /* 73 RFC3261 */
297 { "Resource-Priority", NULL }, /* 74 RFC4412 */
299 { "Response-Key (Deprecated) [RFC3261]
301 { "Retry-After", NULL }, /* 75 RFC3261 */
302 { "Route", NULL }, /* 76 RFC3261 */
303 { "RSeq", NULL }, /* 77 RFC3262 */
304 { "Security-Client", NULL }, /* 78 RFC3329 */
305 { "Security-Server", NULL }, /* 79 RFC3329 */
306 { "Security-Verify", NULL }, /* 80 RFC3329 */
307 { "Server", NULL }, /* 81 RFC3261 */
308 { "Service-Route", NULL }, /* 82 RFC3608 */
309 { "Session-Expires", "x" }, /* 83 RFC4028 */
310 { "SIP-ETag", NULL }, /* 84 RFC3903 */
311 { "SIP-If-Match", NULL }, /* 85 RFC3903 */
312 { "Subject", "s" }, /* 86 RFC3261 */
313 { "Subscription-State", NULL }, /* 87 RFC3265 */
314 { "Supported", "k" }, /* 88 RFC3261 */
315 { "Target-Dialog", NULL }, /* 89 RFC4538 */
316 { "Timestamp", NULL }, /* 90 RFC3261 */
317 { "To", "t" }, /* 91 RFC3261 */
318 { "Trigger-Consent", NULL }, /* 92 RFC5360 */
319 { "Unsupported", NULL }, /* 93 RFC3261 */
320 { "User-Agent", NULL }, /* 94 RFC3261 */
321 { "Via", "v" }, /* 95 RFC3261 */
322 { "Warning", NULL }, /* 96 RFC3261 */
323 { "WWW-Authenticate", NULL }, /* 97 RFC3261 */
328 #define POS_ACCEPT_CONTACT 2
329 #define POS_ACCEPT_ENCODING 3
330 #define POS_ACCEPT_LANGUAGE 4
331 #define POS_ACCEPT_RESOURCE_PRIORITY 5
332 #define POS_ALERT_INFO 6
334 #define POS_ALLOW_EVENTS 8
335 #define POS_ANSWER_MODE 9
336 #define POS_AUTHENTICATION_INFO 10
337 #define POS_AUTHORIZATION 11
338 #define POS_CALL_ID 12
339 #define POS_CALL_INFO 13
340 #define POS_CONTACT 14
341 #define POS_CONTENT_DISPOSITION 15
342 #define POS_CONTENT_ENCODING 16
343 #define POS_CONTENT_LANGUAGE 17
344 #define POS_CONTENT_LENGTH 18
345 #define POS_CONTENT_TYPE 19
348 #define POS_ERROR_INFO 22
350 #define POS_EXPIRES 24
352 #define POS_HISTORY_INFO 26
353 #define POS_IDENTITY 27
354 #define POS_IDENTITY_INFO 28
355 #define POS_IN_REPLY_TO 29
357 #define POS_MAX_BREADTH 31
358 #define POS_MAX_FORWARDS 32
359 #define POS_MIME_VERSION 33
360 #define POS_MIN_EXPIRES 34
361 #define POS_MIN_SE 35
362 #define POS_ORGANIZATION 36
363 #define POS_P_ACCESS_NETWORK_INFO 37
364 #define POS_P_ANSWER_STATE 38
365 #define POS_P_ASSERTED_IDENTITY 39
366 #define POS_P_ASSOCIATED_URI 40
367 #define POS_P_CALLED_PARTY_ID 41
368 #define POS_P_CHARGING_FUNCTION_ADDRESSES 42
369 #define POS_P_CHARGING_VECTOR 43
370 #define POS_P_DCS_TRACE_PARTY_ID 44
371 #define POS_P_DCS_OSPS 45
372 #define POS_P_DCS_BILLING_INFO 46
373 #define POS_P_DCS_LAES 47
374 #define POS_P_DCS_REDIRECT 48
375 #define POS_P_EARLY_MEDIA 49
376 #define POS_P_MEDIA_AUTHORIZATION 50
377 #define POS_P_PREFERRED_IDENTITY 51
378 #define POS_P_PROFILE_KEY 52
379 #define POS_P_USER_DATABASE 53
380 #define POS_P_VISITED_NETWORK_ID 54
382 #define POS_PERMISSION_MISSING 56
383 #define POS_PRIORITY 57
384 #define POS_PRIV_ANSWER_MODE 58
385 #define POS_PRIVACY 59
386 #define POS_PROXY_AUTHENTICATE 60
387 #define POS_PROXY_AUTHORIZATION 61
388 #define POS_PROXY_REQUIRE 62
390 #define POS_REASON 64
391 #define POS_RECORD_ROUTE 65
392 #define POS_REFER_SUB 66
393 #define POS_REFER_TO 67
394 #define POS_REFERED_BY 68
395 #define POS_REJECT_CONTACT 69
396 #define POS_REPLACES 70
397 #define POS_REPLY_TO 71
398 #define POS_REQUEST_DISPOSITION 72
399 #define POS_REQUIRE 73
400 #define POS_RESOURCE_PRIORITY 74
401 #define POS_RETRY_AFTER 75
404 #define POS_SECURITY_CLIENT 78
405 #define POS_SECURITY_SERVER 79
406 #define POS_SECURITY_VERIFY 80
407 #define POS_SERVER 81
408 #define POS_SERVICE_ROUTE 82
409 #define POS_SESSION_EXPIRES 83
410 #define POS_SIP_ETAG 84
411 #define POS_SIP_IF_MATCH 85
412 #define POS_SUBJECT 86
413 #define POS_SUBSCRIPTION_STATE 87
414 #define POS_SUPPORTED 88
415 #define POS_TARGET_DALOG 89
416 #define POS_TIMESTAMP 90
418 #define POS_TRIGGER_CONSENT 92
419 #define POS_UNSUPPORTED 93
420 #define POS_USER_AGENT 94
422 #define POS_WARNING 96
423 #define POS_WWW_AUTHENTICATE 97
426 static gint hf_header_array[] = {
427 -1, /* 0"Unknown-header" - Pad so that the real headers start at index 1 */
429 -1, /* 2"Accept-Contact" RFC3841 */
430 -1, /* 3"Accept-Encoding" */
431 -1, /* 4"Accept-Language" */
432 -1, /* 5"Accept-Resource-Priority" RFC4412 */
433 -1, /* 6"Alert-Info", */
435 -1, /* 8"Allow-Events", RFC3265 */
436 -1, /* 9"Answer-Mode" RFC5373 */
437 -1, /* 10"Authentication-Info" */
438 -1, /* 11"Authorization", */
439 -1, /* 12"Call-ID", */
440 -1, /* 13"Call-Info" */
441 -1, /* 14"Contact", */
442 -1, /* 15"Content-Disposition", */
443 -1, /* 16"Content-Encoding", */
444 -1, /* 17"Content-Language", */
445 -1, /* 18"Content-Length", */
446 -1, /* 19"Content-Type", */
449 -1, /* 22"Error-Info", */
451 -1, /* 24"Expires", */
453 -1, /* 26"History-Info", RFC4244 */
454 -1, /* 27"Identity", */
455 -1, /* 28"Identity-Info", RFC4474 */
456 -1, /* 29"In-Reply-To", RFC3261 */
457 -1, /* 30"Join", RFC3911 */
458 -1, /* 31"Max-Breadth" RFC5393 */
459 -1, /* 32"Max-Forwards", */
460 -1, /* 33"MIME-Version", */
461 -1, /* 34"Min-Expires", */
462 -1, /* 35"Min-SE", RFC4028 */
463 -1, /* 36"Organization", */
464 -1, /* 37"P-Access-Network-Info", RFC3455 */
465 -1, /* 38"P-Answer-State", RFC4964 */
466 -1, /* 39"P-Asserted-Identity", RFC3325 */
467 -1, /* 40"P-Associated-URI", RFC3455 */
468 -1, /* 41"P-Called-Party-ID", RFC3455 */
469 -1, /* 42"P-Charging-Function-Addresses", RFC3455 */
470 -1, /* 43"P-Charging-Vector", RFC3455 */
471 -1, /* 44"P-DCS-Trace-Party-ID", RFC3603 */
472 -1, /* 45"P-DCS-OSPS", RFC3603 */
473 -1, /* 46"P-DCS-Billing-Info", RFC3603 */
474 -1, /* 47"P-DCS-LAES", RFC3603 */
475 -1, /* 48"P-DCS-Redirect", RFC3603 */
476 -1, /* 49"P-Early-Media", */
477 -1, /* 50"P-Media-Authorization", RFC3313 */
478 -1, /* 51"P-Preferred-Identity", RFC3325 */
479 -1, /* 52"P-Profile-Key", */
480 -1, /* 53"P-User-Database RFC4457 */
481 -1, /* 54"P-Visited-Network-ID", RFC3455 */
482 -1, /* 55"Path", RFC3327 */
483 -1, /* 56"Permission-Missing" RFC5360 */
484 -1, /* 57"Priority" */
485 -1, /* 58"Priv-Answer-mode" RFC5373 */
486 -1, /* 59"Privacy", RFC3323 */
487 -1, /* 60"Proxy-Authenticate", */
488 -1, /* 61"Proxy-Authorization", */
489 -1, /* 62"Proxy-Require", */
490 -1, /* 63"RAck", RFC3262 */
491 -1, /* 64"Reason", RFC3326 */
492 -1, /* 65"Record-Route", */
493 -1, /* 66"Refer-Sub",", RFC4488 */
494 -1, /* 67"Refer-To", RFC3515 */
495 -1, /* 68"Referred-By", */
496 -1, /* 69"Reject-Contact", RFC3841 */
497 -1, /* 70"Replaces", RFC3891 */
498 -1, /* 71"Reply-To", RFC3261 */
499 -1, /* 72"Request-Disposition", RFC3841 */
500 -1, /* 73"Require", RFC3261 */
501 -1, /* 74"Resource-Priority", RFC4412 */
502 -1, /* 75"Retry-After", RFC3261 */
503 -1, /* 76"Route", RFC3261 */
504 -1, /* 77"RSeq", RFC3262 */
505 -1, /* 78"Security-Client", RFC3329 */
506 -1, /* 79"Security-Server", RFC3329 */
507 -1, /* 80"Security-Verify", RFC3329 */
508 -1, /* 81"Server", RFC3261 */
509 -1, /* 82"Service-Route", RFC3608 */
510 -1, /* 83"Session-Expires", RFC4028 */
511 -1, /* 84"SIP-ETag", RFC3903 */
512 -1, /* 85"SIP-If-Match", RFC3903 */
513 -1, /* 86"Subject", RFC3261 */
514 -1, /* 87"Subscription-State", RFC3265 */
515 -1, /* 88"Supported", RFC3261 */
516 -1, /* 89"Target-Dialog", RFC4538 */
517 -1, /* 90"Timestamp", RFC3261 */
518 -1, /* 91"To", RFC3261 */
519 -1, /* 92"Trigger-Consent" RFC5380 */
520 -1, /* 93"Unsupported", RFC3261 */
521 -1, /* 94"User-Agent", RFC3261 */
522 -1, /* 95"Via", RFC3261 */
523 -1, /* 96"Warning", RFC3261 */
524 -1, /* 97"WWW-Authenticate", RFC3261 */
528 /* Track associations between parameter name and hf item */
530 const char *param_name;
532 } header_parameter_t;
534 static header_parameter_t auth_parameters_hf_array[] =
536 {"response", &hf_sip_auth_digest_response},
537 {"nc", &hf_sip_auth_nc},
538 {"username", &hf_sip_auth_username},
539 {"realm", &hf_sip_auth_realm},
540 {"nonce", &hf_sip_auth_nonce},
541 {"algorithm", &hf_sip_auth_algorithm},
542 {"opaque", &hf_sip_auth_opaque},
543 {"qop", &hf_sip_auth_qop},
544 {"cnonce", &hf_sip_auth_cnonce},
545 {"uri", &hf_sip_auth_uri},
546 {"domain", &hf_sip_auth_domain},
547 {"stale", &hf_sip_auth_stale},
548 {"auts", &hf_sip_auth_auts},
549 {"rspauth", &hf_sip_auth_rspauth},
550 {"nextnonce", &hf_sip_auth_nextnonce},
551 {"ik", &hf_sip_auth_ik},
552 {"ck", &hf_sip_auth_ck}
555 static header_parameter_t via_parameters_hf_array[] =
557 {"branch", &hf_sip_via_branch},
558 {"maddr", &hf_sip_via_maddr},
559 {"rport", &hf_sip_via_rport},
560 {"received", &hf_sip_via_received},
561 {"ttl", &hf_sip_via_ttl},
562 {"comp", &hf_sip_via_comp},
563 {"sigcomp-id", &hf_sip_via_sigcomp_id}
575 static hf_sip_uri_t sip_pai_uri = {
583 static hf_sip_uri_t sip_ppi_uri = {
591 static hf_sip_uri_t sip_pmiss_uri = {
600 static hf_sip_uri_t sip_tc_uri = {
610 * Type of line. It's either a SIP Request-Line, a SIP Status-Line, or
611 * another type of line.
620 static guint sip_tcp_port = TCP_PORT_SIP;
621 static guint sip_tls_port = TLS_PORT_SIP;
623 /* global_sip_raw_text determines whether we are going to display */
624 /* the raw text of the SIP message, much like the MEGACO dissector does. */
625 static gboolean global_sip_raw_text = FALSE;
626 /* strict_sip_version determines whether the SIP dissector enforces
627 * the SIP version to be "SIP/2.0". */
628 static gboolean strict_sip_version = TRUE;
631 * desegmentation of SIP headers
632 * (when we are over TCP or another protocol providing the desegmentation API)
634 static gboolean sip_desegment_headers = TRUE;
637 * desegmentation of SIP bodies
638 * (when we are over TCP or another protocol providing the desegmentation API)
640 static gboolean sip_desegment_body = TRUE;
642 /* Extension header subdissectors */
643 static dissector_table_t ext_hdr_subdissector_table;
645 /* Forward declaration we need below */
646 void proto_reg_handoff_sip(void);
647 static gboolean dissect_sip_common(tvbuff_t *tvb, int offset, packet_info *pinfo,
648 proto_tree *tree, gboolean is_heur, gboolean use_reassembly);
649 static line_type_t sip_parse_line(tvbuff_t *tvb, int offset, gint linelen,
651 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
652 guint meth_len, guint *meth_idx);
653 static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset,
655 static void dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree,
657 static void dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree);
658 static void tvb_raw_text_add(tvbuff_t *tvb, int offset, int length, proto_tree *tree);
659 static guint sip_is_packet_resend(packet_info *pinfo,
662 guchar cseq_number_set, guint32 cseq_number,
663 line_type_t line_type);
665 static guint sip_find_request(packet_info *pinfo,
668 guchar cseq_number_set, guint32 cseq_number,
669 guint32 *response_time);
671 static guint sip_find_invite(packet_info *pinfo,
674 guchar cseq_number_set, guint32 cseq_number,
675 guint32 *response_time);
677 /* SIP content type and internet media type used by other dissectors
678 * are the same. List of media types from IANA at:
679 * http://www.iana.org/assignments/media-types/index.html */
680 static dissector_table_t media_type_dissector_table;
682 static heur_dissector_list_t heur_subdissector_list;
684 #define SIP2_HDR "SIP/2.0"
685 #define SIP2_HDR_LEN ((gint)strlen (SIP2_HDR))
687 /* Store the info needed by the SIP tap for one packet */
688 static sip_info_value_t *stat_info;
690 /* The buffer size for the cseq_method name */
691 #define MAX_CSEQ_METHOD_SIZE 16
693 /****************************************************************************
694 * Conversation-type definitions
696 * For each call, keep track of the current cseq number and state of
697 * transaction, in order to be able to detect retransmissions.
699 * Don't use the conservation mechanism, but instead:
700 * - store with each dissected packet original frame (if any)
701 * - maintain a global hash table of
702 * (call_id, source_addr, dest_addr) -> (cseq, transaction_state, frame)
704 * N.B. This is broken for a couple of reasons:
705 * - it won't cope properly with overlapping transactions within the
707 * - request response mapping won't work where the response uses a different
708 * address pair from the request
710 * TODO: proper transaction matching uses RFC fields (use Max-forwards or
711 * maybe Via count as extra key to limit view to one hop)
712 ****************************************************************************/
714 static GHashTable *sip_hash = NULL; /* Hash table */
716 /* Types for hash table keys and values */
717 #define MAX_CALL_ID_SIZE 128
719 /* Conversation-type key */
722 char call_id[MAX_CALL_ID_SIZE];
723 address source_address;
725 address dest_address;
734 provisional_response_seen,
736 } transaction_state_t;
738 /* Current conversation-type value */
742 transaction_state_t transaction_state;
743 gchar method[MAX_CSEQ_METHOD_SIZE];
744 nstime_t request_time;
745 guint32 response_code;
749 /* Result to be stored in per-packet info */
752 gint original_frame_num;
753 gint response_request_frame_num;
755 } sip_frame_result_value;
758 /************************/
759 /* Hash table functions */
762 static gint sip_equal(gconstpointer v, gconstpointer v2)
764 const sip_hash_key* val1 = v;
765 const sip_hash_key* val2 = v2;
767 /* Call id must match */
768 if (strcmp(val1->call_id, val2->call_id) != 0)
773 /* Addresses must match */
774 return (ADDRESSES_EQUAL(&(val1->source_address), &(val2->source_address))) &&
775 (val1->source_port == val2->source_port) &&
776 (ADDRESSES_EQUAL(&(val1->dest_address), &(val2->dest_address))) &&
777 (val1->dest_port == val2->dest_port);
780 /* Compute a hash value for a given key. */
781 /* Don't try to use addresses here, call-id should be almost unique. */
782 static guint sip_hash_func(gconstpointer v)
785 const sip_hash_key *key = v;
786 guint value = (guint)strlen(key->call_id);
787 gint chars_to_use = value / 4;
789 /* First few characters from the call-id should be enough... */
790 for (n=0; n < chars_to_use; n++)
792 value += key->call_id[n];
799 /* Initializes the hash table and the mem_chunk area each time a new
800 * file is loaded or re-loaded in wireshark */
802 sip_init_protocol(void)
804 /* Destroy any existing hashes. */
806 g_hash_table_destroy(sip_hash);
808 /* Now create them over */
809 sip_hash = g_hash_table_new(sip_hash_func, sip_equal);
812 /* Structure to collect info about a sip uri */
813 typedef struct _uri_offset_info
815 gint display_name_start;
816 gint display_name_end;
819 gint uri_parameters_start;
820 gint uri_parameters_end;
821 gint name_addr_start;
827 gint uri_host_port_start;
828 gint uri_host_port_end;
831 /* Code to parse a sip uri.
832 * Returns Offset end off parsing or -1 for unsuccessful parsing
835 dissect_sip_uri(tvbuff_t *tvb, packet_info *pinfo _U_, gint start_offset,
836 gint line_end_offset, uri_offset_info *uri_offsets)
844 gint semicolon_offset;
845 gint question_mark_offset;
846 gint parameter_end_offset;
847 gboolean uri_without_angle_quotes = FALSE;
849 /* Initialize the uri_offsets */
850 uri_offsets->display_name_start = -1;
851 uri_offsets->display_name_end = -1;
852 uri_offsets->uri_start = -1;
853 uri_offsets->uri_end = -1;
854 uri_offsets->uri_parameters_start = -1;
855 uri_offsets->uri_parameters_end = -1;
856 uri_offsets->name_addr_start = -1;
857 uri_offsets->name_addr_end = -1;
858 uri_offsets->uri_user_start = -1;
859 uri_offsets->uri_user_end = -1;
860 uri_offsets->uri_host_start = -1;
861 uri_offsets->uri_host_end = -1;
862 uri_offsets->uri_host_port_start = -1;
863 uri_offsets->uri_host_port_end = -1;
865 /* skip Spaces and Tabs */
866 current_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
868 if(current_offset >= line_end_offset) {
869 /* Nothing to parse */
873 uri_offsets->name_addr_start = current_offset;
875 /* First look, if we have a display name */
876 c=tvb_get_guint8(tvb, current_offset);
880 /* We have a display name, look for the next unescaped '"' */
881 uri_offsets->display_name_start = current_offset;
884 queried_offset = tvb_find_guint8(tvb, current_offset + 1, line_end_offset - (current_offset + 1), '"');
885 if(queried_offset == -1)
890 current_offset = queried_offset;
893 /* count back slashes before '"' */
894 for(i=1;tvb_get_guint8(tvb, queried_offset - i) == '\\';i++);
902 } while (current_offset < line_end_offset);
903 if(current_offset >= line_end_offset)
909 uri_offsets->display_name_end = current_offset;
911 /* find start of the URI */
912 queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, '<');
913 if(queried_offset == -1)
918 current_offset = queried_offset + 1;
922 /* We don't have a display name */
927 /* We have either an URI without angles or a display name with a limited character set */
928 /* Look for the right angle quote or colon */
929 queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, '<');
930 colon_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ':');
931 if(queried_offset != -1 && colon_offset != -1)
933 if(queried_offset < colon_offset)
935 /* we have an URI with angle quotes */
936 uri_offsets->display_name_start = current_offset;
937 uri_offsets->display_name_end = queried_offset - 1;
938 current_offset = queried_offset + 1;
942 /* we have an URI without angle quotes */
943 uri_without_angle_quotes = TRUE;
948 if(queried_offset != -1)
950 /* we have an URI with angle quotes */
951 uri_offsets->display_name_start = current_offset;
952 uri_offsets->display_name_end = queried_offset - 1;
953 current_offset = queried_offset + 1;
956 if(colon_offset != -1)
958 /* we have an URI without angle quotes */
959 uri_without_angle_quotes = TRUE;
962 /* If this point is reached, we can't parse the URI */
968 /* Start parsing of URI */
969 uri_offsets->uri_start = current_offset;
970 if(uri_without_angle_quotes == TRUE)
972 /* look for the first ',' or ';' which will mark the end of this URI
973 * In this case a semicolon indicates a header field parameter, and not an uri parameter.
975 comma_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ',');
976 semicolon_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ';');
978 if (semicolon_offset != -1 && comma_offset != -1)
980 if(semicolon_offset < comma_offset)
982 uri_offsets->uri_end = semicolon_offset - 1;
986 uri_offsets->uri_end = comma_offset - 1;
991 if (semicolon_offset != -1)
993 uri_offsets->uri_end = semicolon_offset - 1;
995 else if (comma_offset != -1)
997 uri_offsets->uri_end = comma_offset - 1;
1000 /* If both offsets are equal to -1, we don't have a semicolon or a comma.
1001 * In that case, we assume that the end of the URI is at the line end
1003 uri_offsets->uri_end = line_end_offset - 3; /* remove '\r\n' */
1006 uri_offsets->name_addr_end = uri_offsets->uri_end;
1007 current_offset = uri_offsets->uri_end + 1; /* Now save current_offset, as it is the value to be returned now */
1011 /* look for closing angle quote */
1012 queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, '>');
1013 if(queried_offset == -1)
1018 uri_offsets->name_addr_end = queried_offset;
1019 uri_offsets->uri_end = queried_offset - 1;
1020 current_offset = queried_offset; /* Now save current_offset. It contains the value we have to return */
1022 /* Look for '@' within URI */
1023 queried_offset = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, '@');
1024 if(queried_offset == -1)
1026 /* no '@': look for the first ';' or '?' in the URI */
1027 question_mark_offset = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, '?');
1028 semicolon_offset = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, ';');
1032 /* with '@': look for the first ';' or '?' behind the '@' */
1033 question_mark_offset = tvb_find_guint8(tvb, queried_offset, uri_offsets->uri_end - queried_offset, '?');
1034 semicolon_offset = tvb_find_guint8(tvb, queried_offset, uri_offsets->uri_end - queried_offset, ';');
1038 if (semicolon_offset != -1 && question_mark_offset != -1)
1040 if(semicolon_offset < question_mark_offset)
1042 uri_offsets->uri_parameters_start = semicolon_offset;
1046 uri_offsets->uri_parameters_start = question_mark_offset;
1048 uri_offsets->uri_parameters_end = uri_offsets->uri_end;
1049 uri_offsets->uri_end = uri_offsets->uri_parameters_start - 1;
1053 if (semicolon_offset != -1)
1055 uri_offsets->uri_parameters_start = semicolon_offset;
1056 uri_offsets->uri_parameters_end = uri_offsets->uri_end;
1057 uri_offsets->uri_end = uri_offsets->uri_parameters_start - 1;
1059 if (question_mark_offset != -1)
1061 uri_offsets->uri_parameters_start = question_mark_offset;
1062 uri_offsets->uri_parameters_end = uri_offsets->uri_end;
1063 uri_offsets->uri_end = uri_offsets->uri_parameters_start - 1;
1065 /* If both offsets are equal to -1, we don't have a semicolon or a question mark.
1066 * In that case, we don't have to save any offsets.
1072 /* Look for URI address parts (user, host, host-port) */
1074 /* Look for '@' within URI */
1075 queried_offset = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, '@');
1076 if(queried_offset == -1)
1078 /* no '@' = no user part */
1079 uri_offsets->uri_host_start = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, ':')+1;
1083 /* with '@' = with user part */
1084 uri_offsets->uri_user_start = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, ':')+1;
1085 uri_offsets->uri_user_end = tvb_find_guint8(tvb, uri_offsets->uri_user_start, uri_offsets->uri_end - uri_offsets->uri_start, '@')-1;
1086 uri_offsets->uri_host_start = uri_offsets->uri_user_end + 2;
1089 /* find URI-Host end*/
1090 parameter_end_offset = uri_offsets->uri_host_start;
1092 while (parameter_end_offset < line_end_offset)
1094 parameter_end_offset++;
1095 c = tvb_get_guint8(tvb, parameter_end_offset);
1104 goto uri_host_end_found;
1112 uri_offsets->uri_host_end = parameter_end_offset - 1;
1116 uri_offsets->uri_host_port_start = parameter_end_offset + 1;
1117 parameter_end_offset = uri_offsets->uri_host_port_start;
1118 while (parameter_end_offset < line_end_offset)
1120 parameter_end_offset++;
1121 c = tvb_get_guint8(tvb, parameter_end_offset);
1129 goto uri_host_port_end_found;
1135 uri_host_port_end_found:
1137 uri_offsets->uri_host_port_end = parameter_end_offset -1;
1139 return current_offset;
1143 * Code to add dissected SIP URI Information to proto tree
1147 display_sip_uri (tvbuff_t *tvb, proto_tree *sip_element_tree, uri_offset_info* uri_offsets, hf_sip_uri_t* uri)
1151 proto_tree *uri_item_tree = NULL;
1153 if(uri_offsets->display_name_end != uri_offsets->display_name_start) {
1154 proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, uri_offsets->display_name_start,
1155 uri_offsets->display_name_end - uri_offsets->display_name_start + 1, FALSE);
1158 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);
1159 uri_item_tree = proto_item_add_subtree(ti, *(uri->ett_uri));
1161 if(uri_offsets->uri_user_end >= uri_offsets->uri_user_start) {
1162 proto_tree_add_item(uri_item_tree, *(uri->hf_sip_user), tvb, uri_offsets->uri_user_start,
1163 uri_offsets->uri_user_end - uri_offsets->uri_user_start + 1, FALSE);
1166 proto_tree_add_item(uri_item_tree, *(uri->hf_sip_host), tvb, uri_offsets->uri_host_start,
1167 uri_offsets->uri_host_end - uri_offsets->uri_host_start + 1, FALSE);
1169 if(uri_offsets->uri_host_port_end > uri_offsets->uri_host_port_start) {
1170 proto_tree_add_item(uri_item_tree, *(uri->hf_sip_port), tvb, uri_offsets->uri_host_port_start,
1171 uri_offsets->uri_host_port_end - uri_offsets->uri_host_port_start + 1, FALSE);
1174 return uri_item_tree;
1180 /* Code to parse a contact header item
1181 * Returns Offset end off parsing or -1 for unsuccessful parsing
1184 dissect_sip_contact_item(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint start_offset, gint line_end_offset)
1188 proto_item *ti = NULL;
1189 proto_tree *contact_item_tree = NULL, *uri_tree = NULL;
1191 gint current_offset;
1192 gint queried_offset;
1193 gint contact_params_start_offset = -1;
1194 gint contact_item_end_offset = -1;
1195 uri_offset_info uri_offsets;
1197 uri_offsets.display_name_start = -1;
1198 uri_offsets.display_name_end = -1;
1199 uri_offsets.uri_start = -1;
1200 uri_offsets.uri_end = -1;
1201 uri_offsets.uri_parameters_start = -1;
1202 uri_offsets.uri_parameters_end = -1;
1203 uri_offsets.name_addr_start = -1;
1204 uri_offsets.name_addr_end = -1;
1206 /* skip Spaces and Tabs */
1207 start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1209 if(start_offset >= line_end_offset) {
1210 /* Nothing to parse */
1214 current_offset = dissect_sip_uri(tvb, pinfo, start_offset, line_end_offset, &uri_offsets);
1215 if(current_offset == -1)
1217 /* Parsing failed */
1221 /* Now look for the end of the contact item */
1222 while (current_offset < line_end_offset)
1224 c=tvb_get_guint8(tvb, current_offset);
1226 if(c == ';' && contact_params_start_offset == -1)
1228 /* here we start with contact parameters */
1229 contact_params_start_offset = current_offset;
1234 /* look for the next unescaped '"' */
1237 queried_offset = tvb_find_guint8(tvb, current_offset + 1, line_end_offset - (current_offset + 1), '"');
1238 if(queried_offset == -1)
1240 /* malformed Contact header */
1243 current_offset = queried_offset;
1246 * Look for uneven number of backslashes before '"' */
1247 for(i=0;tvb_get_guint8(tvb, queried_offset - (i+1) ) == '\\';i++);
1254 /* end of contact item found. */
1255 contact_item_end_offset = current_offset - 1; /* remove ',' */
1262 if(contact_item_end_offset == -1)
1263 contact_item_end_offset = line_end_offset - 3; /* remove '\r\n' */
1265 /* Build the tree, now */
1268 ti = proto_tree_add_string(tree, hf_sip_contact_item, tvb, start_offset, contact_item_end_offset - start_offset + 1,
1269 tvb_format_text(tvb, start_offset, contact_item_end_offset - start_offset + 1));
1270 contact_item_tree = proto_item_add_subtree(ti, ett_sip_contact_item);
1272 ti = proto_tree_add_string(contact_item_tree, hf_sip_uri, tvb, uri_offsets.name_addr_start, uri_offsets.name_addr_end - uri_offsets.name_addr_start + 1,
1273 tvb_format_text(tvb, uri_offsets.name_addr_start, uri_offsets.name_addr_end - uri_offsets.name_addr_start + 1));
1274 uri_tree = proto_item_add_subtree(ti, ett_sip_uri);
1276 if(uri_offsets.display_name_start != -1 && uri_offsets.display_name_end != -1)
1278 proto_tree_add_string(uri_tree, hf_sip_display, tvb, uri_offsets.display_name_start,
1279 uri_offsets.display_name_end - uri_offsets.display_name_start + 1,
1280 tvb_format_text(tvb, uri_offsets.display_name_start,
1281 uri_offsets.display_name_end - uri_offsets.display_name_start + 1));
1284 if(uri_offsets.uri_start != -1 && uri_offsets.uri_end != -1)
1286 proto_tree_add_string(uri_tree, hf_sip_contact_addr, tvb, uri_offsets.uri_start,
1287 uri_offsets.uri_end - uri_offsets.uri_start + 1,
1288 tvb_format_text(tvb, uri_offsets.uri_start,
1289 uri_offsets.uri_end - uri_offsets.uri_start + 1));
1292 /* Parse URI and Contact header Parameters now */
1296 return current_offset;
1299 /* Code to parse an authorization header item
1300 * Returns offset at end of parsing, or -1 for unsuccessful parsing
1303 dissect_sip_authorization_item(tvbuff_t *tvb, proto_tree *tree, gint start_offset, gint line_end_offset)
1306 gint current_offset;
1307 gint equals_offset = 0;
1309 header_parameter_t *auth_parameter;
1312 /* skip Spaces and Tabs */
1313 start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1315 if (start_offset >= line_end_offset)
1317 /* Nothing to parse */
1321 current_offset = start_offset;
1323 /* Now look for the end of the parameter */
1324 while (current_offset < line_end_offset)
1326 c = tvb_get_guint8(tvb, current_offset);
1330 equals_offset = current_offset;
1335 /* look for the next unescaped '"' */
1338 current_offset = tvb_find_guint8(tvb, current_offset + 1, line_end_offset - (current_offset + 1), '"');
1339 if(current_offset == -1)
1341 /* malformed parameter */
1346 * Look for uneven number of backslashes before '"' */
1347 for(i=0;tvb_get_guint8(tvb, current_offset - (i+1) ) == '\\';i++);
1351 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1362 if (equals_offset == 0)
1364 /* Give up if equals not found */
1368 /* Extract the parameter name */
1369 name = tvb_get_ephemeral_string(tvb, start_offset, equals_offset-start_offset);
1371 /* Try to add parameter as a filterable item */
1372 for (auth_parameter = &auth_parameters_hf_array[i];
1373 i < array_length(auth_parameters_hf_array);
1374 i++, auth_parameter++)
1376 if (g_ascii_strcasecmp(name, auth_parameter->param_name) == 0)
1378 proto_tree_add_item(tree, *(auth_parameter->hf_item), tvb,
1379 equals_offset+1, current_offset-equals_offset-1,
1385 /* If not matched, just add as text... */
1386 if (i == array_length(auth_parameters_hf_array))
1388 proto_tree_add_text(tree, tvb, start_offset, current_offset-start_offset,
1389 "%s", tvb_format_text(tvb, start_offset,
1390 current_offset-start_offset));
1393 return current_offset;
1396 /* Dissect the details of a Reason header */
1398 dissect_sip_reason_header(tvbuff_t *tvb, proto_tree *tree, gint start_offset, gint line_end_offset){
1400 gint current_offset, semi_colon_offset, length;
1401 gchar *param_name = NULL;
1404 /* skip Spaces and Tabs */
1405 start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1407 if (start_offset >= line_end_offset)
1409 /* Nothing to parse */
1413 current_offset = start_offset;
1414 semi_colon_offset = tvb_find_guint8(tvb, current_offset, line_end_offset-current_offset, ';');
1415 length = semi_colon_offset - current_offset;
1416 proto_tree_add_text(tree, tvb, start_offset, length,
1417 "Reason Protocols: %s", tvb_format_text(tvb, start_offset, length));
1419 param_name = tvb_get_ephemeral_string(tvb, start_offset, length);
1420 if (g_ascii_strcasecmp(param_name, "Q.850") == 0){
1421 current_offset = tvb_find_guint8(tvb, semi_colon_offset, line_end_offset-semi_colon_offset, '=')+1;
1422 length = line_end_offset - current_offset;
1424 /* q850_cause_code_vals */
1425 cause_value = atoi(tvb_get_ephemeral_string(tvb, current_offset, length));
1426 proto_tree_add_text(tree, tvb, current_offset, length,
1427 "Cause: %u(0x%x)[%s]", cause_value,cause_value,
1428 val_to_str(cause_value, q850_cause_code_vals, "Unknown (%d)" ));
1435 /* Dissect the details of a Via header */
1436 static void dissect_sip_via_header(tvbuff_t *tvb, proto_tree *tree, gint start_offset, gint line_end_offset)
1438 gint current_offset;
1439 gint transport_start_offset;
1440 gint address_start_offset;
1441 gint semicolon_offset;
1442 guint transport_slash_count;
1443 gboolean transport_name_started;
1444 gboolean colon_seen;
1445 gboolean ipv6_reference;
1446 gboolean ipv6_address;
1448 gchar *param_name = NULL;
1450 current_offset = start_offset;
1454 /* Reset flags and counters */
1455 transport_start_offset = 0;
1456 semicolon_offset = 0;
1457 transport_name_started = FALSE;
1458 transport_slash_count = 0;
1459 ipv6_reference = FALSE;
1460 ipv6_address = FALSE;
1463 /* skip Spaces and Tabs */
1464 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1466 if (current_offset >= line_end_offset)
1468 /* Nothing more to parse */
1472 /* Now look for the end of the SIP/2.0/transport parameter.
1473 There may be spaces between the slashes */
1474 while (current_offset < line_end_offset)
1476 c = tvb_get_guint8(tvb, current_offset);
1479 transport_slash_count++;
1482 if (!transport_name_started && (transport_slash_count == 2) && isalpha(c))
1484 transport_name_started = TRUE;
1485 transport_start_offset = current_offset;
1488 if (transport_name_started && ((c == ' ') || (c == '\t')))
1490 proto_tree_add_item(tree, hf_sip_via_transport, tvb, transport_start_offset,
1491 current_offset - transport_start_offset, FALSE);
1499 /* skip Spaces and Tabs */
1500 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1502 /* Now read the address part */
1503 address_start_offset = current_offset;
1504 while (current_offset < line_end_offset)
1506 c = tvb_get_guint8(tvb, current_offset);
1509 ipv6_reference = TRUE;
1510 ipv6_address = TRUE;
1514 ipv6_reference = FALSE;
1517 if (colon_seen || (c == ' ') || (c == '\t') || ((c == ':') && (ipv6_reference == FALSE)) || (c == ';'))
1524 /* Add address to tree */
1525 if (ipv6_address == TRUE) {
1526 proto_tree_add_item(tree, hf_sip_via_sent_by_address, tvb, address_start_offset + 1,
1527 current_offset - address_start_offset - 2, FALSE);
1529 proto_tree_add_item(tree, hf_sip_via_sent_by_address, tvb, address_start_offset,
1530 current_offset - address_start_offset, FALSE);
1533 /* Transport port number may follow ([space] : [space])*/
1534 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1535 c = tvb_get_guint8(tvb, current_offset);
1539 /* Port number will follow any space after : */
1544 /* Skip optional space after colon */
1545 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1547 port_offset = current_offset;
1549 /* Find digits of port number */
1550 while (current_offset < line_end_offset)
1552 c = tvb_get_guint8(tvb, current_offset);
1556 if (current_offset > port_offset)
1558 /* Add address port number to tree */
1559 proto_tree_add_uint(tree, hf_sip_via_sent_by_port, tvb, port_offset,
1560 current_offset - port_offset,
1561 atoi(tvb_get_ephemeral_string(tvb, port_offset,
1562 current_offset - port_offset)));
1566 /* Shouldn't see a colon without a port number given */
1576 /* skip Spaces and Tabs */
1577 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1580 /* Dissect any parameters found */
1581 while (current_offset < line_end_offset)
1583 gboolean equals_found = FALSE;
1584 gboolean found_end_of_parameters = FALSE;
1585 gint parameter_name_end = 0;
1586 gint parameter_value_end;
1587 header_parameter_t *via_parameter;
1590 /* Look for the semicolon that signals the start of a parameter */
1591 while (current_offset < line_end_offset)
1593 c = tvb_get_guint8(tvb, current_offset);
1596 semicolon_offset = current_offset;
1601 if ((c != ' ') && (c != '\t'))
1603 found_end_of_parameters = TRUE;
1609 if (found_end_of_parameters)
1614 if (current_offset == line_end_offset)
1619 /* Look for end of parameter name */
1620 while (current_offset < line_end_offset)
1622 c = tvb_get_guint8(tvb, current_offset);
1623 if (!isalpha(c) && (c != '-'))
1630 /* Not all params have an = */
1633 equals_found = TRUE;
1635 parameter_name_end = current_offset;
1637 /* Read until end of parameter value */
1638 while (current_offset < line_end_offset)
1640 c = tvb_get_guint8(tvb, current_offset);
1641 if ((c == ' ') || (c == '\t') || (c == ';') || (c == ','))
1648 /* Note parameter name */
1649 parameter_value_end = current_offset;
1650 param_name = tvb_get_ephemeral_string(tvb, semicolon_offset+1,
1651 parameter_name_end - semicolon_offset - 1);
1653 /* Try to add parameter as a filterable item */
1654 for (via_parameter = &via_parameters_hf_array[i];
1655 i < array_length(via_parameters_hf_array);
1656 i++, via_parameter++)
1658 if (g_ascii_strcasecmp(param_name, via_parameter->param_name) == 0)
1662 proto_tree_add_item(tree, *(via_parameter->hf_item), tvb,
1663 parameter_name_end+1, current_offset-parameter_name_end-1,
1668 proto_tree_add_item(tree, *(via_parameter->hf_item), tvb,
1669 semicolon_offset+1, current_offset-semicolon_offset-1,
1676 /* If not matched, just add as text... */
1677 if (i == array_length(via_parameters_hf_array))
1679 proto_tree_add_text(tree, tvb, semicolon_offset+1, current_offset-semicolon_offset-1,
1680 "%s", tvb_format_text(tvb, semicolon_offset+1,
1681 current_offset-semicolon_offset-1));
1684 /* skip Spaces and Tabs */
1685 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1687 /* There may be a comma, followed by more Via entries... */
1688 if (current_offset < line_end_offset)
1690 c = tvb_get_guint8(tvb, current_offset);
1693 /* Skip it and get out of parameter loop */
1703 /* Code to actually dissect the packets */
1705 dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1710 octet = tvb_get_guint8(tvb,0);
1711 if ((octet & 0xf8) == 0xf8){
1712 call_dissector(sigcomp_handle, tvb, pinfo, tree);
1713 return tvb_length(tvb);
1716 len = dissect_sip_common(tvb, 0, pinfo, tree, FALSE, FALSE);
1718 return 0; /* not SIP */
1724 dissect_sip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1730 octet = tvb_get_guint8(tvb,0);
1731 if ((octet & 0xf8) == 0xf8){
1732 call_dissector(sigcomp_handle, tvb, pinfo, tree);
1736 while (tvb_reported_length_remaining(tvb, offset) != 0) {
1737 len = dissect_sip_common(tvb, offset, pinfo, tree, TRUE, TRUE);
1745 dissect_sip_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1749 gboolean first = TRUE;
1751 while (tvb_reported_length_remaining(tvb, offset) != 0) {
1752 len = dissect_sip_common(tvb, offset, pinfo, tree, !first, TRUE);
1756 * If the first packet doesn't start with
1757 * a valid SIP request or response, don't
1758 * treat this as SIP.
1765 break; /* need more data */
1772 dissect_sip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1774 return dissect_sip_common(tvb, 0, pinfo, tree, FALSE, FALSE) > 0;
1778 dissect_sip_common(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
1779 gboolean dissect_other_as_continuation, gboolean use_reassembly)
1782 gint next_offset, linelen;
1783 int content_length, datalen, reported_datalen;
1784 line_type_t line_type;
1786 gboolean is_known_request;
1787 gboolean found_match = FALSE;
1789 guint token_1_len = 0;
1790 guint current_method_idx = 0;
1791 proto_item *ts = NULL, *ti = NULL, *th = NULL, *sip_element_item = NULL;
1792 proto_tree *sip_tree = NULL, *reqresp_tree = NULL , *hdr_tree = NULL,
1793 *sip_element_tree = NULL, *message_body_tree = NULL, *cseq_tree = NULL,
1794 *via_tree = NULL, *reason_tree = NULL, *rack_tree = NULL;
1795 guchar contacts = 0, contact_is_star = 0, expires_is_0 = 0;
1796 guint32 cseq_number = 0;
1797 guchar cseq_number_set = 0;
1798 char cseq_method[MAX_CSEQ_METHOD_SIZE] = "";
1799 char call_id[MAX_CALL_ID_SIZE] = "";
1800 gchar *media_type_str_lower_case = NULL;
1801 char *content_type_parameter_str = NULL;
1802 guint resend_for_packet = 0;
1803 guint request_for_response = 0;
1804 guint32 response_time = 0;
1809 * Note that "tvb_find_line_end()" will return a value that
1810 * is not longer than what's in the buffer, so the
1811 * "tvb_get_ptr()" calls below won't throw exceptions.
1813 * Note that "tvb_strneql()" doesn't throw exceptions, so
1814 * "sip_parse_line()" won't throw an exception.
1816 orig_offset = offset;
1817 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
1818 if (tvb_strnlen(tvb, offset, linelen) > -1)
1821 * There's a NULL in the line,
1822 * this may be SIP within another protocol.
1823 * This heuristic still needs to improve.
1827 line_type = sip_parse_line(tvb, offset, linelen, &token_1_len);
1829 if (line_type == OTHER_LINE) {
1831 * This is neither a SIP request nor response.
1833 if (!dissect_other_as_continuation) {
1835 * We were asked to reject this.
1841 * Just dissect it as a continuation.
1843 } else if (use_reassembly) {
1845 * Yes, it's a request or response.
1846 * Do header desegmentation if we've been told to,
1847 * and do body desegmentation if we've been told to and
1848 * we find a Content-Length header.
1850 if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo,
1851 sip_desegment_headers, sip_desegment_body)) {
1853 * More data needed for desegmentation.
1859 /* Initialise stat info for passing to tap */
1860 stat_info = ep_alloc(sizeof(sip_info_value_t));
1861 stat_info->response_code = 0;
1862 stat_info->request_method = NULL;
1863 stat_info->reason_phrase = NULL;
1864 stat_info->resend = 0;
1865 stat_info->setup_time = 0;
1866 stat_info->tap_call_id = NULL;
1867 stat_info->tap_from_addr = NULL;
1868 stat_info->tap_to_addr = NULL;
1870 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1871 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIP");
1873 switch (line_type) {
1876 is_known_request = sip_is_known_request(tvb, offset, token_1_len, ¤t_method_idx);
1877 descr = is_known_request ? "Request" : "Unknown request";
1878 if (check_col(pinfo->cinfo, COL_INFO)) {
1879 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
1881 tvb_format_text(tvb, offset, linelen - SIP2_HDR_LEN - 1));
1887 if (check_col(pinfo->cinfo, COL_INFO)) {
1888 col_add_fstr(pinfo->cinfo, COL_INFO, "Status: %s",
1889 tvb_format_text(tvb, offset + SIP2_HDR_LEN + 1, linelen - SIP2_HDR_LEN - 1));
1891 stat_info->reason_phrase = tvb_get_ephemeral_string(tvb, offset + SIP2_HDR_LEN + 5, linelen - (SIP2_HDR_LEN + 5));
1895 default: /* Squelch compiler complaints */
1896 descr = "Continuation";
1897 if (check_col(pinfo->cinfo, COL_INFO))
1898 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
1903 ts = proto_tree_add_item(tree, proto_sip, tvb, offset, -1, FALSE);
1904 sip_tree = proto_item_add_subtree(ts, ett_sip);
1907 switch (line_type) {
1911 ti = proto_tree_add_string(sip_tree, hf_Request_Line, tvb, offset, next_offset-offset,
1912 tvb_format_text(tvb, offset, linelen));
1913 reqresp_tree = proto_item_add_subtree(ti, ett_sip_reqresp);
1915 dfilter_sip_request_line(tvb, reqresp_tree, token_1_len);
1920 ti = proto_tree_add_string(sip_tree, hf_Status_Line, tvb, offset, next_offset-offset,
1921 tvb_format_text(tvb, offset, linelen));
1922 reqresp_tree = proto_item_add_subtree(ti, ett_sip_reqresp);
1924 dfilter_sip_status_line(tvb, reqresp_tree);
1929 ti = proto_tree_add_text(sip_tree, tvb, offset, next_offset,
1930 "%s line: %s", descr,
1931 tvb_format_text(tvb, offset, linelen));
1932 reqresp_tree = proto_item_add_subtree(ti, ett_sip_reqresp);
1933 proto_tree_add_text(sip_tree, tvb, offset, -1,
1934 "Continuation data");
1936 return tvb_length_remaining(tvb, offset);
1939 offset = next_offset;
1941 th = proto_tree_add_item(sip_tree, hf_msg_hdr, tvb, offset,
1942 tvb_length_remaining(tvb, offset), FALSE);
1943 proto_item_set_text(th, "Message Header");
1944 hdr_tree = proto_item_add_subtree(th, ett_sip_hdr);
1948 * Process the headers - if we're not building a protocol tree,
1949 * we just do this to find the blank line separating the
1950 * headers from the message body.
1952 next_offset = offset;
1953 content_length = -1;
1954 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1955 gint line_end_offset;
1957 gint semi_colon_offset;
1959 gint parameter_offset;
1960 gint parameter_end_offset;
1962 gint content_type_len, content_type_parameter_str_len;
1965 dissector_handle_t ext_hdr_handle;
1968 gint sub_value_offset;
1973 gboolean is_no_header_termination = FALSE;
1976 proto_tree *pai_uri_item_tree = NULL;
1977 proto_tree *pmiss_uri_item_tree = NULL;
1978 proto_tree *ppi_uri_item_tree = NULL;
1979 proto_tree *tc_uri_item_tree = NULL;
1980 proto_tree *to_uri_item_tree = NULL;
1981 proto_tree *from_uri_item_tree = NULL;
1982 uri_offset_info uri_offsets;
1988 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
1991 * This is a blank line separating the
1992 * message header from the message body.
1994 offset = next_offset;
1998 line_end_offset = offset + linelen;
1999 if(tvb_reported_length_remaining(tvb, next_offset) == 0){
2000 is_no_header_termination = TRUE;
2002 while ((c = tvb_get_guint8(tvb, next_offset)) == ' ' || c == '\t')
2005 * This line end is not a header seperator.
2006 * It just extends the header with another line.
2007 * Look for next line end:
2009 linelen += (next_offset - line_end_offset);
2010 linelen += tvb_find_line_end(tvb, next_offset, -1, &next_offset, FALSE);
2011 line_end_offset = offset + linelen;
2014 colon_offset = tvb_find_guint8(tvb, offset, linelen, ':');
2015 if (colon_offset == -1) {
2017 * Malformed header - no colon after the name.
2020 proto_tree_add_text(hdr_tree, tvb, offset,
2021 next_offset - offset, "%s",
2022 tvb_format_text(tvb, offset, linelen));
2025 header_len = colon_offset - offset;
2026 hf_index = sip_is_known_sip_header(tvb, offset, header_len);
2029 * Skip whitespace after the colon.
2031 value_offset = tvb_skip_wsp(tvb, colon_offset + 1, line_end_offset - (colon_offset + 1));
2036 value_len = (gint) (line_end_offset - value_offset);
2037 value = tvb_get_ephemeral_string(tvb, value_offset, value_len);
2039 if (hf_index == -1) {
2040 proto_item *ti = proto_tree_add_text(hdr_tree, tvb,
2041 offset, next_offset - offset, "%s",
2042 tvb_format_text(tvb, offset, linelen));
2043 header_name = (gchar*)tvb_get_ephemeral_string(tvb, offset, header_len);
2044 ascii_strdown_inplace(header_name);
2045 ext_hdr_handle = dissector_get_string_handle(ext_hdr_subdissector_table, header_name);
2046 if (ext_hdr_handle != NULL) {
2048 next_tvb = tvb_new_subset(tvb, value_offset, value_len, value_len);
2049 dissector_try_string(ext_hdr_subdissector_table, header_name, next_tvb, pinfo, proto_item_add_subtree(ti, ett_sip_ext_hdr));
2051 expert_add_info_format(pinfo, ti,
2052 PI_UNDECODED, PI_NOTE,
2053 "Unrecognised SIP header (%s)",
2054 tvb_format_text(tvb, offset, header_len));
2058 * Add it to the protocol tree,
2059 * but display the line as is.
2061 switch ( hf_index ) {
2065 sip_element_item = proto_tree_add_string_format(hdr_tree,
2066 hf_header_array[hf_index], tvb,
2067 offset, next_offset - offset,
2069 tvb_format_text(tvb, offset, linelen));
2070 sip_element_tree = proto_item_add_subtree( sip_element_item,
2073 /* See if we have a SIP/SIPS uri enclosed in <>, if so anything in front is
2076 parameter_offset = tvb_find_guint8(tvb, value_offset,value_len, '<');
2077 if ( parameter_offset != -1){
2078 len = parameter_offset - value_offset;
2080 /* Something in front, must be display info
2081 * TODO: Get rid of trailing space(s)
2083 proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, value_offset,
2086 parameter_offset ++;
2087 parameter_end_offset = parameter_offset;
2088 /* RFC3261 paragraph 20
2089 * The Contact, From, and To header fields contain a URI. If the URI
2090 * contains a comma, question mark or semicolon, the URI MUST be
2091 * enclosed in angle brackets (< and >). Any URI parameters are
2092 * contained within these brackets. If the URI is not enclosed in angle
2093 * brackets, any semicolon-delimited parameters are header-parameters,
2094 * not URI parameters.
2096 while (parameter_end_offset < line_end_offset){
2097 parameter_end_offset++;
2098 c = tvb_get_guint8(tvb, parameter_end_offset);
2104 goto separator_found;
2110 parameter_len = parameter_end_offset - parameter_offset;
2111 ti = proto_tree_add_item(sip_element_tree, hf_sip_to_addr, tvb, parameter_offset,
2112 parameter_len, FALSE);
2113 to_uri_item_tree = proto_item_add_subtree(ti, ett_sip_to_uri);
2115 /*info for the tap for voip_calls.c*/
2116 stat_info->tap_to_addr=tvb_get_ephemeral_string(tvb, parameter_offset, parameter_len);
2118 parameter_offset = parameter_end_offset + 1;
2122 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,( line_end_offset - parameter_offset), ';');
2123 if ( parameter_end_offset == -1)
2124 parameter_end_offset = line_end_offset;
2126 offset = parameter_end_offset;
2130 /* Extract SIP/SIPS URI */
2131 parameter_offset = value_offset;
2132 while (parameter_offset < line_end_offset
2133 && (tvb_strneql(tvb, parameter_offset, "sip", 3) != 0))
2135 len = parameter_offset - value_offset;
2137 /* Something in front, must be display info
2138 * TODO: Get rid of trailing space(s)
2140 proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, value_offset,
2143 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
2144 (line_end_offset - parameter_offset), ';');
2145 if ( parameter_end_offset == -1)
2146 parameter_end_offset = line_end_offset;
2147 parameter_len = parameter_end_offset - parameter_offset;
2148 ti = proto_tree_add_item(sip_element_tree, hf_sip_to_addr, tvb, parameter_offset,
2149 parameter_len, FALSE);
2150 to_uri_item_tree = proto_item_add_subtree(ti, ett_sip_to_uri);
2152 /*info for the tap for voip_calls.c*/
2153 stat_info->tap_to_addr=tvb_get_ephemeral_string(tvb, parameter_offset, parameter_len);
2154 offset = parameter_end_offset;
2156 if((dissect_sip_uri(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
2158 if(uri_offsets.uri_user_end > uri_offsets.uri_user_start)
2160 proto_tree_add_item(to_uri_item_tree, hf_sip_to_user, tvb, uri_offsets.uri_user_start,
2161 uri_offsets.uri_user_end - uri_offsets.uri_user_start + 1, FALSE);
2164 proto_tree_add_item(to_uri_item_tree, hf_sip_to_host, tvb, uri_offsets.uri_host_start,
2165 uri_offsets.uri_host_end - uri_offsets.uri_host_start + 1, FALSE);
2167 if(uri_offsets.uri_host_port_end > uri_offsets.uri_host_port_start)
2169 proto_tree_add_item(to_uri_item_tree, hf_sip_to_port, tvb, uri_offsets.uri_host_port_start,
2170 uri_offsets.uri_host_port_end - uri_offsets.uri_host_port_start + 1, FALSE);
2174 /* Find parameter tag if present.
2175 * TODO make this generic to find any interesting parameter
2176 * use the same method as for SIP headers ?
2179 parameter_offset = offset;
2180 while (parameter_offset < line_end_offset
2181 && (tvb_strneql(tvb, parameter_offset, "tag=", 4) != 0))
2183 if ( parameter_offset < line_end_offset ){ /* Tag found */
2184 parameter_offset = parameter_offset + 4;
2185 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
2186 (line_end_offset - parameter_offset), ';');
2187 if ( parameter_end_offset == -1)
2188 parameter_end_offset = line_end_offset;
2189 parameter_len = parameter_end_offset - parameter_offset;
2190 proto_tree_add_item(sip_element_tree, hf_sip_tag, tvb, parameter_offset,
2191 parameter_len, FALSE);
2198 sip_element_item = proto_tree_add_string_format(hdr_tree,
2199 hf_header_array[hf_index], tvb,
2200 offset, next_offset - offset,
2202 tvb_format_text(tvb, offset, linelen));
2203 sip_element_tree = proto_item_add_subtree( sip_element_item, ett_sip_element);
2205 /* See if we have a SIP/SIPS uri enclosed in <>, if so anything in front is
2208 parameter_offset = tvb_find_guint8(tvb, value_offset,value_len, '<');
2209 if ( parameter_offset != -1){
2210 len = parameter_offset - value_offset;
2212 /* Something in front, must be display info
2213 * TODO: Get rid of trailing space(s)
2215 proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, value_offset,
2218 parameter_offset ++;
2219 parameter_end_offset = parameter_offset;
2220 /* RFC3261 paragraph 20
2221 * The Contact, From, and To header fields contain a URI. If the URI
2222 * contains a comma, question mark or semicolon, the URI MUST be
2223 * enclosed in angle brackets (< and >). Any URI parameters are
2224 * contained within these brackets. If the URI is not enclosed in angle
2225 * brackets, any semicolon-delimited parameters are header-parameters,
2226 * not URI parameters.
2228 while (parameter_end_offset < line_end_offset){
2229 parameter_end_offset++;
2230 c = tvb_get_guint8(tvb, parameter_end_offset);
2236 goto separator_found2;
2242 parameter_len = parameter_end_offset - parameter_offset;
2243 ti = proto_tree_add_item(sip_element_tree, hf_sip_from_addr, tvb, parameter_offset,
2244 parameter_len, FALSE);
2245 from_uri_item_tree = proto_item_add_subtree(ti, ett_sip_from_uri);
2246 /*info for the tap for voip_calls.c*/
2247 stat_info->tap_from_addr=tvb_get_ephemeral_string(tvb, parameter_offset, parameter_len);
2248 parameter_offset = parameter_end_offset + 1;
2252 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,( line_end_offset - parameter_offset), ';');
2253 if ( parameter_end_offset == -1)
2254 parameter_end_offset = line_end_offset;
2256 offset = parameter_end_offset;
2260 /* Extract SIP/SIPS URI */
2261 parameter_offset = value_offset;
2262 while (parameter_offset < line_end_offset
2263 && (tvb_strneql(tvb, parameter_offset, "sip", 3) != 0))
2265 len = parameter_offset - value_offset;
2267 /* Something in front, must be display info
2268 * TODO: Get rid of trailing space(s)
2270 proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, value_offset,
2273 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
2274 (line_end_offset - parameter_offset), ';');
2275 if ( parameter_end_offset == -1)
2276 parameter_end_offset = line_end_offset;
2277 parameter_len = parameter_end_offset - parameter_offset;
2278 ti = proto_tree_add_item(sip_element_tree, hf_sip_from_addr, tvb, parameter_offset,
2279 parameter_len, FALSE);
2280 from_uri_item_tree = proto_item_add_subtree(ti, ett_sip_from_uri);
2281 /*info for the tap for voip_calls.c*/
2282 stat_info->tap_from_addr=tvb_get_ephemeral_string(tvb, parameter_offset, parameter_len);
2283 offset = parameter_end_offset;
2285 if((dissect_sip_uri(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
2287 if(uri_offsets.uri_user_end > uri_offsets.uri_user_start)
2289 proto_tree_add_item(from_uri_item_tree, hf_sip_from_user, tvb, uri_offsets.uri_user_start,
2290 uri_offsets.uri_user_end - uri_offsets.uri_user_start + 1, FALSE);
2293 proto_tree_add_item(from_uri_item_tree, hf_sip_from_host, tvb, uri_offsets.uri_host_start,
2294 uri_offsets.uri_host_end - uri_offsets.uri_host_start + 1, FALSE);
2296 if(uri_offsets.uri_host_port_end > uri_offsets.uri_host_port_start)
2298 proto_tree_add_item(from_uri_item_tree, hf_sip_from_port, tvb, uri_offsets.uri_host_port_start,
2299 uri_offsets.uri_host_port_end - uri_offsets.uri_host_port_start + 1, FALSE);
2303 /* Find parameter tag if present.
2304 * TODO make this generic to find any interesting parameter
2305 * use the same method as for SIP headers ?
2308 parameter_offset = offset;
2309 while (parameter_offset < line_end_offset
2310 && (tvb_strneql(tvb, parameter_offset, "tag=", 4) != 0))
2312 if ( parameter_offset < line_end_offset ){ /* Tag found */
2313 parameter_offset = parameter_offset + 4;
2314 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
2315 (line_end_offset - parameter_offset), ';');
2316 if ( parameter_end_offset == -1)
2317 parameter_end_offset = line_end_offset;
2318 parameter_len = parameter_end_offset - parameter_offset;
2319 proto_tree_add_item(sip_element_tree, hf_sip_tag, tvb, parameter_offset,
2320 parameter_len, FALSE);
2325 case POS_P_ASSERTED_IDENTITY :
2328 sip_element_item = proto_tree_add_string_format(hdr_tree,
2329 hf_header_array[hf_index], tvb,
2330 offset, next_offset - offset,
2332 tvb_format_text(tvb, offset, linelen));
2333 sip_element_tree = proto_item_add_subtree( sip_element_item,
2338 if((dissect_sip_uri(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
2339 pai_uri_item_tree = display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_pai_uri);
2342 case POS_P_PREFERRED_IDENTITY :
2345 sip_element_item = proto_tree_add_string_format(hdr_tree,
2346 hf_header_array[hf_index], tvb,
2347 offset, next_offset - offset,
2349 tvb_format_text(tvb, offset, linelen));
2350 sip_element_tree = proto_item_add_subtree( sip_element_item,
2354 if((dissect_sip_uri(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
2355 ppi_uri_item_tree = display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_ppi_uri);
2358 case POS_PERMISSION_MISSING :
2361 sip_element_item = proto_tree_add_string_format(hdr_tree,
2362 hf_header_array[hf_index], tvb,
2363 offset, next_offset - offset,
2365 tvb_format_text(tvb, offset, linelen));
2367 sip_element_tree = proto_item_add_subtree( sip_element_item,
2370 if((dissect_sip_uri(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
2371 pmiss_uri_item_tree = display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_pmiss_uri);
2375 case POS_TRIGGER_CONSENT :
2378 sip_element_item = proto_tree_add_string_format(hdr_tree,
2379 hf_header_array[hf_index], tvb,
2380 offset, next_offset - offset,
2382 tvb_format_text(tvb, offset, linelen));
2384 sip_element_tree = proto_item_add_subtree( sip_element_item,
2388 if((dissect_sip_uri(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1) {
2390 tc_uri_item_tree = display_sip_uri(tvb, sip_element_tree, &uri_offsets, &sip_tc_uri);
2391 if (line_end_offset > uri_offsets.uri_end) {
2392 gint hparam_offset = uri_offsets.uri_end + 1;
2393 /* Is there a header parameter */
2394 if (tvb_find_guint8(tvb, hparam_offset, 1,';')) {
2395 while ((hparam_offset != -1 && hparam_offset < line_end_offset) ) {
2396 /* Is this a target-uri ? */
2397 hparam_offset = hparam_offset + 1;
2398 if (tvb_strncaseeql(tvb, hparam_offset, "target-uri=\"", 12) == 0) {
2399 gint turi_start_offset = hparam_offset + 12;
2400 gint turi_end_offset = tvb_find_guint8(tvb, turi_start_offset, -1,'\"');
2401 if (turi_end_offset != -1)
2402 proto_tree_add_item(tc_uri_item_tree, hf_sip_tc_turi, tvb, turi_start_offset,(turi_end_offset - turi_start_offset),FALSE);
2404 break; /* malformed */
2406 hparam_offset = tvb_find_guint8(tvb, hparam_offset, -1,';');
2414 /* Store the sequence number */
2415 cseq_number = atoi(value);
2416 cseq_number_set = 1;
2417 stat_info->tap_cseq_number=cseq_number;
2421 sip_element_item = proto_tree_add_string_format(hdr_tree,
2422 hf_header_array[hf_index], tvb,
2423 offset, next_offset - offset,
2425 tvb_format_text(tvb, offset, linelen));
2426 cseq_tree = proto_item_add_subtree(sip_element_item, ett_sip_cseq);
2429 /* Walk past number and spaces characters to get to start
2431 for (sub_value_offset=0; sub_value_offset < (gint)strlen(value); sub_value_offset++)
2433 if (!isdigit((guchar)value[sub_value_offset]))
2435 proto_tree_add_uint(cseq_tree, hf_sip_cseq_seq_no,
2436 tvb, value_offset, sub_value_offset,
2442 for (; sub_value_offset < (gint)strlen(value); sub_value_offset++)
2444 if (isalpha((guchar)value[sub_value_offset]))
2446 /* Have reached start of method name */
2451 if (sub_value_offset == (gint)strlen(value))
2453 /* Didn't find method name */
2454 THROW(ReportedBoundsError);
2455 return offset - orig_offset;
2458 /* Extract method name from value */
2459 strlen_to_copy = (int)strlen(value)-sub_value_offset;
2460 if (strlen_to_copy > MAX_CSEQ_METHOD_SIZE) {
2461 /* Note the error in the protocol tree */
2463 proto_tree_add_string_format(hdr_tree,
2464 hf_header_array[hf_index], tvb,
2465 offset, next_offset - offset,
2466 value+sub_value_offset, "%s String too big: %d bytes",
2467 sip_headers[POS_CSEQ].name,
2470 THROW(ReportedBoundsError);
2471 return offset - orig_offset;
2474 g_strlcpy(cseq_method, value+sub_value_offset, MAX_CSEQ_METHOD_SIZE);
2476 /* Add CSeq method to the tree */
2479 proto_tree_add_item(cseq_tree, hf_sip_cseq_method, tvb,
2480 value_offset + sub_value_offset, strlen_to_copy, FALSE);
2488 int cseq_method_offset;
2492 sip_element_item = proto_tree_add_string_format(hdr_tree,
2493 hf_header_array[hf_index], tvb,
2494 offset, next_offset - offset,
2496 tvb_format_text(tvb, offset, linelen));
2497 rack_tree = proto_item_add_subtree(sip_element_item, ett_sip_rack);
2501 for (sub_value_offset=0; sub_value_offset < (gint)strlen(value); sub_value_offset++)
2503 if (!isdigit((guchar)value[sub_value_offset]))
2505 proto_tree_add_uint(rack_tree, hf_sip_rack_rseq_no,
2506 tvb, value_offset, sub_value_offset,
2512 /* Get to start of CSeq number */
2513 for ( ; sub_value_offset < (gint)strlen(value); sub_value_offset++)
2515 if (value[sub_value_offset] != ' ' &&
2516 value[sub_value_offset] != '\t')
2521 cseq_no_offset = sub_value_offset;
2524 for ( ; sub_value_offset < (gint)strlen(value); sub_value_offset++)
2526 if (!isdigit((guchar)value[sub_value_offset]))
2528 proto_tree_add_uint(rack_tree, hf_sip_rack_cseq_no,
2529 tvb, value_offset+cseq_no_offset,
2530 sub_value_offset-cseq_no_offset,
2531 atoi(value+cseq_no_offset));
2536 /* Get to start of CSeq method name */
2537 for ( ; sub_value_offset < (gint)strlen(value); sub_value_offset++)
2539 if (isalpha((guchar)value[sub_value_offset]))
2541 /* Have reached start of method name */
2545 cseq_method_offset = sub_value_offset;
2547 if (sub_value_offset == (gint)strlen(value))
2549 /* Didn't find method name */
2550 THROW(ReportedBoundsError);
2551 return offset - orig_offset;
2554 /* Add CSeq method to the tree */
2557 proto_tree_add_item(rack_tree, hf_sip_rack_cseq_method, tvb,
2558 value_offset + sub_value_offset,
2559 (int)strlen(value)-sub_value_offset, FALSE);
2566 /* Store the Call-id */
2567 g_strlcpy(call_id, value, MAX_CALL_ID_SIZE);
2568 stat_info->tap_call_id = ep_strdup(call_id);
2570 /* Add 'Call-id' string item to tree */
2572 sip_element_item = proto_tree_add_string_format(hdr_tree,
2573 hf_header_array[hf_index], tvb,
2574 offset, next_offset - offset,
2576 tvb_format_text(tvb, offset, linelen));
2581 if (strcmp(value, "0") == 0)
2585 /* Add 'Expires' string item to tree */
2587 sip_element_item = proto_tree_add_uint(hdr_tree,
2588 hf_header_array[hf_index], tvb,
2589 offset, next_offset - offset,
2595 * Content-Type is the same as Internet
2596 * media type used by other dissectors,
2597 * appropriate dissector found by
2598 * lookup in "media_type" dissector table.
2600 case POS_CONTENT_TYPE :
2602 sip_element_item = proto_tree_add_string_format(hdr_tree,
2603 hf_header_array[hf_index], tvb,
2604 offset, next_offset - offset,
2606 tvb_format_text(tvb, offset, linelen));
2608 content_type_len = value_len;
2609 semi_colon_offset = tvb_find_guint8(tvb, value_offset, value_len, ';');
2610 /* Content-Type = ( "Content-Type" / "c" ) HCOLON media-type
2611 * media-type = m-type SLASH m-subtype *(SEMI m-parameter)
2612 * SEMI = SWS ";" SWS ; semicolon
2613 * LWS = [*WSP CRLF] 1*WSP ; linear whitespace
2614 * SWS = [LWS] ; sep whitespace
2616 if ( semi_colon_offset != -1) {
2617 gint content_type_end;
2619 * Skip whitespace after the semicolon.
2621 parameter_offset = tvb_skip_wsp(tvb, semi_colon_offset +1, value_offset + value_len - (semi_colon_offset +1));
2622 content_type_end = tvb_skip_wsp_return(tvb, semi_colon_offset-1);
2623 content_type_len = content_type_end - value_offset;
2624 content_type_parameter_str_len = value_offset + value_len - parameter_offset;
2625 content_type_parameter_str = tvb_get_ephemeral_string(tvb, parameter_offset,
2626 content_type_parameter_str_len);
2628 media_type_str_lower_case = ascii_strdown_inplace(
2629 (gchar *)tvb_get_ephemeral_string(tvb, value_offset, content_type_len));
2632 proto_tree_add_text(hdr_tree, tvb, value_offset,content_type_len,
2633 "media_type_str(lower cased)=%s",media_type_str_lower_case);
2637 case POS_CONTENT_LENGTH :
2638 content_length = atoi(value);
2640 sip_element_item = proto_tree_add_uint_format(hdr_tree,
2641 hf_header_array[hf_index], tvb,
2642 offset, next_offset - offset,
2643 content_length, "%s",
2644 tvb_format_text(tvb, offset, linelen));
2648 case POS_MAX_BREADTH :
2649 case POS_MAX_FORWARDS :
2652 sip_element_item = proto_tree_add_uint(hdr_tree,
2653 hf_header_array[hf_index], tvb,
2654 offset, next_offset - offset,
2661 sip_element_item = proto_tree_add_string_format(hdr_tree,
2662 hf_header_array[hf_index], tvb,
2663 offset, next_offset - offset,
2665 tvb_format_text(tvb, offset, linelen));
2666 sip_element_tree = proto_item_add_subtree( sip_element_item,
2669 if (strcmp(value, "*") == 0)
2671 contact_is_star = 1;
2675 comma_offset = value_offset;
2676 while((comma_offset = dissect_sip_contact_item(tvb, pinfo, sip_element_tree, comma_offset, next_offset)) != -1)
2679 if(comma_offset == next_offset)
2681 /* Line End reached: Stop Parsing */
2685 if(tvb_get_guint8(tvb, comma_offset) != ',')
2687 /* Undefined value reached: Stop Parsing */
2690 comma_offset++; /* skip comma */
2694 case POS_AUTHORIZATION:
2695 case POS_WWW_AUTHENTICATE:
2696 case POS_PROXY_AUTHENTICATE:
2697 case POS_PROXY_AUTHORIZATION:
2698 case POS_AUTHENTICATION_INFO:
2699 /* Add tree using whole text of line */
2702 /* Add whole line as header tree */
2703 sip_element_item = proto_tree_add_string_format(hdr_tree,
2704 hf_header_array[hf_index], tvb,
2705 offset, next_offset - offset,
2707 tvb_format_text(tvb, offset, linelen));
2708 sip_element_tree = proto_item_add_subtree( sip_element_item,
2711 /* Set sip.auth as a hidden field/filter */
2712 ti = proto_tree_add_item(hdr_tree, hf_sip_auth, tvb,
2713 offset, next_offset-offset,
2715 PROTO_ITEM_SET_HIDDEN(ti);
2718 /* Parse each individual parameter in the line */
2719 comma_offset = tvb_pbrk_guint8(tvb, value_offset, line_end_offset - value_offset, " \t\r\n");
2721 /* Authentication-Info does not begin with the scheme name */
2722 if (hf_index != POS_AUTHENTICATION_INFO)
2724 proto_tree_add_item(sip_element_tree, hf_sip_auth_scheme,
2725 tvb, value_offset, comma_offset - value_offset,
2729 while ((comma_offset = dissect_sip_authorization_item(tvb, sip_element_tree, comma_offset, line_end_offset)) != -1)
2731 if(comma_offset == line_end_offset)
2733 /* Line End reached: Stop Parsing */
2737 if(tvb_get_guint8(tvb, comma_offset) != ',')
2739 /* Undefined value reached: Stop Parsing */
2742 comma_offset++; /* skip comma */
2747 /* Add Via subtree */
2749 sip_element_item = proto_tree_add_string_format(hdr_tree,
2750 hf_header_array[hf_index], tvb,
2751 offset, next_offset - offset,
2753 tvb_format_text(tvb, offset, linelen));
2754 via_tree = proto_item_add_subtree(sip_element_item, ett_sip_via);
2756 dissect_sip_via_header(tvb, via_tree, value_offset, line_end_offset);
2760 sip_element_item = proto_tree_add_string_format(hdr_tree,
2761 hf_header_array[hf_index], tvb,
2762 offset, next_offset - offset,
2764 tvb_format_text(tvb, offset, linelen));
2765 reason_tree = proto_item_add_subtree(sip_element_item, ett_sip_reason);
2767 dissect_sip_reason_header(tvb, reason_tree, value_offset, line_end_offset);
2770 /* Default case is to assume its an FT_STRING field */
2772 sip_element_item = proto_tree_add_string_format(hdr_tree,
2773 hf_header_array[hf_index], tvb,
2774 offset, next_offset - offset,
2776 tvb_format_text(tvb, offset, linelen));
2781 }/* if colon_offset */
2782 if (is_no_header_termination == TRUE){
2783 /* Header not terminated by empty line CRLF */
2784 cause=proto_tree_add_text(hdr_tree, tvb, line_end_offset, -1,
2785 "[Header not terminated by empty line (CRLF)]");
2787 proto_item_set_expert_flags(cause, PI_MALFORMED, PI_WARN);
2788 expert_add_info_format(pinfo, sip_element_item,
2789 PI_MALFORMED, PI_WARN,
2790 "Header not terminated by empty line (CRLF)");
2792 offset = next_offset;
2795 datalen = tvb_length_remaining(tvb, offset);
2796 reported_datalen = tvb_reported_length_remaining(tvb, offset);
2797 if (content_length != -1) {
2798 if (datalen > content_length)
2799 datalen = content_length;
2800 if (reported_datalen > content_length)
2801 reported_datalen = content_length;
2806 * There's a message body starting at "offset".
2807 * Set the length of the header item.
2809 proto_item_set_end(th, tvb, offset);
2810 next_tvb = tvb_new_subset(tvb, offset, datalen, reported_datalen);
2812 ti = proto_tree_add_item(sip_tree, hf_sip_msg_body, next_tvb, 0, -1,
2814 message_body_tree = proto_item_add_subtree(ti, ett_sip_message_body);
2817 /* give the content type parameters to sub dissectors */
2819 if ( media_type_str_lower_case != NULL ) {
2820 void *save_private_data = pinfo->private_data;
2821 pinfo->private_data = content_type_parameter_str;
2822 found_match = dissector_try_string(media_type_dissector_table,
2823 media_type_str_lower_case,
2826 pinfo->private_data = save_private_data;
2827 /* If no match dump as text */
2829 if ( found_match != TRUE )
2831 if (!(dissector_try_heuristic(heur_subdissector_list,
2832 next_tvb, pinfo, message_body_tree))) {
2834 while (tvb_offset_exists(next_tvb, tmp_offset)) {
2835 tvb_find_line_end(next_tvb, tmp_offset, -1, &next_offset, FALSE);
2836 linelen = next_offset - tmp_offset;
2837 if(message_body_tree) {
2838 proto_tree_add_text(message_body_tree, next_tvb,
2839 tmp_offset, linelen, "%s",
2840 tvb_format_text(next_tvb, tmp_offset, linelen));
2842 tmp_offset = next_offset;
2850 /* Add to info column interesting things learned from header fields. */
2851 if (check_col(pinfo->cinfo, COL_INFO))
2853 /* Registration requests */
2854 if (strcmp(sip_methods[current_method_idx], "REGISTER") == 0)
2856 if (contact_is_star && expires_is_0)
2858 col_append_str(pinfo->cinfo, COL_INFO, " (remove all bindings)");
2863 col_append_str(pinfo->cinfo, COL_INFO, " (fetch bindings)");
2867 /* Registration responses */
2868 if (line_type == STATUS_LINE && (strcmp(cseq_method, "REGISTER") == 0))
2870 col_append_fstr(pinfo->cinfo, COL_INFO, " (%d bindings)", contacts);
2873 /* Find the total setup time, Must be done before checking for resend
2874 * As that will overwrite the "Request packet no".
2876 if ((line_type == REQUEST_LINE)&&(strcmp(cseq_method, "ACK") == 0))
2878 request_for_response = sip_find_invite(pinfo, cseq_method, call_id,
2879 cseq_number_set, cseq_number,
2881 stat_info->setup_time = response_time;
2884 /* Check if this packet is a resend. */
2885 resend_for_packet = sip_is_packet_resend(pinfo, cseq_method, call_id,
2886 cseq_number_set, cseq_number,
2888 /* Mark whether this is a resend for the tap */
2889 stat_info->resend = (resend_for_packet > 0);
2891 /* And add the filterable field to the request/response line */
2895 item = proto_tree_add_boolean(reqresp_tree, hf_sip_resend, tvb, orig_offset, 0,
2896 resend_for_packet > 0);
2897 PROTO_ITEM_SET_GENERATED(item);
2898 if (resend_for_packet > 0)
2900 item = proto_tree_add_uint(reqresp_tree, hf_sip_original_frame,
2901 tvb, orig_offset, 0, resend_for_packet);
2902 PROTO_ITEM_SET_GENERATED(item);
2906 /* For responses, try to link back to request frame */
2907 if (line_type == STATUS_LINE)
2909 request_for_response = sip_find_request(pinfo, cseq_method, call_id,
2910 cseq_number_set, cseq_number,
2917 if (request_for_response > 0)
2919 item = proto_tree_add_uint(reqresp_tree, hf_sip_matching_request_frame,
2920 tvb, orig_offset, 0, request_for_response);
2921 PROTO_ITEM_SET_GENERATED(item);
2922 item = proto_tree_add_uint(reqresp_tree, hf_sip_response_time,
2923 tvb, orig_offset, 0, response_time);
2924 PROTO_ITEM_SET_GENERATED(item);
2925 if ((line_type == STATUS_LINE)&&(strcmp(cseq_method, "BYE") == 0)){
2926 item = proto_tree_add_uint(reqresp_tree, hf_sip_release_time,
2927 tvb, orig_offset, 0, response_time);
2928 PROTO_ITEM_SET_GENERATED(item);
2934 proto_item_set_len(ts, offset - orig_offset);
2936 if (global_sip_raw_text)
2937 tvb_raw_text_add(tvb, orig_offset, offset - orig_offset, tree);
2939 /* Report this packet to the tap */
2940 if (!pinfo->in_error_pkt)
2942 tap_queue_packet(sip_tap, pinfo, stat_info);
2945 return offset - orig_offset;
2948 /* Display filter for SIP Request-Line */
2950 dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, guint meth_len)
2954 gint next_offset, linelen, parameter_end_offset;
2956 guint parameter_len = meth_len;
2958 proto_tree *ruri_item_tree = NULL;
2962 * We know we have the entire method; otherwise, "sip_parse_line()"
2963 * would have returned OTHER_LINE.
2964 * Request-Line = Method SP Request-URI SP SIP-Version CRLF
2968 /* get method string*/
2969 value = tvb_get_ephemeral_string(tvb, offset, parameter_len);
2971 /* Copy request method for telling tap */
2972 stat_info->request_method = value;
2974 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
2977 proto_tree_add_string(tree, hf_Method, tvb, offset, parameter_len, value);
2979 /* build Request-URI tree*/
2980 offset=parameter_len+1;
2981 parameter_len = (tvb_find_guint8(tvb, offset, linelen, ' '))-offset; /* calc R-URI len*/
2982 ti = proto_tree_add_item(tree, hf_sip_ruri, tvb, offset, parameter_len, FALSE);
2983 ruri_item_tree = proto_item_add_subtree(ti, ett_sip_ruri);
2985 offset = (tvb_find_guint8(tvb, offset, linelen, ':'))+1; /* calc R-URI User/Host begin*/
2986 if ((tvb_find_guint8(tvb, offset, linelen, '@')) != -1){
2987 /* R-URI: User Part found*/
2988 parameter_len = (tvb_find_guint8(tvb, offset, linelen, '@'))-offset; /* calc R-URI User len*/
2989 if (parameter_len > 0) {
2990 proto_tree_add_item(ruri_item_tree, hf_sip_ruri_user, tvb, offset,
2991 parameter_len, FALSE);
2993 offset = offset + parameter_len + 1;
2995 parameter_end_offset=offset;
2997 while (parameter_end_offset < linelen){
2998 parameter_end_offset++;
2999 c = tvb_get_guint8(tvb, parameter_end_offset);
3006 goto host_end_found;
3012 parameter_len = parameter_end_offset-offset; /* calc R-URI host len*/
3013 proto_tree_add_item(ruri_item_tree, hf_sip_ruri_host, tvb, offset, parameter_len, FALSE);
3015 offset = offset + parameter_len + 1;
3018 /* R-URI: Host Port found */
3019 parameter_end_offset = offset;
3020 while (parameter_end_offset < linelen){
3021 parameter_end_offset++;
3022 c = tvb_get_guint8(tvb, parameter_end_offset);
3028 goto host_port_end_found;
3033 host_port_end_found:
3034 parameter_len = parameter_end_offset-offset; /* calc R-URI Host Port len*/
3035 proto_tree_add_item(ruri_item_tree, hf_sip_ruri_port, tvb, offset, parameter_len, FALSE);
3037 /* end of Request-URI tree*/
3041 /* Display filter for SIP Status-Line */
3043 dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree)
3046 gint response_code = 0;
3049 * We know we have the entire status code; otherwise,
3050 * "sip_parse_line()" would have returned OTHER_LINE.
3051 * We also know that we have a version string followed by a
3052 * space at the beginning of the line, for the same reason.
3054 tvb_memcpy(tvb, (guint8 *)string, SIP2_HDR_LEN + 1, 3);
3056 response_code = atoi(string);
3058 /* Add numerical response code to tree */
3060 proto_tree_add_uint(tree, hf_Status_Code, tvb, SIP2_HDR_LEN + 1,
3064 /* Add response code for sending to tap */
3065 stat_info->response_code = response_code;
3068 /* From section 4.1 of RFC 2543:
3070 * Request-Line = Method SP Request-URI SP SIP-Version CRLF
3072 * From section 5.1 of RFC 2543:
3074 * Status-Line = SIP-version SP Status-Code SP Reason-Phrase CRLF
3076 * From section 7.1 of RFC 3261:
3078 * Unlike HTTP, SIP treats the version number as a literal string.
3079 * In practice, this should make no difference.
3082 sip_parse_line(tvbuff_t *tvb, int offset, gint linelen, guint *token_1_lenp)
3093 token_1_start = offset;
3094 space_offset = tvb_find_guint8(tvb, token_1_start, -1, ' ');
3095 if ((space_offset == -1) || (space_offset == token_1_start)) {
3097 * Either there's no space in the line (which means
3098 * the line is empty or doesn't have a token followed
3099 * by a space; neither is valid for a request or status), or
3100 * the first character in the line is a space (meaning
3101 * the method is empty, which isn't valid for a request,
3102 * or the SIP version is empty, which isn't valid for a
3107 token_1_len = space_offset - token_1_start;
3108 token_2_start = space_offset + 1;
3109 space_offset = tvb_find_guint8(tvb, token_2_start, -1, ' ');
3110 if (space_offset == -1) {
3112 * There's no space after the second token, so we don't
3113 * have a third token.
3117 token_2_len = space_offset - token_2_start;
3118 token_3_start = space_offset + 1;
3119 token_3_len = token_1_start + linelen - token_3_start;
3121 *token_1_lenp = token_1_len;
3124 * Is the first token a version string?
3126 if ( (strict_sip_version && (
3127 token_1_len == SIP2_HDR_LEN
3128 && tvb_strneql(tvb, token_1_start, SIP2_HDR, SIP2_HDR_LEN) == 0)
3129 ) || (! strict_sip_version && (
3130 tvb_strncaseeql(tvb, token_1_start, "SIP/", 4) == 0)
3133 * Yes, so this is either a Status-Line or something
3134 * else other than a Request-Line. To be a Status-Line,
3135 * the second token must be a 3-digit number.
3137 if (token_2_len != 3) {
3139 * We don't have 3-character status code.
3143 if (!isdigit(tvb_get_guint8(tvb, token_2_start)) ||
3144 !isdigit(tvb_get_guint8(tvb, token_2_start + 1)) ||
3145 !isdigit(tvb_get_guint8(tvb, token_2_start + 2))) {
3147 * 3 characters yes, 3 digits no.
3154 * No, so this is either a Request-Line or something
3155 * other than a Status-Line. To be a Request-Line, the
3156 * second token must be a URI and the third token must
3157 * be a version string.
3159 if (token_2_len < 3) {
3161 * We don't have a URI consisting of at least 3
3166 colon_pos = tvb_find_guint8(tvb, token_2_start + 1, -1, ':');
3167 if (colon_pos == -1) {
3169 * There is no colon after the method, so the URI
3170 * doesn't have a colon in it, so it's not valid.
3174 if (colon_pos >= token_3_start) {
3176 * The colon is in the version string, not the URI.
3180 /* XXX - Check for a proper URI prefix? */
3181 if ( (strict_sip_version && (
3182 token_3_len != SIP2_HDR_LEN
3183 || tvb_strneql(tvb, token_3_start, SIP2_HDR, SIP2_HDR_LEN) == -1)
3184 ) || (! strict_sip_version && (
3185 tvb_strncaseeql(tvb, token_3_start, "SIP/", 4) == -1)
3188 * The version string isn't an SIP version 2.0 version
3193 return REQUEST_LINE;
3197 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
3198 guint meth_len, guint *meth_idx)
3202 for (i = 1; i < array_length(sip_methods); i++) {
3203 if (meth_len == strlen(sip_methods[i]) &&
3204 tvb_strneql(tvb, meth_offset, sip_methods[i], meth_len) == 0)
3214 /* Returns index of method in sip_headers */
3215 static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset, guint header_len)
3219 for (i = 1; i < array_length(sip_headers); i++) {
3220 if (header_len == strlen(sip_headers[i].name) &&
3221 tvb_strncaseeql(tvb, offset, sip_headers[i].name, header_len) == 0)
3223 if (sip_headers[i].compact_name != NULL &&
3224 header_len == strlen(sip_headers[i].compact_name) &&
3225 tvb_strncaseeql(tvb, offset, sip_headers[i].compact_name, header_len) == 0)
3233 * Display the entire message as raw text.
3236 tvb_raw_text_add(tvbuff_t *tvb, int offset, int length, proto_tree *tree)
3238 proto_tree *raw_tree = NULL;
3239 proto_item *ti = NULL;
3240 int next_offset, linelen, end_offset;
3243 ti = proto_tree_add_item(tree, proto_raw_sip, tvb, offset, length, FALSE);
3244 raw_tree = proto_item_add_subtree(ti, ett_raw_text);
3247 end_offset = offset + length;
3249 while (offset < end_offset) {
3250 tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
3251 linelen = next_offset - offset;
3253 proto_tree_add_string_format(raw_tree, hf_raw_sip_line, tvb, offset, linelen,
3254 tvb_format_text(tvb, offset, linelen),
3256 tvb_format_text(tvb, offset, linelen));
3258 offset = next_offset;
3262 /* Check to see if this packet is a resent request. Return value is the frame number
3263 of the original frame this packet seems to be resending (0 = no resend). */
3264 guint sip_is_packet_resend(packet_info *pinfo,
3267 guchar cseq_number_set,
3268 guint32 cseq_number, line_type_t line_type)
3270 guint32 cseq_to_compare = 0;
3272 sip_hash_key *p_key = 0;
3273 sip_hash_value *p_val = 0;
3274 sip_frame_result_value *sip_frame_result = NULL;
3277 /* Only consider retransmission of UDP packets */
3278 if (pinfo->ptype != PT_UDP)
3283 /* Don't consider packets that appear to be resent only because
3284 they are e.g. returned in ICMP unreachable messages. */
3285 if (pinfo->in_error_pkt)
3290 /* A broken packet may have no cseq number set. Don't consider it as
3292 if (!cseq_number_set)
3297 /* Return any answer stored from previous dissection */
3298 if (pinfo->fd->flags.visited)
3300 sip_frame_result = (sip_frame_result_value*)p_get_proto_data(pinfo->fd, proto_sip);
3301 if (sip_frame_result != NULL)
3303 return sip_frame_result->original_frame_num;
3311 /* No packet entry found, consult global hash table */
3313 /* Prepare the key */
3314 g_strlcpy(key.call_id, call_id, MAX_CALL_ID_SIZE);
3316 /* We're only using these addresses locally (for the hash lookup) so
3317 * there is no need to make a (g_malloc'd) copy of them.
3319 SET_ADDRESS(&key.dest_address, pinfo->net_dst.type, pinfo->net_dst.len,
3320 pinfo->net_dst.data);
3321 SET_ADDRESS(&key.source_address, pinfo->net_src.type,
3322 pinfo->net_src.len, pinfo->net_src.data);
3323 key.dest_port = pinfo->destport;
3324 key.source_port = pinfo->srcport;
3327 p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
3331 /* Table entry found, we'll use its value for comparison */
3332 cseq_to_compare = p_val->cseq;
3334 /* First time through, must update value with current details if
3335 cseq number has changed */
3336 if (cseq_number != p_val->cseq)
3338 p_val->cseq = cseq_number;
3339 g_strlcpy(p_val->method, cseq_method, MAX_CSEQ_METHOD_SIZE);
3340 p_val->transaction_state = nothing_seen;
3341 p_val->frame_number = 0;
3342 if (line_type == REQUEST_LINE)
3344 p_val->request_time = pinfo->fd->abs_ts;
3350 /* Need to create a new table entry */
3352 /* Allocate a new key and value */
3353 p_key = se_alloc(sizeof(sip_hash_key));
3354 p_val = se_alloc(sizeof(sip_hash_value));
3356 /* Just give up if allocations failed */
3357 if (!p_key || !p_val)
3362 /* Fill in key and value details */
3363 g_snprintf(p_key->call_id, MAX_CALL_ID_SIZE, "%s", call_id);
3364 SE_COPY_ADDRESS(&(p_key->dest_address), &pinfo->net_dst);
3365 SE_COPY_ADDRESS(&(p_key->source_address), &pinfo->net_src);
3366 p_key->dest_port = pinfo->destport;
3367 p_key->source_port = pinfo->srcport;
3369 p_val->cseq = cseq_number;
3370 g_strlcpy(p_val->method, cseq_method, MAX_CSEQ_METHOD_SIZE);
3371 p_val->transaction_state = nothing_seen;
3372 p_val->frame_number = 0;
3373 if (line_type == REQUEST_LINE)
3375 p_val->request_time = pinfo->fd->abs_ts;
3379 g_hash_table_insert(sip_hash, p_key, p_val);
3381 /* Assume have seen no cseq yet */
3382 cseq_to_compare = 0;
3386 /******************************************/
3387 /* Is it a resend??? */
3389 /* Does this look like a resent request (discount ACK, CANCEL, or a
3390 different method from the original one) ? */
3392 if ((line_type == REQUEST_LINE) && (cseq_number == cseq_to_compare) &&
3393 (p_val->transaction_state == request_seen) &&
3394 (strcmp(cseq_method, p_val->method) == 0) &&
3395 (strcmp(cseq_method, "ACK") != 0) &&
3396 (strcmp(cseq_method, "CANCEL") != 0))
3398 result = p_val->frame_number;
3401 /* Does this look like a resent final response ? */
3402 if ((line_type == STATUS_LINE) && (cseq_number == cseq_to_compare) &&
3403 (p_val->transaction_state == final_response_seen) &&
3404 (strcmp(cseq_method, p_val->method) == 0) &&
3405 (stat_info->response_code >= 200) &&
3406 (stat_info->response_code == p_val->response_code))
3408 result = p_val->frame_number;
3411 /* Update state for this entry */
3412 p_val->cseq = cseq_number;
3417 p_val->transaction_state = request_seen;
3420 /* This frame is the original request */
3421 p_val->frame_number = pinfo->fd->num;
3425 if (stat_info->response_code >= 200)
3427 p_val->response_code = stat_info->response_code;
3428 p_val->transaction_state = final_response_seen;
3431 /* This frame is the original response */
3432 p_val->frame_number = pinfo->fd->num;
3437 p_val->transaction_state = provisional_response_seen;
3444 sip_frame_result = p_get_proto_data(pinfo->fd, proto_sip);
3445 if (sip_frame_result == NULL)
3447 sip_frame_result = se_alloc(sizeof(sip_frame_result_value));
3450 /* Store return value with this packet */
3451 sip_frame_result->original_frame_num = result;
3452 p_add_proto_data(pinfo->fd, proto_sip, sip_frame_result);
3458 /* Check to see if this packet is a resent request. Return value is the frame number
3459 of the original frame this packet seems to be resending (0 = no resend). */
3460 guint sip_find_request(packet_info *pinfo,
3463 guchar cseq_number_set,
3464 guint32 cseq_number,
3465 guint32 *response_time)
3467 guint32 cseq_to_compare = 0;
3469 sip_hash_value *p_val = 0;
3470 sip_frame_result_value *sip_frame_result = NULL;
3472 gint seconds_between_packets;
3473 gint nseconds_between_packets;
3475 /* Only consider UDP */
3476 if (pinfo->ptype != PT_UDP)
3481 /* Ignore error (usually ICMP) frames */
3482 if (pinfo->in_error_pkt)
3487 /* A broken packet may have no cseq number set. Ignore. */
3488 if (!cseq_number_set)
3493 /* Return any answer stored from previous dissection */
3494 if (pinfo->fd->flags.visited)
3496 sip_frame_result = (sip_frame_result_value*)p_get_proto_data(pinfo->fd, proto_sip);
3497 if (sip_frame_result != NULL)
3499 *response_time = sip_frame_result->response_time;
3500 return sip_frame_result->response_request_frame_num;
3508 /* No packet entry found, consult global hash table */
3510 /* Prepare the key */
3511 g_strlcpy(key.call_id, call_id, MAX_CALL_ID_SIZE);
3513 /* Looking for matching request, so reverse addresses for this lookup */
3514 SET_ADDRESS(&key.dest_address, pinfo->net_src.type, pinfo->net_src.len,
3515 pinfo->net_src.data);
3516 SET_ADDRESS(&key.source_address, pinfo->net_dst.type, pinfo->net_dst.len,
3517 pinfo->net_dst.data);
3518 key.dest_port = pinfo->srcport;
3519 key.source_port = pinfo->destport;
3522 p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
3526 /* Table entry found, we'll use its value for comparison */
3527 cseq_to_compare = p_val->cseq;
3531 /* We don't have the request */
3536 /**************************************************/
3537 /* Is it a response to a request that we've seen? */
3538 if ((cseq_number == cseq_to_compare) &&
3539 (p_val->transaction_state == request_seen) &&
3540 (strcmp(cseq_method, p_val->method) == 0))
3542 result = p_val->frame_number;
3546 /* Store return value with this packet */
3547 sip_frame_result = p_get_proto_data(pinfo->fd, proto_sip);
3548 if (sip_frame_result == NULL)
3550 /* Allocate and set all values to zero */
3551 sip_frame_result = se_alloc0(sizeof(sip_frame_result_value));
3554 sip_frame_result->response_request_frame_num = result;
3556 /* Work out response time */
3557 seconds_between_packets = (gint)
3558 (pinfo->fd->abs_ts.secs - p_val->request_time.secs);
3559 nseconds_between_packets =
3560 pinfo->fd->abs_ts.nsecs - p_val->request_time.nsecs;
3561 sip_frame_result->response_time = (seconds_between_packets*1000) +
3562 (nseconds_between_packets / 1000000);
3563 *response_time = sip_frame_result->response_time;
3565 p_add_proto_data(pinfo->fd, proto_sip, sip_frame_result);
3571 * Find the initial INVITE to calculate the total setup time
3573 guint sip_find_invite(packet_info *pinfo,
3574 gchar *cseq_method _U_,
3576 guchar cseq_number_set,
3577 guint32 cseq_number _U_,
3578 guint32 *response_time)
3580 guint32 cseq_to_compare = 0;
3582 sip_hash_value *p_val = 0;
3583 sip_frame_result_value *sip_frame_result = NULL;
3585 gint seconds_between_packets;
3586 gint nseconds_between_packets;
3588 /* Only consider UDP */
3589 if (pinfo->ptype != PT_UDP)
3594 /* Ignore error (usually ICMP) frames */
3595 if (pinfo->in_error_pkt)
3600 /* A broken packet may have no cseq number set. Ignore. */
3601 if (!cseq_number_set)
3606 /* Return any answer stored from previous dissection */
3607 if (pinfo->fd->flags.visited)
3609 sip_frame_result = (sip_frame_result_value*)p_get_proto_data(pinfo->fd, proto_sip);
3610 if (sip_frame_result != NULL)
3612 *response_time = sip_frame_result->response_time;
3613 return sip_frame_result->response_request_frame_num;
3621 /* No packet entry found, consult global hash table */
3623 /* Prepare the key */
3624 g_strlcpy(key.call_id, call_id, MAX_CALL_ID_SIZE);
3626 /* Looking for matching INVITE */
3627 SET_ADDRESS(&key.dest_address, pinfo->net_dst.type, pinfo->net_dst.len,
3628 pinfo->net_dst.data);
3629 SET_ADDRESS(&key.source_address, pinfo->net_src.type, pinfo->net_src.len,
3630 pinfo->net_src.data);
3631 key.dest_port = pinfo->destport;
3632 key.source_port = pinfo->srcport;
3635 p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
3639 /* Table entry found, we'll use its value for comparison */
3640 cseq_to_compare = p_val->cseq;
3644 /* We don't have the request */
3649 /**************************************************/
3650 /* Is it a response to a request that we've seen? */
3652 if ((cseq_number == cseq_to_compare) &&
3653 (p_val->transaction_state == request_seen) &&
3654 (strcmp(cseq_method, p_val->method) == 0))
3656 result = p_val->frame_number;
3660 result = p_val->frame_number;
3662 /* Store return value with this packet */
3663 sip_frame_result = p_get_proto_data(pinfo->fd, proto_sip);
3664 if (sip_frame_result == NULL)
3666 /* Allocate and set all values to zero */
3667 sip_frame_result = se_alloc0(sizeof(sip_frame_result_value));
3670 sip_frame_result->response_request_frame_num = result;
3672 /* Work out response time */
3673 seconds_between_packets = (gint)
3674 (pinfo->fd->abs_ts.secs - p_val->request_time.secs);
3675 nseconds_between_packets =
3676 pinfo->fd->abs_ts.nsecs - p_val->request_time.nsecs;
3677 sip_frame_result->response_time = (seconds_between_packets*1000) +
3678 (nseconds_between_packets / 1000000);
3679 *response_time = sip_frame_result->response_time;
3681 p_add_proto_data(pinfo->fd, proto_sip, sip_frame_result);
3687 /* Register the protocol with Wireshark */
3688 void proto_register_sip(void)
3691 /* Setup list of header fields */
3692 static hf_register_info hf[] = {
3695 { "Message Header", "sip.msg_hdr",
3696 FT_STRING, BASE_NONE, NULL, 0,
3697 "Message Header in SIP message", HFILL }
3700 { "Method", "sip.Method",
3701 FT_STRING, BASE_NONE,NULL,0x0,
3702 "SIP Method", HFILL }
3705 { "Request-Line", "sip.Request-Line",
3706 FT_STRING, BASE_NONE,NULL,0x0,
3707 "SIP Request-Line", HFILL }
3710 { "Request-URI", "sip.r-uri",
3711 FT_STRING, BASE_NONE,NULL,0x0,
3712 "RFC 3261: SIP R-URI", HFILL }
3714 { &hf_sip_ruri_user,
3715 { "Request-URI User Part", "sip.r-uri.user",
3716 FT_STRING, BASE_NONE,NULL,0x0,
3717 "RFC 3261: SIP R-URI User", HFILL }
3719 { &hf_sip_ruri_host,
3720 { "Request-URI Host Part", "sip.r-uri.host",
3721 FT_STRING, BASE_NONE,NULL,0x0,
3722 "RFC 3261: SIP R-URI Host", HFILL }
3724 { &hf_sip_ruri_port,
3725 { "Request-URI Host Port", "sip.r-uri.port",
3726 FT_STRING, BASE_NONE,NULL,0x0,
3727 "RFC 3261: SIP R-URI Port", HFILL }
3730 { "Status-Code", "sip.Status-Code",
3731 FT_UINT32, BASE_DEC,NULL,0x0,
3732 "SIP Status Code", HFILL }
3735 { "Status-Line", "sip.Status-Line",
3736 FT_STRING, BASE_NONE,NULL,0x0,
3737 "SIP Status-Line", HFILL }
3740 { "SIP Display info", "sip.display.info",
3741 FT_STRING, BASE_NONE,NULL,0x0,
3742 "RFC 3261: Display info", HFILL }
3745 { "SIP to address", "sip.to.addr",
3746 FT_STRING, BASE_NONE,NULL,0x0,
3747 "RFC 3261: To Address", HFILL }
3750 { "SIP to address User Part", "sip.to.user",
3751 FT_STRING, BASE_NONE,NULL,0x0,
3752 "RFC 3261: To Address User", HFILL }
3755 { "SIP to address Host Part", "sip.to.host",
3756 FT_STRING, BASE_NONE,NULL,0x0,
3757 "RFC 3261: To Address Host", HFILL }
3760 { "SIP to address Host Port", "sip.to.port",
3761 FT_STRING, BASE_NONE,NULL,0x0,
3762 "RFC 3261: To Address Port", HFILL }
3764 { &hf_sip_from_addr,
3765 { "SIP from address", "sip.from.addr",
3766 FT_STRING, BASE_NONE,NULL,0x0,
3767 "RFC 3261: From Address", HFILL }
3769 { &hf_sip_from_user,
3770 { "SIP from address User Part", "sip.from.user",
3771 FT_STRING, BASE_NONE,NULL,0x0,
3772 "RFC 3261: From Address User", HFILL }
3774 { &hf_sip_from_host,
3775 { "SIP from address Host Part", "sip.from.host",
3776 FT_STRING, BASE_NONE,NULL,0x0,
3777 "RFC 3261: From Address Host", HFILL }
3779 { &hf_sip_from_port,
3780 { "SIP from address Host Port", "sip.from.port",
3781 FT_STRING, BASE_NONE,NULL,0x0,
3782 "RFC 3261: From Address Port", HFILL }
3784 { &hf_sip_contact_addr,
3785 { "SIP contact address", "sip.contact.addr",
3786 FT_STRING, BASE_NONE,NULL,0x0,
3787 "RFC 3261: contact addr", HFILL }
3791 FT_STRING, BASE_NONE,NULL,0x0,
3792 "RFC 3261: SIP Uri", HFILL }
3794 { &hf_sip_contact_item,
3795 { "Contact Binding", "sip.contact.binding",
3796 FT_STRING, BASE_NONE,NULL,0x0,
3797 "RFC 3261: one contact binding", HFILL }
3800 { "SIP tag", "sip.tag",
3801 FT_STRING, BASE_NONE,NULL,0x0,
3802 "RFC 3261: tag", HFILL }
3805 { "SIP PAI Address", "sip.pai.addr",
3806 FT_STRING, BASE_NONE,NULL,0x0,
3807 "RFC 3325: P-Asserted-Identity Address", HFILL }
3810 { "SIP PAI User Part", "sip.pai.user",
3811 FT_STRING, BASE_NONE,NULL,0x0,
3812 "RFC 3325: P-Asserted-Identity User", HFILL }
3815 { "SIP PAI Host Part", "sip.pai.host",
3816 FT_STRING, BASE_NONE,NULL,0x0,
3817 "RFC 3325: P-Asserted-Identity Host", HFILL }
3820 { "SIP PAI Host Port", "sip.pai.port",
3821 FT_STRING, BASE_NONE,NULL,0x0,
3822 "RFC 3325: P-Asserted-Identity Port", HFILL }
3824 { &hf_sip_pmiss_addr,
3825 { "SIP PMISS Address", "sip.pmiss.addr",
3826 FT_STRING, BASE_NONE,NULL,0x0,
3827 "RFC 3325: Permission Missing Address", HFILL }
3829 { &hf_sip_pmiss_user,
3830 { "SIP PMISS User Part", "sip.pmiss.user",
3831 FT_STRING, BASE_NONE,NULL,0x0,
3832 "RFC 3325: Permission Missing User", HFILL }
3834 { &hf_sip_pmiss_host,
3835 { "SIP PMISS Host Part", "sip.pmiss.host",
3836 FT_STRING, BASE_NONE,NULL,0x0,
3837 "RFC 3325: Permission Missing Host", HFILL }
3839 { &hf_sip_pmiss_port,
3840 { "SIP PMISS Host Port", "sip.pmiss.port",
3841 FT_STRING, BASE_NONE,NULL,0x0,
3842 "RFC 3325: Permission Missing Port", HFILL }
3846 { "SIP PPI Address", "sip.ppi.addr",
3847 FT_STRING, BASE_NONE,NULL,0x0,
3848 "RFC 3325: P-Preferred-Identity Address", HFILL }
3851 { "SIP PPI User Part", "sip.ppi.user",
3852 FT_STRING, BASE_NONE,NULL,0x0,
3853 "RFC 3325: P-Preferred-Identity User", HFILL }
3856 { "SIP PPI Host Part", "sip.ppi.host",
3857 FT_STRING, BASE_NONE,NULL,0x0,
3858 "RFC 3325: P-Preferred-Identity Host", HFILL }
3861 { "SIP PPI Host Port", "sip.ppi.port",
3862 FT_STRING, BASE_NONE,NULL,0x0,
3863 "RFC 3325: P-Preferred-Identity Port", HFILL }
3866 { "SIP TC Address", "sip.tc.addr",
3867 FT_STRING, BASE_NONE,NULL,0x0,
3868 "RFC 3325: Trigger Consent Address", HFILL }
3871 { "SIP TC User Part", "sip.tc.user",
3872 FT_STRING, BASE_NONE,NULL,0x0,
3873 "RFC 3325: Trigger Consent User", HFILL }
3876 { "SIP TC Host Part", "sip.tc.host",
3877 FT_STRING, BASE_NONE,NULL,0x0,
3878 "RFC 3325: Trigger Consent Host", HFILL }
3881 { "SIP TC Host Port", "sip.tc.port",
3882 FT_STRING, BASE_NONE,NULL,0x0,
3883 "RFC 3325: Trigger Consent Port", HFILL }
3886 { "SIP TC Target URI", "sip.tc.target-uri",
3887 FT_STRING, BASE_NONE,NULL,0x0,
3888 "RFC 3325: Trigger Consent Target URI", HFILL }
3890 { &hf_header_array[POS_ACCEPT],
3891 { "Accept", "sip.Accept",
3892 FT_STRING, BASE_NONE,NULL,0x0,
3893 "RFC 3261: Accept Header", HFILL }
3895 { &hf_header_array[POS_ACCEPT_CONTACT],
3896 { "Accept-Contact", "sip.Accept-Contact",
3897 FT_STRING, BASE_NONE,NULL,0x0,
3898 "RFC 3841: Accept-Contact Header", HFILL }
3900 { &hf_header_array[POS_ACCEPT_ENCODING],
3901 { "Accept-Encoding", "sip.Accept-Encoding",
3902 FT_STRING, BASE_NONE,NULL,0x0,
3903 "RFC 3841: Accept-Encoding Header", HFILL }
3905 { &hf_header_array[POS_ACCEPT_LANGUAGE],
3906 { "Accept-Language", "sip.Accept-Language",
3907 FT_STRING, BASE_NONE,NULL,0x0,
3908 "RFC 3261: Accept-Language Header", HFILL }
3910 { &hf_header_array[POS_ACCEPT_RESOURCE_PRIORITY],
3911 { "Accept-Resource-Priority", "sip.Accept-Resource-Priority",
3912 FT_STRING, BASE_NONE,NULL,0x0,
3913 "Draft: Accept-Resource-Priority Header", HFILL }
3915 { &hf_header_array[POS_ALERT_INFO],
3916 { "Alert-Info", "sip.Alert-Info",
3917 FT_STRING, BASE_NONE,NULL,0x0,
3918 "RFC 3261: Alert-Info Header", HFILL }
3920 { &hf_header_array[POS_ALLOW],
3921 { "Allow", "sip.Allow",
3922 FT_STRING, BASE_NONE,NULL,0x0,
3923 "RFC 3261: Allow Header", HFILL }
3925 { &hf_header_array[POS_ALLOW_EVENTS],
3926 { "Allow-Events", "sip.Allow-Events",
3927 FT_STRING, BASE_NONE,NULL,0x0,
3928 "RFC 3265: Allow-Events Header", HFILL }
3930 { &hf_header_array[POS_ANSWER_MODE],
3931 { "Answer-Mode", "sip.Answer-Mode",
3932 FT_STRING, BASE_NONE,NULL,0x0,
3933 "RFC 5373: Answer-Mode Header", HFILL }
3935 { &hf_header_array[POS_AUTHENTICATION_INFO],
3936 { "Authentication-Info", "sip.Authentication-Info",
3937 FT_STRING, BASE_NONE,NULL,0x0,
3938 "RFC 3261: Authentication-Info Header", HFILL }
3940 { &hf_header_array[POS_AUTHORIZATION],
3941 { "Authorization", "sip.Authorization",
3942 FT_STRING, BASE_NONE,NULL,0x0,
3943 "RFC 3261: Authorization Header", HFILL }
3945 { &hf_header_array[POS_CALL_ID],
3946 { "Call-ID", "sip.Call-ID",
3947 FT_STRING, BASE_NONE,NULL,0x0,
3948 "RFC 3261: Call-ID Header", HFILL }
3950 { &hf_header_array[POS_CALL_INFO],
3951 { "Call-Info", "sip.Call-Info",
3952 FT_STRING, BASE_NONE,NULL,0x0,
3953 "RFC 3261: Call-Info Header", HFILL }
3955 { &hf_header_array[POS_CONTACT],
3956 { "Contact", "sip.Contact",
3957 FT_STRING, BASE_NONE,NULL,0x0,
3958 "RFC 3261: Contact Header", HFILL }
3960 { &hf_header_array[POS_CONTENT_DISPOSITION],
3961 { "Content-Disposition", "sip.Content-Disposition",
3962 FT_STRING, BASE_NONE,NULL,0x0,
3963 "RFC 3261: Content-Disposition Header", HFILL }
3965 { &hf_header_array[POS_CONTENT_ENCODING],
3966 { "Content-Encoding", "sip.Content-Encoding",
3967 FT_STRING, BASE_NONE,NULL,0x0,
3968 "RFC 3261: Content-Encoding Header", HFILL }
3970 { &hf_header_array[POS_CONTENT_LANGUAGE],
3971 { "Content-Language", "sip.Content-Language",
3972 FT_STRING, BASE_NONE,NULL,0x0,
3973 "RFC 3261: Content-Language Header", HFILL }
3975 { &hf_header_array[POS_CONTENT_LENGTH],
3976 { "Content-Length", "sip.Content-Length",
3977 FT_UINT32, BASE_DEC,NULL,0x0,
3978 "RFC 3261: Content-Length Header", HFILL }
3980 { &hf_header_array[POS_CONTENT_TYPE],
3981 { "Content-Type", "sip.Content-Type",
3982 FT_STRING, BASE_NONE,NULL,0x0,
3983 "RFC 3261: Content-Type Header", HFILL }
3985 { &hf_header_array[POS_CSEQ],
3986 { "CSeq", "sip.CSeq",
3987 FT_STRING, BASE_NONE,NULL,0x0,
3988 "RFC 3261: CSeq Header", HFILL }
3990 { &hf_header_array[POS_DATE],
3991 { "Date", "sip.Date",
3992 FT_STRING, BASE_NONE,NULL,0x0,
3993 "RFC 3261: Date Header", HFILL }
3995 { &hf_header_array[POS_ERROR_INFO],
3996 { "Error-Info", "sip.Error-Info",
3997 FT_STRING, BASE_NONE,NULL,0x0,
3998 "RFC 3261: Error-Info Header", HFILL }
4000 { &hf_header_array[POS_EVENT],
4001 { "Event", "sip.Event",
4002 FT_STRING, BASE_NONE,NULL,0x0,
4003 "RFC 3265: Event Header", HFILL }
4005 { &hf_header_array[POS_EXPIRES],
4006 { "Expires", "sip.Expires",
4007 FT_UINT32, BASE_DEC,NULL,0x0,
4008 "RFC 3261: Expires Header", HFILL }
4010 { &hf_header_array[POS_FROM],
4011 { "From", "sip.From",
4012 FT_STRING, BASE_NONE,NULL,0x0,
4013 "RFC 3261: From Header", HFILL }
4015 { &hf_header_array[POS_IN_REPLY_TO],
4016 { "In-Reply-To", "sip.In-Reply-To",
4017 FT_STRING, BASE_NONE,NULL,0x0,
4018 "RFC 3261: In-Reply-To Header", HFILL }
4020 { &hf_header_array[POS_JOIN],
4021 { "Join", "sip.Join",
4022 FT_STRING, BASE_NONE,NULL,0x0,
4023 "Draft: Join Header", HFILL }
4025 { &hf_header_array[POS_MAX_BREADTH],
4026 { "Max-Breadth", "sip.Max-Breadth",
4027 FT_UINT32, BASE_DEC,NULL,0x0,
4028 "RFC 5393: Max-Breadth Header", HFILL }
4030 { &hf_header_array[POS_MAX_FORWARDS],
4031 { "Max-Forwards", "sip.Max-Forwards",
4032 FT_UINT32, BASE_DEC,NULL,0x0,
4033 "RFC 3261: Max-Forwards Header", HFILL }
4035 { &hf_header_array[POS_MIME_VERSION],
4036 { "MIME-Version", "sip.MIME-Version",
4037 FT_STRING, BASE_NONE,NULL,0x0,
4038 "RFC 3261: MIME-Version Header", HFILL }
4040 { &hf_header_array[POS_MIN_EXPIRES],
4041 { "Min-Expires", "sip.Min-Expires",
4042 FT_STRING, BASE_NONE,NULL,0x0,
4043 "RFC 3261: Min-Expires Header", HFILL }
4045 { &hf_header_array[POS_MIN_SE],
4046 { "Min-SE", "sip.Min-SE",
4047 FT_STRING, BASE_NONE,NULL,0x0,
4048 "Draft: Min-SE Header", HFILL }
4050 { &hf_header_array[POS_ORGANIZATION],
4051 { "Organization", "sip.Organization",
4052 FT_STRING, BASE_NONE,NULL,0x0,
4053 "RFC 3261: Organization Header", HFILL }
4055 { &hf_header_array[POS_P_ACCESS_NETWORK_INFO],
4056 { "P-Access-Network-Info", "sip.P-Access-Network-Info",
4057 FT_STRING, BASE_NONE,NULL,0x0,
4058 "P-Access-Network-Info Header", HFILL }
4060 { &hf_header_array[POS_P_ANSWER_STATE],
4061 { "P-Answer-State", "sip.P-Answer-State",
4062 FT_STRING, BASE_NONE,NULL,0x0,
4063 "RFC 4964: P-Answer-State Header", HFILL }
4065 { &hf_header_array[POS_P_ASSERTED_IDENTITY],
4066 { "P-Asserted-Identity", "sip.P-Asserted-Identity",
4067 FT_STRING, BASE_NONE,NULL,0x0,
4068 "RFC 3325: P-Asserted-Identity Header", HFILL }
4070 { &hf_header_array[POS_P_ASSOCIATED_URI],
4071 { "P-Associated-URI", "sip.P-Associated-URI",
4072 FT_STRING, BASE_NONE,NULL,0x0,
4073 "RFC 3455: P-Associated-URI Header", HFILL }
4076 { &hf_header_array[POS_P_CALLED_PARTY_ID],
4077 { "P-Called-Party-ID", "sip.P-Called-Party-ID",
4078 FT_STRING, BASE_NONE,NULL,0x0,
4079 "RFC 3455: P-Called-Party-ID Header", HFILL }
4082 { &hf_header_array[POS_P_CHARGING_FUNCTION_ADDRESSES],
4083 { "P-Charging-Function-Addresses","sip.P-Charging-Function-Addresses",
4084 FT_STRING, BASE_NONE,NULL,0x0,
4085 "P-Charging-Function-Addresses", HFILL }
4088 { &hf_header_array[POS_P_CHARGING_VECTOR],
4089 { "P-Charging-Vector", "sip.P-Charging-Vector",
4090 FT_STRING, BASE_NONE,NULL,0x0,
4091 "P-Charging-Vector Header", HFILL }
4094 { &hf_header_array[POS_P_DCS_TRACE_PARTY_ID],
4095 { "P-DCS-Trace-Party-ID", "sip.P-DCS-Trace-Party-ID",
4096 FT_STRING, BASE_NONE,NULL,0x0,
4097 "P-DCS-Trace-Party-ID Header", HFILL }
4100 { &hf_header_array[POS_P_DCS_OSPS],
4101 { "P-DCS-OSPS", "sip.P-DCS-OSPS",
4102 FT_STRING, BASE_NONE,NULL,0x0,
4103 "P-DCS-OSPS Header", HFILL }
4106 { &hf_header_array[POS_P_DCS_BILLING_INFO],
4107 { "P-DCS-Billing-Info", "sip.P-DCS-Billing-Info",
4108 FT_STRING, BASE_NONE,NULL,0x0,
4109 "P-DCS-Billing-Info Header", HFILL }
4112 { &hf_header_array[POS_P_DCS_LAES],
4113 { "P-DCS-LAES", "sip.P-DCS-LAES",
4114 FT_STRING, BASE_NONE,NULL,0x0,
4115 "P-DCS-LAES Header", HFILL }
4118 { &hf_header_array[POS_P_DCS_REDIRECT],
4119 { "P-DCS-Redirect", "sip.P-DCS-Redirect",
4120 FT_STRING, BASE_NONE,NULL,0x0,
4121 "P-DCS-Redirect Header", HFILL }
4124 { &hf_header_array[POS_P_EARLY_MEDIA],
4125 { "P-Early-Media", "sip.P-Early-Media",
4126 FT_STRING, BASE_NONE,NULL,0x0,
4127 "P-Early-Media Header", HFILL }
4130 { &hf_header_array[POS_P_MEDIA_AUTHORIZATION],
4131 { "P-Media-Authorization", "sip.P-Media-Authorization",
4132 FT_STRING, BASE_NONE,NULL,0x0,
4133 "RFC 3313: P-Media-Authorization Header", HFILL }
4136 { &hf_header_array[POS_P_PREFERRED_IDENTITY],
4137 { "P-Preferred-Identity", "sip.P-Preferred-Identity",
4138 FT_STRING, BASE_NONE,NULL,0x0,
4139 "RFC 3325: P-Preferred-Identity Header", HFILL }
4142 { &hf_header_array[POS_P_PROFILE_KEY],
4143 { "P-Profile-Key", "sip.P-Profile-Key",
4144 FT_STRING, BASE_NONE,NULL,0x0,
4145 "P-Profile-Key Header", HFILL }
4148 { &hf_header_array[POS_P_USER_DATABASE],
4149 { "P-User-Database", "sip.P-User-Database",
4150 FT_STRING, BASE_NONE,NULL,0x0,
4151 "P-User-Database Header", HFILL }
4154 { &hf_header_array[POS_P_VISITED_NETWORK_ID],
4155 { "P-Visited-Network-ID", "sip.P-Visited-Network-ID",
4156 FT_STRING, BASE_NONE,NULL,0x0,
4157 "RFC 3455: P-Visited-Network-ID Header", HFILL }
4160 { &hf_header_array[POS_PATH],
4161 { "Path", "sip.Path",
4162 FT_STRING, BASE_NONE,NULL,0x0,
4163 "RFC 3327: Path Header", HFILL }
4166 { &hf_header_array[POS_PERMISSION_MISSING],
4167 { "Permission-Missing", "sip.Permission-Missing",
4168 FT_STRING, BASE_NONE,NULL,0x0,
4169 "RFC 5360: Permission Missing Header", HFILL }
4172 { &hf_header_array[POS_PRIORITY],
4173 { "Priority", "sip.Priority",
4174 FT_STRING, BASE_NONE,NULL,0x0,
4175 "RFC 3261: Priority Header", HFILL }
4177 { &hf_header_array[POS_PRIV_ANSWER_MODE],
4178 { "Priv-Answer-mode", "sip.Priv-Answer-mode",
4179 FT_STRING, BASE_NONE,NULL,0x0,
4180 "Priv-Answer-mode", HFILL }
4182 { &hf_header_array[POS_PRIVACY],
4183 { "Privacy", "sip.Privacy",
4184 FT_STRING, BASE_NONE,NULL,0x0,
4185 "Privacy Header", HFILL }
4188 { &hf_header_array[POS_PROXY_AUTHENTICATE],
4189 { "Proxy-Authenticate", "sip.Proxy-Authenticate",
4190 FT_STRING, BASE_NONE,NULL,0x0,
4191 "RFC 3261: Proxy-Authenticate Header", HFILL }
4193 { &hf_header_array[POS_PROXY_AUTHORIZATION],
4194 { "Proxy-Authorization", "sip.Proxy-Authorization",
4195 FT_STRING, BASE_NONE,NULL,0x0,
4196 "RFC 3261: Proxy-Authorization Header", HFILL }
4199 { &hf_header_array[POS_PROXY_REQUIRE],
4200 { "Proxy-Require", "sip.Proxy-Require",
4201 FT_STRING, BASE_NONE,NULL,0x0,
4202 "RFC 3261: Proxy-Require Header", HFILL }
4204 { &hf_header_array[POS_RACK],
4205 { "RAck", "sip.RAck",
4206 FT_STRING, BASE_NONE,NULL,0x0,
4207 "RFC 3262: RAck Header", HFILL }
4209 { &hf_header_array[POS_REASON],
4210 { "Reason", "sip.Reason",
4211 FT_STRING, BASE_NONE,NULL,0x0,
4212 "RFC 3326 Reason Header", HFILL }
4214 { &hf_header_array[POS_RECORD_ROUTE],
4215 { "Record-Route", "sip.Record-Route",
4216 FT_STRING, BASE_NONE,NULL,0x0,
4217 "RFC 3261: Record-Route Header", HFILL }
4219 { &hf_header_array[POS_REFER_SUB],
4220 { "Refer-Sub", "sip.Refer-Sub",
4221 FT_STRING, BASE_NONE,NULL,0x0,
4222 "RFC 4488: Refer-Sub Header", HFILL }
4224 { &hf_header_array[POS_REFERED_BY],
4225 { "Refered By", "sip.Refered-by",
4226 FT_STRING, BASE_NONE,NULL,0x0,
4227 "RFC 3892: Refered-by Header", HFILL }
4229 { &hf_header_array[POS_REJECT_CONTACT],
4230 { "Reject-Contact", "sip.Reject-Contact",
4231 FT_STRING, BASE_NONE,NULL,0x0,
4232 "RFC 3841: Reject-Contact Header", HFILL }
4234 { &hf_header_array[POS_REPLACES],
4235 { "Replaces", "sip.Replaces",
4236 FT_STRING, BASE_NONE,NULL,0x0,
4237 "RFC 3891: Replaces Header", HFILL }
4239 { &hf_header_array[POS_REPLY_TO],
4240 { "Reply-To", "sip.Reply-To",
4241 FT_STRING, BASE_NONE,NULL,0x0,
4242 "RFC 3261: Reply-To Header", HFILL }
4244 { &hf_header_array[POS_REQUEST_DISPOSITION],
4245 { "Request-Disposition", "sip.Request-Disposition",
4246 FT_STRING, BASE_NONE,NULL,0x0,
4247 "RFC 3841: Request-Disposition Header", HFILL }
4249 { &hf_header_array[POS_REQUIRE],
4250 { "Require", "sip.Require",
4251 FT_STRING, BASE_NONE,NULL,0x0,
4252 "RFC 3261: Require Header", HFILL }
4254 { &hf_header_array[POS_RESOURCE_PRIORITY],
4255 { "Resource-Priority", "sip.Resource-Priority",
4256 FT_STRING, BASE_NONE,NULL,0x0,
4257 "Draft: Resource-Priority Header", HFILL }
4259 { &hf_header_array[POS_RETRY_AFTER],
4260 { "Retry-After", "sip.Retry-After",
4261 FT_STRING, BASE_NONE,NULL,0x0,
4262 "RFC 3261: Retry-After Header", HFILL }
4264 { &hf_header_array[POS_ROUTE],
4265 { "Route", "sip.Route",
4266 FT_STRING, BASE_NONE,NULL,0x0,
4267 "RFC 3261: Route Header", HFILL }
4269 { &hf_header_array[POS_RSEQ],
4270 { "RSeq", "sip.RSeq",
4271 FT_UINT32, BASE_DEC,NULL,0x0,
4272 "RFC 3262: RSeq Header", HFILL }
4274 { &hf_header_array[ POS_SECURITY_CLIENT],
4275 { "Security-Client", "sip.Security-Client",
4276 FT_STRING, BASE_NONE,NULL,0x0,
4277 "RFC 3329 Security-Client Header", HFILL }
4279 { &hf_header_array[ POS_SECURITY_SERVER],
4280 { "Security-Server", "sip.Security-Server",
4281 FT_STRING, BASE_NONE,NULL,0x0,
4282 "RFC 3329 Security-Server Header", HFILL }
4284 { &hf_header_array[ POS_SECURITY_VERIFY],
4285 { "Security-Verify", "sip.Security-Verify",
4286 FT_STRING, BASE_NONE,NULL,0x0,
4287 "RFC 3329 Security-Verify Header", HFILL }
4289 { &hf_header_array[POS_SERVER],
4290 { "Server", "sip.Server",
4291 FT_STRING, BASE_NONE,NULL,0x0,
4292 "RFC 3261: Server Header", HFILL }
4294 { &hf_header_array[POS_SERVICE_ROUTE],
4295 { "Service-Route", "sip.Service-Route",
4296 FT_STRING, BASE_NONE,NULL,0x0,
4297 "RFC 3608: Service-Route Header", HFILL }
4299 { &hf_header_array[POS_SESSION_EXPIRES],
4300 { "Session-Expires", "sip.Session-Expires",
4301 FT_STRING, BASE_NONE,NULL,0x0,
4302 "RFC 4028: Session-Expires Header", HFILL }
4304 { &hf_header_array[POS_SIP_ETAG],
4305 { "ETag", "sip.ETag",
4306 FT_STRING, BASE_NONE,NULL,0x0,
4307 "RFC 3903: SIP-ETag Header", HFILL }
4309 { &hf_header_array[POS_SIP_IF_MATCH],
4310 { "If_Match", "sip.If_Match",
4311 FT_STRING, BASE_NONE,NULL,0x0,
4312 "RFC 3903: SIP-If-Match Header", HFILL }
4314 { &hf_header_array[POS_SUBJECT],
4315 { "Subject", "sip.Subject",
4316 FT_STRING, BASE_NONE,NULL,0x0,
4317 "RFC 3261: Subject Header", HFILL }
4319 { &hf_header_array[POS_SUBSCRIPTION_STATE],
4320 { "Subscription-State", "sip.Subscription-State",
4321 FT_STRING, BASE_NONE,NULL,0x0,
4322 "RFC 3265: Subscription-State Header", HFILL }
4324 { &hf_header_array[POS_SUPPORTED],
4325 { "Supported", "sip.Supported",
4326 FT_STRING, BASE_NONE,NULL,0x0,
4327 "RFC 3261: Supported Header", HFILL }
4329 { &hf_header_array[POS_TARGET_DALOG],
4330 { "Target-Dialog", "sip.Target-Dialog",
4331 FT_STRING, BASE_NONE,NULL,0x0,
4332 "RFC 4538: Target-Dialog Header", HFILL }
4334 { &hf_header_array[POS_TIMESTAMP],
4335 { "Timestamp", "sip.Timestamp",
4336 FT_STRING, BASE_NONE,NULL,0x0,
4337 "RFC 3261: Timestamp Header", HFILL }
4339 { &hf_header_array[POS_TO],
4341 FT_STRING, BASE_NONE,NULL,0x0,
4342 "RFC 3261: To Header", HFILL }
4345 { &hf_header_array[POS_TRIGGER_CONSENT],
4346 { "Trigger-Consent", "sip.Trigger-Consent",
4347 FT_STRING, BASE_NONE,NULL,0x0,
4348 "RFC 5380: Trigger Consent", HFILL }
4351 { &hf_header_array[POS_UNSUPPORTED],
4352 { "Unsupported", "sip.Unsupported",
4353 FT_STRING, BASE_NONE,NULL,0x0,
4354 "RFC 3261: Unsupported Header", HFILL }
4356 { &hf_header_array[POS_USER_AGENT],
4357 { "User-Agent", "sip.User-Agent",
4358 FT_STRING, BASE_NONE,NULL,0x0,
4359 "RFC 3261: User-Agent Header", HFILL }
4361 { &hf_header_array[POS_VIA],
4363 FT_STRING, BASE_NONE,NULL,0x0,
4364 "RFC 3261: Via Header", HFILL }
4366 { &hf_header_array[POS_WARNING],
4367 { "Warning", "sip.Warning",
4368 FT_STRING, BASE_NONE,NULL,0x0,
4369 "RFC 3261: Warning Header", HFILL }
4372 { &hf_header_array[POS_WWW_AUTHENTICATE],
4373 { "WWW-Authenticate", "sip.WWW-Authenticate",
4374 FT_STRING, BASE_NONE,NULL,0x0,
4375 "RFC 3261: WWW-Authenticate Header", HFILL }
4377 { &hf_header_array[POS_REFER_TO],
4378 { "Refer-To", "sip.Refer-To",
4379 FT_STRING, BASE_NONE,NULL,0x0,
4380 "RFC 3515: Refer-To Header", HFILL }
4382 { &hf_header_array[POS_HISTORY_INFO],
4383 { "History-Info", "sip.History-Info",
4384 FT_STRING, BASE_NONE,NULL,0x0,
4385 "RFC 4244: Request History Information", HFILL }
4387 { &hf_header_array[POS_IDENTITY],
4388 { "Identity", "sip.Identity",
4389 FT_STRING, BASE_NONE,NULL,0x0,
4390 "RFC 4474: Request Identity", HFILL }
4392 { &hf_header_array[POS_IDENTITY_INFO],
4393 { "Identity-info", "sip.Identity-info",
4394 FT_STRING, BASE_NONE,NULL,0x0,
4395 "RFC 4474: Request Identity-info", HFILL }
4399 { "Resent Packet", "sip.resend",
4400 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
4403 { &hf_sip_original_frame,
4404 { "Suspected resend of frame", "sip.resend-original",
4405 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4406 "Original transmission of frame", HFILL}
4408 { &hf_sip_matching_request_frame,
4409 { "Request Frame", "sip.response-request",
4410 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
4411 "Request Frame", HFILL}
4413 { &hf_sip_response_time,
4414 { "Response Time (ms)", "sip.response-time",
4415 FT_UINT32, BASE_DEC, NULL, 0x0,
4416 "Response time since original request (in milliseconds)", HFILL}
4418 { &hf_sip_release_time,
4419 { "Release Time (ms)", "sip.release-time",
4420 FT_UINT32, BASE_DEC, NULL, 0x0,
4421 "release time since original BYE (in milliseconds)", HFILL}
4424 { "Authentication", "sip.auth",
4425 FT_STRING, BASE_NONE, NULL, 0x0,
4426 "SIP Authentication", HFILL}
4428 { &hf_sip_auth_scheme,
4429 { "Authentication Scheme", "sip.auth.scheme",
4430 FT_STRING, BASE_NONE, NULL, 0x0,
4431 "SIP Authentication Scheme", HFILL}
4433 { &hf_sip_auth_digest_response,
4434 { "Digest Authentication Response", "sip.auth.digest.response",
4435 FT_STRING, BASE_NONE, NULL, 0x0,
4436 "SIP Digest Authentication Response Value ", HFILL}
4439 { "Nonce Count", "sip.auth.nc",
4440 FT_STRING, BASE_NONE, NULL, 0x0,
4441 "SIP Authentication Nonce count", HFILL}
4443 { &hf_sip_auth_username,
4444 { "Username", "sip.auth.username",
4445 FT_STRING, BASE_NONE, NULL, 0x0,
4446 "SIP Authentication Username", HFILL}
4448 { &hf_sip_auth_realm,
4449 { "Realm", "sip.auth.realm",
4450 FT_STRING, BASE_NONE, NULL, 0x0,
4451 "SIP Authentication Realm", HFILL}
4453 { &hf_sip_auth_nonce,
4454 { "Nonce Value", "sip.auth.nonce",
4455 FT_STRING, BASE_NONE, NULL, 0x0,
4456 "SIP Authentication Nonce", HFILL}
4458 { &hf_sip_auth_algorithm,
4459 { "Algorithm", "sip.auth.algorithm",
4460 FT_STRING, BASE_NONE, NULL, 0x0,
4461 "SIP Authentication Algorithm", HFILL}
4463 { &hf_sip_auth_opaque,
4464 { "Opaque Value", "sip.auth.opaque",
4465 FT_STRING, BASE_NONE, NULL, 0x0,
4466 "SIP Authentication Opaque value", HFILL}
4469 { "QOP", "sip.auth.qop",
4470 FT_STRING, BASE_NONE, NULL, 0x0,
4471 "SIP Authentication QOP", HFILL}
4473 { &hf_sip_auth_cnonce,
4474 { "CNonce Value", "sip.auth.cnonce",
4475 FT_STRING, BASE_NONE, NULL, 0x0,
4476 "SIP Authentication Client Nonce", HFILL}
4479 { "Authentication URI", "sip.auth.uri",
4480 FT_STRING, BASE_NONE, NULL, 0x0,
4481 "SIP Authentication URI", HFILL}
4483 { &hf_sip_auth_domain,
4484 { "Authentication Domain", "sip.auth.domain",
4485 FT_STRING, BASE_NONE, NULL, 0x0,
4486 "SIP Authentication Domain", HFILL}
4488 { &hf_sip_auth_stale,
4489 { "Stale Flag", "sip.auth.stale",
4490 FT_STRING, BASE_NONE, NULL, 0x0,
4491 "SIP Authentication Stale Flag", HFILL}
4493 { &hf_sip_auth_auts,
4494 { "Authentication Token", "sip.auth.auts",
4495 FT_STRING, BASE_NONE, NULL, 0x0,
4496 "SIP Authentication Token", HFILL}
4498 { &hf_sip_auth_rspauth,
4499 { "Response auth", "sip.auth.rspauth",
4500 FT_STRING, BASE_NONE, NULL, 0x0,
4501 "SIP Authentication Response auth", HFILL}
4503 { &hf_sip_auth_nextnonce,
4504 { "Next Nonce", "sip.auth.nextnonce",
4505 FT_STRING, BASE_NONE, NULL, 0x0,
4506 "SIP Authentication Next Nonce", HFILL}
4509 { "Integrity Key", "sip.auth.ik",
4510 FT_STRING, BASE_NONE, NULL, 0x0,
4511 "SIP Authentication Integrity Key", HFILL}
4514 { "Cyphering Key", "sip.auth.ck",
4515 FT_STRING, BASE_NONE, NULL, 0x0,
4516 "SIP Authentication Cyphering Key", HFILL}
4518 { &hf_sip_cseq_seq_no,
4519 { "Sequence Number", "sip.CSeq.seq",
4520 FT_UINT32, BASE_DEC, NULL, 0x0,
4521 "CSeq header sequence number", HFILL}
4523 { &hf_sip_cseq_method,
4524 { "Method", "sip.CSeq.method",
4525 FT_STRING, BASE_NONE, NULL, 0x0,
4526 "CSeq header method", HFILL}
4528 { &hf_sip_via_transport,
4529 { "Transport", "sip.Via.transport",
4530 FT_STRING, BASE_NONE, NULL, 0x0,
4531 "Via header Transport", HFILL}
4533 { &hf_sip_via_sent_by_address,
4534 { "Sent-by Address", "sip.Via.sent-by.address",
4535 FT_STRING, BASE_NONE, NULL, 0x0,
4536 "Via header Sent-by Address", HFILL}
4538 { &hf_sip_via_sent_by_port,
4539 { "Sent-by port", "sip.Via.sent-by.port",
4540 FT_UINT16, BASE_DEC, NULL, 0x0,
4541 "Via header Sent-by Port", HFILL}
4543 { &hf_sip_via_branch,
4544 { "Branch", "sip.Via.branch",
4545 FT_STRING, BASE_NONE, NULL, 0x0,
4546 "SIP Via Branch", HFILL},
4548 { &hf_sip_via_maddr,
4549 { "Maddr", "sip.Via.maddr",
4550 FT_STRING, BASE_NONE, NULL, 0x0,
4551 "SIP Via Maddr", HFILL},
4553 { &hf_sip_via_rport,
4554 { "RPort", "sip.Via.rport",
4555 FT_STRING, BASE_NONE, NULL, 0x0,
4556 "SIP Via RPort", HFILL},
4558 { &hf_sip_via_received,
4559 { "Received", "sip.Via.received",
4560 FT_STRING, BASE_NONE, NULL, 0x0,
4561 "SIP Via Received", HFILL},
4564 { "TTL", "sip.Via.ttl",
4565 FT_STRING, BASE_NONE, NULL, 0x0,
4566 "SIP Via TTL", HFILL}
4569 { "Comp", "sip.Via.comp",
4570 FT_STRING, BASE_NONE, NULL, 0x0,
4571 "SIP Via comp", HFILL}
4573 { &hf_sip_via_sigcomp_id,
4574 { "Sigcomp identifier", "sip.Via.sigcomp-id",
4575 FT_STRING, BASE_NONE, NULL, 0x0,
4576 "SIP Via sigcomp identifier", HFILL}
4578 { &hf_sip_rack_rseq_no,
4579 { "RSeq Sequence Number", "sip.RAck.RSeq.seq",
4580 FT_UINT32, BASE_DEC, NULL, 0x0,
4581 "RAck RSeq header sequence number (from prov response)", HFILL}
4583 { &hf_sip_rack_cseq_no,
4584 { "CSeq Sequence Number", "sip.RAck.CSeq.seq",
4585 FT_UINT32, BASE_DEC, NULL, 0x0,
4586 "RAck CSeq header sequence number (from prov response)", HFILL}
4588 { &hf_sip_rack_cseq_method,
4589 { "CSeq Method", "sip.RAck.CSeq.method",
4590 FT_STRING, BASE_NONE, NULL, 0x0,
4591 "RAck CSeq header method (from prov response)", HFILL}
4594 { "Message Body", "sip.msg_body",
4595 FT_NONE, BASE_NONE, NULL, 0x0,
4596 "Message Body in SIP message", HFILL }
4599 /* raw_sip header field(s) */
4600 static hf_register_info raw_hf[] = {
4603 { "Raw SIP Line", "raw_sip.line",
4604 FT_STRING, BASE_NONE,NULL,0x0,
4605 "Raw SIP Line", HFILL }
4608 /* Setup protocol subtree array */
4609 static gint *ett[] = {
4616 &ett_sip_contact_item,
4617 &ett_sip_message_body,
4630 static gint *ett_raw[] = {
4634 module_t *sip_module;
4636 /* Register the protocol name and description */
4637 proto_sip = proto_register_protocol("Session Initiation Protocol",
4639 proto_raw_sip = proto_register_protocol("Session Initiation Protocol (SIP as raw text)",
4640 "Raw_SIP", "raw_sip");
4641 new_register_dissector("sip", dissect_sip, proto_sip);
4642 register_dissector("sip.tcp", dissect_sip_tcp, proto_sip);
4644 /* Required function calls to register the header fields and subtrees used */
4645 proto_register_field_array(proto_sip, hf, array_length(hf));
4646 proto_register_subtree_array(ett, array_length(ett));
4647 proto_register_subtree_array(ett_raw, array_length(ett_raw));
4649 /* Register raw_sip field(s) */
4650 proto_register_field_array(proto_raw_sip, raw_hf, array_length(raw_hf));
4652 sip_module = prefs_register_protocol(proto_sip, proto_reg_handoff_sip);
4654 prefs_register_uint_preference(sip_module, "tcp.port",
4656 "SIP Server TCP Port",
4658 prefs_register_uint_preference(sip_module, "tls.port",
4660 "SIP Server TLS Port",
4663 prefs_register_bool_preference(sip_module, "display_raw_text",
4664 "Display raw text for SIP message",
4665 "Specifies that the raw text of the "
4666 "SIP message should be displayed "
4667 "in addition to the dissection tree",
4668 &global_sip_raw_text);
4669 prefs_register_bool_preference(sip_module, "strict_sip_version",
4670 "Enforce strict SIP version check (" SIP2_HDR ")",
4671 "If enabled, only " SIP2_HDR " traffic will be dissected as SIP. "
4672 "Disable it to allow SIP traffic with a different version "
4673 "to be dissected as SIP.",
4674 &strict_sip_version);
4675 prefs_register_bool_preference(sip_module, "desegment_headers",
4676 "Reassemble SIP headers spanning multiple TCP segments",
4677 "Whether the SIP dissector should reassemble headers "
4678 "of a request spanning multiple TCP segments. "
4679 "To use this option, you must also enable "
4680 "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
4681 &sip_desegment_headers);
4682 prefs_register_bool_preference(sip_module, "desegment_body",
4683 "Reassemble SIP bodies spanning multiple TCP segments",
4684 "Whether the SIP dissector should use the "
4685 "\"Content-length:\" value, if present, to reassemble "
4686 "the body of a request spanning multiple TCP segments, "
4687 "and reassemble chunked data spanning multiple TCP segments. "
4688 "To use this option, you must also enable "
4689 "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
4690 &sip_desegment_body);
4692 register_init_routine(&sip_init_protocol);
4693 register_heur_dissector_list("sip", &heur_subdissector_list);
4694 /* Register for tapping */
4695 sip_tap = register_tap("sip");
4697 ext_hdr_subdissector_table = register_dissector_table("sip.hdr", "SIP Extension header", FT_STRING, BASE_NONE);
4702 proto_reg_handoff_sip(void)
4704 static dissector_handle_t sip_tcp_handle;
4705 static guint saved_sip_tcp_port;
4706 static guint saved_sip_tls_port;
4707 static gboolean sip_prefs_initialized = FALSE;
4709 if (!sip_prefs_initialized) {
4710 dissector_handle_t sip_handle;
4711 sip_handle = find_dissector("sip");
4712 sip_tcp_handle = find_dissector("sip.tcp");
4713 sigcomp_handle = find_dissector("sigcomp");
4714 /* SIP content type and internet media type used by other dissectors are the same */
4715 media_type_dissector_table = find_dissector_table("media_type");
4717 dissector_add("udp.port", UDP_PORT_SIP, sip_handle);
4718 dissector_add_string("media_type", "message/sip", sip_handle);
4720 heur_dissector_add("udp", dissect_sip_heur, proto_sip);
4721 heur_dissector_add("tcp", dissect_sip_tcp_heur, proto_sip);
4722 heur_dissector_add("sctp", dissect_sip_heur, proto_sip);
4723 heur_dissector_add("stun2", dissect_sip_heur, proto_sip);
4724 sip_prefs_initialized = TRUE;
4726 dissector_delete("tcp.port", saved_sip_tcp_port, sip_tcp_handle);
4727 ssl_dissector_delete(saved_sip_tls_port, "sip.tcp", TRUE);
4729 /* Set our port number for future use */
4730 saved_sip_tcp_port = sip_tcp_port;
4731 saved_sip_tls_port = sip_tls_port;
4732 dissector_add("tcp.port", saved_sip_tcp_port, sip_tcp_handle);
4733 ssl_dissector_add(saved_sip_tls_port, "sip.tcp", TRUE);