2 * Routines for the Session Initiation Protocol (SIP) dissection.
5 * TODO: Pay attention to Content-Type: It might not always be SDP.
6 * Content-Type is fixed, mixed/mode is not handled though.
7 * hf_ display filters for headers of SIP extension RFCs:
8 * Done for RFC 3265, RFC 3262
9 * Use hash table for list of headers
10 * Add sip msg body dissection based on Content-Type for:
11 * SDP, MIME, and other types
12 * Align SIP methods with recent Internet Drafts or RFC
13 * (SIP INFO, rfc2976 - done)
14 * (SIP SUBSCRIBE-NOTIFY - done)
18 * Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi>
19 * Copyright 2001, Jean-Francois Mule <jfm@cablelabs.com>
20 * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
24 * Wireshark - Network traffic analyzer
25 * By Gerald Combs <gerald@wireshark.org>
26 * Copyright 1998 Gerald Combs
28 * Copied from packet-cops.c
30 * This program is free software; you can redistribute it and/or
31 * modify it under the terms of the GNU General Public License
32 * as published by the Free Software Foundation; either version 2
33 * of the License, or (at your option) any later version.
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
40 * You should have received a copy of the GNU General Public License
41 * along with this program; if not, write to the Free Software
42 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
54 #include <epan/prefs.h>
57 #include <epan/packet.h>
58 #include <epan/req_resp_hdrs.h>
59 #include <epan/emem.h>
61 #include "packet-sip.h"
63 #include <epan/emem.h>
65 #include "packet-tcp.h"
67 #define TCP_PORT_SIP 5060
68 #define UDP_PORT_SIP 5060
70 static gint sip_tap = -1;
71 static dissector_handle_t sigcomp_handle;
73 /* Initialize the protocol and registered fields */
74 static gint proto_sip = -1;
75 static gint proto_raw_sip = -1;
76 static gint hf_msg_hdr = -1;
77 static gint hf_Method = -1;
78 static gint hf_Request_Line = -1;
79 static gint hf_Status_Code = -1;
80 static gint hf_Status_Line = -1;
81 static gint hf_sip_display = -1;
82 static gint hf_sip_to_addr = -1;
83 static gint hf_sip_from_addr = -1;
84 static gint hf_sip_tag = -1;
85 static gint hf_sip_uri = -1;
86 static gint hf_sip_contact_addr = -1;
87 static gint hf_sip_contact_item = -1;
88 static gint hf_sip_resend = -1;
89 static gint hf_sip_original_frame = -1;
91 static gint hf_sip_auth = -1;
92 static gint hf_sip_auth_scheme = -1;
93 static gint hf_sip_auth_digest_response = -1;
94 static gint hf_sip_auth_nc = -1;
95 static gint hf_sip_auth_username = -1;
96 static gint hf_sip_auth_realm = -1;
97 static gint hf_sip_auth_nonce = -1;
98 static gint hf_sip_auth_algorithm = -1;
99 static gint hf_sip_auth_opaque = -1;
100 static gint hf_sip_auth_qop = -1;
101 static gint hf_sip_auth_cnonce = -1;
102 static gint hf_sip_auth_uri = -1;
103 static gint hf_sip_auth_domain = -1;
104 static gint hf_sip_auth_stale = -1;
105 static gint hf_sip_auth_auts = -1;
106 static gint hf_sip_auth_rspauth = -1;
107 static gint hf_sip_auth_nextnonce = -1;
109 /* Initialize the subtree pointers */
110 static gint ett_sip = -1;
111 static gint ett_sip_reqresp = -1;
112 static gint ett_sip_hdr = -1;
113 static gint ett_raw_text = -1;
114 static gint ett_sip_element = -1;
115 static gint ett_sip_uri = -1;
116 static gint ett_sip_contact_item = -1;
117 static gint ett_sip_message_body = -1;
119 /* PUBLISH method added as per http://www.ietf.org/internet-drafts/draft-ietf-sip-publish-01.txt */
120 static const char *sip_methods[] = {
121 "<Invalid method>", /* Pad so that the real methods start at index 1 */
142 * Updated with info from http://www.iana.org/assignments/sip-parameters
143 * (last updated 2004-10-17)
144 * Updated with: http://www.ietf.org/internet-drafts/draft-ietf-sip-resource-priority-05.txt
148 const char *compact_name;
150 static const sip_header_t sip_headers[] = {
151 { "Unknown-header", NULL }, /* 0 Pad so that the real headers start at index 1 */
152 { "Accept", NULL }, /* 1 */
153 { "Accept-Contact", "a" }, /* 2 RFC3841 */
154 { "Accept-Encoding", NULL }, /* 3 */
155 { "Accept-Language", NULL }, /* 4 */
156 { "Accept-Resource-Priority", NULL }, /* 5 draft-ietf-sip-resource-priority-05.txt */
157 { "Alert-Info", NULL },
159 { "Allow-Events", "u" }, /* 8 RFC3265 */
160 { "Authentication-Info", NULL },
161 { "Authorization", NULL }, /* 10 */
163 { "Call-Info", NULL },
165 { "Content-Disposition", NULL },
166 { "Content-Encoding", "e" }, /* 15 */
167 { "Content-Language", NULL },
168 { "Content-Length", "l" },
169 { "Content-Type", "c" },
171 { "Date", NULL }, /* 20 */
172 { "Error-Info", NULL },
176 { "In-Reply-To", NULL }, /* 25 RFC3261 */
177 { "Join", NULL }, /* 26 RFC-ietf-sip-join-03.txt */
178 { "Max-Forwards", NULL },
179 { "MIME-Version", NULL },
180 { "Min-Expires", NULL },
181 { "Min-SE", NULL }, /* 30 RFC-ietf-sip-session-timer-15.txt */
182 { "Organization", NULL },
183 { "P-Access-Network-Info", NULL }, /* 32 RFC3455 */
184 { "P-Asserted-Identity", NULL }, /* 33 RFC3325 */
185 { "P-Associated-URI", NULL }, /* 34 RFC3455 */
186 { "P-Called-Party-ID", NULL }, /* 35 RFC3455 */
187 { "P-Charging-Function-Addresses",NULL },/* 36 RFC3455 */
188 { "P-Charging-Vector", NULL }, /* 37 RFC3455 */
189 { "P-DCS-Trace-Party-ID", NULL }, /* 38 RFC3603 */
190 { "P-DCS-OSPS", NULL }, /* 39 RFC3603 */
191 { "P-DCS-Billing-Info", NULL }, /* 40 RFC3603 */
192 { "P-DCS-LAES", NULL }, /* 41 RFC3603 */
193 { "P-DCS-Redirect", NULL }, /* 42 RFC3603 */
194 { "P-Media-Authorization", NULL }, /* 43 RFC3313 */
195 { "P-Preferred-Identity", NULL }, /* 44 RFC3325 */
196 { "P-Visited-Network-ID", NULL }, /* 45 RFC3455 */
197 { "Path", NULL }, /* 46 RFC3327 */
198 { "Priority", NULL },
199 { "Privacy", NULL }, /* 48 RFC3323 */
200 { "Proxy-Authenticate", NULL },
201 { "Proxy-Authorization", NULL }, /* 50 */
202 { "Proxy-Require", NULL },
204 { "Reason", NULL }, /* 53 RFC3326 */
205 { "Record-Route", NULL },
206 { "Referred-By", "b" }, /* 55 RFC3892 */
207 { "Reject-Contact", "j" }, /* 56 RFC3841 */
208 { "Replaces", NULL }, /* 57 RFC3891 */
209 { "Reply-To", NULL }, /* 58 RFC3261 */
210 { "Request-Disposition", "d" }, /* 59 RFC3841 */
211 { "Require", NULL }, /* 60 RFC3261 */
212 { "Resource-Priority", NULL }, /* 61 draft-ietf-sip-resource-priority-05.txt */
213 { "Retry-After", NULL }, /* 62 RFC3261 */
214 { "Route", NULL }, /* 63 RFC3261 */
215 { "RSeq", NULL }, /* 64 RFC3841 */
216 { "Security-Client", NULL }, /* 65 RFC3329 */
217 { "Security-Server", NULL }, /* 66 RFC3329 */
218 { "Security-Verify", NULL }, /* 67 RFC3329 */
219 { "Server", NULL }, /* 68 RFC3261 */
220 { "Service-Route", NULL }, /* 69 RFC3608 */
221 { "Session-Expires", "x" }, /* 70 RFC-ietf-sip-session-timer-15.txt */
222 { "SIP-ETag", NULL }, /* 71 draft-ietf-sip-publish-03 */
223 { "SIP-If-Match", NULL }, /* 72 draft-ietf-sip-publish-03 */
224 { "Subject", "s" }, /* 73 RFC3261 */
225 { "Subscription-State", NULL }, /* 74 RFC3265 */
226 { "Supported", "k" }, /* 75 RFC3261 */
227 { "Timestamp", NULL }, /* 76 RFC3261 */
228 { "To", "t" }, /* 77 RFC3261 */
229 { "Unsupported", NULL }, /* 78 RFC3261 */
230 { "User-Agent", NULL }, /* 79 RFC3261 */
231 { "Via", "v" }, /* 80 RFC3261 */
232 { "Warning", NULL }, /* 81 RFC3261 */
233 { "WWW-Authenticate", NULL }, /* 82 RFC3261 */
234 { "Refer-To", "r" }, /* 83 RFC3515 */
235 { "History-Info", NULL }, /* 84 RFC4244 */
241 #define POS_ACCEPT_CONTACT 2
242 #define POS_ACCEPT_ENCODING 3
243 #define POS_ACCEPT_LANGUAGE 4
244 #define POS_ACCEPT_RESOURCE_PRIORITY 5
245 #define POS_ALERT_INFO 6
247 #define POS_ALLOW_EVENTS 8
248 #define POS_AUTHENTICATION_INFO 9
249 #define POS_AUTHORIZATION 10
250 #define POS_CALL_ID 11
251 #define POS_CALL_INFO 12
252 #define POS_CONTACT 13
253 #define POS_CONTENT_DISPOSITION 14
254 #define POS_CONTENT_ENCODING 15
255 #define POS_CONTENT_LANGUAGE 16
256 #define POS_CONTENT_LENGTH 17
257 #define POS_CONTENT_TYPE 18
260 #define POS_ERROR_INFO 21
262 #define POS_EXPIRES 23
264 #define POS_IN_REPLY_TO 25
266 #define POS_MAX_FORWARDS 27
267 #define POS_MIME_VERSION 28
268 #define POS_MIN_EXPIRES 29
269 #define POS_MIN_SE 30
270 #define POS_ORGANIZATION 31
271 #define POS_P_ACCESS_NETWORK_INFO 32
272 #define POS_P_ASSERTED_IDENTITY 33
273 #define POS_P_ASSOCIATED_URI 34
274 #define POS_P_CALLED_PARTY_ID 35
275 #define POS_P_CHARGING_FUNCTION_ADDRESSES 36
276 #define POS_P_CHARGING_VECTOR 37
277 #define POS_P_DCS_TRACE_PARTY_ID 38
278 #define POS_P_DCS_OSPS 39
279 #define POS_P_DCS_BILLING_INFO 40
280 #define POS_P_DCS_LAES 41
281 #define POS_P_DCS_REDIRECT 42
282 #define POS_P_MEDIA_AUTHORIZATION 43
283 #define POS_P_PREFERRED_IDENTITY 44
284 #define POS_P_VISITED_NETWORK_ID 45
286 #define POS_PRIORITY 47
287 #define POS_PRIVACY 48
288 #define POS_PROXY_AUTHENTICATE 49
289 #define POS_PROXY_AUTHORIZATION 50
290 #define POS_PROXY_REQUIRE 51
292 #define POS_REASON 53
293 #define POS_RECORD_ROUTE 54
294 #define POS_REFERED_BY 55
295 #define POS_REJECT_CONTACT 56
296 #define POS_REPLACES 57
297 #define POS_REPLY_TO 58
298 #define POS_REQUEST_DISPOSITION 59
299 #define POS_REQUIRE 60
300 #define POS_RESOURCE_PRIORITY 61
301 #define POS_RETRY_AFTER 62
304 #define POS_SECURITY_CLIENT 65
305 #define POS_SECURITY_SERVER 66
306 #define POS_SECURITY_VERIFY 67
307 #define POS_SERVER 68
308 #define POS_SERVICE_ROUTE 69
309 #define POS_SESSION_EXPIRES 70
310 #define POS_SIP_ETAG 71
311 #define POS_SIP_IF_MATCH 72
312 #define POS_SUBJECT 73
313 #define POS_SUBSCRIPTION_STATE 74
314 #define POS_SUPPORTED 75
315 #define POS_TIMESTAMP 76
317 #define POS_UNSUPPORTED 78
318 #define POS_USER_AGENT 79
320 #define POS_WARNING 81
321 #define POS_WWW_AUTHENTICATE 82
322 #define POS_REFER_TO 83
323 #define POS_HISTORY_INFO 84
325 static gint hf_header_array[] = {
326 -1, /* 0"Unknown-header" - Pad so that the real headers start at index 1 */
328 -1, /* 2"Accept-Contact" RFC3841 */
329 -1, /* 3"Accept-Encoding" */
330 -1, /* 4"Accept-Language" */
331 -1, /* 5"Accept-Resource-Priority" draft-ietf-sip-resource-priority-05.txt */
332 -1, /* 6"Alert-Info", */
334 -1, /* 8"Allow-Events", RFC3265 */
335 -1, /* 9"Authentication-Info" */
336 -1, /* 10"Authorization", */
337 -1, /* 11"Call-ID", */
338 -1, /* 12"Call-Info" */
339 -1, /* 13"Contact", */
340 -1, /* 14"Content-Disposition", */
341 -1, /* 15"Content-Encoding", */
342 -1, /* 16"Content-Language", */
343 -1, /* 17"Content-Length", */
344 -1, /* 18"Content-Type", */
347 -1, /* 21"Error-Info", */
349 -1, /* 23"Expires", */
351 -1, /* 25"In-Reply-To", RFC3261 */
352 -1, /* 26"Join", RFC-ietf-sip-join-03.txt */
353 -1, /* 27"Max-Forwards", */
354 -1, /* 28"MIME-Version", */
355 -1, /* 29"Min-Expires", */
356 -1, /* 30"Min-SE", RFC-ietf-sip-session-timer-15.txt */
357 -1, /* 31"Organization", */
358 -1, /* 32"P-Access-Network-Info", RFC3455 */
359 -1, /* 33"P-Asserted-Identity", RFC3325 */
360 -1, /* 34"P-Associated-URI", RFC3455 */
361 -1, /* 35"P-Called-Party-ID", RFC3455 */
362 -1, /* 36"P-Charging-Function-Addresses", RFC3455 */
363 -1, /* 37"P-Charging-Vector", RFC3455 */
364 -1, /* 38"P-DCS-Trace-Party-ID", RFC3603 */
365 -1, /* 39"P-DCS-OSPS", RFC3603 */
366 -1, /* 40"P-DCS-Billing-Info", RFC3603 */
367 -1, /* 41"P-DCS-LAES", RFC3603 */
368 -1, /* 42"P-DCS-Redirect", RFC3603 */
369 -1, /* 43"P-Media-Authorization", RFC3313 */
370 -1, /* 44"P-Preferred-Identity", RFC3325 */
371 -1, /* 45"P-Visited-Network-ID", RFC3455 */
372 -1, /* 46"Path", RFC3327 */
373 -1, /* 47"Priority" */
374 -1, /* 48"Privacy", RFC3323 */
375 -1, /* 49"Proxy-Authenticate", */
376 -1, /* 50"Proxy-Authorization", */
377 -1, /* 51"Proxy-Require", */
379 -1, /* 53"Reason", RFC3326 */
380 -1, /* 54"Record-Route", */
381 -1, /* 55"Referred-By", */
382 -1, /* 56"Reject-Contact", RFC3841 */
383 -1, /* 57"Replaces", RFC3891 */
384 -1, /* 58"Reply-To", RFC3261 */
385 -1, /* 59"Request-Disposition", RFC3841 */
386 -1, /* 60"Require", RFC3261 */
387 -1, /* 61"Resource-Priority",draft-ietf-sip-resource-priority-05.txt */
388 -1, /* 62"Retry-After", RFC3261 */
389 -1, /* 63"Route", RFC3261 */
390 -1, /* 64"RSeq", RFC3841 */
391 -1, /* 65"Security-Client", RFC3329 */
392 -1, /* 66"Security-Server", RFC3329 */
393 -1, /* 67"Security-Verify", RFC3329 */
394 -1, /* 68"Server", RFC3261 */
395 -1, /* 69"Service-Route", RFC3608 */
396 -1, /* 70"Session-Expires", RFC-ietf-sip-session-timer-15.txt */
397 -1, /* 71"SIP-ETag", draft-ietf-sip-publish-04 */
398 -1, /* 72"SIP-If-Match", draft-ietf-sip-publish-04 */
399 -1, /* 73"Subject", RFC3261 */
400 -1, /* 74"Subscription-State", RFC3265 */
401 -1, /* 75"Supported", RFC3261 */
402 -1, /* 76"Timestamp", RFC3261 */
403 -1, /* 77"To", RFC3261 */
404 -1, /* 78"Unsupported", RFC3261 */
405 -1, /* 79"User-Agent", RFC3261 */
406 -1, /* 80"Via", RFC3261 */
407 -1, /* 81"Warning", RFC3261 */
408 -1, /* 82"WWW-Authenticate", RFC3261 */
409 -1, /* 83"Refer-To", RFC3515 */
410 -1, /* 84"History-Info", RFC4244 */
414 /* Track associations between parameter name and hf item */
416 const char *param_name;
420 static auth_parameter_t auth_parameters_hf_array[] =
422 {"response", &hf_sip_auth_digest_response},
423 {"nc", &hf_sip_auth_nc},
424 {"username", &hf_sip_auth_username},
425 {"realm", &hf_sip_auth_realm},
426 {"nonce", &hf_sip_auth_nonce},
427 {"algorithm", &hf_sip_auth_algorithm},
428 {"opaque", &hf_sip_auth_opaque},
429 {"qop", &hf_sip_auth_qop},
430 {"cnonce", &hf_sip_auth_cnonce},
431 {"uri", &hf_sip_auth_uri},
432 {"domain", &hf_sip_auth_domain},
433 {"stale", &hf_sip_auth_stale},
434 {"auts", &hf_sip_auth_auts},
435 {"rspauth", &hf_sip_auth_rspauth},
436 {"nextnonce", &hf_sip_auth_nextnonce},
440 * Type of line. It's either a SIP Request-Line, a SIP Status-Line, or
441 * another type of line.
449 /* global_sip_raw_text determines whether we are going to display */
450 /* the raw text of the SIP message, much like the MEGACO dissector does. */
451 static gboolean global_sip_raw_text = FALSE;
452 /* strict_sip_version determines whether the SIP dissector enforces
453 * the SIP version to be "SIP/2.0". */
454 static gboolean strict_sip_version = TRUE;
457 * desegmentation of SIP headers
458 * (when we are over TCP or another protocol providing the desegmentation API)
460 static gboolean sip_desegment_headers = TRUE;
463 * desegmentation of SIP bodies
464 * (when we are over TCP or another protocol providing the desegmentation API)
466 static gboolean sip_desegment_body = TRUE;
468 static gboolean dissect_sip_common(tvbuff_t *tvb, int offset, packet_info *pinfo,
469 proto_tree *tree, gboolean is_heur, gboolean use_reassembly);
470 static line_type_t sip_parse_line(tvbuff_t *tvb, int offset, gint linelen,
472 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
473 guint meth_len, guint *meth_idx);
474 static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset,
476 static void dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree,
478 static void dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree);
479 static void tvb_raw_text_add(tvbuff_t *tvb, int offset, int length, proto_tree *tree);
480 static guint sip_is_packet_resend(packet_info *pinfo,
483 guchar cseq_number_set, guint32 cseq_number,
484 line_type_t line_type);
487 /* SIP content type and internet media type used by other dissectors
488 * are the same. List of media types from IANA at:
489 * http://www.iana.org/assignments/media-types/index.html */
490 static dissector_table_t media_type_dissector_table;
492 static heur_dissector_list_t heur_subdissector_list;
494 #define SIP2_HDR "SIP/2.0"
495 #define SIP2_HDR_LEN (strlen (SIP2_HDR))
497 /* Store the info needed by the SIP tap for one packet */
498 static sip_info_value_t *stat_info;
500 /* The buffer size for the cseq_method name */
501 #define MAX_CSEQ_METHOD_SIZE 16
503 /****************************************************************************
504 * Conversation-type definitions
506 * For each call, keep track of the current cseq number and state of
507 * transaction, in order to be able to detect retransmissions.
509 * Don't use the conservation mechanism, but instead:
510 * - store with each dissected packet original frame (if any)
511 * - maintain a global hash table of
512 * (call_id, source_addr, dest_addr) -> (cseq, transaction_state, frame)
513 ****************************************************************************/
515 static GHashTable *sip_hash = NULL; /* Hash table */
517 /* Types for hash table keys and values */
518 #define MAX_CALL_ID_SIZE 128
521 char call_id[MAX_CALL_ID_SIZE];
522 address source_address;
524 address dest_address;
533 provisional_response_seen,
535 } transaction_state_t;
540 transaction_state_t transaction_state;
541 gchar method[MAX_CSEQ_METHOD_SIZE];
542 guint32 response_code;
547 /************************/
548 /* Hash table functions */
551 static gint sip_equal(gconstpointer v, gconstpointer v2)
553 const sip_hash_key* val1 = v;
554 const sip_hash_key* val2 = v2;
556 /* Call id must match */
557 if (strcmp(val1->call_id, val2->call_id) != 0)
562 /* Addresses must match */
563 return (ADDRESSES_EQUAL(&(val1->source_address), &(val2->source_address))) &&
564 (val1->source_port == val2->source_port) &&
565 (ADDRESSES_EQUAL(&(val1->dest_address), &(val2->dest_address))) &&
566 (val1->dest_port == val2->dest_port);
569 /* Compute a hash value for a given key. */
570 /* Don't try to use addresses here, call-id should be almost unique. */
571 static guint sip_hash_func(gconstpointer v)
574 const sip_hash_key *key = v;
575 guint value = strlen(key->call_id);
576 gint chars_to_use = value / 4;
578 /* First few characters from the call-id should be enough... */
579 for (n=0; n < chars_to_use; n++)
581 value += key->call_id[n];
588 /* Initializes the hash table and the mem_chunk area each time a new
589 * file is loaded or re-loaded in wireshark */
591 sip_init_protocol(void)
593 /* Destroy any existing hashes. */
595 g_hash_table_destroy(sip_hash);
597 /* Now create them over */
598 sip_hash = g_hash_table_new(sip_hash_func, sip_equal);
602 * Copied from the mgcp dissector. (This function should be moved to /epan )
603 * tvb_skip_wsp - Returns the position in tvb of the first non-whitespace
604 * character following offset or offset + maxlength -1 whichever
608 * tvb - The tvbuff in which we are skipping whitespace.
609 * offset - The offset in tvb from which we begin trying to skip whitespace.
610 * maxlength - The maximum distance from offset that we may try to skip
613 * Returns: The position in tvb of the first non-whitespace
614 * character following offset or offset + maxlength -1 whichever
617 static gint tvb_skip_wsp(tvbuff_t* tvb, gint offset, gint maxlength)
619 gint counter = offset;
620 gint end = offset + maxlength,tvb_len;
623 /* Get the length remaining */
624 tvb_len = tvb_length(tvb);
625 end = offset + maxlength;
631 /* Skip past spaces, tabs, CRs and LFs until run out or meet something else */
632 for (counter = offset;
634 ((tempchar = tvb_get_guint8(tvb,counter)) == ' ' ||
635 tempchar == '\t' || tempchar == '\r' || tempchar == '\n');
641 /* Structure to collect info about a sip uri */
642 typedef struct _uri_offset_info
644 gint display_name_start;
645 gint display_name_end;
648 gint uri_parameters_start;
649 gint uri_parameters_end;
650 gint name_addr_start;
654 /* Code to parse a sip uri.
655 * Returns Offset end off parsing or -1 for unsuccessful parsing
658 dissect_sip_uri(tvbuff_t *tvb, packet_info *pinfo _U_, gint start_offset,
659 gint line_end_offset, uri_offset_info *uri_offsets)
667 gint semicolon_offset;
668 gint question_mark_offset;
669 gboolean uri_without_angle_quotes = FALSE;
671 /* skip Spaces and Tabs */
672 current_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
674 if(current_offset >= line_end_offset) {
675 /* Nothing to parse */
679 uri_offsets->name_addr_start = current_offset;
681 /* First look, if we have a display name */
682 c=tvb_get_guint8(tvb, current_offset);
686 /* We have a display name, look for the next unescaped '"' */
687 uri_offsets->display_name_start = current_offset;
690 queried_offset = tvb_find_guint8(tvb, current_offset + 1, line_end_offset - (current_offset + 1), '"');
691 if(queried_offset == -1)
696 current_offset = queried_offset;
699 /* count back slashes before '"' */
700 for(i=1;tvb_get_guint8(tvb, queried_offset - i) == '\\';i++);
708 } while (current_offset < line_end_offset);
709 if(current_offset >= line_end_offset)
715 uri_offsets->display_name_end = current_offset;
717 /* find start of the URI */
718 queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, '<');
719 if(queried_offset == -1)
724 current_offset = queried_offset + 1;
728 /* We don't have a display name */
733 /* We have either an URI without angles or a display name with a limited character set */
734 /* Look for the right angle quote or colon */
735 queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, '<');
736 colon_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ':');
737 if(queried_offset != -1 && colon_offset != -1)
739 if(queried_offset < colon_offset)
741 /* we have an URI with angle quotes */
742 uri_offsets->display_name_start = current_offset;
743 uri_offsets->display_name_end = queried_offset - 1;
744 current_offset = queried_offset + 1;
748 /* we have an URI without angle quotes */
749 uri_without_angle_quotes = TRUE;
754 if(queried_offset != -1)
756 /* we have an URI with angle quotes */
757 uri_offsets->display_name_start = current_offset;
758 uri_offsets->display_name_end = queried_offset - 1;
759 current_offset = queried_offset + 1;
762 if(colon_offset != -1)
764 /* we have an URI without angle quotes */
765 uri_without_angle_quotes = TRUE;
768 /* If this point is reached, we can't parse the URI */
774 /* Start parsing of URI */
775 uri_offsets->uri_start = current_offset;
776 if(uri_without_angle_quotes == TRUE)
778 /* look for the first ',' or ';' which will mark the end of this URI
779 * In this case a semicolon indicates a header field parameter, and not an uri parameter.
781 comma_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ',');
782 semicolon_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, ';');
784 if (semicolon_offset != -1 && comma_offset != -1)
786 if(semicolon_offset < comma_offset)
788 uri_offsets->uri_end = semicolon_offset - 1;
792 uri_offsets->uri_end = comma_offset - 1;
797 if (semicolon_offset != -1)
799 uri_offsets->uri_end = semicolon_offset - 1;
801 if (comma_offset != -1)
803 uri_offsets->uri_end = comma_offset - 1;
805 /* If both offsets are equal to -1, we don't have a semicolon or a comma.
806 * In that case, we assume that the end of the URI is at the line end
808 uri_offsets->uri_end = line_end_offset - 2;
810 uri_offsets->name_addr_end = uri_offsets->uri_end;
811 current_offset = uri_offsets->uri_end + 1; /* Now save current_offset, as it is the value to be returned now */
815 /* look for closing angle quote */
816 queried_offset = tvb_find_guint8(tvb, current_offset, line_end_offset - current_offset, '>');
817 if(queried_offset == -1)
822 uri_offsets->name_addr_end = queried_offset;
823 uri_offsets->uri_end = queried_offset - 1;
824 current_offset = queried_offset; /* Now save current_offset. It contains the value we have to return */
826 /* Look for '@' within URI */
827 queried_offset = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, '@');
828 if(queried_offset == -1)
830 /* no '@': look for the first ';' or '?' in the URI */
831 question_mark_offset = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, '?');
832 semicolon_offset = tvb_find_guint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, ';');
836 /* with '@': look for the first ';' or '?' behind the '@' */
837 question_mark_offset = tvb_find_guint8(tvb, queried_offset, uri_offsets->uri_end - queried_offset, '?');
838 semicolon_offset = tvb_find_guint8(tvb, queried_offset, uri_offsets->uri_end - queried_offset, ';');
842 if (semicolon_offset != -1 && question_mark_offset != -1)
844 if(semicolon_offset < question_mark_offset)
846 uri_offsets->uri_parameters_start = semicolon_offset;
850 uri_offsets->uri_parameters_start = question_mark_offset;
852 uri_offsets->uri_parameters_end = uri_offsets->uri_end;
853 uri_offsets->uri_end = uri_offsets->uri_parameters_start - 1;
857 if (semicolon_offset != -1)
859 uri_offsets->uri_parameters_start = semicolon_offset;
860 uri_offsets->uri_parameters_end = uri_offsets->uri_end;
861 uri_offsets->uri_end = uri_offsets->uri_parameters_start - 1;
863 if (question_mark_offset != -1)
865 uri_offsets->uri_parameters_start = question_mark_offset;
866 uri_offsets->uri_parameters_end = uri_offsets->uri_end;
867 uri_offsets->uri_end = uri_offsets->uri_parameters_start - 1;
869 /* If both offsets are equal to -1, we don't have a semicolon or a question mark.
870 * In that case, we don't have to save any offsets.
876 return current_offset;
880 /* Code to parse a contact header item
881 * Returns Offset end off parsing or -1 for unsuccessful parsing
884 dissect_sip_contact_item(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint start_offset, gint line_end_offset)
888 proto_item *ti = NULL;
889 proto_tree *contact_item_tree = NULL, *uri_tree = NULL;
893 gint contact_params_start_offset = -1;
894 gint contact_item_end_offset = -1;
895 uri_offset_info uri_offsets;
897 uri_offsets.display_name_start = -1;
898 uri_offsets.display_name_end = -1;
899 uri_offsets.uri_start = -1;
900 uri_offsets.uri_end = -1;
901 uri_offsets.uri_parameters_start = -1;
902 uri_offsets.uri_parameters_end = -1;
903 uri_offsets.name_addr_start = -1;
904 uri_offsets.name_addr_end = -1;
906 /* skip Spaces and Tabs */
907 start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
909 if(start_offset >= line_end_offset) {
910 /* Nothing to parse */
914 current_offset = dissect_sip_uri(tvb, pinfo, start_offset, line_end_offset, &uri_offsets);
915 if(current_offset == -1)
921 /* Now look for the end of the contact item */
922 while (current_offset < line_end_offset)
924 c=tvb_get_guint8(tvb, current_offset);
926 if(c == ';' && contact_params_start_offset == -1)
928 /* here we start with contact parameters */
929 contact_params_start_offset = current_offset;
934 /* look for the next unescaped '"' */
937 queried_offset = tvb_find_guint8(tvb, current_offset + 1, line_end_offset - (current_offset + 1), '"');
938 if(queried_offset == -1)
940 /* malformed Contact header */
943 current_offset = queried_offset;
946 * Look for uneven number of backslashes before '"' */
947 for(i=0;tvb_get_guint8(tvb, queried_offset - (i+1) ) == '\\';i++);
954 /* end of contact item found. */
955 contact_item_end_offset = current_offset - 1; /* remove ',' */
962 if(contact_item_end_offset == -1)
963 contact_item_end_offset = line_end_offset - 3; /* remove '\r\n' */
965 /* Build the tree, now */
968 ti = proto_tree_add_string(tree, hf_sip_contact_item, tvb, start_offset, contact_item_end_offset - start_offset + 1,
969 tvb_format_text(tvb, start_offset, contact_item_end_offset - start_offset + 1));
970 contact_item_tree = proto_item_add_subtree(ti, ett_sip_contact_item);
972 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,
973 tvb_format_text(tvb, uri_offsets.name_addr_start, uri_offsets.name_addr_end - uri_offsets.name_addr_start + 1));
974 uri_tree = proto_item_add_subtree(ti, ett_sip_uri);
976 if(uri_offsets.display_name_start != -1 && uri_offsets.display_name_end != -1)
978 proto_tree_add_string(uri_tree, hf_sip_display, tvb, uri_offsets.display_name_start,
979 uri_offsets.display_name_end - uri_offsets.display_name_start + 1,
980 tvb_format_text(tvb, uri_offsets.display_name_start,
981 uri_offsets.display_name_end - uri_offsets.display_name_start + 1));
984 if(uri_offsets.uri_start != -1 && uri_offsets.uri_end != -1)
986 proto_tree_add_string(uri_tree, hf_sip_contact_addr, tvb, uri_offsets.uri_start,
987 uri_offsets.uri_end - uri_offsets.uri_start + 1,
988 tvb_format_text(tvb, uri_offsets.uri_start,
989 uri_offsets.uri_end - uri_offsets.uri_start + 1));
992 /* Parse URI and Contact header Parameters now */
996 return current_offset;
999 /* Code to parse an authorization header item
1000 * Returns offset at end of parsing, or -1 for unsuccessful parsing
1003 dissect_sip_authorization_item(tvbuff_t *tvb, proto_tree *tree, gint start_offset, gint line_end_offset)
1006 gint current_offset;
1007 gint equals_offset = 0;
1009 auth_parameter_t *auth_parameter;
1011 gboolean in_quoted_string = FALSE;
1013 /* skip Spaces and Tabs */
1014 start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1016 if (start_offset >= line_end_offset)
1018 /* Nothing to parse */
1022 current_offset = start_offset;
1024 /* Now look for the end of the parameter */
1025 while (current_offset < line_end_offset)
1027 c = tvb_get_guint8(tvb, current_offset);
1031 equals_offset = current_offset;
1036 /* look for the next unescaped '"' */
1039 current_offset = tvb_find_guint8(tvb, current_offset + 1, line_end_offset - (current_offset + 1), '"');
1040 if(current_offset == -1)
1042 /* malformed parameter */
1047 * Look for uneven number of backslashes before '"' */
1048 for(i=0;tvb_get_guint8(tvb, current_offset - (i+1) ) == '\\';i++);
1052 current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1063 if (equals_offset == 0)
1065 /* Give up if equals not found */
1069 /* Extract the parameter name */
1070 name = tvb_get_ephemeral_string(tvb, start_offset, equals_offset-start_offset);
1072 /* Try to add parameter as a filterable item */
1073 for (auth_parameter = &auth_parameters_hf_array[i];
1074 i < array_length(auth_parameters_hf_array);
1075 i++, auth_parameter++)
1077 if (strcasecmp(name, auth_parameter->param_name) == 0)
1079 proto_tree_add_item(tree, *(auth_parameter->hf_item), tvb,
1080 equals_offset+1, current_offset-equals_offset-1,
1086 /* If not matched, just add as text... */
1087 if (i == array_length(auth_parameters_hf_array))
1089 proto_tree_add_text(tree, tvb, start_offset, current_offset-start_offset,
1090 "%s", tvb_format_text(tvb, start_offset,
1091 current_offset-start_offset));
1094 return current_offset;
1098 /* Code to actually dissect the packets */
1100 dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1105 octet = tvb_get_guint8(tvb,0);
1106 if ((octet & 0xf8) == 0xf8){
1107 call_dissector(sigcomp_handle, tvb, pinfo, tree);
1108 return tvb_length(tvb);
1111 len = dissect_sip_common(tvb, 0, pinfo, tree, FALSE, FALSE);
1113 return 0; /* not SIP */
1119 dissect_sip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1125 octet = tvb_get_guint8(tvb,0);
1126 if ((octet & 0xf8) == 0xf8){
1127 call_dissector(sigcomp_handle, tvb, pinfo, tree);
1131 while (tvb_reported_length_remaining(tvb, offset) != 0) {
1132 len = dissect_sip_common(tvb, offset, pinfo, tree, TRUE, TRUE);
1140 dissect_sip_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1144 gboolean first = TRUE;
1146 while (tvb_reported_length_remaining(tvb, offset) != 0) {
1147 len = dissect_sip_common(tvb, offset, pinfo, tree, !first, TRUE);
1151 * If the first packet doesn't start with
1152 * a valid SIP request or response, don't
1153 * treat this as SIP.
1160 break; /* need more data */
1167 dissect_sip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1169 return dissect_sip_common(tvb, 0, pinfo, tree, FALSE, FALSE) > 0;
1173 dissect_sip_common(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
1174 gboolean dissect_other_as_continuation, gboolean use_reassembly)
1177 gint next_offset, linelen;
1178 int content_length, datalen, reported_datalen;
1179 line_type_t line_type;
1181 gboolean is_known_request;
1182 gboolean found_match = FALSE;
1184 guint token_1_len = 0;
1185 guint current_method_idx = 0;
1186 proto_item *ts = NULL, *ti = NULL, *th = NULL, *sip_element_item = NULL;
1187 proto_tree *sip_tree = NULL, *reqresp_tree = NULL , *hdr_tree = NULL, *sip_element_tree = NULL, *message_body_tree = NULL;
1188 guchar contacts = 0, contact_is_star = 0, expires_is_0 = 0;
1189 guint32 cseq_number = 0;
1190 guchar cseq_number_set = 0;
1191 char cseq_method[MAX_CSEQ_METHOD_SIZE] = "";
1192 char call_id[MAX_CALL_ID_SIZE] = "";
1193 char *media_type_str = NULL;
1194 char *media_type_str_lower_case = NULL;
1195 char *content_type_parameter_str = NULL;
1196 guint resend_for_packet = 0;
1199 /* Initialise stat info for passing to tap */
1200 stat_info = ep_alloc(sizeof(sip_info_value_t));
1201 stat_info->response_code = 0;
1202 stat_info->request_method = NULL;
1203 stat_info->reason_phrase = NULL;
1204 stat_info->resend = 0;
1205 stat_info->tap_call_id = NULL;
1206 stat_info->tap_from_addr = NULL;
1207 stat_info->tap_to_addr = NULL;
1210 * Note that "tvb_find_line_end()" will return a value that
1211 * is not longer than what's in the buffer, so the
1212 * "tvb_get_ptr()" calls below won't throw exceptions.
1214 * Note that "tvb_strneql()" doesn't throw exceptions, so
1215 * "sip_parse_line()" won't throw an exception.
1217 orig_offset = offset;
1218 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
1219 if (tvb_strnlen(tvb, offset, linelen) > -1)
1222 * There's a NULL in the line,
1223 * this may be SIP within another protocol.
1224 * This heuristic still needs to improve.
1228 line_type = sip_parse_line(tvb, offset, linelen, &token_1_len);
1229 if (line_type == OTHER_LINE) {
1231 * This is neither a SIP request nor response.
1233 if (!dissect_other_as_continuation) {
1235 * We were asked to reject this.
1241 * Just dissect it as a continuation.
1243 } else if (use_reassembly) {
1246 * Yes, it's a request or response.
1247 * Do header desegmentation if we've been told to,
1248 * and do body desegmentation if we've been told to and
1249 * we find a Content-Length header.
1251 if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo,
1252 sip_desegment_headers, sip_desegment_body)) {
1254 * More data needed for desegmentation.
1260 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1261 col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIP");
1263 switch (line_type) {
1266 is_known_request = sip_is_known_request(tvb, offset, token_1_len, ¤t_method_idx);
1267 descr = is_known_request ? "Request" : "Unknown request";
1268 if (check_col(pinfo->cinfo, COL_INFO)) {
1269 col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
1271 tvb_format_text(tvb, offset, linelen - SIP2_HDR_LEN - 1));
1277 if (check_col(pinfo->cinfo, COL_INFO)) {
1278 col_add_fstr(pinfo->cinfo, COL_INFO, "Status: %s",
1279 tvb_format_text(tvb, offset + SIP2_HDR_LEN + 1, linelen - SIP2_HDR_LEN - 1));
1281 stat_info->reason_phrase = tvb_get_ephemeral_string(tvb, offset + SIP2_HDR_LEN + 5, linelen - (SIP2_HDR_LEN + 5));
1285 default: /* Squelch compiler complaints */
1286 descr = "Continuation";
1287 if (check_col(pinfo->cinfo, COL_INFO))
1288 col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
1293 ts = proto_tree_add_item(tree, proto_sip, tvb, offset, -1, FALSE);
1294 sip_tree = proto_item_add_subtree(ts, ett_sip);
1297 switch (line_type) {
1301 ti = proto_tree_add_string(sip_tree, hf_Request_Line, tvb, offset, linelen,
1302 tvb_format_text(tvb, offset, linelen));
1303 reqresp_tree = proto_item_add_subtree(ti, ett_sip_reqresp);
1305 dfilter_sip_request_line(tvb, reqresp_tree, token_1_len);
1310 ti = proto_tree_add_string(sip_tree, hf_Status_Line, tvb, offset, linelen,
1311 tvb_format_text(tvb, offset, linelen));
1312 reqresp_tree = proto_item_add_subtree(ti, ett_sip_reqresp);
1314 dfilter_sip_status_line(tvb, reqresp_tree);
1319 ti = proto_tree_add_text(sip_tree, tvb, offset, next_offset,
1320 "%s line: %s", descr,
1321 tvb_format_text(tvb, offset, linelen));
1322 reqresp_tree = proto_item_add_subtree(ti, ett_sip_reqresp);
1323 proto_tree_add_text(sip_tree, tvb, offset, -1,
1324 "Continuation data");
1326 return tvb_length_remaining(tvb, offset);
1329 offset = next_offset;
1331 th = proto_tree_add_item(sip_tree, hf_msg_hdr, tvb, offset, -1, FALSE);
1332 hdr_tree = proto_item_add_subtree(th, ett_sip_hdr);
1336 * Process the headers - if we're not building a protocol tree,
1337 * we just do this to find the blank line separating the
1338 * headers from the message body.
1340 next_offset = offset;
1341 content_length = -1;
1342 while (tvb_reported_length_remaining(tvb, offset) > 0) {
1343 gint line_end_offset;
1345 gint semi_colon_offset;
1347 gint parameter_offset;
1348 gint parameter_end_offset;
1350 gint content_type_len, content_type_parameter_str_len;
1359 linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
1362 * This is a blank line separating the
1363 * message header from the message body.
1365 offset = next_offset;
1369 line_end_offset = offset + linelen;
1370 while ((c = tvb_get_guint8(tvb, next_offset)) == ' ' || c == '\t')
1373 * This line end is not a header seperator.
1374 * It just extends the header with another line.
1375 * Look for next line end:
1377 linelen += (next_offset - line_end_offset);
1378 linelen += tvb_find_line_end(tvb, next_offset, -1, &next_offset, FALSE);
1379 line_end_offset = offset + linelen;
1382 colon_offset = tvb_find_guint8(tvb, offset, linelen, ':');
1383 if (colon_offset == -1) {
1385 * Malformed header - no colon after the name.
1388 proto_tree_add_text(hdr_tree, tvb, offset,
1389 next_offset - offset, "%s",
1390 tvb_format_text(tvb, offset, linelen));
1393 header_len = colon_offset - offset;
1394 hf_index = sip_is_known_sip_header(tvb, offset, header_len);
1396 if (hf_index == -1) {
1398 proto_tree_add_text(hdr_tree, tvb,
1399 offset, next_offset - offset, "%s",
1400 tvb_format_text(tvb, offset, linelen));
1404 * Skip whitespace after the colon.
1406 value_offset = tvb_skip_wsp(tvb, colon_offset + 1, line_end_offset - (colon_offset + 1));
1411 value_len = line_end_offset - value_offset;
1412 value = tvb_get_ephemeral_string(tvb, value_offset,
1416 * Add it to the protocol tree,
1417 * but display the line as is.
1419 switch ( hf_index ) {
1423 sip_element_item = proto_tree_add_string_format(hdr_tree,
1424 hf_header_array[hf_index], tvb,
1425 offset, next_offset - offset,
1427 tvb_format_text(tvb, offset, linelen));
1428 sip_element_tree = proto_item_add_subtree( sip_element_item,
1431 /* See if we have a SIP/SIPS uri enclosed in <>, if so anything in front is
1434 parameter_offset = tvb_find_guint8(tvb, value_offset,value_len, '<');
1435 if ( parameter_offset != -1){
1436 len = parameter_offset - value_offset;
1438 /* Something in front, must be display info
1439 * TODO: Get rid of trailing space(s)
1441 proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, value_offset,
1444 parameter_offset ++;
1445 parameter_end_offset = parameter_offset;
1446 /* RFC3261 paragraph 20
1447 * The Contact, From, and To header fields contain a URI. If the URI
1448 * contains a comma, question mark or semicolon, the URI MUST be
1449 * enclosed in angle brackets (< and >). Any URI parameters are
1450 * contained within these brackets. If the URI is not enclosed in angle
1451 * brackets, any semicolon-delimited parameters are header-parameters,
1452 * not URI parameters.
1454 while (parameter_end_offset < line_end_offset){
1455 parameter_end_offset++;
1456 c = tvb_get_guint8(tvb, parameter_end_offset);
1462 goto separator_found;
1468 parameter_len = parameter_end_offset - parameter_offset;
1469 proto_tree_add_item(sip_element_tree, hf_sip_to_addr, tvb, parameter_offset,
1470 parameter_len, FALSE);
1471 /*info for the tap for voip_calls.c*/
1472 stat_info->tap_to_addr=tvb_get_ephemeral_string(tvb, parameter_offset, parameter_len);
1474 parameter_offset = parameter_end_offset + 1;
1478 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,( line_end_offset - parameter_offset), ';');
1479 if ( parameter_end_offset == -1)
1480 parameter_end_offset = line_end_offset;
1482 offset = parameter_end_offset;
1486 /* Extract SIP/SIPS URI */
1487 parameter_offset = value_offset;
1488 while (parameter_offset < line_end_offset
1489 && (tvb_strneql(tvb, parameter_offset, "sip", 3) != 0))
1491 len = parameter_offset - value_offset;
1493 /* Something in front, must be display info
1494 * TODO: Get rid of trailing space(s)
1496 proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, value_offset,
1499 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
1500 (line_end_offset - parameter_offset), ';');
1501 if ( parameter_end_offset == -1)
1502 parameter_end_offset = line_end_offset;
1503 parameter_len = parameter_end_offset - parameter_offset;
1504 proto_tree_add_item(sip_element_tree, hf_sip_to_addr, tvb, parameter_offset,
1505 parameter_len, FALSE);
1506 /*info for the tap for voip_calls.c*/
1507 stat_info->tap_to_addr=tvb_get_ephemeral_string(tvb, parameter_offset, parameter_len);
1508 offset = parameter_end_offset;
1510 /* Find parameter tag if present.
1511 * TODO make this generic to find any interesting parameter
1512 * use the same method as for SIP headers ?
1515 parameter_offset = offset;
1516 while (parameter_offset < line_end_offset
1517 && (tvb_strneql(tvb, parameter_offset, "tag=", 4) != 0))
1519 if ( parameter_offset < line_end_offset ){ /* Tag found */
1520 parameter_offset = parameter_offset + 4;
1521 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
1522 (line_end_offset - parameter_offset), ';');
1523 if ( parameter_end_offset == -1)
1524 parameter_end_offset = line_end_offset;
1525 parameter_len = parameter_end_offset - parameter_offset;
1526 proto_tree_add_item(sip_element_tree, hf_sip_tag, tvb, parameter_offset,
1527 parameter_len, FALSE);
1534 sip_element_item = proto_tree_add_string_format(hdr_tree,
1535 hf_header_array[hf_index], tvb,
1536 offset, next_offset - offset,
1538 tvb_format_text(tvb, offset, linelen));
1539 sip_element_tree = proto_item_add_subtree( sip_element_item, ett_sip_element);
1541 /* See if we have a SIP/SIPS uri enclosed in <>, if so anything in front is
1544 parameter_offset = tvb_find_guint8(tvb, value_offset,value_len, '<');
1545 if ( parameter_offset != -1){
1546 len = parameter_offset - value_offset;
1548 /* Something in front, must be display info
1549 * TODO: Get rid of trailing space(s)
1551 proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, value_offset,
1554 parameter_offset ++;
1555 parameter_end_offset = parameter_offset;
1556 /* RFC3261 paragraph 20
1557 * The Contact, From, and To header fields contain a URI. If the URI
1558 * contains a comma, question mark or semicolon, the URI MUST be
1559 * enclosed in angle brackets (< and >). Any URI parameters are
1560 * contained within these brackets. If the URI is not enclosed in angle
1561 * brackets, any semicolon-delimited parameters are header-parameters,
1562 * not URI parameters.
1564 while (parameter_end_offset < line_end_offset){
1565 parameter_end_offset++;
1566 c = tvb_get_guint8(tvb, parameter_end_offset);
1572 goto separator_found2;
1578 parameter_len = parameter_end_offset - parameter_offset;
1579 dfilter_store_sip_from_addr(tvb, sip_element_tree,
1580 parameter_offset, parameter_len);
1581 /*info for the tap for voip_calls.c*/
1582 stat_info->tap_from_addr=tvb_get_ephemeral_string(tvb, parameter_offset, parameter_len);
1583 parameter_offset = parameter_end_offset + 1;
1587 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,( line_end_offset - parameter_offset), ';');
1588 if ( parameter_end_offset == -1)
1589 parameter_end_offset = line_end_offset;
1591 offset = parameter_end_offset;
1595 /* Extract SIP/SIPS URI */
1596 parameter_offset = value_offset;
1597 while (parameter_offset < line_end_offset
1598 && (tvb_strneql(tvb, parameter_offset, "sip", 3) != 0))
1600 len = parameter_offset - value_offset;
1602 /* Something in front, must be display info
1603 * TODO: Get rid of trailing space(s)
1605 proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, value_offset,
1608 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
1609 (line_end_offset - parameter_offset), ';');
1610 if ( parameter_end_offset == -1)
1611 parameter_end_offset = line_end_offset;
1612 parameter_len = parameter_end_offset - parameter_offset;
1613 proto_tree_add_item(sip_element_tree, hf_sip_from_addr, tvb, parameter_offset,
1614 parameter_len, FALSE);
1615 /*info for the tap for voip_calls.c*/
1616 stat_info->tap_from_addr=tvb_get_ephemeral_string(tvb, parameter_offset, parameter_len);
1617 offset = parameter_end_offset;
1619 /* Find parameter tag if present.
1620 * TODO make this generic to find any interesting parameter
1621 * use the same method as for SIP headers ?
1624 parameter_offset = offset;
1625 while (parameter_offset < line_end_offset
1626 && (tvb_strneql(tvb, parameter_offset, "tag=", 4) != 0))
1628 if ( parameter_offset < line_end_offset ){ /* Tag found */
1629 parameter_offset = parameter_offset + 4;
1630 parameter_end_offset = tvb_find_guint8(tvb, parameter_offset,
1631 (line_end_offset - parameter_offset), ';');
1632 if ( parameter_end_offset == -1)
1633 parameter_end_offset = line_end_offset;
1634 parameter_len = parameter_end_offset - parameter_offset;
1635 proto_tree_add_item(sip_element_tree, hf_sip_tag, tvb, parameter_offset,
1636 parameter_len, FALSE);
1642 /* Store the sequence number */
1643 cseq_number = atoi(value);
1644 cseq_number_set = 1;
1645 stat_info->tap_cseq_number=cseq_number;
1647 /* Walk past number and spaces characters to get to start
1649 for (value_offset=0; value_offset < (gint)strlen(value); value_offset++)
1651 if (isalpha((guchar)value[value_offset]))
1656 if (value_offset == (gint)strlen(value))
1658 THROW(ReportedBoundsError);
1659 return offset - orig_offset;
1662 /* Extract method name from value */
1663 strlen_to_copy = strlen(value)-value_offset+1;
1664 if (strlen_to_copy > MAX_CSEQ_METHOD_SIZE) {
1665 /* Note the error in the protocol tree */
1667 proto_tree_add_string_format(hdr_tree,
1668 hf_header_array[hf_index], tvb,
1669 offset, next_offset - offset,
1670 value+value_offset, "%s String too big: %d bytes",
1671 sip_headers[POS_CSEQ].name,
1674 THROW(ReportedBoundsError);
1675 return offset - orig_offset;
1678 strncpy(cseq_method, value+value_offset, MIN(strlen_to_copy, MAX_CSEQ_METHOD_SIZE));
1680 /* Add 'CSeq' string item to tree */
1682 proto_tree_add_string_format(hdr_tree,
1683 hf_header_array[hf_index], tvb,
1684 offset, next_offset - offset,
1686 tvb_format_text(tvb, offset, linelen));
1692 /* Store the Call-id */
1693 strncpy(call_id, value,
1694 strlen(value)+1 < MAX_CALL_ID_SIZE ?
1697 stat_info->tap_call_id = ep_strdup(call_id);
1699 /* Add 'Call-id' string item to tree */
1701 proto_tree_add_string_format(hdr_tree,
1702 hf_header_array[hf_index], tvb,
1703 offset, next_offset - offset,
1705 tvb_format_text(tvb, offset, linelen));
1710 if (strcmp(value, "0") == 0)
1714 /* Add 'Expires' string item to tree */
1716 proto_tree_add_string_format(hdr_tree,
1717 hf_header_array[hf_index], tvb,
1718 offset, next_offset - offset,
1720 tvb_format_text(tvb, offset, linelen));
1725 * Content-Type is the same as Internet
1726 * media type used by other dissectors,
1727 * appropriate dissector found by
1728 * lookup in "media_type" dissector table.
1730 case POS_CONTENT_TYPE :
1732 proto_tree_add_string_format(hdr_tree,
1733 hf_header_array[hf_index], tvb,
1734 offset, next_offset - offset,
1736 tvb_format_text(tvb, offset, linelen));
1738 content_type_len = value_len;
1739 semi_colon_offset = tvb_find_guint8(tvb, value_offset, value_len, ';');
1740 if ( semi_colon_offset != -1) {
1742 * Skip whitespace after the semicolon.
1744 parameter_offset = tvb_skip_wsp(tvb, semi_colon_offset +1, value_offset + value_len - (semi_colon_offset +1));
1746 content_type_len = semi_colon_offset - value_offset;
1747 content_type_parameter_str_len = value_offset + value_len - parameter_offset;
1748 content_type_parameter_str = tvb_get_ephemeral_string(tvb, parameter_offset,
1749 content_type_parameter_str_len);
1751 media_type_str = tvb_get_ephemeral_string(tvb, value_offset, content_type_len);
1752 #if GLIB_MAJOR_VERSION < 2
1753 media_type_str_lower_case = ep_strdup(media_type_str);
1754 g_strdown(media_type_str_lower_case);
1756 media_type_str_lower_case = g_ascii_strdown(media_type_str, -1);
1760 case POS_CONTENT_LENGTH :
1762 proto_tree_add_string_format(hdr_tree,
1763 hf_header_array[hf_index], tvb,
1764 offset, next_offset - offset,
1766 tvb_format_text(tvb, offset, linelen));
1768 content_length = atoi(value);
1773 sip_element_item = proto_tree_add_string_format(hdr_tree,
1774 hf_header_array[hf_index], tvb,
1775 offset, next_offset - offset,
1777 tvb_format_text(tvb, offset, linelen));
1778 sip_element_tree = proto_item_add_subtree( sip_element_item,
1781 if (strcmp(value, "*") == 0)
1783 contact_is_star = 1;
1787 comma_offset = value_offset;
1788 while((comma_offset = dissect_sip_contact_item(tvb, pinfo, sip_element_tree, comma_offset, next_offset)) != -1)
1791 if(comma_offset == next_offset)
1793 /* Line End reached: Stop Parsing */
1797 if(tvb_get_guint8(tvb, comma_offset) != ',')
1799 /* Undefined value reached: Stop Parsing */
1802 comma_offset++; /* skip comma */
1806 case POS_AUTHORIZATION:
1807 case POS_WWW_AUTHENTICATE:
1808 case POS_PROXY_AUTHENTICATE:
1809 case POS_PROXY_AUTHORIZATION:
1810 case POS_AUTHENTICATION_INFO:
1811 /* Add tree using whole text of line */
1814 /* Add whole line as header tree */
1815 sip_element_item = proto_tree_add_string_format(hdr_tree,
1816 hf_header_array[hf_index], tvb,
1817 offset, next_offset - offset,
1819 tvb_format_text(tvb, offset, linelen));
1820 sip_element_tree = proto_item_add_subtree( sip_element_item,
1823 /* Set sip.auth as a hidden field/filter */
1824 ti = proto_tree_add_item(hdr_tree, hf_sip_auth, tvb,
1825 offset, next_offset-offset,
1827 PROTO_ITEM_SET_HIDDEN(ti);
1830 /* Parse each individual parameter in the line */
1831 comma_offset = tvb_pbrk_guint8(tvb, value_offset, line_end_offset - value_offset, " \t\r\n");
1833 /* Authentication-Info does not begin with the scheme name */
1834 if (hf_index != POS_AUTHENTICATION_INFO)
1836 proto_tree_add_item(sip_element_tree, hf_sip_auth_scheme,
1837 tvb, value_offset, comma_offset - value_offset,
1841 while ((comma_offset = dissect_sip_authorization_item(tvb, sip_element_tree, comma_offset, line_end_offset)) != -1)
1843 if(comma_offset == line_end_offset)
1845 /* Line End reached: Stop Parsing */
1849 if(tvb_get_guint8(tvb, comma_offset) != ',')
1851 /* Undefined value reached: Stop Parsing */
1854 comma_offset++; /* skip comma */
1860 proto_tree_add_string_format(hdr_tree,
1861 hf_header_array[hf_index], tvb,
1862 offset, next_offset - offset,
1864 tvb_format_text(tvb, offset, linelen));
1869 }/* if colon_offset */
1870 offset = next_offset;
1873 datalen = tvb_length_remaining(tvb, offset);
1874 reported_datalen = tvb_reported_length_remaining(tvb, offset);
1875 if (content_length != -1) {
1876 if (datalen > content_length)
1877 datalen = content_length;
1878 if (reported_datalen > content_length)
1879 reported_datalen = content_length;
1884 * There's a message body starting at "offset".
1885 * Set the length of the header item.
1887 proto_item_set_end(th, tvb, offset);
1888 next_tvb = tvb_new_subset(tvb, offset, datalen, reported_datalen);
1890 ti = proto_tree_add_text(sip_tree, next_tvb, 0, -1,
1892 message_body_tree = proto_item_add_subtree(ti, ett_sip_message_body);
1895 /* give the content type parameters to sub dissectors */
1897 if ( media_type_str_lower_case != NULL ) {
1898 void *save_private_data = pinfo->private_data;
1899 pinfo->private_data = content_type_parameter_str;
1900 found_match = dissector_try_string(media_type_dissector_table,
1901 media_type_str_lower_case,
1904 pinfo->private_data = save_private_data;
1905 /* If no match dump as text */
1907 if ( found_match != TRUE )
1909 if (!(dissector_try_heuristic(heur_subdissector_list,
1910 next_tvb, pinfo, message_body_tree))) {
1912 while (tvb_offset_exists(next_tvb, tmp_offset)) {
1913 tvb_find_line_end(next_tvb, tmp_offset, -1, &next_offset, FALSE);
1914 linelen = next_offset - tmp_offset;
1915 if(message_body_tree) {
1916 proto_tree_add_text(message_body_tree, next_tvb,
1917 tmp_offset, linelen, "%s",
1918 tvb_format_text(next_tvb, tmp_offset, linelen));
1920 tmp_offset = next_offset;
1928 /* Add to info column interesting things learned from header fields. */
1929 if (check_col(pinfo->cinfo, COL_INFO))
1931 /* Registration requests */
1932 if (strcmp(sip_methods[current_method_idx], "REGISTER") == 0)
1934 if (contact_is_star && expires_is_0)
1936 col_append_str(pinfo->cinfo, COL_INFO, " (remove all bindings)");
1941 col_append_str(pinfo->cinfo, COL_INFO, " (fetch bindings)");
1945 /* Registration responses */
1946 if (line_type == STATUS_LINE && (strcmp(cseq_method, "REGISTER") == 0))
1948 col_append_fstr(pinfo->cinfo, COL_INFO, " (%d bindings)", contacts);
1952 /* Check if this packet is a resend. */
1953 resend_for_packet = sip_is_packet_resend(pinfo, cseq_method, call_id,
1954 cseq_number_set, cseq_number,
1956 /* Mark whether this is a resend for the tap */
1957 stat_info->resend = (resend_for_packet > 0);
1959 /* And add the filterable field to the request/response line */
1963 item = proto_tree_add_boolean(reqresp_tree, hf_sip_resend, tvb, orig_offset, 0,
1964 resend_for_packet > 0);
1965 PROTO_ITEM_SET_GENERATED(item);
1966 if (resend_for_packet > 0)
1968 item = proto_tree_add_uint(reqresp_tree, hf_sip_original_frame,
1969 tvb, orig_offset, 0, resend_for_packet);
1970 PROTO_ITEM_SET_GENERATED(item);
1976 proto_item_set_len(ts, offset - orig_offset);
1978 if (global_sip_raw_text)
1979 tvb_raw_text_add(tvb, orig_offset, offset - orig_offset, tree);
1981 /* Report this packet to the tap */
1982 if (!pinfo->in_error_pkt)
1984 tap_queue_packet(sip_tap, pinfo, stat_info);
1987 return offset - orig_offset;
1990 /* Display filter for SIP Request-Line */
1992 dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, guint meth_len)
1997 * We know we have the entire method; otherwise, "sip_parse_line()"
1998 * would have returned OTHER_LINE.
2000 string = tvb_get_ephemeral_string(tvb, 0, meth_len);
2002 proto_tree_add_string(tree, hf_Method, tvb, 0, meth_len, string);
2004 /* Copy request method for telling tap */
2005 stat_info->request_method = string;
2008 /* Display filter for SIP Status-Line */
2010 dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree)
2013 gint response_code = 0;
2016 * We know we have the entire status code; otherwise,
2017 * "sip_parse_line()" would have returned OTHER_LINE.
2018 * We also know that we have a version string followed by a
2019 * space at the beginning of the line, for the same reason.
2021 tvb_memcpy(tvb, (guint8 *)string, SIP2_HDR_LEN + 1, 3);
2023 response_code = atoi(string);
2025 /* Add numerical response code to tree */
2027 proto_tree_add_uint(tree, hf_Status_Code, tvb, SIP2_HDR_LEN + 1,
2031 /* Add response code for sending to tap */
2032 stat_info->response_code = response_code;
2035 void dfilter_store_sip_from_addr(tvbuff_t *tvb,proto_tree *tree,guint parameter_offset,
2036 guint parameter_len)
2038 proto_tree_add_item(tree, hf_sip_from_addr, tvb, parameter_offset,
2039 parameter_len, FALSE);
2042 /* From section 4.1 of RFC 2543:
2044 * Request-Line = Method SP Request-URI SP SIP-Version CRLF
2046 * From section 5.1 of RFC 2543:
2048 * Status-Line = SIP-version SP Status-Code SP Reason-Phrase CRLF
2050 * From section 7.1 of RFC 3261:
2052 * Unlike HTTP, SIP treats the version number as a literal string.
2053 * In practice, this should make no difference.
2056 sip_parse_line(tvbuff_t *tvb, int offset, gint linelen, guint *token_1_lenp)
2067 token_1_start = offset;
2068 space_offset = tvb_find_guint8(tvb, token_1_start, -1, ' ');
2069 if ((space_offset == -1) || (space_offset == token_1_start)) {
2071 * Either there's no space in the line (which means
2072 * the line is empty or doesn't have a token followed
2073 * by a space; neither is valid for a request or status), or
2074 * the first character in the line is a space (meaning
2075 * the method is empty, which isn't valid for a request,
2076 * or the SIP version is empty, which isn't valid for a
2081 token_1_len = space_offset - token_1_start;
2082 token_2_start = space_offset + 1;
2083 space_offset = tvb_find_guint8(tvb, token_2_start, -1, ' ');
2084 if (space_offset == -1) {
2086 * There's no space after the second token, so we don't
2087 * have a third token.
2091 token_2_len = space_offset - token_2_start;
2092 token_3_start = space_offset + 1;
2093 token_3_len = token_1_start + linelen - token_3_start;
2095 *token_1_lenp = token_1_len;
2098 * Is the first token a version string?
2100 if ( (strict_sip_version && (
2101 token_1_len == SIP2_HDR_LEN
2102 && tvb_strneql(tvb, token_1_start, SIP2_HDR, SIP2_HDR_LEN) == 0)
2103 ) || (! strict_sip_version && (
2104 tvb_strncaseeql(tvb, token_1_start, "SIP/", 4) == 0)
2107 * Yes, so this is either a Status-Line or something
2108 * else other than a Request-Line. To be a Status-Line,
2109 * the second token must be a 3-digit number.
2111 if (token_2_len != 3) {
2113 * We don't have 3-character status code.
2117 if (!isdigit(tvb_get_guint8(tvb, token_2_start)) ||
2118 !isdigit(tvb_get_guint8(tvb, token_2_start + 1)) ||
2119 !isdigit(tvb_get_guint8(tvb, token_2_start + 2))) {
2121 * 3 characters yes, 3 digits no.
2128 * No, so this is either a Request-Line or something
2129 * other than a Status-Line. To be a Request-Line, the
2130 * second token must be a URI and the third token must
2131 * be a version string.
2133 if (token_2_len < 3) {
2135 * We don't have a URI consisting of at least 3
2140 colon_pos = tvb_find_guint8(tvb, token_2_start + 1, -1, ':');
2141 if (colon_pos == -1) {
2143 * There is no colon after the method, so the URI
2144 * doesn't have a colon in it, so it's not valid.
2148 if (colon_pos >= token_3_start) {
2150 * The colon is in the version string, not the URI.
2154 /* XXX - Check for a proper URI prefix? */
2155 if ( (strict_sip_version && (
2156 token_3_len != SIP2_HDR_LEN
2157 || tvb_strneql(tvb, token_3_start, SIP2_HDR, SIP2_HDR_LEN) == -1)
2158 ) || (! strict_sip_version && (
2159 tvb_strncaseeql(tvb, token_3_start, "SIP/", 4) == -1)
2162 * The version string isn't an SIP version 2.0 version
2167 return REQUEST_LINE;
2171 static gboolean sip_is_known_request(tvbuff_t *tvb, int meth_offset,
2172 guint meth_len, guint *meth_idx)
2176 for (i = 1; i < array_length(sip_methods); i++) {
2177 if (meth_len == strlen(sip_methods[i]) &&
2178 tvb_strneql(tvb, meth_offset, sip_methods[i], meth_len) == 0)
2188 /* Returns index of method in sip_headers */
2189 static gint sip_is_known_sip_header(tvbuff_t *tvb, int offset, guint header_len)
2193 for (i = 1; i < array_length(sip_headers); i++) {
2194 if (header_len == strlen(sip_headers[i].name) &&
2195 tvb_strncaseeql(tvb, offset, sip_headers[i].name, header_len) == 0)
2197 if (sip_headers[i].compact_name != NULL &&
2198 header_len == strlen(sip_headers[i].compact_name) &&
2199 tvb_strncaseeql(tvb, offset, sip_headers[i].compact_name, header_len) == 0)
2207 * Display the entire message as raw text.
2210 tvb_raw_text_add(tvbuff_t *tvb, int offset, int length, proto_tree *tree)
2212 proto_tree *raw_tree = NULL;
2213 proto_item *ti = NULL;
2214 int next_offset, linelen, end_offset;
2217 ti = proto_tree_add_item(tree, proto_raw_sip, tvb, offset, length, FALSE);
2218 raw_tree = proto_item_add_subtree(ti, ett_raw_text);
2221 end_offset = offset + length;
2223 while (offset < end_offset) {
2224 tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
2225 linelen = next_offset - offset;
2227 proto_tree_add_text(raw_tree, tvb, offset, linelen,
2228 "%s", tvb_format_text(tvb, offset, linelen));
2230 offset = next_offset;
2234 /* Check to see if this packet is a resent request. Return value is number
2235 of the original frame this packet seems to be resending (0 = no resend). */
2236 guint sip_is_packet_resend(packet_info *pinfo,
2239 guchar cseq_number_set,
2240 guint32 cseq_number, line_type_t line_type)
2242 guint32 cseq_to_compare = 0;
2244 sip_hash_key *p_key = 0;
2245 sip_hash_value *p_val = 0;
2248 /* Only consider retransmission of UDP packets */
2249 if (pinfo->ptype != PT_UDP)
2254 /* Don't consider packets that appear to be resent only because
2255 they are e.g. returned in ICMP unreachable messages. */
2256 if (pinfo->in_error_pkt)
2261 /* A broken packet may have no cseq number set. Don't consider it as
2263 if (!cseq_number_set)
2268 /* Return any answer stored from previous dissection */
2269 if (pinfo->fd->flags.visited)
2271 return GPOINTER_TO_UINT(p_get_proto_data(pinfo->fd, proto_sip));
2274 /* No packet entry found, consult global hash table */
2276 /* Prepare the key */
2277 strncpy(key.call_id, call_id,
2278 (strlen(call_id)+1 <= MAX_CALL_ID_SIZE) ?
2281 COPY_ADDRESS(&key.dest_address, &pinfo->net_dst);
2282 COPY_ADDRESS(&key.source_address, &pinfo->net_src);
2283 key.dest_port = pinfo->destport;
2284 key.source_port = pinfo->srcport;
2287 p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
2291 /* Table entry found, we'll use its value for comparison */
2292 cseq_to_compare = p_val->cseq;
2296 /* Need to create a new table entry */
2298 /* Allocate a new key and value */
2299 p_key = se_alloc(sizeof(sip_hash_key));
2300 p_val = se_alloc(sizeof(sip_hash_value));
2302 /* Just give up if allocations failed */
2303 if (!p_key || !p_val)
2308 /* Fill in key and value details */
2309 g_snprintf(p_key->call_id, MAX_CALL_ID_SIZE, "%s", call_id);
2310 COPY_ADDRESS(&(p_key->dest_address), &pinfo->net_dst);
2311 COPY_ADDRESS(&(p_key->source_address), &pinfo->net_src);
2312 p_key->dest_port = pinfo->destport;
2313 p_key->source_port = pinfo->srcport;
2315 p_val->cseq = cseq_number;
2316 strncpy(p_val->method, cseq_method, MAX_CSEQ_METHOD_SIZE-1);
2317 p_val->method[MAX_CSEQ_METHOD_SIZE-1] = '\0';
2318 p_val->transaction_state = nothing_seen;
2319 p_val->frame_number = 0;
2322 g_hash_table_insert(sip_hash, p_key, p_val);
2324 /* Assume have seen no cseq yet */
2325 cseq_to_compare = 0;
2329 /******************************************/
2330 /* Is it a resend??? */
2332 /* Does this look like a resent request (discount ACK, CANCEL, or a
2333 different method from the original one) ? */
2335 if ((line_type == REQUEST_LINE) && (cseq_number == cseq_to_compare) &&
2336 (p_val->transaction_state == request_seen) &&
2337 (strcmp(cseq_method, p_val->method) == 0) &&
2338 (strcmp(cseq_method, "ACK") != 0) &&
2339 (strcmp(cseq_method, "CANCEL") != 0))
2341 result = p_val->frame_number;
2344 /* Does this look like a resent final response ? */
2345 if ((line_type == STATUS_LINE) && (cseq_number == cseq_to_compare) &&
2346 (p_val->transaction_state == final_response_seen) &&
2347 (strcmp(cseq_method, p_val->method) == 0) &&
2348 (stat_info->response_code >= 200) &&
2349 (stat_info->response_code == p_val->response_code))
2351 result = p_val->frame_number;
2354 /* Update state for this entry */
2355 p_val->cseq = cseq_number;
2360 p_val->transaction_state = request_seen;
2363 p_val->frame_number = pinfo->fd->num;
2367 if (stat_info->response_code >= 200)
2369 p_val->response_code = stat_info->response_code;
2370 p_val->transaction_state = final_response_seen;
2373 p_val->frame_number = pinfo->fd->num;
2378 p_val->transaction_state = provisional_response_seen;
2385 /* Store return value with this packet */
2386 p_add_proto_data(pinfo->fd, proto_sip, GUINT_TO_POINTER(result));
2392 /* Register the protocol with Wireshark */
2393 void proto_register_sip(void)
2396 /* Setup list of header fields */
2397 static hf_register_info hf[] = {
2400 { "Message Header", "sip.msg_hdr",
2401 FT_NONE, 0, NULL, 0,
2402 "Message Header in SIP message", HFILL }
2405 { "Method", "sip.Method",
2406 FT_STRING, BASE_NONE,NULL,0x0,
2407 "SIP Method", HFILL }
2410 { "Request-Line", "sip.Request-Line",
2411 FT_STRING, BASE_NONE,NULL,0x0,
2412 "SIP Request-Line", HFILL }
2415 { "Status-Code", "sip.Status-Code",
2416 FT_UINT32, BASE_DEC,NULL,0x0,
2417 "SIP Status Code", HFILL }
2420 { "Status-Line", "sip.Status-Line",
2421 FT_STRING, BASE_NONE,NULL,0x0,
2422 "SIP Status-Line", HFILL }
2425 { "SIP Display info", "sip.display.info",
2426 FT_STRING, BASE_NONE,NULL,0x0,
2427 "RFC 3261: Display info", HFILL }
2430 { "SIP to address", "sip.to.addr",
2431 FT_STRING, BASE_NONE,NULL,0x0,
2432 "RFC 3261: to addr", HFILL }
2434 { &hf_sip_from_addr,
2435 { "SIP from address", "sip.from.addr",
2436 FT_STRING, BASE_NONE,NULL,0x0,
2437 "RFC 3261: from addr", HFILL }
2439 { &hf_sip_contact_addr,
2440 { "SIP contact address", "sip.contact.addr",
2441 FT_STRING, BASE_NONE,NULL,0x0,
2442 "RFC 3261: contact addr", HFILL }
2446 FT_STRING, BASE_NONE,NULL,0x0,
2447 "RFC 3261: SIP Uri", HFILL }
2449 { &hf_sip_contact_item,
2450 { "Contact Binding", "sip.contact.binding",
2451 FT_STRING, BASE_NONE,NULL,0x0,
2452 "RFC 3261: one contact binding", HFILL }
2455 { "SIP tag", "sip.tag",
2456 FT_STRING, BASE_NONE,NULL,0x0,
2457 "RFC 3261: tag", HFILL }
2459 { &hf_header_array[POS_ACCEPT],
2460 { "Accept", "sip.Accept",
2461 FT_STRING, BASE_NONE,NULL,0x0,
2462 "RFC 3261: Accept Header", HFILL }
2464 { &hf_header_array[POS_ACCEPT_CONTACT],
2465 { "Accept-Contact", "sip.Accept-Contact",
2466 FT_STRING, BASE_NONE,NULL,0x0,
2467 "RFC 3841: Accept-Contact Header", HFILL }
2469 { &hf_header_array[POS_ACCEPT_ENCODING],
2470 { "Accept-Encoding", "sip.Accept-Encoding",
2471 FT_STRING, BASE_NONE,NULL,0x0,
2472 "RFC 3841: Accept-Encoding Header", HFILL }
2474 { &hf_header_array[POS_ACCEPT_LANGUAGE],
2475 { "Accept-Language", "sip.Accept-Language",
2476 FT_STRING, BASE_NONE,NULL,0x0,
2477 "RFC 3261: Accept-Language Header", HFILL }
2479 { &hf_header_array[POS_ACCEPT_RESOURCE_PRIORITY],
2480 { "Accept-Resource-Priority", "sip.Accept-Resource-Priority",
2481 FT_STRING, BASE_NONE,NULL,0x0,
2482 "Draft: Accept-Resource-Priority Header", HFILL }
2484 { &hf_header_array[POS_ALERT_INFO],
2485 { "Alert-Info", "sip.Alert-Info",
2486 FT_STRING, BASE_NONE,NULL,0x0,
2487 "RFC 3261: Alert-Info Header", HFILL }
2489 { &hf_header_array[POS_ALLOW],
2490 { "Allow", "sip.Allow",
2491 FT_STRING, BASE_NONE,NULL,0x0,
2492 "RFC 3261: Allow Header", HFILL }
2494 { &hf_header_array[POS_ALLOW_EVENTS],
2495 { "Allow-Events", "sip.Allow-Events",
2496 FT_STRING, BASE_NONE,NULL,0x0,
2497 "RFC 3265: Allow-Events Header", HFILL }
2499 { &hf_header_array[POS_AUTHENTICATION_INFO],
2500 { "Authentication-Info", "sip.Authentication-Info",
2501 FT_STRING, BASE_NONE,NULL,0x0,
2502 "RFC 3261: Authentication-Info Header", HFILL }
2504 { &hf_header_array[POS_AUTHORIZATION],
2505 { "Authorization", "sip.Authorization",
2506 FT_STRING, BASE_NONE,NULL,0x0,
2507 "RFC 3261: Authorization Header", HFILL }
2509 { &hf_header_array[POS_CALL_ID],
2510 { "Call-ID", "sip.Call-ID",
2511 FT_STRING, BASE_NONE,NULL,0x0,
2512 "RFC 3261: Call-ID Header", HFILL }
2514 { &hf_header_array[POS_CALL_INFO],
2515 { "Call-Info", "sip.Call-Info",
2516 FT_STRING, BASE_NONE,NULL,0x0,
2517 "RFC 3261: Call-Info Header", HFILL }
2519 { &hf_header_array[POS_CONTACT],
2520 { "Contact", "sip.Contact",
2521 FT_STRING, BASE_NONE,NULL,0x0,
2522 "RFC 3261: Contact Header", HFILL }
2524 { &hf_header_array[POS_CONTENT_DISPOSITION],
2525 { "Content-Disposition", "sip.Content-Disposition",
2526 FT_STRING, BASE_NONE,NULL,0x0,
2527 "RFC 3261: Content-Disposition Header", HFILL }
2529 { &hf_header_array[POS_CONTENT_ENCODING],
2530 { "Content-Encoding", "sip.Content-Encoding",
2531 FT_STRING, BASE_NONE,NULL,0x0,
2532 "RFC 3261: Content-Encoding Header", HFILL }
2534 { &hf_header_array[POS_CONTENT_LANGUAGE],
2535 { "Content-Language", "sip.Content-Language",
2536 FT_STRING, BASE_NONE,NULL,0x0,
2537 "RFC 3261: Content-Language Header", HFILL }
2539 { &hf_header_array[POS_CONTENT_LENGTH],
2540 { "Content-Length", "sip.Content-Length",
2541 FT_STRING, BASE_NONE,NULL,0x0,
2542 "RFC 3261: Content-Length Header", HFILL }
2544 { &hf_header_array[POS_CONTENT_TYPE],
2545 { "Content-Type", "sip.Content-Type",
2546 FT_STRING, BASE_NONE,NULL,0x0,
2547 "RFC 3261: Content-Type Header", HFILL }
2549 { &hf_header_array[POS_CSEQ],
2550 { "CSeq", "sip.CSeq",
2551 FT_STRING, BASE_NONE,NULL,0x0,
2552 "RFC 3261: CSeq Header", HFILL }
2554 { &hf_header_array[POS_DATE],
2555 { "Date", "sip.Date",
2556 FT_STRING, BASE_NONE,NULL,0x0,
2557 "RFC 3261: Date Header", HFILL }
2559 { &hf_header_array[POS_ERROR_INFO],
2560 { "Error-Info", "sip.Error-Info",
2561 FT_STRING, BASE_NONE,NULL,0x0,
2562 "RFC 3261: Error-Info Header", HFILL }
2564 { &hf_header_array[POS_EVENT],
2565 { "Event", "sip.Event",
2566 FT_STRING, BASE_NONE,NULL,0x0,
2567 "RFC 3265: Event Header", HFILL }
2569 { &hf_header_array[POS_EXPIRES],
2570 { "Expires", "sip.Expires",
2571 FT_STRING, BASE_NONE,NULL,0x0,
2572 "RFC 3261: Expires Header", HFILL }
2574 { &hf_header_array[POS_FROM],
2575 { "From", "sip.From",
2576 FT_STRING, BASE_NONE,NULL,0x0,
2577 "RFC 3261: From Header", HFILL }
2579 { &hf_header_array[POS_IN_REPLY_TO],
2580 { "In-Reply-To", "sip.In-Reply-To",
2581 FT_STRING, BASE_NONE,NULL,0x0,
2582 "RFC 3261: In-Reply-To Header", HFILL }
2584 { &hf_header_array[POS_JOIN],
2585 { "Join", "sip.Join",
2586 FT_STRING, BASE_NONE,NULL,0x0,
2587 "Draft: Join Header", HFILL }
2589 { &hf_header_array[POS_MAX_FORWARDS],
2590 { "Max-Forwards", "sip.Max-Forwards",
2591 FT_STRING, BASE_NONE,NULL,0x0,
2592 "RFC 3261: Max-Forwards Header", HFILL }
2594 { &hf_header_array[POS_MIME_VERSION],
2595 { "MIME-Version", "sip.MIME-Version",
2596 FT_STRING, BASE_NONE,NULL,0x0,
2597 "RFC 3261: MIME-Version Header", HFILL }
2599 { &hf_header_array[POS_MIN_EXPIRES],
2600 { "Min-Expires", "sip.Min-Expires",
2601 FT_STRING, BASE_NONE,NULL,0x0,
2602 "RFC 3261: Min-Expires Header", HFILL }
2604 { &hf_header_array[POS_MIN_SE],
2605 { "Min-SE", "sip.Min-SE",
2606 FT_STRING, BASE_NONE,NULL,0x0,
2607 "Draft: Min-SE Header", HFILL }
2609 { &hf_header_array[POS_ORGANIZATION],
2610 { "Organization", "sip.Organization",
2611 FT_STRING, BASE_NONE,NULL,0x0,
2612 "RFC 3261: Organization Header", HFILL }
2614 { &hf_header_array[POS_P_ACCESS_NETWORK_INFO],
2615 { "P-Access-Network-Info", "sip.P-Access-Network-Info",
2616 FT_STRING, BASE_NONE,NULL,0x0,
2617 "P-Access-Network-Info Header", HFILL }
2620 { &hf_header_array[POS_P_ASSERTED_IDENTITY],
2621 { "P-Asserted-Identity", "sip.P-Asserted-Identity",
2622 FT_STRING, BASE_NONE,NULL,0x0,
2623 "P-Asserted-Identity Header", HFILL }
2626 { &hf_header_array[POS_P_ASSOCIATED_URI],
2627 { "P-Associated-URI", "sip.P-Associated-URI",
2628 FT_STRING, BASE_NONE,NULL,0x0,
2629 "P-Associated-URI Header", HFILL }
2632 { &hf_header_array[POS_P_CALLED_PARTY_ID],
2633 { "P-Called-Party-ID", "sip.P-Called-Party-ID",
2634 FT_STRING, BASE_NONE,NULL,0x0,
2635 "P-Called-Party-ID Header", HFILL }
2638 { &hf_header_array[POS_P_CHARGING_FUNCTION_ADDRESSES],
2639 { "P-Charging-Function-Addresses","sip.P-Charging-Function-Addresses",
2640 FT_STRING, BASE_NONE,NULL,0x0,
2641 "P-Charging-Function-Addresses", HFILL }
2644 { &hf_header_array[POS_P_CHARGING_VECTOR],
2645 { "P-Charging-Vector", "sip.P-Charging-Vector",
2646 FT_STRING, BASE_NONE,NULL,0x0,
2647 "P-Charging-Vector Header", HFILL }
2650 { &hf_header_array[POS_P_DCS_TRACE_PARTY_ID],
2651 { "P-DCS-Trace-Party-ID", "sip.P-DCS-Trace-Party-ID",
2652 FT_STRING, BASE_NONE,NULL,0x0,
2653 "P-DCS-Trace-Party-ID Header", HFILL }
2656 { &hf_header_array[POS_P_DCS_OSPS],
2657 { "P-DCS-OSPS", "sip.P-DCS-OSPS",
2658 FT_STRING, BASE_NONE,NULL,0x0,
2659 "P-DCS-OSPS Header", HFILL }
2662 { &hf_header_array[POS_P_DCS_BILLING_INFO],
2663 { "P-DCS-Billing-Info", "sip.P-DCS-Billing-Info",
2664 FT_STRING, BASE_NONE,NULL,0x0,
2665 "P-DCS-Billing-Info Header", HFILL }
2668 { &hf_header_array[POS_P_DCS_LAES],
2669 { "P-DCS-LAES", "sip.P-DCS-LAES",
2670 FT_STRING, BASE_NONE,NULL,0x0,
2671 "P-DCS-LAES Header", HFILL }
2674 { &hf_header_array[POS_P_DCS_REDIRECT],
2675 { "P-DCS-Redirect", "sip.P-DCS-Redirect",
2676 FT_STRING, BASE_NONE,NULL,0x0,
2677 "P-DCS-Redirect Header", HFILL }
2680 { &hf_header_array[POS_P_MEDIA_AUTHORIZATION],
2681 { "P-Media-Authorization", "sip.P-Media-Authorization",
2682 FT_STRING, BASE_NONE,NULL,0x0,
2683 "P-Media-Authorization Header", HFILL }
2686 { &hf_header_array[POS_P_PREFERRED_IDENTITY],
2687 { "P-Preferred-Identity", "sip.P-Preferred-Identity",
2688 FT_STRING, BASE_NONE,NULL,0x0,
2689 "P-Preferred-Identity Header", HFILL }
2692 { &hf_header_array[POS_P_VISITED_NETWORK_ID],
2693 { "P-Visited-Network-ID", "sip.P-Visited-Network-ID",
2694 FT_STRING, BASE_NONE,NULL,0x0,
2695 "P-Visited-Network-ID Header", HFILL }
2698 { &hf_header_array[POS_PATH],
2699 { "Path", "sip.Path",
2700 FT_STRING, BASE_NONE,NULL,0x0,
2701 "Path Header", HFILL }
2704 { &hf_header_array[POS_PRIORITY],
2705 { "Priority", "sip.Priority",
2706 FT_STRING, BASE_NONE,NULL,0x0,
2707 "RFC 3261: Priority Header", HFILL }
2709 { &hf_header_array[POS_PRIVACY],
2710 { "Privacy", "sip.Privacy",
2711 FT_STRING, BASE_NONE,NULL,0x0,
2712 "Privacy Header", HFILL }
2715 { &hf_header_array[POS_PROXY_AUTHENTICATE],
2716 { "Proxy-Authenticate", "sip.Proxy-Authenticate",
2717 FT_STRING, BASE_NONE,NULL,0x0,
2718 "RFC 3261: Proxy-Authenticate Header", HFILL }
2720 { &hf_header_array[POS_PROXY_AUTHORIZATION],
2721 { "Proxy-Authorization", "sip.Proxy-Authorization",
2722 FT_STRING, BASE_NONE,NULL,0x0,
2723 "RFC 3261: Proxy-Authorization Header", HFILL }
2726 { &hf_header_array[POS_PROXY_REQUIRE],
2727 { "Proxy-Require", "sip.Proxy-Require",
2728 FT_STRING, BASE_NONE,NULL,0x0,
2729 "RFC 3261: Proxy-Require Header", HFILL }
2731 { &hf_header_array[POS_RACK],
2732 { "RAck", "sip.RAck",
2733 FT_STRING, BASE_NONE,NULL,0x0,
2734 "RFC 3262: RAck Header", HFILL }
2736 { &hf_header_array[POS_REASON],
2737 { "Reason", "sip.Reason",
2738 FT_STRING, BASE_NONE,NULL,0x0,
2739 "RFC 3326 Reason Header", HFILL }
2741 { &hf_header_array[POS_RECORD_ROUTE],
2742 { "Record-Route", "sip.Record-Route",
2743 FT_STRING, BASE_NONE,NULL,0x0,
2744 "RFC 3261: Record-Route Header", HFILL }
2746 { &hf_header_array[POS_REFERED_BY],
2747 { "Refered By", "sip.Refered-by",
2748 FT_STRING, BASE_NONE,NULL,0x0,
2749 "RFC 3892: Refered-by Header", HFILL }
2751 { &hf_header_array[POS_REJECT_CONTACT],
2752 { "Reject-Contact", "sip.Reject-Contact",
2753 FT_STRING, BASE_NONE,NULL,0x0,
2754 "RFC 3841: Reject-Contact Header", HFILL }
2756 { &hf_header_array[POS_REPLACES],
2757 { "Replaces", "sip.Replaces",
2758 FT_STRING, BASE_NONE,NULL,0x0,
2759 "RFC 3891: Replaces Header", HFILL }
2761 { &hf_header_array[POS_REPLY_TO],
2762 { "Reply-To", "sip.Reply-To",
2763 FT_STRING, BASE_NONE,NULL,0x0,
2764 "RFC 3261: Reply-To Header", HFILL }
2766 { &hf_header_array[POS_REQUEST_DISPOSITION],
2767 { "Request-Disposition", "sip.Request-Disposition",
2768 FT_STRING, BASE_NONE,NULL,0x0,
2769 "RFC 3841: Request-Disposition Header", HFILL }
2771 { &hf_header_array[POS_REQUIRE],
2772 { "Require", "sip.Require",
2773 FT_STRING, BASE_NONE,NULL,0x0,
2774 "RFC 3261: Require Header", HFILL }
2776 { &hf_header_array[POS_RESOURCE_PRIORITY],
2777 { "Resource-Priority", "sip.Resource-Priority",
2778 FT_STRING, BASE_NONE,NULL,0x0,
2779 "Draft: Resource-Priority Header", HFILL }
2781 { &hf_header_array[POS_RETRY_AFTER],
2782 { "Retry-After", "sip.Retry-After",
2783 FT_STRING, BASE_NONE,NULL,0x0,
2784 "RFC 3261: Retry-After Header", HFILL }
2786 { &hf_header_array[POS_ROUTE],
2787 { "Route", "sip.Route",
2788 FT_STRING, BASE_NONE,NULL,0x0,
2789 "RFC 3261: Route Header", HFILL }
2791 { &hf_header_array[POS_RSEQ],
2792 { "RSeq", "sip.RSeq",
2793 FT_STRING, BASE_NONE,NULL,0x0,
2794 "RFC 3262: RSeq Header", HFILL }
2796 { &hf_header_array[ POS_SECURITY_CLIENT],
2797 { "Security-Client", "sip.Security-Client",
2798 FT_STRING, BASE_NONE,NULL,0x0,
2799 "RFC 3329 Security-Client Header", HFILL }
2801 { &hf_header_array[ POS_SECURITY_SERVER],
2802 { "Security-Server", "sip.Security-Server",
2803 FT_STRING, BASE_NONE,NULL,0x0,
2804 "RFC 3329 Security-Server Header", HFILL }
2806 { &hf_header_array[ POS_SECURITY_VERIFY],
2807 { "Security-Verify", "sip.Security-Verify",
2808 FT_STRING, BASE_NONE,NULL,0x0,
2809 "RFC 3329 Security-Verify Header", HFILL }
2811 { &hf_header_array[POS_SERVER],
2812 { "Server", "sip.Server",
2813 FT_STRING, BASE_NONE,NULL,0x0,
2814 "RFC 3261: Server Header", HFILL }
2816 { &hf_header_array[POS_SERVICE_ROUTE],
2817 { "Service-Route", "sip.Service-Route",
2818 FT_STRING, BASE_NONE,NULL,0x0,
2819 "Service-Route Header", HFILL }
2821 { &hf_header_array[POS_SESSION_EXPIRES],
2822 { "Session-Expires", "sip.Session-Expires",
2823 FT_STRING, BASE_NONE,NULL,0x0,
2824 "Session-Expires Header", HFILL }
2826 { &hf_header_array[POS_SIP_ETAG],
2827 { "ETag", "sip.ETag",
2828 FT_STRING, BASE_NONE,NULL,0x0,
2829 "SIP-ETag Header", HFILL }
2831 { &hf_header_array[POS_SIP_IF_MATCH],
2832 { "If_Match", "sip.If_Match",
2833 FT_STRING, BASE_NONE,NULL,0x0,
2834 "SIP-If-Match Header", HFILL }
2836 { &hf_header_array[POS_SUBJECT],
2837 { "Subject", "sip.Subject",
2838 FT_STRING, BASE_NONE,NULL,0x0,
2839 "RFC 3261: Subject Header", HFILL }
2841 { &hf_header_array[POS_SUBSCRIPTION_STATE],
2842 { "Subscription-State", "sip.Subscription-State",
2843 FT_STRING, BASE_NONE,NULL,0x0,
2844 "RFC 3265: Subscription-State Header", HFILL }
2846 { &hf_header_array[POS_SUPPORTED],
2847 { "Supported", "sip.Supported",
2848 FT_STRING, BASE_NONE,NULL,0x0,
2849 "RFC 3261: Supported Header", HFILL }
2851 { &hf_header_array[POS_TIMESTAMP],
2852 { "Timestamp", "sip.Timestamp",
2853 FT_STRING, BASE_NONE,NULL,0x0,
2854 "RFC 3261: Timestamp Header", HFILL }
2856 { &hf_header_array[POS_TO],
2858 FT_STRING, BASE_NONE,NULL,0x0,
2859 "RFC 3261: To Header", HFILL }
2862 { &hf_header_array[POS_UNSUPPORTED],
2863 { "Unsupported", "sip.Unsupported",
2864 FT_STRING, BASE_NONE,NULL,0x0,
2865 "RFC 3261: Unsupported Header", HFILL }
2867 { &hf_header_array[POS_USER_AGENT],
2868 { "User-Agent", "sip.User-Agent",
2869 FT_STRING, BASE_NONE,NULL,0x0,
2870 "RFC 3261: User-Agent Header", HFILL }
2872 { &hf_header_array[POS_VIA],
2874 FT_STRING, BASE_NONE,NULL,0x0,
2875 "RFC 3261: Via Header", HFILL }
2877 { &hf_header_array[POS_WARNING],
2878 { "Warning", "sip.Warning",
2879 FT_STRING, BASE_NONE,NULL,0x0,
2880 "RFC 3261: Warning Header", HFILL }
2883 { &hf_header_array[POS_WWW_AUTHENTICATE],
2884 { "WWW-Authenticate", "sip.WWW-Authenticate",
2885 FT_STRING, BASE_NONE,NULL,0x0,
2886 "RFC 3261: WWW-Authenticate Header", HFILL }
2888 { &hf_header_array[POS_REFER_TO],
2889 { "Refer-To", "sip.Refer-To",
2890 FT_STRING, BASE_NONE,NULL,0x0,
2891 "Refer-To Header", HFILL }
2893 { &hf_header_array[POS_HISTORY_INFO],
2894 { "History-Info", "sip.History-Info",
2895 FT_STRING, BASE_NONE,NULL,0x0,
2896 "RFC 4244: Request History Information", HFILL }
2899 { "Resent Packet", "sip.resend",
2900 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2903 { &hf_sip_original_frame,
2904 { "Suspected resend of frame", "sip.resend-original",
2905 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2906 "Original transmission of frame", HFILL}
2909 { "Authentication", "sip.auth",
2910 FT_STRING, BASE_NONE, NULL, 0x0,
2911 "SIP Authentication", HFILL}
2913 { &hf_sip_auth_scheme,
2914 { "Authentication Scheme", "sip.auth.scheme",
2915 FT_STRING, BASE_NONE, NULL, 0x0,
2916 "SIP Authentication Scheme", HFILL}
2918 { &hf_sip_auth_digest_response,
2919 { "Digest Authentication Response", "sip.auth.digest.response",
2920 FT_STRING, BASE_NONE, NULL, 0x0,
2921 "SIP Digest Authentication Response Value ", HFILL}
2924 { "Nonce Count", "sip.auth.nc",
2925 FT_STRING, BASE_NONE, NULL, 0x0,
2926 "SIP Authentication nonce count", HFILL}
2928 { &hf_sip_auth_username,
2929 { "Username", "sip.auth.username",
2930 FT_STRING, BASE_NONE, NULL, 0x0,
2931 "Sip authentication username", HFILL}
2933 { &hf_sip_auth_realm,
2934 { "Realm", "sip.auth.realm",
2935 FT_STRING, BASE_NONE, NULL, 0x0,
2936 "Sip Authentication realm", HFILL}
2938 { &hf_sip_auth_nonce,
2939 { "Nonce Value", "sip.auth.nonce",
2940 FT_STRING, BASE_NONE, NULL, 0x0,
2941 "SIP Authentication nonce value", HFILL}
2943 { &hf_sip_auth_algorithm,
2944 { "Algorithm", "sip.auth.algorithm",
2945 FT_STRING, BASE_NONE, NULL, 0x0,
2946 "SIP Authentication Algorithm", HFILL}
2948 { &hf_sip_auth_opaque,
2949 { "Opaque Value", "sip.auth.opaque",
2950 FT_STRING, BASE_NONE, NULL, 0x0,
2951 "SIP Authentication opaque value", HFILL}
2954 { "QOP", "sip.auth.qop",
2955 FT_STRING, BASE_NONE, NULL, 0x0,
2956 "SIP Authentication QOP", HFILL}
2958 { &hf_sip_auth_cnonce,
2959 { "CNonce Value", "sip.auth.cnonce",
2960 FT_STRING, BASE_NONE, NULL, 0x0,
2961 "SIP Authentication Client Nonce value ", HFILL}
2964 { "Authentication URI", "sip.auth.uri",
2965 FT_STRING, BASE_NONE, NULL, 0x0,
2966 "SIP Authentication URI", HFILL}
2968 { &hf_sip_auth_domain,
2969 { "Authentication Domain", "sip.auth.domain",
2970 FT_STRING, BASE_NONE, NULL, 0x0,
2971 "SIP Authentication Domain", HFILL}
2973 { &hf_sip_auth_stale,
2974 { "Stale Flag", "sip.auth.stale",
2975 FT_STRING, BASE_NONE, NULL, 0x0,
2976 "SIP Authentication Stale Flag", HFILL}
2978 { &hf_sip_auth_auts,
2979 { "Authentication Token", "sip.auth.auts",
2980 FT_STRING, BASE_NONE, NULL, 0x0,
2981 "SIP Authentication Token", HFILL}
2983 { &hf_sip_auth_rspauth,
2984 { "Response auth", "sip.auth.rspauth",
2985 FT_STRING, BASE_NONE, NULL, 0x0,
2986 "SIP Response auth", HFILL}
2988 { &hf_sip_auth_nextnonce,
2989 { "Next Nonce", "sip.auth.nextnonce",
2990 FT_STRING, BASE_NONE, NULL, 0x0,
2991 "SIP Next Nonce", HFILL}
2995 /* Setup protocol subtree array */
2996 static gint *ett[] = {
3002 &ett_sip_contact_item,
3003 &ett_sip_message_body,
3005 static gint *ett_raw[] = {
3009 module_t *sip_module;
3011 /* Register the protocol name and description */
3012 proto_sip = proto_register_protocol("Session Initiation Protocol",
3014 proto_raw_sip = proto_register_protocol("Session Initiation Protocol (SIP as raw text)",
3015 "Raw_SIP", "raw_sip");
3016 new_register_dissector("sip", dissect_sip, proto_sip);
3018 /* Required function calls to register the header fields and subtrees used */
3019 proto_register_field_array(proto_sip, hf, array_length(hf));
3020 proto_register_subtree_array(ett, array_length(ett));
3021 proto_register_subtree_array(ett_raw, array_length(ett_raw));
3023 /* SIP content type and internet media type used by other dissectors are the same */
3024 media_type_dissector_table = find_dissector_table("media_type");
3026 sip_module = prefs_register_protocol(proto_sip, NULL);
3028 prefs_register_bool_preference(sip_module, "display_raw_text",
3029 "Display raw text for SIP message",
3030 "Specifies that the raw text of the "
3031 "SIP message should be displayed "
3032 "in addition to the dissection tree",
3033 &global_sip_raw_text);
3034 prefs_register_bool_preference(sip_module, "strict_sip_version",
3035 "Enforce strict SIP version check (" SIP2_HDR ")",
3036 "If enabled, only " SIP2_HDR " traffic will be dissected as SIP. "
3037 "Disable it to allow SIP traffic with a different version "
3038 "to be dissected as SIP.",
3039 &strict_sip_version);
3040 prefs_register_bool_preference(sip_module, "desegment_headers",
3041 "Reassemble SIP headers spanning multiple TCP segments",
3042 "Whether the SIP dissector should reassemble headers "
3043 "of a request spanning multiple TCP segments. "
3044 "To use this option, you must also enable "
3045 "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
3046 &sip_desegment_headers);
3047 prefs_register_bool_preference(sip_module, "desegment_body",
3048 "Reassemble SIP bodies spanning multiple TCP segments",
3049 "Whether the SIP dissector should use the "
3050 "\"Content-length:\" value, if present, to reassemble "
3051 "the body of a request spanning multiple TCP segments, "
3052 "and reassemble chunked data spanning multiple TCP segments. "
3053 "To use this option, you must also enable "
3054 "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
3055 &sip_desegment_body);
3057 register_init_routine(&sip_init_protocol);
3058 register_heur_dissector_list("sip", &heur_subdissector_list);
3059 /* Register for tapping */
3060 sip_tap = register_tap("sip");
3064 proto_reg_handoff_sip(void)
3066 dissector_handle_t sip_handle, sip_tcp_handle;
3068 sip_handle = new_create_dissector_handle(dissect_sip, proto_sip);
3069 dissector_add("udp.port", UDP_PORT_SIP, sip_handle);
3070 dissector_add_string("media_type", "message/sip", sip_handle);
3071 sigcomp_handle = find_dissector("sigcomp");
3073 sip_tcp_handle = create_dissector_handle(dissect_sip_tcp, proto_sip);
3074 dissector_add("tcp.port", TCP_PORT_SIP, sip_tcp_handle);
3076 heur_dissector_add("udp", dissect_sip_heur, proto_sip);
3077 heur_dissector_add("tcp", dissect_sip_tcp_heur, proto_sip);
3078 heur_dissector_add("sctp", dissect_sip_heur, proto_sip);