Coverage Report

Created: 2026-01-02 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-sip.c
Line
Count
Source
1
/* packet-sip.c
2
 * Routines for the Session Initiation Protocol (SIP) dissection.
3
 * RFCs 3261-3264
4
 *
5
 * TODO:
6
 *      hf_ display filters for headers of SIP extension RFCs (ongoing)
7
 *
8
 * Copyright 2000, Heikki Vatiainen <hessu@cs.tut.fi>
9
 * Copyright 2001, Jean-Francois Mule <jfm@cablelabs.com>
10
 * Copyright 2004, Anders Broman <anders.broman@ericsson.com>
11
 * Copyright 2011, Anders Broman <anders.broman@ericsson.com>, Johan Wahl <johan.wahl@ericsson.com>
12
 * Copyright 2018, Anders Broman <anders.broman@ericsson.com>
13
 * Copyright 2020, Atul Sharma <asharm37@ncsu.edu>
14
 *
15
 * Wireshark - Network traffic analyzer
16
 * By Gerald Combs <gerald@wireshark.org>
17
 * Copyright 1998 Gerald Combs
18
 *
19
 * SPDX-License-Identifier: GPL-2.0-or-later
20
 *
21
 */
22
23
#include "config.h"
24
25
#include <epan/packet.h>
26
27
#include <epan/exported_pdu.h>
28
#include <epan/expert.h>
29
#include <epan/prefs.h>
30
#include <epan/req_resp_hdrs.h>
31
#include <epan/stat_tap_ui.h>
32
#include <epan/proto_data.h>
33
#include <epan/uat.h>
34
#include <epan/follow.h>
35
#include <epan/addr_resolv.h>
36
#include <epan/epan_dissect.h>
37
#include <epan/iana_charsets.h>
38
#include <epan/tfs.h>
39
40
#include <wsutil/array.h>
41
#include <wsutil/str_util.h>
42
#include <wsutil/wsgcrypt.h>
43
44
#include "packet-tls.h"
45
46
#include "packet-isup.h"
47
#include "packet-e164.h"
48
#include "packet-e212.h"
49
#include "packet-sip.h"
50
51
#include "packet-media-type.h"
52
#include "packet-acdr.h"
53
54
#include "packet-sdp.h"  /* SDP needs a transport layer to determine request/response */
55
56
/* un-comment the following as well as this line in conversation.c, to enable debug printing */
57
/* #define DEBUG_CONVERSATION */
58
#include "conversation_debug.h"
59
60
#define TLS_PORT_SIP 5061
61
28
#define DEFAULT_SIP_PORT_RANGE "5060"
62
63
void proto_register_sip(void);
64
65
static int sip_tap = -1;
66
static int sip_follow_tap = -1;
67
static int exported_pdu_tap = -1;
68
static dissector_handle_t sip_handle;
69
static dissector_handle_t sip_tcp_handle;
70
static dissector_handle_t sigcomp_handle;
71
static dissector_handle_t sip_diag_handle;
72
static dissector_handle_t sip_uri_userinfo_handle;
73
static dissector_handle_t sip_via_branch_handle;
74
static dissector_handle_t sip_via_be_route_handle;
75
/* Dissector to dissect the text part of an reason code */
76
static dissector_handle_t sip_reason_code_handle;
77
78
/* Initialize the protocol and registered fields */
79
static int proto_sip;
80
static int proto_raw_sip;
81
static int hf_sip_raw_line;
82
static int hf_sip_msg_hdr;
83
static int hf_sip_Method;
84
static int hf_Request_Line;
85
static int hf_sip_ruri_display;
86
static int hf_sip_ruri;
87
static int hf_sip_ruri_user;
88
static int hf_sip_ruri_host;
89
static int hf_sip_ruri_port;
90
static int hf_sip_ruri_param;
91
static int hf_sip_Status_Code;
92
static int hf_sip_Status_Line;
93
static int hf_sip_display;
94
static int hf_sip_to_display;
95
static int hf_sip_to_addr;
96
static int hf_sip_to_user;
97
static int hf_sip_to_host;
98
static int hf_sip_to_port;
99
static int hf_sip_to_param;
100
static int hf_sip_to_tag;
101
static int hf_sip_from_display;
102
static int hf_sip_from_addr;
103
static int hf_sip_from_user;
104
static int hf_sip_from_host;
105
static int hf_sip_from_port;
106
static int hf_sip_from_param;
107
static int hf_sip_from_tag;
108
static int hf_sip_tag;
109
static int hf_sip_pai_display;
110
static int hf_sip_pai_addr;
111
static int hf_sip_pai_user;
112
static int hf_sip_pai_host;
113
static int hf_sip_pai_port;
114
static int hf_sip_pai_param;
115
static int hf_sip_pmiss_display;
116
static int hf_sip_pmiss_addr;
117
static int hf_sip_pmiss_user;
118
static int hf_sip_pmiss_host;
119
static int hf_sip_pmiss_port;
120
static int hf_sip_pmiss_param;
121
static int hf_sip_ppi_display;
122
static int hf_sip_ppi_addr;
123
static int hf_sip_ppi_user;
124
static int hf_sip_ppi_host;
125
static int hf_sip_ppi_port;
126
static int hf_sip_ppi_param;
127
static int hf_sip_tc_display;
128
static int hf_sip_tc_addr;
129
static int hf_sip_tc_user;
130
static int hf_sip_tc_host;
131
static int hf_sip_tc_port;
132
static int hf_sip_tc_param;
133
static int hf_sip_tc_turi;
134
static int hf_sip_contact_param;
135
static int hf_sip_resend;
136
static int hf_sip_original_frame;
137
static int hf_sip_matching_request_frame;
138
static int hf_sip_response_time;
139
static int hf_sip_release_time;
140
static int hf_sip_curi_display;
141
static int hf_sip_curi;
142
static int hf_sip_curi_user;
143
static int hf_sip_curi_host;
144
static int hf_sip_curi_port;
145
static int hf_sip_curi_param;
146
static int hf_sip_route_display;
147
static int hf_sip_route;
148
static int hf_sip_route_user;
149
static int hf_sip_route_host;
150
static int hf_sip_route_port;
151
static int hf_sip_route_param;
152
static int hf_sip_record_route_display;
153
static int hf_sip_record_route;
154
static int hf_sip_record_route_user;
155
static int hf_sip_record_route_host;
156
static int hf_sip_record_route_port;
157
static int hf_sip_record_route_param;
158
static int hf_sip_service_route_display;
159
static int hf_sip_service_route;
160
static int hf_sip_service_route_user;
161
static int hf_sip_service_route_host;
162
static int hf_sip_service_route_port;
163
static int hf_sip_service_route_param;
164
static int hf_sip_path_display;
165
static int hf_sip_path;
166
static int hf_sip_path_user;
167
static int hf_sip_path_host;
168
static int hf_sip_path_port;
169
static int hf_sip_path_param;
170
171
static int hf_sip_auth;
172
static int hf_sip_auth_scheme;
173
static int hf_sip_auth_digest_response;
174
static int hf_sip_auth_nc;
175
static int hf_sip_auth_username;
176
static int hf_sip_auth_realm;
177
static int hf_sip_auth_nonce;
178
static int hf_sip_auth_algorithm;
179
static int hf_sip_auth_opaque;
180
static int hf_sip_auth_qop;
181
static int hf_sip_auth_cnonce;
182
static int hf_sip_auth_uri;
183
static int hf_sip_auth_domain;
184
static int hf_sip_auth_stale;
185
static int hf_sip_auth_auts;
186
static int hf_sip_auth_rspauth;
187
static int hf_sip_auth_nextnonce;
188
static int hf_sip_auth_ik;
189
static int hf_sip_auth_ck;
190
191
static int hf_sip_cseq_seq_no;
192
static int hf_sip_cseq_method;
193
194
static int hf_sip_via_transport;
195
static int hf_sip_via_sent_by_address;
196
static int hf_sip_via_sent_by_port;
197
static int hf_sip_via_branch;
198
static int hf_sip_via_maddr;
199
static int hf_sip_via_rport;
200
static int hf_sip_via_received;
201
static int hf_sip_via_ttl;
202
static int hf_sip_via_comp;
203
static int hf_sip_via_sigcomp_id;
204
static int hf_sip_via_oc;
205
static int hf_sip_via_oc_val;
206
static int hf_sip_via_oc_algo;
207
static int hf_sip_via_oc_validity;
208
static int hf_sip_via_oc_seq;
209
static int hf_sip_oc_seq_timestamp;
210
static int hf_sip_via_be_route;
211
212
static int hf_sip_rack_rseq_no;
213
static int hf_sip_rack_cseq_no;
214
static int hf_sip_rack_cseq_method;
215
216
static int hf_sip_reason_protocols;
217
static int hf_sip_reason_cause_q850;
218
static int hf_sip_reason_cause_sip;
219
static int hf_sip_reason_cause_other;
220
static int hf_sip_reason_text;
221
222
static int hf_sip_msg_body;
223
static int hf_sip_sec_mechanism;
224
static int hf_sip_sec_mechanism_alg;
225
static int hf_sip_sec_mechanism_ealg;
226
static int hf_sip_sec_mechanism_prot;
227
static int hf_sip_sec_mechanism_spi_c;
228
static int hf_sip_sec_mechanism_spi_s;
229
static int hf_sip_sec_mechanism_port1;
230
static int hf_sip_sec_mechanism_port_c;
231
static int hf_sip_sec_mechanism_port2;
232
static int hf_sip_sec_mechanism_port_s;
233
static int hf_sip_session_id_sess_id;
234
static int hf_sip_session_id_param;
235
static int hf_sip_session_id_local_uuid;
236
static int hf_sip_session_id_remote_uuid;
237
static int hf_sip_session_id_logme;
238
static int hf_sip_continuation;
239
static int hf_sip_feature_cap;
240
241
static int hf_sip_p_acc_net_i_acc_type;
242
static int hf_sip_p_acc_net_i_ucid_3gpp;
243
244
static int hf_sip_service_priority;
245
static int hf_sip_icid_value;
246
static int hf_sip_icid_gen_addr;
247
static int hf_sip_call_id_gen;
248
249
/* Initialize the subtree pointers */
250
static int ett_sip;
251
static int ett_sip_reqresp;
252
static int ett_sip_hdr;
253
static int ett_sip_ext_hdr;
254
static int ett_raw_text;
255
static int ett_sip_element;
256
static int ett_sip_hist;
257
static int ett_sip_uri;
258
static int ett_sip_contact_item;
259
static int ett_sip_message_body;
260
static int ett_sip_cseq;
261
static int ett_sip_via;
262
static int ett_sip_reason;
263
static int ett_sip_security_client;
264
static int ett_sip_security_server;
265
static int ett_sip_security_verify;
266
static int ett_sip_rack;
267
static int ett_sip_route;
268
static int ett_sip_record_route;
269
static int ett_sip_service_route;
270
static int ett_sip_path;
271
static int ett_sip_ruri;
272
static int ett_sip_to_uri;
273
static int ett_sip_curi;
274
static int ett_sip_from_uri;
275
static int ett_sip_pai_uri;
276
static int ett_sip_pmiss_uri;
277
static int ett_sip_ppi_uri;
278
static int ett_sip_tc_uri;
279
static int ett_sip_session_id;
280
static int ett_sip_p_access_net_info;
281
static int ett_sip_p_charging_vector;
282
static int ett_sip_feature_caps;
283
static int ett_sip_via_be_route;
284
285
static expert_field ei_sip_unrecognized_header;
286
static expert_field ei_sip_header_no_colon;
287
static expert_field ei_sip_header_not_terminated;
288
#if 0
289
static expert_field ei_sip_odd_register_response;
290
#endif
291
static expert_field ei_sip_call_id_invalid;
292
static expert_field ei_sip_sipsec_malformed;
293
static expert_field ei_sip_via_sent_by_port;
294
static expert_field ei_sip_content_length_invalid;
295
static expert_field ei_sip_retry_after_invalid;
296
static expert_field ei_sip_Status_Code_invalid;
297
static expert_field ei_sip_authorization_invalid;
298
static expert_field ei_sip_session_id_sess_id;
299
300
/* patterns used for tvb_ws_mempbrk_pattern_uint8 */
301
static ws_mempbrk_pattern pbrk_comma_semi;
302
static ws_mempbrk_pattern pbrk_whitespace;
303
static ws_mempbrk_pattern pbrk_param_end;
304
static ws_mempbrk_pattern pbrk_param_end_colon_brackets;
305
static ws_mempbrk_pattern pbrk_header_end_dquote;
306
static ws_mempbrk_pattern pbrk_tab_sp_fslash;
307
static ws_mempbrk_pattern pbrk_addr_end;
308
static ws_mempbrk_pattern pbrk_via_param_end;
309
310
311
/* PUBLISH method added as per https://tools.ietf.org/html/draft-ietf-sip-publish-01 */
312
static const char *sip_methods[] = {
313
5.32k
#define SIP_METHOD_INVALID  0
314
        "<Invalid method>",      /* Pad so that the real methods start at index 1 */
315
#define SIP_METHOD_ACK      1
316
        "ACK",
317
#define SIP_METHOD_BYE      2
318
        "BYE",
319
#define SIP_METHOD_CANCEL   3
320
        "CANCEL",
321
#define SIP_METHOD_DO       4
322
        "DO",
323
#define SIP_METHOD_INFO     5
324
        "INFO",
325
0
#define SIP_METHOD_INVITE   6
326
        "INVITE",
327
#define SIP_METHOD_MESSAGE  7
328
        "MESSAGE",
329
#define SIP_METHOD_NOTIFY   8
330
        "NOTIFY",
331
#define SIP_METHOD_OPTIONS  9
332
        "OPTIONS",
333
#define SIP_METHOD_PRACK    10
334
        "PRACK",
335
#define SIP_METHOD_QAUTH    11
336
        "QAUTH",
337
0
#define SIP_METHOD_REFER    12
338
        "REFER",
339
91
#define SIP_METHOD_REGISTER 13
340
        "REGISTER",
341
#define SIP_METHOD_SPRACK   14
342
        "SPRACK",
343
0
#define SIP_METHOD_SUBSCRIBE    15
344
        "SUBSCRIBE",
345
#define SIP_METHOD_UPDATE   16
346
        "UPDATE",
347
#define SIP_METHOD_PUBLISH  17
348
        "PUBLISH"
349
};
350
351
/* from RFC 3261
352
 * Updated with info from https://www.iana.org/assignments/sip-parameters
353
 * (last updated 2009-11-11)
354
 * Updated with: https://tools.ietf.org/html/draft-ietf-sip-resource-priority-05
355
 */
356
typedef struct {
357
        const char *name;
358
        const char *compact_name;
359
} sip_header_t;
360
static const sip_header_t sip_headers[] = {
361
    { "Unknown-header",                 NULL }, /* 0 Pad so that the real headers start at index 1 */
362
    { "Accept",                         NULL }, /*  */
363
14
#define POS_ACCEPT                       1
364
    { "Accept-Contact",                 "a"  }, /* RFC3841  */
365
14
#define POS_ACCEPT_CONTACT               2
366
    { "Accept-Encoding",                NULL }, /* */
367
14
#define POS_ACCEPT_ENCODING              3
368
    { "Accept-Language",                NULL }, /* */
369
14
#define POS_ACCEPT_LANGUAGE              4
370
    { "Accept-Resource-Priority",       NULL }, /* RFC4412 */
371
14
#define POS_ACCEPT_RESOURCE_PRIORITY     5
372
    { "Additional-Identity",            NULL }, /* 3GPP TS 24.229 v16.7.0 */
373
14
#define POS_ADDITIONAL_IDENTITY          6
374
    { "Alert-Info",                     NULL },
375
14
#define POS_ALERT_INFO                   7
376
    { "Allow",                          NULL },
377
14
#define POS_ALLOW                        8
378
    { "Allow-Events",                   "u"  }, /* RFC3265  */
379
14
#define POS_ALLOW_EVENTS                 9
380
    { "Answer-Mode",                    NULL }, /* RFC5373 */
381
14
#define POS_ANSWER_MODE                 10
382
    { "Attestation-Info",               NULL }, /* [3GPP TS 24.229 v15.11.0] */
383
14
#define POS_ATTESTATION_INFO            11
384
    { "Authentication-Info",            NULL },
385
14
#define POS_AUTHENTICATION_INFO         12
386
    { "Authorization",                  NULL }, /*  */
387
14
#define POS_AUTHORIZATION               13
388
    { "Call-ID",                        "i"  },
389
24
#define POS_CALL_ID                     14
390
    { "Call-Info",                      NULL },
391
14
#define POS_CALL_INFO                   15
392
    { "Cellular-Network-Info",          NULL }, /* [3GPP TS 24.229 v13.9.0] */
393
14
#define POS_CELLULAR_NETWORK_INFO       16
394
    { "Contact",                        "m"  },
395
294
#define POS_CONTACT                     17
396
    { "Content-Disposition",            NULL },
397
14
#define POS_CONTENT_DISPOSITION         18
398
    { "Content-Encoding",               "e"  },  /*   */
399
24
#define POS_CONTENT_ENCODING            19
400
    { "Content-Language",               NULL },
401
14
#define POS_CONTENT_LANGUAGE            20
402
    { "Content-Length",                 "l"  },
403
114
#define POS_CONTENT_LENGTH              21
404
    { "Content-Type",                   "c"  },
405
14
#define POS_CONTENT_TYPE                22
406
    { "CSeq",                           NULL },
407
14
#define POS_CSEQ                        23
408
    { "Date",                           NULL },  /*   */
409
14
#define POS_DATE                        24
410
/*              Encryption (Deprecated)       [RFC3261] */
411
    { "Error-Info",                     NULL },  /*   */
412
14
#define POS_ERROR_INFO                  25
413
    { "Event",                          "o"  },  /*   */
414
14
#define POS_EVENT                       26
415
    { "Expires",                        NULL },  /*   */
416
14
#define POS_EXPIRES                     27
417
    { "Feature-Caps",                   NULL },  /*  RFC6809 */
418
14
#define POS_FEATURE_CAPS                28
419
    { "Flow-Timer",                     NULL },  /*  RFC5626  */
420
14
#define POS_FLOW_TIMER                  29
421
    { "From",                           "f"  },  /*   */
422
14
#define POS_FROM                        30
423
424
    { "Geolocation",                   NULL  },  /*   */
425
14
#define POS_GEOLOCATION                 31
426
    { "Geolocation-Error",             NULL  },  /*   */
427
14
#define POS_GEOLOCATION_ERROR           32
428
    { "Geolocation-Routing",           NULL  },  /*   */
429
14
#define POS_GEOLOCATION_ROUTING         33
430
431
/*              Hide                          RFC3261 (deprecated)*/
432
    { "History-Info",                   NULL },  /*  RFC4244  */
433
14
#define POS_HISTORY_INFO                34
434
    { "Identity",                       "y"  },  /*  RFC4474  */
435
14
#define POS_IDENTITY                    35
436
    { "Identity-Info",                  "n"  },  /*  RFC4474  */
437
14
#define POS_IDENTITY_INFO               36
438
    { "Info-Package",                   NULL },  /*  RFC-ietf-sipcore-info-events-10.txt  */
439
14
#define POS_INFO_PKG                    37
440
    { "In-Reply-To",                    NULL },  /*  RFC3261  */
441
14
#define POS_IN_REPLY_TO                 38
442
    { "Join",                           NULL },  /*  RFC3911  */
443
14
#define POS_JOIN                        39
444
    { "Max-Breadth",                    NULL },  /*  RFC5393*/
445
14
#define POS_MAX_BREADTH                 40
446
    { "Max-Forwards",                   NULL },  /*   */
447
14
#define POS_MAX_FORWARDS                41
448
    { "MIME-Version",                   NULL },  /*   */
449
14
#define POS_MIME_VERSION                42
450
    { "Min-Expires",                    NULL },  /*   */
451
14
#define POS_MIN_EXPIRES                 43
452
    { "Min-SE",                         NULL },  /*  RFC4028  */
453
14
#define POS_MIN_SE                      44
454
    { "Organization",                   NULL },  /*  RFC3261  */
455
14
#define POS_ORGANIZATION                45
456
    { "Origination-Id",                 NULL },  /*  [3GPP TS 24.229 v15.11.0]  */
457
14
#define POS_ORIGINATION_ID              46
458
    { "P-Access-Network-Info",          NULL },  /*  RFC3455  */
459
14
#define POS_P_ACCESS_NETWORK_INFO       47
460
    { "P-Answer-State",                 NULL },  /*  RFC4964  */
461
14
#define POS_P_ANSWER_STATE              48
462
    { "P-Asserted-Identity",            NULL },  /*  RFC3325  */
463
14
#define POS_P_ASSERTED_IDENTITY         49
464
    { "P-Asserted-Service",             NULL },  /*  RFC6050  */
465
14
#define POS_P_ASSERTED_SERV             50
466
    { "P-Associated-URI",               NULL },  /*  RFC3455  */
467
14
#define POS_P_ASSOCIATED_URI            51
468
    { "P-Called-Party-ID",              NULL },  /*  RFC3455  */
469
14
#define POS_P_CALLED_PARTY_ID           52
470
    { "P-Charge-Info",                  NULL },  /*  RFC8496  */
471
14
#define POS_P_CHARGE_INFO               53
472
    { "P-Charging-Function-Addresses",  NULL },  /*  RFC3455  */
473
14
#define POS_P_CHARGING_FUNC_ADDRESSES   54
474
    { "P-Charging-Vector",              NULL },  /*  RFC3455  */
475
14
#define POS_P_CHARGING_VECTOR           55
476
    { "P-DCS-Trace-Party-ID",           NULL },  /*  RFC5503  */
477
14
#define POS_P_DCS_TRACE_PARTY_ID        56
478
    { "P-DCS-OSPS",                     NULL },  /*  RFC5503  */
479
14
#define POS_P_DCS_OSPS                  57
480
    { "P-DCS-Billing-Info",             NULL },  /*  RFC5503  */
481
14
#define POS_P_DCS_BILLING_INFO          58
482
    { "P-DCS-LAES",                     NULL },  /*  RFC5503  */
483
14
#define POS_P_DCS_LAES                  59
484
    { "P-DCS-Redirect",                 NULL },  /*  RFC5503  */
485
14
#define POS_P_DCS_REDIRECT              60
486
    { "P-Early-Media",                  NULL },  /*  RFC5009  */
487
14
#define POS_P_EARLY_MEDIA               61
488
    { "P-Media-Authorization",          NULL },  /*  RFC3313  */
489
14
#define POS_P_MEDIA_AUTHORIZATION       62
490
    { "P-Preferred-Identity",           NULL },  /*  RFC3325  */
491
14
#define POS_P_PREFERRED_IDENTITY        63
492
    { "P-Preferred-Service",            NULL },  /*  RFC6050  */
493
14
#define POS_P_PREFERRED_SERV            64
494
    { "P-Profile-Key",                  NULL },  /*  RFC5002  */
495
14
#define POS_P_PROFILE_KEY               65
496
    { "P-Refused-URI-List",             NULL },  /*  RFC5318  */
497
14
#define POS_P_REFUSED_URI_LST           66
498
    { "P-Served-User",                  NULL },  /*  RFC5502  */
499
14
#define POS_P_SERVED_USER               67
500
    { "P-User-Database",                NULL },  /*  RFC4457  */
501
14
#define POS_P_USER_DATABASE             68
502
    { "P-Visited-Network-ID",           NULL },  /*  RFC3455  */
503
14
#define POS_P_VISITED_NETWORK_ID        69
504
    { "Path",                           NULL },  /*  RFC3327  */
505
14
#define POS_PATH                        70
506
    { "Permission-Missing",             NULL },  /*  RFC5360  */
507
14
#define POS_PERMISSION_MISSING          71
508
    { "Policy-Contact",                 NULL },  /*  RFC3261  */
509
14
#define POS_POLICY_CONTACT              72
510
    { "Policy-ID",                      NULL },  /*  RFC3261  */
511
14
#define POS_POLICY_ID                   73
512
    { "Priority",                       NULL },  /*  RFC3261  */
513
14
#define POS_PRIORITY                    74
514
    { "Priority-Share",                 NULL },  /*  [3GPP TS 24.229 v13.16.0]  */
515
14
#define POS_PRIORITY_SHARE              75
516
    { "Priv-Answer-Mode",               NULL },  /*  RFC5373  */
517
14
#define POS_PRIV_ANSWER_MODE            76
518
    { "Privacy",                        NULL },  /*  RFC3323  */
519
14
#define POS_PRIVACY                     77
520
    { "Proxy-Authenticate",             NULL },  /*  */
521
14
#define POS_PROXY_AUTHENTICATE          78
522
    { "Proxy-Authorization",            NULL },  /*  */
523
14
#define POS_PROXY_AUTHORIZATION         79
524
    { "Proxy-Require",                  NULL },  /*  */
525
14
#define POS_PROXY_REQUIRE               80
526
    { "RAck",                           NULL },  /*  RFC3262  */
527
14
#define POS_RACK                        81
528
    { "Reason",                         NULL },  /*  RFC3326  */
529
14
#define POS_REASON                      82
530
    { "Reason-Phrase",                  NULL },  /*  RFC3326  */
531
14
#define POS_REASON_PHRASE               83
532
    { "Record-Route",                   NULL },  /*   */
533
14
#define POS_RECORD_ROUTE                84
534
    { "Recv-Info",                      NULL },  /*  RFC6086 */
535
14
#define POS_RECV_INFO                   85
536
    { "Refer-Sub",                      NULL },  /*  RFC4488  */
537
14
#define POS_REFER_SUB                   86
538
    { "Refer-To",                       "r"  },  /*  RFC3515  */
539
14
#define POS_REFER_TO                    87
540
    { "Referred-By",                    "b"  },  /*  RFC3892  */
541
14
#define POS_REFERRED_BY                 88
542
    { "Reject-Contact",                 "j"  },  /*  RFC3841  */
543
14
#define POS_REJECT_CONTACT              89
544
    { "Relayed-Charge",                 NULL },   /*  [3GPP TS 24.229 v12.14.0]   */
545
14
#define POS_RELAYED_CHARGE              90
546
    { "Replaces",                       NULL },  /*  RFC3891  */
547
14
#define POS_REPLACES                    91
548
    { "Reply-To",                       NULL },  /*  RFC3261  */
549
14
#define POS_REPLY_TO                    92
550
    { "Request-Disposition",            "d"  },  /*  RFC3841  */
551
14
#define POS_REQUEST_DISPOSITION         93
552
    { "Require",                        NULL },  /*  RFC3261  */
553
14
#define POS_REQUIRE                     94
554
    { "Resource-Priority",              NULL },  /*  RFC4412  */
555
14
#define POS_RESOURCE_PRIORITY           95
556
    { "Resource-Share",                 NULL },  /*  [3GPP TS 24.229 v13.7.0]  */
557
14
#define POS_RESOURCE_SHARE              96
558
    /*{ "Response-Key (Deprecated)     [RFC3261]*/
559
    { "Response-Source",                NULL },  /*  [3GPP TS 24.229 v15.11.0]  */
560
14
#define POS_RESPONSE_SOURCE             97
561
    { "Restoration-Info",               NULL },  /*  [3GPP TS 24.229 v12.14.0]  */
562
14
#define POS_RESTORATION_INFO            98
563
    { "Retry-After",                    NULL },  /*  RFC3261  */
564
14
#define POS_RETRY_AFTER                 99
565
    { "Route",                          NULL },  /*  RFC3261  */
566
14
#define POS_ROUTE                      100
567
    { "RSeq",                           NULL },  /*  RFC3262  */
568
14
#define POS_RSEQ                       101
569
    { "Security-Client",                NULL },  /*  RFC3329  */
570
14
#define POS_SECURITY_CLIENT            102
571
    { "Security-Server",                NULL },  /*  RFC3329  */
572
14
#define POS_SECURITY_SERVER            103
573
    { "Security-Verify",                NULL },  /*  RFC3329  */
574
14
#define POS_SECURITY_VERIFY            104
575
    { "Server",                         NULL },  /*  RFC3261  */
576
14
#define POS_SERVER                     105
577
    { "Service-Interact-Info",          NULL },  /*  [3GPP TS 24.229 v13.18.0]  */
578
14
#define POS_SERVICE_INTERACT_INFO      106
579
    { "Service-Route",                  NULL },  /*  RFC3608  */
580
14
#define POS_SERVICE_ROUTE              107
581
    { "Session-Expires",                "x"  },  /*  RFC4028  */
582
14
#define POS_SESSION_EXPIRES            108
583
    { "Session-ID",                     NULL },  /*  RFC7329  */
584
14
#define POS_SESSION_ID                 109
585
    { "SIP-ETag",                       NULL },  /*  RFC3903  */
586
14
#define POS_SIP_ETAG                   110
587
    { "SIP-If-Match",                   NULL },  /*  RFC3903  */
588
14
#define POS_SIP_IF_MATCH               111
589
    { "Subject",                        "s"  },  /*  RFC3261  */
590
14
#define POS_SUBJECT                    112
591
    { "Subscription-State",             NULL },  /*  RFC3265  */
592
14
#define POS_SUBSCRIPTION_STATE         113
593
    { "Supported",                      "k"  },  /*  RFC3261  */
594
14
#define POS_SUPPORTED                  114
595
    { "Suppress-If-Match",              NULL },  /*  RFC5839  */
596
14
#define POS_SUPPRESS_IF_MATCH          115
597
    { "Target-Dialog",                  NULL },  /*  RFC4538  */
598
14
#define POS_TARGET_DIALOG              116
599
    { "Timestamp",                      NULL },  /*  RFC3261  */
600
14
#define POS_TIMESTAMP                  117
601
    { "To",                             "t"  },  /*  RFC3261  */
602
14
#define POS_TO                         118
603
    { "Trigger-Consent",                NULL },  /*  RFC5360  */
604
14
#define POS_TRIGGER_CONSENT            119
605
    { "Unsupported",                    NULL },  /*  RFC3261  */
606
14
#define POS_UNSUPPORTED                120
607
    { "User-Agent",                     NULL },  /*  RFC3261  */
608
14
#define POS_USER_AGENT                 121
609
    { "Via",                            "v"  },  /*  RFC3261  */
610
59
#define POS_VIA                        122
611
    { "Warning",                        NULL },  /*  RFC3261  */
612
14
#define POS_WARNING                    123
613
    { "WWW-Authenticate",               NULL },  /*  RFC3261  */
614
14
#define POS_WWW_AUTHENTICATE           124
615
    { "Diversion",                      NULL },  /*  RFC5806  */
616
14
#define POS_DIVERSION                  125
617
    { "User-to-User",                   NULL },  /*  RFC7433   */
618
14
#define POS_USER_TO_USER               126
619
};
620
621
622
static int hf_header_array[array_length(sip_headers)];
623
624
/* Track associations between parameter name and hf item */
625
typedef struct {
626
    const char  *param_name;
627
    const int   *hf_item;
628
} header_parameter_t;
629
630
static header_parameter_t auth_parameters_hf_array[] =
631
{
632
    {"response",        &hf_sip_auth_digest_response},
633
    {"nc",              &hf_sip_auth_nc},
634
    {"username",        &hf_sip_auth_username},
635
    {"realm",           &hf_sip_auth_realm},
636
    {"nonce",           &hf_sip_auth_nonce},
637
    {"algorithm",       &hf_sip_auth_algorithm},
638
    {"opaque",          &hf_sip_auth_opaque},
639
    {"qop",             &hf_sip_auth_qop},
640
    {"cnonce",          &hf_sip_auth_cnonce},
641
    {"uri",             &hf_sip_auth_uri},
642
    {"domain",          &hf_sip_auth_domain},
643
    {"stale",           &hf_sip_auth_stale},
644
    {"auts",            &hf_sip_auth_auts},
645
    {"rspauth",         &hf_sip_auth_rspauth},
646
    {"nextnonce",       &hf_sip_auth_nextnonce},
647
    {"ik",              &hf_sip_auth_ik},
648
    {"ck",              &hf_sip_auth_ck}
649
};
650
651
static header_parameter_t via_parameters_hf_array[] =
652
{
653
    {"branch",        &hf_sip_via_branch},
654
    {"maddr",         &hf_sip_via_maddr},
655
    {"rport",         &hf_sip_via_rport},
656
    {"received",      &hf_sip_via_received},
657
    {"ttl",           &hf_sip_via_ttl},
658
    {"comp",          &hf_sip_via_comp},
659
    {"sigcomp-id",    &hf_sip_via_sigcomp_id},
660
    {"oc",            &hf_sip_via_oc},
661
    {"oc-validity",   &hf_sip_via_oc_validity },
662
    {"oc-seq",        &hf_sip_via_oc_seq},
663
    {"oc-algo",       &hf_sip_via_oc_algo},
664
    {"be-route",      &hf_sip_via_be_route}
665
};
666
667
typedef enum {
668
    MECH_PARA_STRING = 0,
669
    MECH_PARA_UINT = 1,
670
} mech_parameter_type_t;
671
672
/* Track associations between parameter name and hf item for security mechanism*/
673
typedef struct {
674
    const char  *param_name;
675
    const int   para_type;
676
    const int   *hf_item;
677
} mech_parameter_t;
678
679
static mech_parameter_t sec_mechanism_parameters_hf_array[] =
680
{
681
    {"alg",     MECH_PARA_STRING,    &hf_sip_sec_mechanism_alg},
682
    {"ealg",    MECH_PARA_STRING,    &hf_sip_sec_mechanism_ealg},
683
    {"prot",    MECH_PARA_STRING,    &hf_sip_sec_mechanism_prot},
684
    {"spi-c",   MECH_PARA_UINT,      &hf_sip_sec_mechanism_spi_c},
685
    {"spi-s",   MECH_PARA_UINT,      &hf_sip_sec_mechanism_spi_s},
686
    {"port1",   MECH_PARA_UINT,      &hf_sip_sec_mechanism_port1},
687
    {"port-c",  MECH_PARA_UINT,      &hf_sip_sec_mechanism_port_c},
688
    {"port2",   MECH_PARA_UINT,      &hf_sip_sec_mechanism_port2},
689
    {"port-s",  MECH_PARA_UINT,      &hf_sip_sec_mechanism_port_s},
690
    {NULL, 0, 0}
691
};
692
693
typedef struct {
694
    int *hf_sip_display;
695
    int *hf_sip_addr;
696
    int *hf_sip_user;
697
    int *hf_sip_host;
698
    int *hf_sip_port;
699
    int *hf_sip_param;
700
    int *ett_uri;
701
} hf_sip_uri_t;
702
703
static hf_sip_uri_t sip_pai_uri = {
704
    &hf_sip_pai_display,
705
    &hf_sip_pai_addr,
706
    &hf_sip_pai_user,
707
    &hf_sip_pai_host,
708
    &hf_sip_pai_port,
709
    &hf_sip_pai_param,
710
    &ett_sip_pai_uri
711
};
712
713
static hf_sip_uri_t sip_ppi_uri = {
714
    &hf_sip_ppi_display,
715
    &hf_sip_ppi_addr,
716
    &hf_sip_ppi_user,
717
    &hf_sip_ppi_host,
718
    &hf_sip_ppi_port,
719
    &hf_sip_ppi_param,
720
    &ett_sip_ppi_uri
721
};
722
723
static hf_sip_uri_t sip_pmiss_uri = {
724
    &hf_sip_pmiss_display,
725
    &hf_sip_pmiss_addr,
726
    &hf_sip_pmiss_user,
727
    &hf_sip_pmiss_host,
728
    &hf_sip_pmiss_port,
729
    &hf_sip_pmiss_param,
730
    &ett_sip_pmiss_uri
731
};
732
733
static hf_sip_uri_t sip_tc_uri = {
734
    &hf_sip_tc_display,
735
    &hf_sip_tc_addr,
736
    &hf_sip_tc_user,
737
    &hf_sip_tc_host,
738
    &hf_sip_tc_port,
739
    &hf_sip_tc_param,
740
    &ett_sip_tc_uri
741
};
742
743
static hf_sip_uri_t sip_to_uri = {
744
    &hf_sip_to_display,
745
    &hf_sip_to_addr,
746
    &hf_sip_to_user,
747
    &hf_sip_to_host,
748
    &hf_sip_to_port,
749
    &hf_sip_to_param,
750
    &ett_sip_to_uri
751
};
752
753
static hf_sip_uri_t sip_from_uri = {
754
    &hf_sip_from_display,
755
    &hf_sip_from_addr,
756
    &hf_sip_from_user,
757
    &hf_sip_from_host,
758
    &hf_sip_from_port,
759
    &hf_sip_from_param,
760
    &ett_sip_from_uri
761
};
762
763
static hf_sip_uri_t sip_req_uri = {
764
    &hf_sip_ruri_display,
765
    &hf_sip_ruri,
766
    &hf_sip_ruri_user,
767
    &hf_sip_ruri_host,
768
    &hf_sip_ruri_port,
769
    &hf_sip_ruri_param,
770
    &ett_sip_ruri
771
};
772
773
static hf_sip_uri_t sip_contact_uri = {
774
    &hf_sip_curi_display,
775
    &hf_sip_curi,
776
    &hf_sip_curi_user,
777
    &hf_sip_curi_host,
778
    &hf_sip_curi_port,
779
    &hf_sip_curi_param,
780
    &ett_sip_curi
781
};
782
783
static hf_sip_uri_t sip_route_uri = {
784
    &hf_sip_route_display,
785
    &hf_sip_route,
786
    &hf_sip_route_user,
787
    &hf_sip_route_host,
788
    &hf_sip_route_port,
789
    &hf_sip_route_param,
790
    &ett_sip_route
791
};
792
793
static hf_sip_uri_t sip_record_route_uri = {
794
    &hf_sip_record_route_display,
795
    &hf_sip_record_route,
796
    &hf_sip_record_route_user,
797
    &hf_sip_record_route_host,
798
    &hf_sip_record_route_port,
799
    &hf_sip_record_route_param,
800
    &ett_sip_record_route
801
};
802
803
static hf_sip_uri_t sip_service_route_uri = {
804
    &hf_sip_service_route_display,
805
    &hf_sip_service_route,
806
    &hf_sip_service_route_user,
807
    &hf_sip_service_route_host,
808
    &hf_sip_service_route_port,
809
    &hf_sip_service_route_param,
810
    &ett_sip_service_route
811
};
812
813
static hf_sip_uri_t sip_path_uri = {
814
    &hf_sip_path_display,
815
    &hf_sip_path,
816
    &hf_sip_path_user,
817
    &hf_sip_path_host,
818
    &hf_sip_path_port,
819
    &hf_sip_path_param,
820
    &ett_sip_path
821
};
822
823
/*
824
 * Type of line.  It's either a SIP Request-Line, a SIP Status-Line, or
825
 * another type of line.
826
 */
827
typedef enum {
828
    REQUEST_LINE,
829
    STATUS_LINE,
830
    OTHER_LINE
831
} line_type_t;
832
833
/* Preferences */
834
static unsigned sip_tls_port = TLS_PORT_SIP;
835
836
/* global_sip_raw_text determines whether we are going to display       */
837
/* the raw text of the SIP message, much like the MEGACO dissector does.    */
838
static bool global_sip_raw_text;
839
/* global_sip_raw_text_without_crlf determines whether we are going to display  */
840
/* the raw text of the SIP message with or without the '\r\n'.          */
841
static bool global_sip_raw_text_without_crlf;
842
/* global_sip_raw_text_body_default_encoding determines what charset we are going to display the body */
843
static int global_sip_raw_text_body_default_encoding = IANA_CS_UTF_8;
844
/* strict_sip_version determines whether the SIP dissector enforces
845
 * the SIP version to be "SIP/2.0". */
846
static bool strict_sip_version = true;
847
848
/*
849
 * desegmentation of SIP headers
850
 * (when we are over TCP or another protocol providing the desegmentation API)
851
 */
852
static bool sip_desegment_headers = true;
853
854
/*
855
 * desegmentation of SIP bodies
856
 * (when we are over TCP or another protocol providing the desegmentation API)
857
 */
858
static bool sip_desegment_body = true;
859
860
/*
861
 * same source port for retransmissions
862
 */
863
static bool sip_retrans_the_same_sport = true;
864
865
/* whether we hold off tracking RTP conversations until an SDP answer is received */
866
static bool sip_delay_sdp_changes;
867
868
/* Hide the generated Call IDs or not */
869
static bool sip_hide_generatd_call_ids;
870
871
/* Extension header subdissectors */
872
static dissector_table_t ext_hdr_subdissector_table;
873
874
/* Custom SIP headers */
875
typedef struct _header_field_t {
876
    char* header_name;
877
    char* header_desc;
878
} header_field_t;
879
880
static header_field_t* sip_custom_header_fields;
881
static unsigned sip_custom_num_header_fields;
882
static GHashTable *sip_custom_header_fields_hash;
883
static hf_register_info *dynamic_hf;
884
static unsigned dynamic_hf_size;
885
886
static bool
887
header_fields_update_cb(void *r, char **err)
888
0
{
889
0
    header_field_t *rec = (header_field_t *)r;
890
0
    char c;
891
892
0
    if (rec->header_name == NULL) {
893
0
        *err = g_strdup("Header name can't be empty");
894
0
        return false;
895
0
    }
896
897
0
    g_strstrip(rec->header_name);
898
0
    if (rec->header_name[0] == 0) {
899
0
        *err = g_strdup("Header name can't be empty");
900
0
        return false;
901
0
    }
902
903
    /* Check for invalid characters (to avoid asserting out when
904
    * registering the field).
905
    */
906
0
    c = proto_check_field_name(rec->header_name);
907
0
    if (c) {
908
0
        *err = ws_strdup_printf("Header name can't contain '%c'", c);
909
0
        return false;
910
0
    }
911
912
0
    *err = NULL;
913
0
    return true;
914
0
}
915
916
static void *
917
header_fields_copy_cb(void* n, const void* o, size_t siz _U_)
918
0
{
919
0
    header_field_t* new_rec = (header_field_t*)n;
920
0
    const header_field_t* old_rec = (const header_field_t*)o;
921
922
0
    new_rec->header_name = g_strdup(old_rec->header_name);
923
0
    new_rec->header_desc = g_strdup(old_rec->header_desc);
924
925
0
    return new_rec;
926
0
}
927
928
static void
929
header_fields_free_cb(void*r)
930
0
{
931
0
    header_field_t* rec = (header_field_t*)r;
932
933
0
    g_free(rec->header_name);
934
0
    g_free(rec->header_desc);
935
0
}
936
937
static void
938
deregister_header_fields(void)
939
14
{
940
14
    if (dynamic_hf) {
941
        /* Deregister all fields */
942
0
        for (unsigned i = 0; i < dynamic_hf_size; i++) {
943
0
            proto_deregister_field(proto_sip, *(dynamic_hf[i].p_id));
944
0
            g_free(dynamic_hf[i].p_id);
945
0
        }
946
947
0
        proto_add_deregistered_data(dynamic_hf);
948
0
        dynamic_hf = NULL;
949
0
        dynamic_hf_size = 0;
950
0
    }
951
952
14
    if (sip_custom_header_fields_hash) {
953
0
        g_hash_table_destroy(sip_custom_header_fields_hash);
954
0
        sip_custom_header_fields_hash = NULL;
955
0
    }
956
14
}
957
958
static void
959
header_fields_post_update_cb(void)
960
14
{
961
14
    int* hf_id;
962
14
    char* header_name;
963
14
    char* header_name_key;
964
965
14
    deregister_header_fields();
966
967
14
    if (sip_custom_num_header_fields) {
968
0
        sip_custom_header_fields_hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
969
0
        dynamic_hf = g_new0(hf_register_info, sip_custom_num_header_fields);
970
0
        dynamic_hf_size = sip_custom_num_header_fields;
971
972
0
        for (unsigned i = 0; i < dynamic_hf_size; i++) {
973
0
            hf_id = g_new(int, 1);
974
0
            *hf_id = -1;
975
0
            header_name = g_strdup(sip_custom_header_fields[i].header_name);
976
0
            header_name_key = g_ascii_strdown(header_name, -1);
977
978
0
            dynamic_hf[i].p_id = hf_id;
979
0
            dynamic_hf[i].hfinfo.name = header_name;
980
0
            dynamic_hf[i].hfinfo.abbrev = ws_strdup_printf("sip.%s", header_name);
981
0
            dynamic_hf[i].hfinfo.type = FT_STRING;
982
0
            dynamic_hf[i].hfinfo.display = BASE_NONE;
983
0
            dynamic_hf[i].hfinfo.strings = NULL;
984
0
            dynamic_hf[i].hfinfo.bitmask = 0;
985
0
            dynamic_hf[i].hfinfo.blurb = g_strdup(sip_custom_header_fields[i].header_desc);
986
0
            HFILL_INIT(dynamic_hf[i]);
987
988
0
            g_hash_table_insert(sip_custom_header_fields_hash, header_name_key, hf_id);
989
0
        }
990
991
0
        proto_register_field_array(proto_sip, dynamic_hf, dynamic_hf_size);
992
0
    }
993
14
}
994
995
static void
996
header_fields_reset_cb(void)
997
0
{
998
0
    deregister_header_fields();
999
0
}
1000
1001
UAT_CSTRING_CB_DEF(sip_custom_header_fields, header_name, header_field_t)
1002
UAT_CSTRING_CB_DEF(sip_custom_header_fields, header_desc, header_field_t)
1003
1004
/* SIP authorization parameters */
1005
static bool global_sip_validate_authorization;
1006
1007
typedef struct _authorization_user_t {
1008
    char* username;
1009
    char* realm;
1010
    char* password;
1011
} authorization_user_t;
1012
1013
static authorization_user_t* sip_authorization_users;
1014
static unsigned sip_authorization_num_users;
1015
1016
static bool
1017
authorization_users_update_cb(void *r, char **err)
1018
0
{
1019
0
    authorization_user_t *rec = (authorization_user_t *)r;
1020
0
    char c;
1021
1022
0
    if (rec->username == NULL) {
1023
0
        *err = g_strdup("Username can't be empty");
1024
0
        return false;
1025
0
    }
1026
1027
0
    g_strstrip(rec->username);
1028
0
    if (rec->username[0] == 0) {
1029
0
        *err = g_strdup("Username can't be empty");
1030
0
        return false;
1031
0
    }
1032
1033
    /* Check for invalid characters (to avoid asserting out when
1034
    * registering the field).
1035
    */
1036
0
    c = proto_check_field_name(rec->username);
1037
0
    if (c) {
1038
0
        *err = ws_strdup_printf("Username can't contain '%c'", c);
1039
0
        return false;
1040
0
    }
1041
1042
0
    *err = NULL;
1043
0
    return true;
1044
0
}
1045
1046
static void *
1047
authorization_users_copy_cb(void* n, const void* o, size_t siz _U_)
1048
0
{
1049
0
    authorization_user_t* new_rec = (authorization_user_t*)n;
1050
0
    const authorization_user_t* old_rec = (const authorization_user_t*)o;
1051
1052
0
    new_rec->username = g_strdup(old_rec->username);
1053
0
    new_rec->realm = g_strdup(old_rec->realm);
1054
0
    new_rec->password = g_strdup(old_rec->password);
1055
1056
0
    return new_rec;
1057
0
}
1058
1059
static void
1060
authorization_users_free_cb(void*r)
1061
0
{
1062
0
    authorization_user_t* rec = (authorization_user_t*)r;
1063
1064
0
    g_free(rec->username);
1065
0
    g_free(rec->realm);
1066
0
    g_free(rec->password);
1067
0
}
1068
1069
UAT_CSTRING_CB_DEF(sip_authorization_users, username, authorization_user_t)
1070
UAT_CSTRING_CB_DEF(sip_authorization_users, realm, authorization_user_t)
1071
UAT_CSTRING_CB_DEF(sip_authorization_users, password, authorization_user_t)
1072
1073
/* Forward declaration we need below */
1074
void proto_reg_handoff_sip(void);
1075
static int dissect_sip_common(tvbuff_t *tvb, int offset, int remaining_length, packet_info *pinfo,
1076
    proto_tree *tree, bool is_heur, bool use_reassembly);
1077
static line_type_t sip_parse_line(tvbuff_t *tvb, int offset, int linelen,
1078
    unsigned *token_1_len);
1079
static bool sip_is_known_request(tvbuff_t *tvb, packet_info* pinfo, int meth_offset,
1080
    unsigned meth_len, unsigned *meth_idx);
1081
static int sip_is_known_sip_header(char *header_name, unsigned header_len);
1082
static void dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset,
1083
    unsigned meth_len, int linelen);
1084
static void dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int line_end, int offset);
1085
static void tvb_raw_text_add(tvbuff_t *tvb, int offset, int length, int body_offset, packet_info* pinfo, proto_tree *tree);
1086
static unsigned sip_is_packet_resend(packet_info *pinfo,
1087
                const char *cseq_method,
1088
                char* call_id,
1089
                unsigned char cseq_number_set, uint32_t cseq_number,
1090
                line_type_t line_type);
1091
1092
static unsigned sip_find_request(packet_info *pinfo,
1093
                const char *cseq_method,
1094
                char* call_id,
1095
                unsigned char cseq_number_set, uint32_t cseq_number,
1096
                uint32_t *response_time);
1097
1098
static unsigned sip_find_invite(packet_info *pinfo,
1099
                const char *cseq_method,
1100
                char* call_id,
1101
                unsigned char cseq_number_set, uint32_t cseq_number,
1102
                uint32_t *response_time);
1103
1104
typedef struct
1105
{
1106
    char * username;
1107
    char * realm;
1108
    char * uri;
1109
    char * nonce;
1110
    char * cnonce;
1111
    char * nonce_count;
1112
    char * response;
1113
    char * qop;
1114
    char * algorithm;
1115
    char * method;
1116
} sip_authorization_t;
1117
1118
static authorization_user_t * sip_get_authorization(sip_authorization_t *authorization_info);
1119
static bool sip_validate_authorization(sip_authorization_t *authorization_info, char *password);
1120
1121
static authorization_user_t * sip_get_authorization(sip_authorization_t *authorization_info)
1122
0
{
1123
0
    unsigned i;
1124
0
    for (i = 0; i < sip_authorization_num_users; i++) {
1125
0
        if ((!strcmp(sip_authorization_users[i].username, authorization_info->username)) &&
1126
0
            (!strcmp(sip_authorization_users[i].realm, authorization_info->realm))) {
1127
0
            return &sip_authorization_users[i];
1128
0
        }
1129
0
    }
1130
0
    return NULL;
1131
0
}
1132
1133
/* SIP content type and internet media type used by other dissectors
1134
 * are the same.  List of media types from IANA at:
1135
 * http://www.iana.org/assignments/media-types/index.html */
1136
static dissector_table_t media_type_dissector_table;
1137
1138
static heur_dissector_list_t heur_subdissector_list;
1139
1140
115
#define SIP2_HDR "SIP/2.0"
1141
774
#define SIP2_HDR_LEN 7
1142
1143
/* Store the info needed by the SIP tap for one packet */
1144
static sip_info_value_t *stat_info;
1145
1146
/* The buffer size for the cseq_method name */
1147
0
#define MAX_CSEQ_METHOD_SIZE 16
1148
1149
/****************************************************************************
1150
 * Conversation-type definitions
1151
 *
1152
 * For each call, keep track of the current cseq number and state of
1153
 * transaction, in order to be able to detect retransmissions.
1154
 *
1155
 * Don't use the conversation mechanism, but instead:
1156
 * - store with each dissected packet original frame (if any)
1157
 * - maintain a global hash table of
1158
 *   (call_id, source_addr, dest_addr) -> (cseq, transaction_state, frame)
1159
 *
1160
 * N.B. This is broken for a couple of reasons:
1161
 * - it won't cope properly with overlapping transactions within the
1162
 *   same dialog
1163
 * - request response mapping won't work where the response uses a different
1164
 *   address pair from the request
1165
 *
1166
 * TODO: proper transaction matching uses RFC fields (use Max-forwards or
1167
 * maybe Via count as extra key to limit view to one hop)
1168
 ****************************************************************************/
1169
1170
static GHashTable *sip_hash;           /* Hash table */
1171
static GHashTable *sip_headers_hash;     /* Hash table */
1172
1173
/* Types for hash table keys and values */
1174
0
#define MAX_CALL_ID_SIZE 128
1175
0
#define MAGIC_SOURCE_PORT 0
1176
1177
/* Conversation-type key */
1178
typedef struct
1179
{
1180
    char call_id[MAX_CALL_ID_SIZE];
1181
    address source_address;
1182
    uint32_t source_port;
1183
    address dest_address;
1184
    uint32_t dest_port;
1185
    port_type ptype;
1186
} sip_hash_key;
1187
1188
1189
typedef enum
1190
{
1191
    nothing_seen,
1192
    request_seen,
1193
    provisional_response_seen,
1194
    final_response_seen
1195
} transaction_state_t;
1196
1197
/* Current conversation-type value */
1198
typedef struct
1199
{
1200
    uint32_t            cseq;
1201
    transaction_state_t transaction_state;
1202
    const char         *method;
1203
    nstime_t            request_time;
1204
    uint32_t            response_code;
1205
    int                 frame_number;
1206
} sip_hash_value;
1207
1208
/* Result to be stored in per-packet info */
1209
typedef struct
1210
{
1211
    int        original_frame_num;
1212
    int        response_request_frame_num;
1213
    int        response_time;
1214
} sip_frame_result_value;
1215
1216
1217
/************************/
1218
/* Hash table functions */
1219
1220
/* Equal keys */
1221
static int sip_equal(const void *v, const void *v2)
1222
0
{
1223
0
    const sip_hash_key* val1 = (const sip_hash_key*)v;
1224
0
    const sip_hash_key* val2 = (const sip_hash_key*)v2;
1225
1226
    /* Call id must match */
1227
0
    if (strcmp(val1->call_id, val2->call_id) != 0)
1228
0
    {
1229
0
        return 0;
1230
0
    }
1231
1232
    /* Addresses must match */
1233
0
    return  (addresses_equal(&(val1->source_address), &(val2->source_address))) &&
1234
0
        (val1->source_port == val2->source_port) &&
1235
0
        (addresses_equal(&(val1->dest_address), &(val2->dest_address))) &&
1236
0
        (val1->dest_port == val2->dest_port) &&
1237
0
        (val1->ptype == val2->ptype);
1238
0
}
1239
1240
1241
/* Initializes the hash table each time a new
1242
 * file is loaded or re-loaded in wireshark */
1243
static void
1244
sip_init_protocol(void)
1245
14
{
1246
14
    unsigned i;
1247
14
    char *value_copy;
1248
14
    sip_hash = g_hash_table_new(g_str_hash , sip_equal);
1249
1250
    /* Hash table for quick lookup of SIP headers names to hf entry (POS_x) */
1251
14
    sip_headers_hash = g_hash_table_new(g_str_hash , g_str_equal);
1252
1.77k
    for (i = 1; i < array_length(sip_headers); i++){
1253
1.76k
        value_copy = wmem_strdup(wmem_file_scope(), sip_headers[i].name);
1254
1.76k
        ascii_strdown_inplace(value_copy);
1255
1.76k
        g_hash_table_insert(sip_headers_hash, (void *)value_copy, GINT_TO_POINTER(i));
1256
1.76k
    }
1257
14
}
1258
1259
static void
1260
sip_cleanup_protocol(void)
1261
0
{
1262
0
     g_hash_table_destroy(sip_hash);
1263
0
     g_hash_table_destroy(sip_headers_hash);
1264
0
}
1265
1266
/* Call the export PDU tap with relevant data */
1267
static void
1268
export_sip_pdu(packet_info *pinfo, tvbuff_t *tvb)
1269
0
{
1270
0
  exp_pdu_data_t *exp_pdu_data = export_pdu_create_common_tags(pinfo, "sip", EXP_PDU_TAG_DISSECTOR_NAME);
1271
1272
0
  exp_pdu_data->tvb_captured_length = tvb_captured_length(tvb);
1273
0
  exp_pdu_data->tvb_reported_length = tvb_reported_length(tvb);
1274
0
  exp_pdu_data->pdu_tvb = tvb;
1275
1276
0
  tap_queue_packet(exported_pdu_tap, pinfo, exp_pdu_data);
1277
1278
0
}
1279
1280
typedef enum
1281
{
1282
    SIP_URI_TYPE_ABSOLUTE_URI,
1283
    SIP_URI_TYPE_SIP,
1284
    SIP_URI_TYPE_TEL
1285
1286
} sip_uri_type_enum_t;
1287
1288
/* Structure to collect info about a sip uri */
1289
typedef struct _uri_offset_info
1290
{
1291
    sip_uri_type_enum_t uri_type;
1292
    int display_name_start;
1293
    int display_name_end;
1294
    int uri_start;
1295
    int uri_end;
1296
    int uri_parameters_start;
1297
    int uri_parameters_end;
1298
    int name_addr_start;
1299
    int name_addr_end;
1300
    int uri_user_start;
1301
    int uri_user_end;
1302
    int uri_host_start;
1303
    int uri_host_end;
1304
    int uri_host_port_start;
1305
    int uri_host_port_end;
1306
} uri_offset_info;
1307
1308
static void
1309
390
sip_uri_offset_init(uri_offset_info *uri_offsets){
1310
1311
    /* Initialize the uri_offsets */
1312
390
    uri_offsets->uri_type = SIP_URI_TYPE_ABSOLUTE_URI;
1313
390
    uri_offsets->display_name_start = -1;
1314
390
    uri_offsets->display_name_end = -1;
1315
390
    uri_offsets->uri_start = -1;
1316
390
    uri_offsets->uri_end = -1;
1317
390
    uri_offsets->uri_parameters_start = -1;
1318
390
    uri_offsets->uri_parameters_end = -1;
1319
390
    uri_offsets->name_addr_start = -1;
1320
390
    uri_offsets->name_addr_end = -1;
1321
390
    uri_offsets->uri_user_start = -1;
1322
390
    uri_offsets->uri_user_end = -1;
1323
390
    uri_offsets->uri_host_start = -1;
1324
390
    uri_offsets->uri_host_end = -1;
1325
390
    uri_offsets->uri_host_port_start = -1;
1326
390
    uri_offsets->uri_host_port_end = -1;
1327
1328
390
}
1329
1330
static int
1331
dissect_tel_uri(tvbuff_t *tvb, packet_info *pinfo _U_, int current_offset,
1332
                int line_end_offset, uri_offset_info *uri_offsets)
1333
0
{
1334
0
    unsigned char c = '\0';
1335
0
    uri_offsets->uri_type = SIP_URI_TYPE_TEL;
1336
1337
0
    if (uri_offsets->uri_end == -1)
1338
0
    {
1339
        /* name-addr form was NOT used e.g no closing ">" */
1340
        /* look for the first ',' or ';' which will mark the end of this URI
1341
         * In this case a semicolon indicates a header field parameter, and not an uri parameter.
1342
         */
1343
0
        int end_offset;
1344
1345
0
        end_offset = tvb_ws_mempbrk_pattern_uint8(tvb, current_offset, line_end_offset - current_offset, &pbrk_comma_semi, NULL);
1346
1347
0
        if (end_offset != -1)
1348
0
        {
1349
0
            uri_offsets->uri_end = end_offset - 1;
1350
0
        }
1351
0
        else
1352
0
        {
1353
            /* We don't have a semicolon or a comma.
1354
             * In that case, we assume that the end of the URI is at the line end
1355
              */
1356
0
            uri_offsets->uri_end = line_end_offset - 3; /* remove '\r\n' */
1357
0
        }
1358
0
        uri_offsets->name_addr_end = uri_offsets->uri_end;
1359
0
    }
1360
1361
0
    uri_offsets->uri_user_start = current_offset;
1362
1363
0
    int parameter_end_offset = uri_offsets->uri_user_start;
1364
0
    if (parameter_end_offset < line_end_offset)
1365
0
    {
1366
0
        parameter_end_offset++;
1367
0
        parameter_end_offset = tvb_ws_mempbrk_pattern_uint8(tvb, parameter_end_offset, line_end_offset - parameter_end_offset, &pbrk_param_end, &c);
1368
0
        if (parameter_end_offset == -1)
1369
0
        {
1370
0
            parameter_end_offset = line_end_offset;
1371
0
        } else {
1372
            /* after adding character to this switch(), update also pbrk_param_end */
1373
0
            switch (c) {
1374
0
                case '>':
1375
0
                case ',':
1376
0
                    break;
1377
0
                case ';':
1378
0
                    uri_offsets->uri_parameters_start = parameter_end_offset + 1;
1379
0
                    break;
1380
0
                case '?':
1381
0
                case ' ':
1382
0
                case '\r':
1383
0
                    break;
1384
0
                default:
1385
0
                    DISSECTOR_ASSERT_NOT_REACHED();
1386
0
                    break;
1387
0
            }
1388
0
        }
1389
0
    }
1390
1391
0
    uri_offsets->uri_user_end = parameter_end_offset -1;
1392
1393
0
    return uri_offsets->name_addr_end;
1394
0
}
1395
1396
/* Code to parse a sip uri.
1397
 * Returns Offset end off parsing or -1 for unsuccessful parsing
1398
 * - sip_uri_offset_init() must have been called first.
1399
 */
1400
static int
1401
dissect_sip_uri(tvbuff_t *tvb, packet_info *pinfo _U_, int start_offset,
1402
                int line_end_offset, uri_offset_info *uri_offsets)
1403
305
{
1404
305
    unsigned char c = '\0';
1405
305
    int current_offset;
1406
305
    int queried_offset;
1407
305
    int parameter_end_offset;
1408
305
    bool in_ipv6 = false;
1409
1410
    /* skip Spaces and Tabs */
1411
305
    current_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1412
1413
305
    if(current_offset >= line_end_offset) {
1414
        /* Nothing to parse */
1415
0
        return -1;
1416
0
    }
1417
    /* Set uri start offset in case this was called directly */
1418
305
    uri_offsets->uri_start = current_offset;
1419
1420
    /* Check if it's really a sip uri (it might be a tel uri) */
1421
305
    if (tvb_strneql(tvb, current_offset, "tel:", 4) == 0) {
1422
0
        return dissect_tel_uri(tvb, pinfo, current_offset + 4, line_end_offset, uri_offsets);
1423
305
    } else if (tvb_strneql(tvb, current_offset, "sip", 3) != 0){
1424
163
        if (uri_offsets->uri_end != -1) {
1425
            /* We know where the URI ends, set the offsets*/
1426
105
            return uri_offsets->name_addr_end;
1427
105
        }
1428
58
        return -1;
1429
163
    }
1430
1431
142
    uri_offsets->uri_type = SIP_URI_TYPE_SIP;
1432
1433
142
    if(uri_offsets->uri_end == -1)
1434
140
    {
1435
        /* name-addr form was NOT used e.g no closing ">" */
1436
        /* look for the first ',' or ';' which will mark the end of this URI
1437
         * In this case a semicolon indicates a header field parameter, and not an uri parameter.
1438
         */
1439
140
        int end_offset;
1440
1441
140
        end_offset = tvb_ws_mempbrk_pattern_uint8(tvb, current_offset, line_end_offset - current_offset, &pbrk_comma_semi, NULL);
1442
1443
140
        if (end_offset != -1)
1444
89
        {
1445
89
            uri_offsets->uri_end = end_offset - 1;
1446
89
        }
1447
51
        else
1448
51
        {
1449
            /* We don't have a semicolon or a comma.
1450
             * In that case, we assume that the end of the URI is at the line end
1451
              */
1452
51
            uri_offsets->uri_end = line_end_offset - 3; /* remove '\r\n' */
1453
51
        }
1454
140
        uri_offsets->name_addr_end = uri_offsets->uri_end;
1455
140
    }
1456
1457
    /* Look for URI address parts (user, host, host-port) */
1458
1459
    /* Look for '@' within URI */
1460
142
    queried_offset = tvb_find_uint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, '@');
1461
142
    if(queried_offset == -1)
1462
140
    {
1463
        /* no '@' = no user part */
1464
140
        uri_offsets->uri_host_start = tvb_find_uint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, ':')+1;
1465
140
    }
1466
2
    else
1467
2
    {
1468
        /* with '@' = with user part */
1469
2
        uri_offsets->uri_user_start = tvb_find_uint8(tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start, ':')+1;
1470
2
        uri_offsets->uri_user_end = tvb_find_uint8(tvb, uri_offsets->uri_user_start, uri_offsets->uri_end - uri_offsets->uri_start, '@')-1;
1471
2
        uri_offsets->uri_host_start = uri_offsets->uri_user_end + 2;
1472
2
    }
1473
1474
    /* find URI-Host end*/
1475
142
    parameter_end_offset = uri_offsets->uri_host_start;
1476
1477
142
    in_ipv6 = (tvb_get_uint8(tvb, parameter_end_offset) == '[');
1478
181
    while (parameter_end_offset < line_end_offset)
1479
181
    {
1480
181
        parameter_end_offset++;
1481
181
        parameter_end_offset = tvb_ws_mempbrk_pattern_uint8(tvb, parameter_end_offset, line_end_offset - parameter_end_offset, &pbrk_param_end_colon_brackets, &c);
1482
181
        if (parameter_end_offset == -1)
1483
11
        {
1484
11
            parameter_end_offset = line_end_offset;
1485
11
            break;
1486
11
        }
1487
1488
        /* after adding character to this switch() , update also pbrk_param_end_colon_brackets */
1489
170
        switch (c) {
1490
0
            case '>':
1491
12
            case ',':
1492
12
                goto uri_host_end_found;
1493
30
            case ';':
1494
30
                uri_offsets->uri_parameters_start = parameter_end_offset + 1;
1495
30
                goto uri_host_end_found;
1496
1
            case '?':
1497
16
            case ' ':
1498
17
            case '\r':
1499
17
                goto uri_host_end_found;
1500
74
            case ':':
1501
74
                if (!in_ipv6)
1502
72
                    goto uri_host_end_found;
1503
2
                break;
1504
3
            case '[':
1505
3
                in_ipv6 = true;
1506
3
                break;
1507
34
            case ']':
1508
34
                in_ipv6 = false;
1509
34
                break;
1510
0
            default :
1511
0
                DISSECTOR_ASSERT_NOT_REACHED();
1512
0
                break;
1513
170
        }
1514
170
    }
1515
1516
142
uri_host_end_found:
1517
1518
142
    uri_offsets->uri_host_end = parameter_end_offset - 1;
1519
1520
142
    if (c == ':')
1521
72
    {
1522
72
        uri_offsets->uri_host_port_start = parameter_end_offset + 1;
1523
72
        parameter_end_offset = uri_offsets->uri_host_port_start;
1524
72
        while (parameter_end_offset < line_end_offset)
1525
72
        {
1526
72
            parameter_end_offset++;
1527
72
            parameter_end_offset = tvb_ws_mempbrk_pattern_uint8(tvb, parameter_end_offset, line_end_offset - parameter_end_offset, &pbrk_param_end, &c);
1528
72
            if (parameter_end_offset == -1)
1529
25
            {
1530
25
                parameter_end_offset = line_end_offset;
1531
25
                break;
1532
25
            }
1533
1534
            /* after adding character to this switch(), update also pbrk_param_end */
1535
47
            switch (c) {
1536
0
                case '>':
1537
2
                case ',':
1538
2
                    goto uri_host_port_end_found;
1539
3
                case ';':
1540
3
                    uri_offsets->uri_parameters_start = parameter_end_offset + 1;
1541
3
                    goto uri_host_port_end_found;
1542
0
                case '?':
1543
33
                case ' ':
1544
42
                case '\r':
1545
42
                    goto uri_host_port_end_found;
1546
0
                default :
1547
0
                    DISSECTOR_ASSERT_NOT_REACHED();
1548
0
                    break;
1549
47
            }
1550
47
        }
1551
1552
72
    uri_host_port_end_found:
1553
1554
72
        uri_offsets->uri_host_port_end = parameter_end_offset -1;
1555
72
    }
1556
1557
142
    return uri_offsets->name_addr_end;
1558
142
}
1559
1560
void
1561
dfilter_store_sip_from_addr(tvbuff_t *tvb,proto_tree *tree,unsigned parameter_offset, unsigned parameter_len)
1562
0
{
1563
0
    proto_item *pi;
1564
1565
0
    pi = proto_tree_add_item(tree, hf_sip_from_addr, tvb, parameter_offset, parameter_len, ENC_UTF_8);
1566
0
    proto_item_set_generated(pi);
1567
0
}
1568
1569
static proto_item *
1570
sip_proto_tree_add_uint(proto_tree *tree, wmem_allocator_t* allocator, int hfindex, tvbuff_t *tvb, int start, int length, int value_offset, int value_len)
1571
0
{
1572
0
    const char *str;
1573
0
    unsigned long val;
1574
1575
    /* don't fetch string when field is not referenced */
1576
0
    if (!proto_field_is_referenced(tree, hfindex))
1577
0
        return tree;
1578
1579
0
    str = (char*)tvb_get_string_enc(allocator, tvb, value_offset, value_len, ENC_UTF_8|ENC_NA);
1580
0
    val = strtoul(str, NULL, 10);
1581
1582
0
    return proto_tree_add_uint(tree, hfindex, tvb, start, length, (uint32_t) val);
1583
0
}
1584
1585
static proto_item *
1586
sip_proto_tree_add_string(proto_tree *tree, wmem_allocator_t* allocator, int hfindex, tvbuff_t *tvb, int start, int length, int value_offset, int value_len)
1587
360
{
1588
360
    const char *str;
1589
1590
    /* don't fetch string when field is not referenced */
1591
360
    if (!proto_field_is_referenced(tree, hfindex))
1592
0
        return tree;
1593
1594
360
    str = (char*)tvb_get_string_enc(allocator, tvb, value_offset, value_len, ENC_UTF_8|ENC_NA);
1595
1596
360
    return proto_tree_add_string(tree, hfindex, tvb, start, length, str);
1597
360
}
1598
1599
static void
1600
sip_proto_set_format_text(const proto_tree *tree, wmem_allocator_t* allocator, proto_item *item, tvbuff_t *tvb, int offset, int length)
1601
470
{
1602
470
    if (tree != item && item && PTREE_DATA(item)->visible)
1603
470
        proto_item_set_text(item, "%s", tvb_format_text(allocator, tvb, offset, length));
1604
470
}
1605
/*
1606
 * XXXX If/when more parameters are added consider doing something similar to what's done in
1607
 * packet-magaco.c for find_megaco_localParam_names() possibly adding the hf to the array and have a generic
1608
 * dissection function here.
1609
 */
1610
static void
1611
dissect_sip_generic_parameters(tvbuff_t *tvb, proto_tree* tree, packet_info *pinfo, int current_offset, int line_end_offset)
1612
0
{
1613
0
    int semi_colon_offset, par_name_end_offset, equals_offset, length;
1614
    /* Loop over the generic parameter(s)*/
1615
0
    while (current_offset < line_end_offset) {
1616
0
        char *param_name = NULL;
1617
1618
        /* skip Spaces and Tabs */
1619
0
        current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
1620
1621
0
        semi_colon_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, ';');
1622
1623
0
        if (semi_colon_offset == -1) {
1624
0
            semi_colon_offset = line_end_offset;
1625
0
        }
1626
1627
0
        length = semi_colon_offset - current_offset;
1628
1629
        /* Parse parameter and value */
1630
0
        equals_offset = tvb_find_uint8(tvb, current_offset + 1, length, '=');
1631
0
        if (equals_offset != -1) {
1632
            /* Has value part */
1633
0
            par_name_end_offset = equals_offset;
1634
            /* Extract the parameter name */
1635
0
            param_name = (char*)tvb_get_string_enc(pinfo->pool, tvb, current_offset, par_name_end_offset - current_offset, ENC_UTF_8 | ENC_NA);
1636
            /* Access-Info fields  */
1637
0
            if ((param_name != NULL) && (g_ascii_strcasecmp(param_name, "service-priority") == 0)) {
1638
0
                proto_tree_add_item(tree, hf_sip_service_priority, tvb,
1639
0
                    equals_offset + 1, semi_colon_offset - equals_offset - 1, ENC_UTF_8);
1640
0
            }
1641
0
            else {
1642
0
                proto_tree_add_format_text(tree, tvb, current_offset, length);
1643
0
            }
1644
0
        }
1645
0
        else {
1646
0
            proto_tree_add_format_text(tree, tvb, current_offset, length);
1647
0
        }
1648
0
        current_offset = semi_colon_offset + 1;
1649
0
    }
1650
0
}
1651
1652
1653
/*
1654
 *           History-Info = "History-Info" HCOLON
1655
 *                            hi-entry *(COMMA hi-entry)
1656
 *
1657
 *          hi-entry = hi-targeted-to-uri *( SEMI hi-param )
1658
 *          hi-targeted-to-uri= name-addr
1659
 *
1660
 *
1661
 *          hi-param = hi-index / hi-extension
1662
 *
1663
 *          hi-index = "index" EQUAL 1*DIGIT *(DOT 1*DIGIT)
1664
 *
1665
 *          hi-extension = generic-param
1666
 */
1667
1668
static int
1669
dissect_sip_history_info(tvbuff_t *tvb, proto_tree* tree, packet_info *pinfo _U_, int current_offset,
1670
                int line_end_offset)
1671
0
{
1672
0
    int comma_offset;
1673
0
    bool first_time = true;
1674
1675
    /* split the line at the commas */
1676
0
    while (line_end_offset > current_offset){
1677
0
        comma_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, ',');
1678
0
        if(comma_offset == -1){
1679
0
            if(first_time == true){
1680
                /* It was only on parameter no need to split it up */
1681
0
                return line_end_offset;
1682
0
            }
1683
            /* Last parameter */
1684
0
            comma_offset = line_end_offset;
1685
0
        }
1686
0
        first_time = false;
1687
0
        proto_tree_add_format_text(tree, tvb, current_offset, comma_offset-current_offset);
1688
1689
0
        current_offset = comma_offset+1;
1690
0
    }
1691
1692
0
    return line_end_offset;
1693
1694
0
}
1695
1696
1697
/*
1698
 *    The syntax for the P-Charging-Function-Addresses header is described
1699
 *   as follows:
1700
 *
1701
 *      P-Charging-Addr        = "P-Charging-Function-Addresses" HCOLON
1702
 *                               charge-addr-params
1703
 *                               *(SEMI charge-addr-params)
1704
 *      charge-addr-params     = ccf / ecf / generic-param
1705
 *      ccf                    = "ccf" EQUAL gen-value
1706
 *      ecf                    = "ecf" EQUAL gen-value
1707
 *      generic-param          =  token [ EQUAL gen-value ]
1708
 *      gen-value              =  token / host / quoted-string
1709
 *
1710
 */
1711
1712
static int
1713
dissect_sip_p_charging_func_addresses(tvbuff_t *tvb, proto_tree* tree, packet_info *pinfo _U_, int current_offset,
1714
                int line_end_offset)
1715
0
{
1716
0
    int semi_offset, start_quote_offset, end_quote_offset;
1717
0
    bool first_time = true;
1718
1719
0
    while (line_end_offset > current_offset){
1720
        /* Do we have a quoted string ? */
1721
0
        start_quote_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, '"');
1722
0
        if(start_quote_offset>0){
1723
            /* Find end of quoted string */
1724
0
            end_quote_offset = tvb_find_uint8(tvb, start_quote_offset+1, line_end_offset - (start_quote_offset+1), '"');
1725
            /* Find parameter end */
1726
0
            if (end_quote_offset>0)
1727
0
                semi_offset = tvb_find_uint8(tvb, end_quote_offset+1, line_end_offset - (end_quote_offset+1), ';');
1728
0
            else {
1729
                /* XXX expert info about unterminated string */
1730
0
                semi_offset = tvb_find_uint8(tvb, start_quote_offset+1, line_end_offset - (start_quote_offset+1), ';');
1731
0
            }
1732
0
        }else{
1733
            /* Find parameter end */
1734
0
            semi_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, ';');
1735
0
        }
1736
0
        if(semi_offset == -1){
1737
0
            if(first_time == true){
1738
            /* It was only one parameter no need to split it up */
1739
0
            return line_end_offset;
1740
0
            }
1741
            /* Last parameter */
1742
0
            semi_offset = line_end_offset;
1743
0
        }
1744
0
        first_time = false;
1745
0
        proto_tree_add_format_text(tree, tvb, current_offset, semi_offset-current_offset);
1746
1747
0
        current_offset = semi_offset+1;
1748
1749
0
    }
1750
1751
0
    return current_offset;
1752
0
}
1753
1754
/*
1755
 *  token         =  1*(alphanum / "-" / "." / "!" / "%" / "*"
1756
 *                    / "_" / "+" / "`" / "'" / "~" )
1757
 *  LWS           =  [*WSP CRLF] 1*WSP ; linear whitespace
1758
 *  name-addr     =  [ display-name ] LAQUOT addr-spec RAQUOT
1759
 *  addr-spec     =  SIP-URI / SIPS-URI / absoluteURI
1760
 *  display-name  =  *(token LWS)/ quoted-string
1761
 *  absoluteURI    =  scheme ":" ( hier-part / opaque-part )
1762
 */
1763
1764
static int
1765
dissect_sip_name_addr_or_addr_spec(tvbuff_t *tvb, packet_info *pinfo _U_, int start_offset,
1766
                int line_end_offset, uri_offset_info *uri_offsets)
1767
287
{
1768
287
    char c;
1769
287
    int i;
1770
287
    int current_offset;
1771
287
    int queried_offset;
1772
287
    int colon_offset;
1773
287
    bool uri_without_angle_quotes = false;
1774
1775
    /* skip Spaces and Tabs */
1776
287
    current_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
1777
1778
287
    if(current_offset >= line_end_offset) {
1779
        /* Nothing to parse */
1780
0
        return -1;
1781
0
    }
1782
1783
287
    uri_offsets->name_addr_start = current_offset;
1784
1785
    /* First look, if we have a display name */
1786
287
    c=tvb_get_uint8(tvb, current_offset);
1787
287
    switch(c)
1788
287
    {
1789
0
        case '"':
1790
            /* We have a display name, look for the next unescaped '"' */
1791
0
            uri_offsets->display_name_start = current_offset;
1792
0
            do
1793
0
            {
1794
0
                queried_offset = tvb_find_uint8(tvb, current_offset + 1, line_end_offset - (current_offset + 1), '"');
1795
0
                if(queried_offset == -1)
1796
0
                {
1797
                    /* malformed URI */
1798
0
                    return -1;
1799
0
                }
1800
0
                current_offset = queried_offset;
1801
1802
                /* Is it escaped? */
1803
                /* count back slashes before '"' */
1804
0
                for(i=1;tvb_get_uint8(tvb, queried_offset - i) == '\\';i++);
1805
0
                i--;
1806
1807
0
                if(i % 2 == 0)
1808
0
                {
1809
                    /* not escaped */
1810
0
                    break;
1811
0
                }
1812
0
            } while (current_offset < line_end_offset);
1813
0
            if(current_offset >= line_end_offset)
1814
0
            {
1815
                /* malformed URI */
1816
0
                return -1;
1817
0
            }
1818
1819
0
            uri_offsets->display_name_end = current_offset;
1820
1821
            /* find start of the URI */
1822
0
            queried_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, '<');
1823
0
            if(queried_offset == -1)
1824
0
            {
1825
                /* malformed Uri */
1826
0
                return -1;
1827
0
            }
1828
0
            current_offset = queried_offset + 1;
1829
0
            break;
1830
1831
0
        case '<':
1832
            /* We don't have a display name */
1833
0
            current_offset++;
1834
0
            break;
1835
1836
287
        default:
1837
            /* We have either an URI without angles or a display name with a limited character set */
1838
            /* Look for the right angle quote or colon */
1839
287
            queried_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, '<');
1840
287
            colon_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, ':');
1841
287
            if(queried_offset != -1 && colon_offset != -1)
1842
46
            {
1843
46
                if(queried_offset < colon_offset)
1844
23
                {
1845
                    /* we have an URI with angle quotes */
1846
23
                    uri_offsets->display_name_start = current_offset;
1847
23
                    uri_offsets->display_name_end = queried_offset - 1;
1848
23
                    current_offset = queried_offset + 1;
1849
23
                }
1850
23
                else
1851
23
                {
1852
                    /* we have an URI without angle quotes */
1853
23
                    uri_without_angle_quotes = true;
1854
23
                }
1855
46
            }
1856
241
            else
1857
241
            {
1858
241
                if(queried_offset != -1)
1859
11
                {
1860
                    /* we have an URI with angle quotes */
1861
11
                    uri_offsets->display_name_start = current_offset;
1862
11
                    uri_offsets->display_name_end = queried_offset - 1;
1863
11
                    current_offset = queried_offset + 1;
1864
11
                    break;
1865
11
                }
1866
230
                if(colon_offset != -1)
1867
175
                {
1868
                    /* we have an URI without angle quotes */
1869
175
                    uri_without_angle_quotes = true;
1870
175
                    break;
1871
175
                }
1872
                /* If this point is reached, we can't parse the URI */
1873
55
                return -1;
1874
230
            }
1875
46
            break;
1876
287
    }
1877
    /* Start of URI */
1878
232
    uri_offsets->uri_start = current_offset;
1879
232
    if(uri_without_angle_quotes==false){
1880
        /* name-addr form was used */
1881
        /* look for closing angle quote */
1882
34
        queried_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, '>');
1883
34
        if(queried_offset == -1)
1884
30
        {
1885
            /* malformed Uri */
1886
30
            return -1;
1887
30
        }
1888
4
        uri_offsets->name_addr_end = queried_offset;
1889
4
        uri_offsets->uri_end = queried_offset - 1;
1890
4
    }
1891
202
    return dissect_sip_uri(tvb, pinfo, current_offset, line_end_offset, uri_offsets);
1892
232
}
1893
1894
1895
/*
1896
* Code to add dissected SIP URI Information to proto tree
1897
*/
1898
1899
static proto_tree *
1900
display_sip_uri (tvbuff_t *tvb, proto_tree *sip_element_tree, packet_info *pinfo, uri_offset_info* uri_offsets, hf_sip_uri_t* uri)
1901
247
{
1902
247
    proto_item *ti;
1903
247
    proto_tree *uri_item_tree = NULL;
1904
247
    tvbuff_t *next_tvb;
1905
1906
247
    if(uri_offsets->display_name_end != uri_offsets->display_name_start) {
1907
4
        proto_tree_add_item(sip_element_tree, *(uri->hf_sip_display), tvb, uri_offsets->display_name_start,
1908
4
                            uri_offsets->display_name_end - uri_offsets->display_name_start + 1, ENC_UTF_8|ENC_NA);
1909
4
        ti = proto_tree_add_item(sip_element_tree, hf_sip_display, tvb, uri_offsets->display_name_start,
1910
4
                                 uri_offsets->display_name_end - uri_offsets->display_name_start + 1, ENC_UTF_8);
1911
4
        proto_item_set_hidden(ti);
1912
4
    }
1913
1914
247
    ti = proto_tree_add_item(sip_element_tree, *(uri->hf_sip_addr),
1915
247
                             tvb, uri_offsets->uri_start, uri_offsets->uri_end - uri_offsets->uri_start + 1, ENC_UTF_8|ENC_NA);
1916
247
    uri_item_tree = proto_item_add_subtree(ti, *(uri->ett_uri));
1917
1918
247
    if (uri_offsets->uri_type != SIP_URI_TYPE_SIP && uri_offsets->uri_type != SIP_URI_TYPE_TEL) {
1919
105
        return ti;
1920
105
    }
1921
1922
142
    if(uri_offsets->uri_user_end > uri_offsets->uri_user_start) {
1923
2
        proto_tree_add_item(uri_item_tree, *(uri->hf_sip_user), tvb, uri_offsets->uri_user_start,
1924
2
                            uri_offsets->uri_user_end - uri_offsets->uri_user_start + 1, ENC_UTF_8|ENC_NA);
1925
2
        if (tvb_get_uint8(tvb, uri_offsets->uri_user_start) == '+') {
1926
0
            dissect_e164_msisdn(tvb, pinfo, uri_item_tree, uri_offsets->uri_user_start + 1, uri_offsets->uri_user_end - uri_offsets->uri_user_start, E164_ENC_UTF8);
1927
0
        }
1928
1929
        /* If we have a SIP diagnostics sub dissector call it */
1930
2
        if (sip_uri_userinfo_handle) {
1931
0
            next_tvb = tvb_new_subset_length(tvb, uri_offsets->uri_user_start,
1932
0
                                      uri_offsets->uri_user_end - uri_offsets->uri_user_start + 1);
1933
0
            call_dissector(sip_uri_userinfo_handle, next_tvb, pinfo, uri_item_tree);
1934
0
        }
1935
1936
2
    }
1937
1938
142
    if(uri_offsets->uri_host_end > uri_offsets->uri_host_start) {
1939
141
        proto_tree_add_item(uri_item_tree, *(uri->hf_sip_host), tvb, uri_offsets->uri_host_start,
1940
141
                            uri_offsets->uri_host_end - uri_offsets->uri_host_start + 1, ENC_UTF_8|ENC_NA);
1941
141
    }
1942
1943
142
    if(uri_offsets->uri_host_port_end > uri_offsets->uri_host_port_start) {
1944
72
        proto_tree_add_item(uri_item_tree, *(uri->hf_sip_port), tvb, uri_offsets->uri_host_port_start,
1945
72
                            uri_offsets->uri_host_port_end - uri_offsets->uri_host_port_start + 1, ENC_UTF_8|ENC_NA);
1946
72
    }
1947
1948
142
    if (uri_offsets->uri_parameters_start != -1) {
1949
        /* Move current offset to the start of the first param */
1950
33
        int current_offset          = uri_offsets->uri_parameters_start;
1951
33
        int uri_params_start_offset = current_offset;
1952
33
        int queried_offset;
1953
33
        int uri_param_end_offset = -1;
1954
33
        unsigned char c;
1955
1956
        /* Put the contact parameters in the tree */
1957
1958
281
        while (current_offset < uri_offsets->name_addr_end) {
1959
248
            queried_offset = tvb_ws_mempbrk_pattern_uint8(tvb, current_offset, uri_offsets->name_addr_end - current_offset, &pbrk_comma_semi, &c);
1960
1961
248
            if (queried_offset == -1) {
1962
                /* Reached line end */
1963
                /* Check if the line ends with a ">", if so decrement end offset. */
1964
25
                c = tvb_get_uint8(tvb, uri_offsets->name_addr_end);
1965
1966
25
                if (c == '>') {
1967
0
                    uri_param_end_offset = uri_offsets->name_addr_end - 1;
1968
25
                } else {
1969
25
                    uri_param_end_offset = uri_offsets->name_addr_end;
1970
25
                }
1971
25
                current_offset       = uri_offsets->name_addr_end;
1972
223
            } else if (c==',') {
1973
7
                uri_param_end_offset = queried_offset;
1974
7
                current_offset       = queried_offset+1; /* must move forward */
1975
216
            } else if (c==';') {
1976
                /* More parameters */
1977
216
                uri_param_end_offset = queried_offset-1;
1978
216
                current_offset       = tvb_skip_wsp(tvb, queried_offset+1, uri_offsets->name_addr_end - queried_offset + 1);
1979
216
            }
1980
1981
248
            proto_tree_add_item(uri_item_tree, *(uri->hf_sip_param), tvb, uri_params_start_offset ,
1982
248
                uri_param_end_offset - uri_params_start_offset +1, ENC_UTF_8|ENC_NA);
1983
1984
            /* In case there are more parameters, point to the start of it */
1985
248
            uri_params_start_offset = current_offset;
1986
248
        }
1987
33
    }
1988
1989
142
    return uri_item_tree;
1990
247
}
1991
1992
1993
1994
1995
/* Code to parse a contact header item
1996
 * Returns Offset end off parsing or -1 for unsuccessful parsing
1997
 * * contact-param  =  (name-addr / addr-spec) *(SEMI contact-params)
1998
 */
1999
static int
2000
dissect_sip_contact_item(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset, int line_end_offset,
2001
            unsigned char* contacts_expires_0, unsigned char* contacts_expires_unknown)
2002
306
{
2003
306
    unsigned char c;
2004
306
    int current_offset;
2005
306
    int queried_offset;
2006
306
    int contact_params_start_offset = -1;
2007
    /*int contact_param_end_offset = -1;*/
2008
306
    uri_offset_info uri_offsets;
2009
306
    bool end_of_hdr = false;
2010
306
    bool has_expires_param = false;
2011
2012
    /* skip Spaces and Tabs */
2013
306
    start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
2014
2015
306
    if(start_offset >= line_end_offset) {
2016
        /* Nothing to parse */
2017
19
        return -1;
2018
19
    }
2019
2020
    /* Initialize the uri_offsets */
2021
287
    sip_uri_offset_init(&uri_offsets);
2022
    /* contact-param  =  (name-addr / addr-spec) *(SEMI contact-params) */
2023
287
    current_offset = dissect_sip_name_addr_or_addr_spec(tvb, pinfo, start_offset, line_end_offset, &uri_offsets);
2024
287
    if(current_offset == -1)
2025
143
    {
2026
        /* Parsing failed */
2027
143
        return -1;
2028
143
    }
2029
144
    display_sip_uri(tvb, tree, pinfo, &uri_offsets, &sip_contact_uri);
2030
2031
    /* check if there's a comma before a ';', in which case we stop parsing this item at the comma */
2032
144
    queried_offset = tvb_find_uint8(tvb, uri_offsets.uri_end, line_end_offset - uri_offsets.uri_end, ',');
2033
2034
    /* Check if we have contact parameters, the uri should be followed by a ';' */
2035
144
    contact_params_start_offset = tvb_find_uint8(tvb, uri_offsets.uri_end, line_end_offset - uri_offsets.uri_end, ';');
2036
2037
144
    if (queried_offset != -1 && (queried_offset < contact_params_start_offset || contact_params_start_offset == -1)) {
2038
        /* no expires param */
2039
31
        (*contacts_expires_unknown)++;
2040
31
        return queried_offset;
2041
31
    }
2042
2043
    /* check if contact-params is present */
2044
113
    if(contact_params_start_offset == -1) {
2045
        /* no expires param */
2046
55
        (*contacts_expires_unknown)++;
2047
55
        return line_end_offset;
2048
55
    }
2049
2050
    /* Move current offset to the start of the first param */
2051
58
    contact_params_start_offset++;
2052
58
    current_offset = contact_params_start_offset;
2053
2054
    /* Put the contact parameters in the tree */
2055
2056
58
    queried_offset = current_offset;
2057
2058
150
    while(current_offset< line_end_offset){
2059
93
        c = '\0';
2060
93
        queried_offset++;
2061
93
        queried_offset = (queried_offset < line_end_offset) ? tvb_ws_mempbrk_pattern_uint8(tvb, queried_offset, line_end_offset - queried_offset, &pbrk_header_end_dquote, &c) : -1;
2062
93
        if (queried_offset != -1)
2063
92
        {
2064
92
            switch (c) {
2065
                /* prevent tree from displaying the '\r\n' as part of the param */
2066
1
                case '\r':
2067
54
                case '\n':
2068
54
                    end_of_hdr = true;
2069
                    /* fall through */
2070
55
                case ',':
2071
90
                case ';':
2072
92
                case '"':
2073
92
                    break;
2074
0
                default :
2075
0
                    DISSECTOR_ASSERT_NOT_REACHED();
2076
0
                    break;
2077
92
            }
2078
92
        }
2079
2080
93
        if (queried_offset == -1) {
2081
            /* Last parameter, line end */
2082
1
            current_offset = line_end_offset;
2083
92
        }else if(c=='"'){
2084
            /* Do we have a quoted string ? */
2085
2
            queried_offset = tvb_find_uint8(tvb, queried_offset+1, line_end_offset - queried_offset, '"');
2086
2
            if(queried_offset==-1){
2087
                /* We have an opening quote but no closing quote. */
2088
1
                current_offset = line_end_offset;
2089
1
            } else {
2090
1
                current_offset = tvb_ws_mempbrk_pattern_uint8(tvb, queried_offset+1, line_end_offset - queried_offset, &pbrk_comma_semi, &c);
2091
1
                if(current_offset==-1){
2092
                    /* Last parameter, line end */
2093
1
                    current_offset = line_end_offset;
2094
1
                }
2095
1
            }
2096
90
        }else{
2097
90
            current_offset = queried_offset;
2098
90
        }
2099
93
        proto_tree_add_item(tree, hf_sip_contact_param, tvb, contact_params_start_offset ,
2100
93
            current_offset - contact_params_start_offset, ENC_UTF_8);
2101
2102
        /* need to check for an 'expires' parameter
2103
         * TODO: this should be done in a common way for all headers,
2104
         * but To/From/etc do their own right now so doing the same here
2105
         */
2106
        /* also, this is a bad way of checking param names, but it's what To/From
2107
         * etc, do. But legally "exPiRes = value" is also legit.
2108
         */
2109
93
        if (tvb_strncaseeql(tvb, contact_params_start_offset, "expires=", 8) == 0) {
2110
0
            int32_t expire;
2111
            /* if the expires param value is 0, then it's de-registering
2112
             * this assumes the message is a REGISTER request/response, but these
2113
             * contacts_expires_0/contacts_expires_unknown variables only get used then,
2114
             * so that's ok
2115
             */
2116
0
            if (!ws_strtoi32((char*)tvb_get_string_enc(pinfo->pool, tvb, contact_params_start_offset+8,
2117
0
                    current_offset - (contact_params_start_offset+8), ENC_UTF_8|ENC_NA), NULL, &expire))
2118
0
                return contact_params_start_offset+8;
2119
0
            has_expires_param = true;
2120
0
            if (expire == 0) {
2121
0
                (*contacts_expires_0)++;
2122
                /* RFC 3261 10.3 "Processing REGISTER requests":
2123
                 * "The registrar returns a 200 (OK) response.  The response
2124
                 * MUST contain Contact header field values enumerating all
2125
                 * current bindings."
2126
                 * This implies it is invalid for the response to contain the
2127
                 * deregistered, no longer current, Contacts with expires=0.
2128
                 * However, this warning was removed due to 3GPP usage.
2129
                 * Cf. 3GPP TS 24.229 "5.4.1.4 User-initiated deregistration":
2130
                 * "send a 200 (OK) response to a REGISTER request that
2131
                 * contains a list of Contact header fields enumerating all
2132
                 * contacts and flows that are currently registered, and all
2133
                 * contacts that have been deregistered."
2134
                 * https://gitlab.com/wireshark/wireshark/-/issues/10364
2135
                 */
2136
#if 0
2137
                if (stat_info && stat_info->response_code > 199 && stat_info->response_code < 300) {
2138
                    proto_tree_add_expert_format(tree, pinfo, &ei_sip_odd_register_response,
2139
                        tvb, contact_params_start_offset, current_offset - contact_params_start_offset,
2140
                        "SIP REGISTER %d response contains Contact with expires=0",
2141
                        stat_info->response_code);
2142
                }
2143
#endif
2144
0
            }
2145
0
        }
2146
2147
        /* In case there are more parameters, point to the start of it */
2148
93
        contact_params_start_offset = current_offset+1;
2149
93
        queried_offset = contact_params_start_offset;
2150
93
        if (end_of_hdr) {
2151
            /* '\r' or '\n' found, stop parsing and also set current offset to end
2152
             * so the return value indicates we reached line end
2153
             */
2154
54
            current_offset = line_end_offset;
2155
54
        }
2156
93
        if (c == ',') {
2157
            /* comma separator found, stop parsing of current contact-param here */
2158
1
            break;
2159
1
        }
2160
93
    }
2161
2162
58
    if (!has_expires_param) {
2163
58
        (*contacts_expires_unknown)++;
2164
58
    }
2165
2166
58
    return current_offset;
2167
58
}
2168
2169
/* Code to parse an authorization header item
2170
 * Returns offset at end of parsing, or -1 for unsuccessful parsing
2171
 */
2172
static int
2173
dissect_sip_authorization_item(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int start_offset, int line_end_offset, sip_authorization_t *authorization_info)
2174
0
{
2175
0
    int current_offset, par_name_end_offset, queried_offset, value_offset, value_search_offset;
2176
0
    int equals_offset = 0;
2177
0
    char *name;
2178
0
    header_parameter_t *auth_parameter;
2179
0
    unsigned i = 0;
2180
2181
    /* skip Spaces and Tabs */
2182
0
    start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
2183
2184
0
    if (start_offset >= line_end_offset)
2185
0
    {
2186
        /* Nothing to parse */
2187
0
        return -1;
2188
0
    }
2189
2190
0
    current_offset = start_offset;
2191
0
    equals_offset = tvb_find_uint8(tvb, current_offset + 1, line_end_offset - (current_offset + 1), '=');
2192
0
    if(equals_offset == -1){
2193
        /* malformed parameter */
2194
0
        return -1;
2195
0
    }
2196
0
    par_name_end_offset = equals_offset - 1;
2197
0
    par_name_end_offset = tvb_skip_wsp_return(tvb,par_name_end_offset);
2198
2199
    /* Extract the parameter name */
2200
0
    name = (char*)tvb_get_string_enc(pinfo->pool, tvb, start_offset, par_name_end_offset-start_offset, ENC_UTF_8|ENC_NA);
2201
2202
0
    value_offset = tvb_skip_wsp(tvb, equals_offset + 1, line_end_offset - (equals_offset + 1));
2203
0
    if (tvb_get_uint8(tvb, value_offset) == '\"') {
2204
        /* quoted value */
2205
0
        value_search_offset = value_offset;
2206
0
        do {
2207
0
            value_search_offset++;
2208
0
            queried_offset = tvb_find_uint8 (tvb, value_search_offset, line_end_offset - value_search_offset, '\"');
2209
0
        } while ((queried_offset != -1) && (tvb_get_uint8(tvb, queried_offset - 1) == '\\'));
2210
0
        if (queried_offset == -1) {
2211
            /* Closing quote not found, return line end */
2212
0
            current_offset = line_end_offset;
2213
0
        } else {
2214
            /* Include closing quotes */
2215
0
            current_offset = queried_offset + 1;
2216
0
        }
2217
0
    } else {
2218
        /* unquoted value */
2219
0
        queried_offset = tvb_find_uint8 (tvb, value_offset, line_end_offset - value_offset, ',');
2220
0
        if (queried_offset == -1) {
2221
            /* Last parameter, line end */
2222
0
            current_offset = line_end_offset;
2223
0
        } else {
2224
0
            current_offset = queried_offset;
2225
0
        }
2226
0
    }
2227
2228
    /* Try to add parameter as a filterable item */
2229
0
    for (auth_parameter = &auth_parameters_hf_array[i];
2230
0
         i < array_length(auth_parameters_hf_array);
2231
0
         i++, auth_parameter++)
2232
0
    {
2233
0
        if (g_ascii_strcasecmp(name, auth_parameter->param_name) == 0)
2234
0
        {
2235
0
            proto_tree_add_item(tree, *(auth_parameter->hf_item), tvb,
2236
0
                                value_offset, current_offset - value_offset,
2237
0
                                ENC_UTF_8|ENC_NA);
2238
0
            if (global_sip_validate_authorization) {
2239
0
                int real_value_offset = value_offset;
2240
0
                int real_value_length = current_offset - value_offset;
2241
0
                if ((tvb_get_uint8(tvb, value_offset) == '\"') && (tvb_get_uint8(tvb, current_offset - 1) == '\"') && (real_value_length > 1)) {
2242
0
                    real_value_offset++;
2243
0
                    real_value_length -= 2;
2244
0
                }
2245
0
                if (g_ascii_strcasecmp(name, "response") == 0) {
2246
0
                    authorization_info->response = (char*)tvb_get_string_enc(pinfo->pool, tvb, real_value_offset, real_value_length, ENC_ASCII);
2247
0
                } else if (g_ascii_strcasecmp(name, "nc") == 0) {
2248
0
                    authorization_info->nonce_count = (char*)tvb_get_string_enc(pinfo->pool, tvb, real_value_offset, real_value_length, ENC_ASCII);
2249
0
                } else if (g_ascii_strcasecmp(name, "username") == 0) {
2250
0
                    authorization_info->username = (char*)tvb_get_string_enc(pinfo->pool, tvb, real_value_offset, real_value_length, ENC_ASCII);
2251
0
                } else if (g_ascii_strcasecmp(name, "realm") == 0) {
2252
0
                    authorization_info->realm = (char*)tvb_get_string_enc(pinfo->pool, tvb, real_value_offset, real_value_length, ENC_ASCII);
2253
0
                } else if (g_ascii_strcasecmp(name, "algorithm") == 0) {
2254
0
                    authorization_info->algorithm = (char*)tvb_get_string_enc(pinfo->pool, tvb, real_value_offset, real_value_length, ENC_ASCII);
2255
0
                } else if (g_ascii_strcasecmp(name, "nonce") == 0) {
2256
0
                    authorization_info->nonce = (char*)tvb_get_string_enc(pinfo->pool, tvb, real_value_offset, real_value_length, ENC_ASCII);
2257
0
                } else if (g_ascii_strcasecmp(name, "qop") == 0) {
2258
0
                    authorization_info->qop = (char*)tvb_get_string_enc(pinfo->pool, tvb, real_value_offset, real_value_length, ENC_ASCII);
2259
0
                } else if (g_ascii_strcasecmp(name, "cnonce") == 0) {
2260
0
                    authorization_info->cnonce = (char*)tvb_get_string_enc(pinfo->pool, tvb, real_value_offset, real_value_length, ENC_ASCII);
2261
0
                } else if (g_ascii_strcasecmp(name, "uri") == 0) {
2262
0
                    authorization_info->uri = (char*)tvb_get_string_enc(pinfo->pool, tvb, real_value_offset, real_value_length, ENC_ASCII);
2263
0
                }
2264
0
            }
2265
0
            break;
2266
0
        }
2267
0
    }
2268
2269
    /* If not matched, just add as text... */
2270
0
    if (i == array_length(auth_parameters_hf_array))
2271
0
    {
2272
0
        proto_tree_add_format_text(tree, tvb, start_offset, current_offset-start_offset);
2273
0
    }
2274
2275
    /* Find comma/end of line */
2276
0
    queried_offset = tvb_find_uint8 (tvb, current_offset, line_end_offset - current_offset, ',');
2277
0
    if (queried_offset == -1) {
2278
0
        current_offset = line_end_offset;
2279
0
    } else {
2280
0
        current_offset = queried_offset;
2281
0
    }
2282
0
    return current_offset;
2283
0
}
2284
2285
/* Dissect the details of a Reason header
2286
 * Reason            =  "Reason" HCOLON reason-value *(COMMA reason-value)
2287
 * reason-value      =  protocol *(SEMI reason-params)
2288
 * protocol          =  "SIP" / "Q.850" / token
2289
 * reason-params     =  protocol-cause / reason-text / reason-extension
2290
 * protocol-cause    =  "cause" EQUAL cause
2291
 * cause             =  1*DIGIT
2292
 * reason-text       =  "text" EQUAL quoted-string
2293
 * reason-extension  =  generic-param
2294
 */
2295
static void
2296
0
dissect_sip_reason_header(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int start_offset, int line_end_offset){
2297
2298
0
    int   current_offset, semi_colon_offset, length, end_quote_offset;
2299
0
    const char *param_name = NULL;
2300
0
    unsigned cause_value;
2301
0
    sip_reason_code_info_t sip_reason_code_info;
2302
2303
        /* skip Spaces and Tabs */
2304
0
    start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
2305
2306
0
    if (start_offset >= line_end_offset)
2307
0
    {
2308
        /* Nothing to parse */
2309
0
        return;
2310
0
    }
2311
2312
0
    current_offset = start_offset;
2313
0
    semi_colon_offset = tvb_find_uint8(tvb, current_offset, line_end_offset-current_offset, ';');
2314
2315
0
    if(semi_colon_offset == -1)
2316
0
        return;
2317
2318
0
    length = semi_colon_offset - current_offset;
2319
0
    proto_tree_add_item_ret_string(tree, hf_sip_reason_protocols, tvb, start_offset, length, ENC_UTF_8|ENC_NA, pinfo->pool, (const uint8_t**)&param_name);
2320
0
    current_offset = tvb_find_uint8(tvb, semi_colon_offset, line_end_offset - semi_colon_offset, '=') + 1;
2321
    /* Do we have a text parameter too? */
2322
0
    semi_colon_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, ';');
2323
2324
0
    if (semi_colon_offset == -1){
2325
0
        length = line_end_offset - current_offset;
2326
0
    } else {
2327
        /* Text parameter exist, set length accordingly */
2328
0
        length = semi_colon_offset - current_offset;
2329
0
    }
2330
2331
    /* Get cause value */
2332
0
    cause_value = (unsigned)strtoul((char*)tvb_get_string_enc(pinfo->pool, tvb, current_offset, length, ENC_UTF_8 | ENC_NA), NULL, 10);
2333
2334
0
    if (g_ascii_strcasecmp(param_name, "Q.850") == 0){
2335
0
        proto_tree_add_uint(tree, hf_sip_reason_cause_q850, tvb, current_offset, length, cause_value);
2336
0
        sip_reason_code_info.protocol_type_num = SIP_PROTO_Q850;
2337
0
    }
2338
0
    else if (g_ascii_strcasecmp(param_name, "SIP") == 0) {
2339
0
        proto_tree_add_uint(tree, hf_sip_reason_cause_sip, tvb, current_offset, length, cause_value);
2340
0
        sip_reason_code_info.protocol_type_num = SIP_PROTO_SIP;
2341
0
    }
2342
0
    else {
2343
0
        proto_tree_add_uint(tree, hf_sip_reason_cause_other, tvb, current_offset, length, cause_value);
2344
0
        sip_reason_code_info.protocol_type_num = SIP_PROTO_OTHER;
2345
0
    }
2346
2347
0
    if (semi_colon_offset == -1)
2348
        /* Nothing to parse */
2349
0
        return;
2350
2351
    /* reason-text       =  "text" EQUAL quoted-string */
2352
0
    current_offset = tvb_find_uint8(tvb, semi_colon_offset, line_end_offset - semi_colon_offset, '"') + 1;
2353
0
    if (current_offset == -1)
2354
        /* Nothing to parse */
2355
0
        return;
2356
0
    end_quote_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, '"');
2357
0
    if (end_quote_offset == -1)
2358
        /* Nothing to parse */
2359
0
        return;
2360
0
    length = end_quote_offset - current_offset;
2361
0
    proto_tree_add_item(tree, hf_sip_reason_text, tvb, current_offset, length, ENC_UTF_8);
2362
2363
0
    if (sip_reason_code_handle) {
2364
0
        tvbuff_t *next_tvb;
2365
2366
0
        sip_reason_code_info.cause_value = cause_value;
2367
2368
0
        next_tvb = tvb_new_subset_length(tvb, current_offset, length);
2369
0
        call_dissector_with_data(sip_reason_code_handle, next_tvb, pinfo, tree, &sip_reason_code_info);
2370
0
    }
2371
0
}
2372
2373
/* Dissect the details of a security client header
2374
 * sec-mechanism    = mechanism-name *(SEMI mech-parameters)
2375
 *     mech-parameters  = ( preference / digest-algorithm /
2376
 *                          digest-qop / digest-verify / extension )
2377
 *    preference       = "q" EQUAL qvalue
2378
 *    qvalue           = ( "0" [ "." 0*3DIGIT ] )
2379
 *                        / ( "1" [ "." 0*3("0") ] )
2380
 *    digest-algorithm = "d-alg" EQUAL token
2381
 *    digest-qop       = "d-qop" EQUAL token
2382
 *    digest-verify    = "d-ver" EQUAL LDQUOT 32LHEX RDQUOT
2383
 *    extension        = generic-param
2384
 *
2385
 *
2386
 */
2387
static void
2388
0
dissect_sip_sec_mechanism(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int start_offset, int line_end_offset){
2389
2390
0
    int   current_offset, semi_colon_offset, length, par_name_end_offset, equals_offset;
2391
2392
    /* skip Spaces and Tabs */
2393
0
    start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
2394
2395
0
    if (start_offset >= line_end_offset)
2396
0
    {
2397
        /* Nothing to parse */
2398
0
        return;
2399
0
    }
2400
2401
0
    current_offset = start_offset;
2402
0
    semi_colon_offset = tvb_find_uint8(tvb, current_offset, line_end_offset-current_offset, ';');
2403
0
    if(semi_colon_offset == -1){
2404
0
        semi_colon_offset = line_end_offset;
2405
0
    }
2406
2407
0
    length = semi_colon_offset-current_offset;
2408
0
    proto_tree_add_item(tree, hf_sip_sec_mechanism, tvb,
2409
0
                                start_offset, length,
2410
0
                                ENC_UTF_8);
2411
2412
0
    current_offset = current_offset + length + 1;
2413
2414
2415
0
    while(current_offset < line_end_offset){
2416
0
        char *param_name = NULL, *value = NULL;
2417
0
        uint8_t hf_index = 0;
2418
        /* skip Spaces and Tabs */
2419
0
        current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
2420
2421
0
        semi_colon_offset = tvb_find_uint8(tvb, current_offset, line_end_offset-current_offset, ';');
2422
2423
0
        if(semi_colon_offset == -1){
2424
0
            semi_colon_offset = line_end_offset;
2425
0
        }
2426
2427
0
        length = semi_colon_offset - current_offset;
2428
2429
        /* Parse parameter and value */
2430
0
        equals_offset = tvb_find_uint8(tvb, current_offset + 1, length, '=');
2431
0
        if(equals_offset != -1){
2432
            /* Has value part */
2433
0
            par_name_end_offset = equals_offset;
2434
            /* Extract the parameter name */
2435
0
            param_name = (char*)tvb_get_string_enc(pinfo->pool, tvb, current_offset, par_name_end_offset-current_offset, ENC_UTF_8|ENC_NA);
2436
            /* Extract the value */
2437
0
            value = (char*)tvb_get_string_enc(pinfo->pool, tvb, equals_offset+1, semi_colon_offset-equals_offset+1, ENC_UTF_8|ENC_NA);
2438
0
        } else {
2439
0
            return;
2440
0
        }
2441
2442
2443
0
        while (sec_mechanism_parameters_hf_array[hf_index].param_name) {
2444
            /* Protection algorithm to be used */
2445
0
            if (g_ascii_strcasecmp(param_name, sec_mechanism_parameters_hf_array[hf_index].param_name) == 0) {
2446
0
                switch (sec_mechanism_parameters_hf_array[hf_index].para_type) {
2447
0
                    case MECH_PARA_STRING:
2448
0
                        proto_tree_add_item(tree, *sec_mechanism_parameters_hf_array[hf_index].hf_item, tvb,
2449
0
                                            equals_offset+1, semi_colon_offset-equals_offset-1,
2450
0
                                            ENC_UTF_8);
2451
0
                        break;
2452
0
                    case MECH_PARA_UINT:
2453
0
                        if (!value) {
2454
0
                            proto_tree_add_expert(tree, pinfo, &ei_sip_sipsec_malformed,
2455
0
                                                  tvb, current_offset, -1);
2456
0
                        } else {
2457
0
                            uint32_t semi_para;
2458
0
                            semi_para = (uint32_t)strtoul(value, NULL, 10);
2459
0
                            proto_tree_add_uint(tree, *sec_mechanism_parameters_hf_array[hf_index].hf_item, tvb,
2460
0
                                                equals_offset+1, semi_colon_offset-equals_offset-1, semi_para);
2461
0
                        }
2462
0
                        break;
2463
0
                    default:
2464
0
                        break;
2465
0
                }
2466
0
                break;
2467
0
            }
2468
0
            hf_index++;
2469
0
        }
2470
2471
0
        if (!sec_mechanism_parameters_hf_array[hf_index].param_name) {
2472
0
            proto_tree_add_format_text(tree, tvb, current_offset, length);
2473
0
        }
2474
2475
0
        current_offset = semi_colon_offset+1;
2476
0
    }
2477
2478
0
}
2479
2480
/* Dissect the details of a Route (and Record-Route) header */
2481
static void dissect_sip_route_header(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, hf_sip_uri_t *sip_route_uri_p, int start_offset, int line_end_offset)
2482
0
{
2483
0
    int current_offset;
2484
0
    uri_offset_info uri_offsets;
2485
2486
0
    current_offset = start_offset;
2487
2488
    /* skip Spaces and Tabs */
2489
0
    current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
2490
2491
0
    if (current_offset >= line_end_offset) {
2492
0
        return;
2493
0
    }
2494
2495
0
    while (current_offset < line_end_offset) {
2496
0
        current_offset = tvb_find_uint8(tvb, current_offset, (line_end_offset - 1) - current_offset, ',');
2497
2498
0
        if (current_offset != -1) { /* found any ',' ? */
2499
0
            sip_uri_offset_init(&uri_offsets);
2500
0
            current_offset = dissect_sip_name_addr_or_addr_spec(tvb, pinfo, start_offset, current_offset, &uri_offsets);
2501
0
            if(current_offset == -1)
2502
0
                return;
2503
0
            display_sip_uri(tvb, tree, pinfo, &uri_offsets, sip_route_uri_p);
2504
2505
0
            current_offset++;
2506
0
            start_offset = current_offset + 1;
2507
2508
0
        } else {
2509
            /* current_offset = (line_end_offset - 1); */
2510
2511
0
            sip_uri_offset_init(&uri_offsets);
2512
0
            current_offset = dissect_sip_name_addr_or_addr_spec(tvb, pinfo, start_offset, line_end_offset, &uri_offsets);
2513
0
            if(current_offset == -1)
2514
0
                return;
2515
0
            display_sip_uri(tvb, tree, pinfo, &uri_offsets, sip_route_uri_p);
2516
2517
0
            return;
2518
0
        }
2519
2520
0
        current_offset++;
2521
0
    }
2522
2523
0
    return;
2524
0
}
2525
2526
/* Dissect the details of a Via header
2527
 *
2528
 * Via               =  ( "Via" / "v" ) HCOLON via-parm *(COMMA via-parm)
2529
 * via-parm          =  sent-protocol LWS sent-by *( SEMI via-params )
2530
 * via-params        =  via-ttl / via-maddr
2531
 *                      / via-received / via-branch
2532
 *                      / via-extension
2533
 * via-ttl           =  "ttl" EQUAL ttl
2534
 * via-maddr         =  "maddr" EQUAL host
2535
 * via-received      =  "received" EQUAL (IPv4address / IPv6address)
2536
 * via-branch        =  "branch" EQUAL token
2537
 * via-extension     =  generic-param
2538
 * sent-protocol     =  protocol-name SLASH protocol-version
2539
 *                      SLASH transport
2540
 * protocol-name     =  "SIP" / token
2541
 * protocol-version  =  token
2542
 * transport         =  "UDP" / "TCP" / "TLS" / "SCTP"
2543
 *                      / other-transport
2544
 * sent-by           =  host [ COLON port ]
2545
 * ttl               =  1*3DIGIT ; 0 to 255
2546
 *
2547
 */
2548
static void dissect_sip_via_header(tvbuff_t *tvb, proto_tree *tree, int start_offset, int line_end_offset, packet_info *pinfo)
2549
45
{
2550
45
    int   current_offset;
2551
45
    int   address_start_offset;
2552
45
    int   semicolon_offset;
2553
45
    bool colon_seen;
2554
45
    bool ipv6_reference;
2555
45
    bool ipv6_address;
2556
45
    unsigned char c;
2557
45
    char *param_name = NULL;
2558
2559
45
    current_offset = start_offset;
2560
2561
94
    while (1)
2562
88
    {
2563
        /* Reset flags and counters */
2564
88
        semicolon_offset = 0;
2565
88
        ipv6_reference = false;
2566
88
        ipv6_address = false;
2567
88
        colon_seen = false;
2568
2569
        /* skip Spaces and Tabs */
2570
88
        current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
2571
2572
88
        if (current_offset >= line_end_offset)
2573
39
        {
2574
            /* Nothing more to parse */
2575
39
            return;
2576
39
        }
2577
2578
        /* Now look for the end of the SIP/2.0/transport parameter.
2579
         *  There may be spaces between the slashes
2580
         *  sent-protocol     =  protocol-name SLASH protocol-version
2581
         *                       SLASH transport
2582
         */
2583
2584
49
        current_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, '/');
2585
49
        if (current_offset != -1)
2586
29
        {
2587
29
            current_offset++;
2588
29
            current_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, '/');
2589
29
        }
2590
2591
49
        if (current_offset != -1)
2592
6
        {
2593
6
            current_offset++;
2594
            /* skip Spaces and Tabs */
2595
6
            current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
2596
6
        } else
2597
43
            current_offset = line_end_offset;
2598
2599
2600
        /* We should now be at the start of the first transport name (or at the end of the line) */
2601
2602
        /*
2603
         * transport         =  "UDP" / "TCP" / "TLS" / "SCTP"
2604
         *                      / other-transport
2605
         */
2606
51
        while (current_offset < line_end_offset)
2607
8
        {
2608
8
            int transport_start_offset = current_offset;
2609
2610
8
            current_offset = tvb_ws_mempbrk_pattern_uint8(tvb, current_offset, line_end_offset - current_offset, &pbrk_tab_sp_fslash, &c);
2611
8
            if (current_offset != -1){
2612
8
                proto_tree_add_item(tree, hf_sip_via_transport, tvb, transport_start_offset,
2613
8
                                    current_offset - transport_start_offset, ENC_UTF_8);
2614
                /* Check if we have more transport parameters */
2615
8
                if(c=='/'){
2616
2
                    current_offset++;
2617
2
                    continue;
2618
2
                }
2619
6
                current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
2620
6
                c = tvb_get_uint8(tvb, current_offset);
2621
6
                if(c=='/'){
2622
0
                    current_offset++;
2623
0
                    continue;
2624
0
                }
2625
6
                break;
2626
6
            }else{
2627
0
                current_offset = line_end_offset;
2628
0
            }
2629
2630
8
        }
2631
2632
        /* skip Spaces and Tabs */
2633
49
        current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
2634
2635
        /* Now read the address part */
2636
49
        address_start_offset = current_offset;
2637
49
        while (current_offset < line_end_offset)
2638
6
        {
2639
6
            current_offset = tvb_ws_mempbrk_pattern_uint8(tvb, current_offset, line_end_offset - current_offset, &pbrk_addr_end, &c);
2640
6
            if (current_offset == -1)
2641
1
            {
2642
1
                current_offset = line_end_offset;
2643
1
                break;
2644
1
            }
2645
2646
5
            if (c == '[') {
2647
0
                ipv6_reference = true;
2648
0
                ipv6_address = true;
2649
0
            }
2650
5
            else if (c == ']')
2651
0
            {
2652
0
                ipv6_reference = false;
2653
0
            }
2654
2655
5
            if (colon_seen || (c == ' ') || (c == '\t') || ((c == ':') && (ipv6_reference == false)) || (c == ';'))
2656
5
            {
2657
5
                break;
2658
5
            }
2659
2660
0
            current_offset++;
2661
0
        }
2662
        /* Add address to tree */
2663
49
        if (ipv6_address == true) {
2664
0
            proto_tree_add_item(tree, hf_sip_via_sent_by_address, tvb, address_start_offset + 1,
2665
0
                                current_offset - address_start_offset - 2, ENC_UTF_8);
2666
49
        } else {
2667
49
            proto_tree_add_item(tree, hf_sip_via_sent_by_address, tvb, address_start_offset,
2668
49
                                current_offset - address_start_offset, ENC_UTF_8);
2669
49
        }
2670
2671
        /* Transport port number may follow ([space] : [space])*/
2672
49
        current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
2673
49
        c = tvb_get_uint8(tvb, current_offset);
2674
2675
49
        if (c == ':')
2676
0
        {
2677
            /* Port number will follow any space after : */
2678
0
            int port_offset;
2679
0
            current_offset++;
2680
2681
            /* Skip optional space after colon */
2682
0
            current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
2683
2684
0
            port_offset = current_offset;
2685
2686
            /* Find digits of port number */
2687
0
            while (current_offset < line_end_offset)
2688
0
            {
2689
0
                c = tvb_get_uint8(tvb, current_offset);
2690
2691
0
                if (!g_ascii_isdigit(c))
2692
0
                {
2693
0
                    if (current_offset > port_offset)
2694
0
                    {
2695
                        /* Add address port number to tree */
2696
0
                        uint16_t port;
2697
0
                        bool port_valid;
2698
0
                        proto_item* pi;
2699
0
                        port_valid = ws_strtou16((char*)tvb_get_string_enc(pinfo->pool, tvb, port_offset,
2700
0
                            current_offset - port_offset, ENC_UTF_8|ENC_NA), NULL, &port);
2701
0
                        pi = proto_tree_add_uint(tree, hf_sip_via_sent_by_port, tvb, port_offset,
2702
0
                                            current_offset - port_offset, port);
2703
0
                        if (!port_valid)
2704
0
                            expert_add_info(pinfo, pi, &ei_sip_via_sent_by_port);
2705
0
                    }
2706
0
                    else
2707
0
                    {
2708
                        /* Shouldn't see a colon without a port number given */
2709
0
                        return;
2710
0
                    }
2711
0
                    break;
2712
0
                }
2713
2714
0
                current_offset++;
2715
0
            }
2716
0
        }
2717
2718
        /* skip Spaces and Tabs */
2719
49
        current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
2720
2721
2722
        /* Dissect any parameters found */
2723
61
        while (current_offset < line_end_offset)
2724
16
        {
2725
16
            bool equals_found = false;
2726
16
            bool found_end_of_parameters = false;
2727
16
            int parameter_name_end = 0;
2728
16
            header_parameter_t *via_parameter;
2729
16
            unsigned i = 0;
2730
2731
            /* Look for the semicolon that signals the start of a parameter */
2732
16
            while (current_offset < line_end_offset)
2733
16
            {
2734
16
                c = tvb_get_uint8(tvb, current_offset);
2735
16
                if (c == ';')
2736
12
                {
2737
12
                    semicolon_offset = current_offset;
2738
12
                    current_offset++;
2739
12
                    break;
2740
12
                }
2741
4
                else
2742
4
                if ((c != ' ') && (c != '\t'))
2743
4
                {
2744
4
                    found_end_of_parameters = true;
2745
4
                    break;
2746
4
                }
2747
0
                current_offset++;
2748
0
            }
2749
2750
16
            if (found_end_of_parameters)
2751
4
            {
2752
4
                break;
2753
4
            }
2754
2755
12
            if (current_offset == line_end_offset)
2756
0
            {
2757
0
                return;
2758
0
            }
2759
2760
            /* Look for end of parameter name */
2761
12
            while (current_offset < line_end_offset)
2762
12
            {
2763
12
                c = tvb_get_uint8(tvb, current_offset);
2764
12
                if (!g_ascii_isalpha(c) && (c != '-'))
2765
12
                {
2766
12
                    break;
2767
12
                }
2768
0
                current_offset++;
2769
0
            }
2770
2771
            /* Not all params have an = */
2772
12
            if (c == '=')
2773
0
            {
2774
0
                equals_found = true;
2775
0
            }
2776
12
            parameter_name_end = current_offset;
2777
2778
            /* Read until end of parameter value */
2779
12
            current_offset = tvb_ws_mempbrk_pattern_uint8(tvb, current_offset, line_end_offset - current_offset, &pbrk_via_param_end, NULL);
2780
12
            if (current_offset == -1)
2781
1
                current_offset = line_end_offset;
2782
2783
            /* Note parameter name */
2784
12
            param_name = (char*)tvb_get_string_enc(pinfo->pool, tvb, semicolon_offset+1,
2785
12
                                                  parameter_name_end - semicolon_offset - 1, ENC_UTF_8|ENC_NA);
2786
2787
            /* Try to add parameter as a filterable item */
2788
12
            for (via_parameter = &via_parameters_hf_array[i];
2789
156
                 i < array_length(via_parameters_hf_array);
2790
144
                 i++, via_parameter++)
2791
144
            {
2792
144
                if (g_ascii_strcasecmp(param_name, via_parameter->param_name) == 0)
2793
0
                {
2794
0
                    if (equals_found)
2795
0
                    {
2796
0
                        proto_item* via_parameter_item;
2797
0
                        via_parameter_item = proto_tree_add_item(tree, *(via_parameter->hf_item), tvb,
2798
0
                            parameter_name_end + 1, current_offset - parameter_name_end - 1,
2799
0
                            ENC_UTF_8 | ENC_NA);
2800
2801
0
                        if (sip_via_branch_handle && g_ascii_strcasecmp(param_name, "branch") == 0)
2802
0
                        {
2803
0
                            tvbuff_t *next_tvb;
2804
0
                            next_tvb = tvb_new_subset_length(tvb, parameter_name_end + 1, current_offset - parameter_name_end - 1);
2805
2806
0
                            call_dissector(sip_via_branch_handle, next_tvb, pinfo, tree);
2807
0
                        }
2808
0
                        else if (g_ascii_strcasecmp(param_name, "oc") == 0) {
2809
0
                            proto_item *ti;
2810
0
                            char *value = (char*)tvb_get_string_enc(pinfo->pool, tvb, parameter_name_end + 1,
2811
0
                                current_offset - parameter_name_end - 1, ENC_UTF_8 | ENC_NA);
2812
0
                            ti = proto_tree_add_uint(tree, hf_sip_via_oc_val, tvb,
2813
0
                                parameter_name_end + 1, current_offset - parameter_name_end - 1,
2814
0
                                (uint32_t)strtoul(value, NULL, 10));
2815
0
                            proto_item_set_generated(ti);
2816
0
                        }
2817
0
                        else if (g_ascii_strcasecmp(param_name, "oc-seq") == 0) {
2818
0
                            proto_item *ti;
2819
0
                            nstime_t ts;
2820
0
                            int dec_p_off = tvb_find_uint8(tvb, parameter_name_end + 1, - 1, '.');
2821
0
                            char *value;
2822
2823
0
                            if(dec_p_off > 0){
2824
0
                                value = (char*)tvb_get_string_enc(pinfo->pool, tvb,
2825
0
                                    parameter_name_end + 1, dec_p_off - parameter_name_end, ENC_UTF_8 | ENC_NA);
2826
0
                                ts.secs = (time_t)strtoul(value, NULL, 10);
2827
0
                                value = (char*)tvb_get_string_enc(pinfo->pool, tvb,
2828
0
                                    dec_p_off + 1, current_offset - parameter_name_end - 1, ENC_UTF_8 | ENC_NA);
2829
0
                                ts.nsecs = (uint32_t)strtoul(value, NULL, 10) * 1000;
2830
0
                                ti = proto_tree_add_time(tree, hf_sip_oc_seq_timestamp, tvb,
2831
0
                                    parameter_name_end + 1, current_offset - parameter_name_end - 1, &ts);
2832
0
                                proto_item_set_generated(ti);
2833
0
                            }
2834
0
                        } else if (sip_via_be_route_handle && g_ascii_strcasecmp(param_name, "be-route") == 0) {
2835
0
                            tvbuff_t* next_tvb;
2836
0
                            next_tvb = tvb_new_subset_length(tvb, parameter_name_end + 1, current_offset - parameter_name_end - 1);
2837
0
                            call_dissector(sip_via_be_route_handle, next_tvb, pinfo, proto_item_add_subtree(via_parameter_item, ett_sip_via_be_route));
2838
0
                        }
2839
0
                    }
2840
0
                    else
2841
0
                    {
2842
0
                        proto_tree_add_item(tree, *(via_parameter->hf_item), tvb,
2843
0
                                            semicolon_offset+1, current_offset-semicolon_offset-1,
2844
0
                                            ENC_UTF_8|ENC_NA);
2845
0
                    }
2846
0
                    break;
2847
0
                }
2848
144
            }
2849
2850
            /* If not matched, just add as text... */
2851
12
            if (i == array_length(via_parameters_hf_array))
2852
12
            {
2853
12
                proto_tree_add_format_text(tree, tvb, semicolon_offset+1, current_offset-semicolon_offset-1);
2854
12
            }
2855
2856
            /* skip Spaces and Tabs */
2857
12
            current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
2858
2859
            /* There may be a comma, followed by more Via entries... */
2860
12
            if (current_offset < line_end_offset)
2861
11
            {
2862
11
                c = tvb_get_uint8(tvb, current_offset);
2863
11
                if (c == ',')
2864
0
                {
2865
                    /* Skip it and get out of parameter loop */
2866
0
                    current_offset++;
2867
0
                    break;
2868
0
                }
2869
11
            }
2870
12
        }
2871
49
    }
2872
45
}
2873
2874
/* Dissect the details of a Session-ID header
2875
 *
2876
 * Session-ID           =  "Session-ID" HCOLON sess-id
2877
 *                         *( SEMI generic-param )
2878
 * sess-id              =  32(DIGIT / %x61-66)  ; 32 chars of [0-9a-f]
2879
 */
2880
static void dissect_sip_session_id_header(tvbuff_t *tvb, proto_tree *tree, int start_offset, int line_end_offset, packet_info *pinfo)
2881
0
{
2882
0
    int current_offset, semi_colon_offset, equals_offset, length, logme_end_offset;
2883
0
    GByteArray *bytes;
2884
0
    proto_item *pi;
2885
2886
0
    current_offset = start_offset;
2887
0
    semi_colon_offset = tvb_find_uint8(tvb, current_offset, line_end_offset-current_offset, ';');
2888
0
    if(semi_colon_offset == -1){
2889
0
        semi_colon_offset = line_end_offset;
2890
0
    }
2891
2892
0
    length = semi_colon_offset-current_offset;
2893
0
    bytes = g_byte_array_sized_new(16);
2894
0
    if (length != 0) {
2895
0
        pi = proto_tree_add_bytes_item(tree, hf_sip_session_id_sess_id, tvb,
2896
0
                                  start_offset, length, ENC_UTF_8|ENC_STR_HEX|ENC_SEP_NONE,
2897
0
                                  bytes, NULL, NULL);
2898
0
    } else {
2899
0
        pi = proto_tree_add_item(tree, hf_sip_session_id_sess_id, tvb,
2900
0
            start_offset, length, ENC_UTF_8 | ENC_STR_HEX | ENC_SEP_NONE);
2901
0
        expert_add_info(pinfo, pi, &ei_sip_session_id_sess_id);
2902
0
    }
2903
2904
0
    current_offset = current_offset + length + 1;
2905
2906
    /* skip Spaces and Tabs */
2907
0
    current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
2908
2909
0
    if (current_offset < line_end_offset) {
2910
        /* Parse parameter and value */
2911
0
        equals_offset = tvb_find_uint8(tvb, current_offset + 1, length, '=');
2912
0
        if (equals_offset != -1) {
2913
            /* Extract the parameter name */
2914
0
            GByteArray *uuid = g_byte_array_sized_new(16);
2915
0
            char *param_name = (char*)tvb_get_string_enc(pinfo->pool, tvb, current_offset,
2916
0
                                                    tvb_skip_wsp_return(tvb, equals_offset - 1) - current_offset,
2917
0
                                                    ENC_UTF_8|ENC_NA);
2918
2919
0
            if ((bytes->len == 16) && (g_ascii_strcasecmp(param_name, "remote") == 0) &&
2920
0
                tvb_get_string_bytes(tvb, equals_offset + 1, line_end_offset - equals_offset - 1,
2921
0
                                     ENC_UTF_8|ENC_STR_HEX|ENC_SEP_NONE, uuid, NULL) &&
2922
0
                (uuid->len == 16)) {
2923
                /* Decode header as draft-ietf-insipid-session-id
2924
                 *
2925
                 * session-id          = "Session-ID" HCOLON session-id-value
2926
                 * session-id-value    = local-uuid *(SEMI sess-id-param)
2927
                 * local-uuid          = sess-uuid / null
2928
                 * remote-uuid         = sess-uuid / null
2929
                 * sess-uuid           = 32(DIGIT / %x61-66)  ;32 chars of [0-9a-f]
2930
                 * sess-id-param       = remote-param / generic-param
2931
                 * remote-param        = "remote" EQUAL remote-uuid
2932
                 * null                = 32("0")
2933
                 */
2934
0
                e_guid_t guid;
2935
2936
0
                proto_item_set_hidden(pi);
2937
0
                guid.data1 = (bytes->data[0] << 24) | (bytes->data[1] << 16) |
2938
0
                             (bytes->data[2] <<  8) |  bytes->data[3];
2939
0
                guid.data2 = (bytes->data[4] <<  8) |  bytes->data[5];
2940
0
                guid.data3 = (bytes->data[6] <<  8) |  bytes->data[7];
2941
0
                memcpy(guid.data4, &bytes->data[8], 8);
2942
0
                proto_tree_add_guid(tree, hf_sip_session_id_local_uuid, tvb,
2943
0
                                    start_offset, semi_colon_offset - start_offset, &guid);
2944
0
                guid.data1 = (uuid->data[0] << 24) | (uuid->data[1] << 16) |
2945
0
                             (uuid->data[2] <<  8) |  uuid->data[3];
2946
0
                guid.data2 = (uuid->data[4] <<  8) |  uuid->data[5];
2947
0
                guid.data3 = (uuid->data[6] <<  8) |  uuid->data[7];
2948
0
                memcpy(guid.data4, &uuid->data[8], 8);
2949
0
                proto_tree_add_guid(tree, hf_sip_session_id_remote_uuid, tvb,
2950
0
                                    equals_offset + 1, line_end_offset - equals_offset - 1, &guid);
2951
             /* Decode logme parameter as per https://tools.ietf.org/html/rfc8497
2952
                *
2953
                * sess-id-param       =/ logme-param
2954
                * logme-param         = "logme"
2955
                */
2956
0
                semi_colon_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, ';');
2957
0
                while(semi_colon_offset != -1){
2958
0
                    current_offset = semi_colon_offset + 1;
2959
0
                    if(current_offset != line_end_offset){
2960
0
                        logme_end_offset = current_offset + 5;
2961
0
                        current_offset = tvb_skip_wsp_return(tvb,semi_colon_offset);
2962
                        /* Extract logme parameter name */
2963
0
                        char *name = (char*)tvb_get_string_enc(pinfo->pool, tvb, current_offset,logme_end_offset - current_offset, ENC_UTF_8|ENC_NA);
2964
0
                        if(g_ascii_strcasecmp(name, "logme") == 0){
2965
0
                             proto_tree_add_boolean(tree, hf_sip_session_id_logme, tvb, current_offset, logme_end_offset - current_offset, 1);
2966
0
                        } else if(current_offset != line_end_offset){
2967
0
                             proto_tree_add_item(tree, hf_sip_session_id_param, tvb, current_offset,line_end_offset - current_offset, ENC_UTF_8);
2968
0
                        }
2969
0
                    }
2970
0
                    semi_colon_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, ';');
2971
0
                }
2972
0
          } else {
2973
                /* Display generic parameter */
2974
0
                proto_tree_add_item(tree, hf_sip_session_id_param, tvb, current_offset,
2975
0
                                    line_end_offset - current_offset, ENC_UTF_8);
2976
0
            }
2977
0
            g_byte_array_free(uuid, true);
2978
0
        } else {
2979
            /* Display generic parameter */
2980
0
            proto_tree_add_item(tree, hf_sip_session_id_param, tvb, current_offset,
2981
0
                                line_end_offset - current_offset, ENC_UTF_8);
2982
0
        }
2983
0
    }
2984
2985
0
    g_byte_array_free(bytes, true);
2986
0
}
2987
2988
/* Dissect the headers for P-Access-Network-Info Headers
2989
 *
2990
 *  Spec found in 3GPP 24.229 7.2A.4
2991
 *  P-Access-Network-Info  = "P-Access-Network-Info" HCOLON
2992
 *  access-net-spec *(COMMA access-net-spec)
2993
 *  access-net-spec        = (access-type / access-class) *(SEMI access-info)
2994
 *  access-type            = "IEEE-802.11" / "IEEE-802.11a" / "IEEE-802.11b" / "IEEE-802.11g" / "IEEE-802.11n" / "3GPP-GERAN" /
2995
 *                           "3GPP-UTRAN-FDD" / "3GPP-UTRAN-TDD" / "3GPP-E-UTRAN-FDD" / "3GPP-E-UTRAN-TDD" / "ADSL" / "ADSL2" /
2996
 *                           "ADSL2+" / "RADSL" / "SDSL" / "HDSL" / "HDSL2" / "G.SHDSL" / "VDSL" / "IDSL" / "3GPP2-1X" /
2997
 *                           "3GPP2-1X-Femto" / "3GPP2-1X-HRPD" / "3GPP2-UMB" / "DOCSIS" / "IEEE-802.3" / "IEEE-802.3a" /
2998
 *                           "IEEE-802.3e" / "IEEE-802.3i" / "IEEE-802.3j" / "IEEE-802.3u" / "IEEE-802.3ab"/ "IEEE-802.3ae" /
2999
 *                           "IEEE-802.3ak" / "IEEE-802.3aq" / "IEEE-802.3an" / "IEEE-802.3y" / "IEEE-802.3z" / "GPON" /
3000
                             "XGPON1" / "GSTN"/ token
3001
 *  access-class           = "3GPP-GERAN" / "3GPP-UTRAN" / "3GPP-E-UTRAN" / "3GPP-WLAN" / "3GPP-GAN" / "3GPP-HSPA" / token
3002
 *  np                     = "network-provided"
3003
 *  access-info            = cgi-3gpp / utran-cell-id-3gpp / dsl-location / i-wlan-node-id / ci-3gpp2 / ci-3gpp2-femto /
3004
                             eth-location / fiber-location / np / gstn-location / extension-access-info
3005
 *  extension-access-info  = gen-value
3006
 *  cgi-3gpp               = "cgi-3gpp" EQUAL (token / quoted-string)
3007
 *  utran-cell-id-3gpp     = "utran-cell-id-3gpp" EQUAL (token / quoted-string)
3008
 *  i-wlan-node-id         = "i-wlan-node-id" EQUAL (token / quoted-string)
3009
 *  dsl-location           = "dsl-location" EQUAL (token / quoted-string)
3010
 *  eth-location           = "eth-location" EQUAL (token / quoted-string)
3011
 *  fiber-location         = "fiber-location" EQUAL (token / quoted-string)
3012
 *  ci-3gpp2               = "ci-3gpp2" EQUAL (token / quoted-string)
3013
 *  ci-3gpp2-femto         = "ci-3gpp2-femto" EQUAL (token / quoted-string)
3014
 *  gstn-location          = "gstn-location" EQUAL (token / quoted-string)
3015
 *
3016
 */
3017
void dissect_sip_p_access_network_info_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int start_offset, int line_end_offset)
3018
0
{
3019
3020
0
    int   current_offset, semi_colon_offset, length, par_name_end_offset, equals_offset;
3021
3022
    /* skip Spaces and Tabs */
3023
0
    start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
3024
3025
0
    if (start_offset >= line_end_offset)
3026
0
    {
3027
        /* Nothing to parse */
3028
0
        return;
3029
0
    }
3030
3031
    /* Get the Access Type / Access Class*/
3032
0
    current_offset = start_offset;
3033
0
    semi_colon_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, ';');
3034
3035
0
    if (semi_colon_offset == -1)
3036
0
        return;
3037
3038
0
    length = semi_colon_offset - current_offset;
3039
0
    proto_tree_add_item(tree, hf_sip_p_acc_net_i_acc_type, tvb, start_offset, length, ENC_UTF_8);
3040
3041
0
    current_offset = current_offset + length + 1;
3042
3043
3044
0
    while (current_offset < line_end_offset){
3045
0
        char *param_name = NULL;
3046
3047
        /* skip Spaces and Tabs */
3048
0
        current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
3049
3050
0
        semi_colon_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, ';');
3051
3052
0
        if (semi_colon_offset == -1){
3053
0
            semi_colon_offset = line_end_offset;
3054
0
        }
3055
3056
0
        length = semi_colon_offset - current_offset;
3057
3058
        /* Parse parameter and value */
3059
0
        equals_offset = tvb_find_uint8(tvb, current_offset + 1, length, '=');
3060
0
        if (equals_offset != -1){
3061
            /* Has value part */
3062
0
            par_name_end_offset = equals_offset;
3063
            /* Extract the parameter name */
3064
0
            param_name = (char*)tvb_get_string_enc(pinfo->pool, tvb, current_offset, par_name_end_offset - current_offset, ENC_UTF_8 | ENC_NA);
3065
            /* Access-Info fields  */
3066
0
            if ((param_name != NULL)&&(g_ascii_strcasecmp(param_name, "utran-cell-id-3gpp") == 0)) {
3067
0
                proto_tree_add_item(tree, hf_sip_p_acc_net_i_ucid_3gpp, tvb,
3068
0
                    equals_offset + 1, semi_colon_offset - equals_offset - 1, ENC_UTF_8);
3069
                /* check if value is quoted */
3070
0
                if (tvb_get_uint8(tvb, equals_offset + 1) == '"') {
3071
0
                    dissect_e212_mcc_mnc_in_utf8_address(tvb, pinfo, tree, equals_offset + 2);
3072
0
                } else {
3073
0
                    dissect_e212_mcc_mnc_in_utf8_address(tvb, pinfo, tree, equals_offset + 1);
3074
0
                }
3075
0
            }
3076
0
            else {
3077
0
                proto_tree_add_format_text(tree, tvb, current_offset, length);
3078
0
            }
3079
0
        }
3080
0
        else {
3081
0
            proto_tree_add_format_text(tree, tvb, current_offset, length);
3082
0
        }
3083
3084
0
        current_offset = semi_colon_offset + 1;
3085
0
    }
3086
0
}
3087
3088
/*
3089
The syntax for the P-Charging-Vector header field is described as
3090
follows:
3091
3092
    P-Charging-Vector  = "P-Charging-Vector" HCOLON icid-value
3093
    *(SEMI charge-params)
3094
    charge-params      = icid-gen-addr / orig-ioi / term-ioi /
3095
    transit-ioi / related-icid /
3096
    related-icid-gen-addr / generic-param
3097
    icid-value                = "icid-value" EQUAL gen-value
3098
    icid-gen-addr             = "icid-generated-at" EQUAL host
3099
    orig-ioi                  = "orig-ioi" EQUAL gen-value
3100
    term-ioi                  = "term-ioi" EQUAL gen-value
3101
    transit-ioi               = "transit-ioi" EQUAL transit-ioi-list
3102
    transit-ioi-list          = DQUOTE transit-ioi-param
3103
    *(COMMA transit-ioi-param) DQUOTE
3104
    transit-ioi-param         = transit-ioi-indexed-value /
3105
    transit-ioi-void-value
3106
    transit-ioi-indexed-value = transit-ioi-name "."
3107
    transit-ioi-index
3108
    transit-ioi-name          = ALPHA *(ALPHA / DIGIT)
3109
    transit-ioi-index         = 1*DIGIT
3110
    transit-ioi-void-value    = "void"
3111
    related-icid              = "related-icid" EQUAL gen-value
3112
    related-icid-gen-addr     = "related-icid-generated-at" EQUAL host
3113
*/
3114
static void
3115
dissect_sip_p_charging_vector_header(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int start_offset, int line_end_offset)
3116
0
{
3117
3118
0
    int   current_offset, semi_colon_offset, length, equals_offset;
3119
3120
    /* skip Spaces and Tabs */
3121
0
    start_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
3122
3123
0
    if (start_offset >= line_end_offset)
3124
0
    {
3125
        /* Nothing to parse */
3126
0
        return;
3127
0
    }
3128
3129
    /* icid-value                = "icid-value" EQUAL gen-value */
3130
0
    current_offset = start_offset;
3131
0
    semi_colon_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, ';');
3132
3133
0
    if (semi_colon_offset == -1) {
3134
        /* No parameters, is that allowed?*/
3135
0
        semi_colon_offset = line_end_offset;
3136
0
    }
3137
3138
0
    length = semi_colon_offset - current_offset;
3139
3140
    /* Parse parameter and value */
3141
0
    equals_offset = tvb_find_uint8(tvb, current_offset + 1, length, '=');
3142
0
    if (equals_offset == -1) {
3143
        /* Does not conform to ABNF */
3144
0
        return;
3145
0
    }
3146
3147
    /* Get the icid-value */
3148
0
    proto_tree_add_item(tree, hf_sip_icid_value, tvb,
3149
0
        equals_offset + 1, semi_colon_offset - equals_offset - 1, ENC_UTF_8);
3150
3151
0
    current_offset = semi_colon_offset + 1;
3152
3153
    /* Add the rest of the parameters to the tree */
3154
0
    while (current_offset < line_end_offset) {
3155
0
        char *param_name = NULL;
3156
0
        int par_name_end_offset;
3157
        /* skip Spaces and Tabs */
3158
0
        current_offset = tvb_skip_wsp(tvb, current_offset, line_end_offset - current_offset);
3159
3160
0
        semi_colon_offset = tvb_find_uint8(tvb, current_offset, line_end_offset - current_offset, ';');
3161
3162
0
        if (semi_colon_offset == -1) {
3163
0
            semi_colon_offset = line_end_offset;
3164
0
        }
3165
3166
0
        length = semi_colon_offset - current_offset;
3167
3168
        /* Parse parameter and value */
3169
0
        equals_offset = tvb_find_uint8(tvb, current_offset + 1, length, '=');
3170
0
        if (equals_offset != -1) {
3171
            /* Has value part */
3172
0
            par_name_end_offset = equals_offset;
3173
            /* Extract the parameter name */
3174
0
            param_name = (char*)tvb_get_string_enc(pinfo->pool, tvb, current_offset, par_name_end_offset - current_offset, ENC_UTF_8 | ENC_NA);
3175
            /* charge-params */
3176
0
            if ((param_name != NULL) && (g_ascii_strcasecmp(param_name, "icid-gen-addr") == 0)) {
3177
0
                proto_tree_add_item(tree, hf_sip_icid_gen_addr, tvb,
3178
0
                    equals_offset + 1, semi_colon_offset - equals_offset - 1, ENC_UTF_8);
3179
0
            }
3180
0
            else {
3181
0
                proto_tree_add_format_text(tree, tvb, current_offset, length);
3182
0
            }
3183
0
        }
3184
0
        else {
3185
0
            proto_tree_add_format_text(tree, tvb, current_offset, length);
3186
0
        }
3187
3188
0
        current_offset = semi_colon_offset + 1;
3189
0
    }
3190
3191
3192
0
}
3193
3194
/*
3195
https://tools.ietf.org/html/rfc6809
3196
The ABNF for the Feature-Caps header fields is:
3197
3198
Feature-Caps = "Feature-Caps" HCOLON fc-value
3199
*(COMMA fc-value)
3200
fc-value     = "*" *(SEMI feature-cap)
3201
3202
The ABNF for the feature-capability indicator is:
3203
3204
feature-cap       =  "+" fcap-name [EQUAL LDQUOT (fcap-value-list
3205
/ fcap-string-value ) RDQUOT]
3206
fcap-name         =  ftag-name
3207
fcap-value-list   =  tag-value-list
3208
fcap-string-value =  string-value
3209
;; ftag-name, tag-value-list, string-value defined in RFC 3840
3210
3211
NOTE: In comparison with media feature tags, the "+" sign in front of
3212
the feature-capability indicator name is mandatory.
3213
3214
*/
3215
static void
3216
dissect_sip_p_feature_caps(tvbuff_t *tvb, proto_tree *tree, int start_offset, int line_end_offset)
3217
0
{
3218
0
    int current_offset, next_offset, length;
3219
0
    uint16_t semi_plus = 0x3b2b;
3220
3221
    /* skip Spaces and Tabs */
3222
0
    next_offset = tvb_skip_wsp(tvb, start_offset, line_end_offset - start_offset);
3223
3224
0
    if (next_offset >= line_end_offset) {
3225
        /* Nothing to parse */
3226
0
        return;
3227
0
    }
3228
3229
0
    while (next_offset < line_end_offset) {
3230
        /* Find the end of feature cap or start of feature cap parameter, ";+" should indicate the start of a new feature-cap */
3231
0
        current_offset = next_offset;
3232
0
        next_offset = tvb_find_uint16(tvb, current_offset, line_end_offset - current_offset, semi_plus);
3233
0
        if (next_offset == -1) {
3234
0
            length = line_end_offset - current_offset;
3235
0
            next_offset = line_end_offset;
3236
0
        }
3237
0
        else {
3238
0
            length = next_offset - current_offset;
3239
0
            next_offset += 2;
3240
0
        }
3241
0
        proto_tree_add_item(tree, hf_sip_feature_cap, tvb, current_offset, length, ENC_UTF_8);
3242
0
    }
3243
0
}
3244
3245
/* Code to actually dissect the packets */
3246
static int
3247
dissect_sip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
3248
9
{
3249
9
    uint8_t octet;
3250
9
    int len;
3251
9
    int remaining_length;
3252
3253
9
    octet = tvb_get_uint8(tvb,0);
3254
9
    if ((octet  & 0xf8) == 0xf8){
3255
1
        call_dissector(sigcomp_handle, tvb, pinfo, tree);
3256
1
        return tvb_reported_length(tvb);
3257
1
    }
3258
3259
8
    remaining_length = tvb_reported_length(tvb);
3260
8
    len = dissect_sip_common(tvb, 0, remaining_length, pinfo, tree, false, false);
3261
8
    if (len < 0)
3262
8
        return 0;   /* not SIP */
3263
0
    else
3264
0
        return len;
3265
8
}
3266
3267
static int
3268
dissect_sip_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
3269
0
{
3270
0
    uint8_t octet;
3271
0
    int offset = 0, linelen;
3272
0
    int len;
3273
0
    int remaining_length;
3274
3275
0
    octet = tvb_get_uint8(tvb,0);
3276
0
    if ((octet  & 0xf8) == 0xf8){
3277
0
        call_dissector(sigcomp_handle, tvb, pinfo, tree);
3278
0
        return tvb_reported_length(tvb);
3279
0
    }
3280
3281
0
    remaining_length = tvb_reported_length(tvb);
3282
    /* If we have exactly one non printable byte of payload, this is
3283
     * probably just a keep alive at the beginning of a capture. Better
3284
     * to treat it as such than to mark it and everything up to the next
3285
     * line end as Continuation Data.
3286
     */
3287
0
    if (remaining_length == 1 && !g_ascii_isprint(octet)) {
3288
0
        return 0;
3289
0
    }
3290
    /* Check if we have enough data or if we need another segment, as a safety measure set a length limit*/
3291
0
    if (remaining_length < 1500){
3292
0
        linelen = tvb_find_line_end(tvb, offset, remaining_length, NULL, true);
3293
0
        if (linelen == -1){
3294
0
            pinfo->desegment_offset = offset;
3295
0
            pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
3296
0
            return -1;
3297
0
        }
3298
0
    }
3299
0
    len = dissect_sip_common(tvb, offset, remaining_length, pinfo, tree, true, true);
3300
0
    if (len <= 0)
3301
0
        return len;
3302
0
    offset += len;
3303
0
    remaining_length = remaining_length - len;
3304
3305
    /*
3306
     * This is a bit of a cludge as the TCP dissector does not call the dissectors again if not all
3307
     * the data in the segment was dissected and we do not know if we need another segment or not.
3308
     * so DESEGMENT_ONE_MORE_SEGMENT can't be used in all cases.
3309
     *
3310
     */
3311
0
    while (remaining_length > 0) {
3312
        /* Check if we have enough data or if we need another segment, as a safety measure set a length limit*/
3313
0
        if (remaining_length < 1500){
3314
0
            linelen = tvb_find_line_end(tvb, offset, remaining_length, NULL, true);
3315
0
            if (linelen == -1){
3316
0
                pinfo->desegment_offset = offset;
3317
0
                pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
3318
0
                return -1;
3319
0
            }
3320
0
        }
3321
0
        len = dissect_sip_common(tvb, offset, remaining_length, pinfo, tree, true, true);
3322
0
        if (len <= 0)
3323
0
            return len;
3324
0
        offset += len;
3325
0
        remaining_length = remaining_length - len;
3326
0
    }
3327
0
    return offset;
3328
0
}
3329
3330
static bool
3331
dissect_sip_tcp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
3332
3.28k
{
3333
3.28k
    int offset = 0;
3334
3.28k
    int len;
3335
3.28k
    bool first = true;
3336
3.28k
    int remaining_length;
3337
3338
3.28k
    remaining_length = tvb_captured_length(tvb);
3339
3.28k
    while (remaining_length > 0) {
3340
3.28k
        len = dissect_sip_common(tvb, offset, remaining_length, pinfo, tree, !first, true);
3341
3.28k
        if (len == -2) {
3342
3.28k
            if (first) {
3343
                /*
3344
                 * If the first packet doesn't start with
3345
                 * a valid SIP request or response, don't
3346
                 * treat this as SIP.
3347
                 */
3348
3.28k
                return false;
3349
3.28k
            }
3350
0
            break;
3351
3.28k
        }
3352
0
        if (len == -1)
3353
0
            break;  /* need more data */
3354
0
        offset += len;
3355
0
        remaining_length = remaining_length - len;
3356
0
        first = false;
3357
0
    }
3358
0
    return true;
3359
3.28k
}
3360
3361
static bool
3362
dissect_sip_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
3363
2.04k
{
3364
2.04k
    int remaining_length = tvb_captured_length(tvb);
3365
3366
2.04k
    return dissect_sip_common(tvb, 0, remaining_length, pinfo, tree, false, false) > 0;
3367
2.04k
}
3368
3369
static int
3370
dissect_sip_common(tvbuff_t *tvb, int offset, int remaining_length, packet_info *pinfo, proto_tree *tree,
3371
    bool dissect_other_as_continuation, bool use_reassembly)
3372
5.32k
{
3373
5.32k
    int orig_offset, body_offset;
3374
5.32k
    int next_offset, linelen;
3375
5.32k
    int datalen, reported_datalen;
3376
5.32k
    uint32_t content_length;
3377
5.32k
    bool content_length_valid;
3378
5.32k
    line_type_t line_type;
3379
5.32k
    tvbuff_t *next_tvb;
3380
5.32k
    bool is_known_request;
3381
5.32k
    int found_match = 0;
3382
5.32k
    const char *descr;
3383
5.32k
    unsigned token_1_len = 0;
3384
5.32k
    unsigned current_method_idx = SIP_METHOD_INVALID;
3385
5.32k
    proto_item *ts, *ti_a = NULL, *th = NULL;
3386
5.32k
    proto_tree *sip_tree, *reqresp_tree      = NULL, *hdr_tree  = NULL,
3387
5.32k
        *message_body_tree = NULL, *cseq_tree = NULL,
3388
5.32k
        *via_tree         = NULL, *reason_tree       = NULL, *rack_tree = NULL,
3389
5.32k
        *route_tree       = NULL, *security_client_tree = NULL, *session_id_tree = NULL,
3390
5.32k
        *p_access_net_info_tree = NULL;
3391
5.32k
    unsigned char contacts = 0, contact_is_star = 0, expires_is_0 = 0, contacts_expires_0 = 0, contacts_expires_unknown = 0;
3392
5.32k
    uint32_t cseq_number = 0;
3393
5.32k
    unsigned char  cseq_number_set = 0;
3394
5.32k
    const char *cseq_method = "";
3395
5.32k
    char   *call_id = NULL;
3396
5.32k
    char   *media_type_str_lower_case = NULL;
3397
5.32k
    media_content_info_t content_info = { MEDIA_CONTAINER_SIP_DATA, NULL, NULL, NULL };
3398
5.32k
    char   *content_encoding_parameter_str = NULL;
3399
5.32k
    unsigned   resend_for_packet = 0;
3400
5.32k
    unsigned   request_for_response = 0;
3401
5.32k
    uint32_t response_time = 0;
3402
5.32k
    int     strlen_to_copy;
3403
5.32k
    heur_dtbl_entry_t *hdtbl_entry;
3404
3405
    /*
3406
     * If this should be a request of response, do this quick check to see if
3407
     * it begins with a string...
3408
     * Otherwise, SIP heuristics are expensive...
3409
     *
3410
     */
3411
3412
5.32k
    if (!dissect_other_as_continuation &&
3413
5.32k
        ((remaining_length < 1) || !g_ascii_isprint(tvb_get_uint8(tvb, offset))))
3414
3.36k
    {
3415
3.36k
        return -2;
3416
3.36k
    }
3417
3418
    /*
3419
     * Note that "tvb_find_line_end()" will return a value that
3420
     * is not longer than what's in the buffer, so the
3421
     * "tvb_get_ptr()" calls below won't throw exceptions.
3422
     *
3423
     * Note that "tvb_strneql()" doesn't throw exceptions, so
3424
     * "sip_parse_line()" won't throw an exception.
3425
     */
3426
1.96k
    orig_offset = offset;
3427
1.96k
    linelen = tvb_find_line_end(tvb, offset, remaining_length, &next_offset, false);
3428
1.96k
    if(linelen==0){
3429
0
        return -2;
3430
0
    }
3431
3432
1.96k
    if (tvb_strnlen(tvb, offset, linelen) > -1)
3433
1.39k
    {
3434
        /*
3435
         * There's a NULL in the line,
3436
         * this may be SIP within another protocol.
3437
         * This heuristic still needs to improve.
3438
         */
3439
1.39k
        return -2;
3440
1.39k
    }
3441
565
    line_type = sip_parse_line(tvb, offset, linelen, &token_1_len);
3442
3443
565
    if (line_type == OTHER_LINE) {
3444
        /*
3445
         * This is neither a SIP request nor response.
3446
         */
3447
462
        if (!dissect_other_as_continuation) {
3448
            /*
3449
             * We were asked to reject this.
3450
             */
3451
462
            return -2;
3452
462
        }
3453
3454
        /*
3455
         * Just dissect it as a continuation.
3456
         */
3457
462
    } else if ((use_reassembly)&&( pinfo->ptype == PT_TCP)) {
3458
        /*
3459
         * Yes, it's a request or response.
3460
         * Do header desegmentation if we've been told to,
3461
         * and do body desegmentation if we've been told to and
3462
         * we find a Content-Length header.
3463
         *
3464
         * RFC 6594, Section 20.14. requires Content-Length for TCP.
3465
         */
3466
0
        if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo,
3467
0
            sip_desegment_headers, sip_desegment_body, false, NULL,
3468
0
            NULL, NULL)) {
3469
            /*
3470
             * More data needed for desegmentation.
3471
             */
3472
0
            return -1;
3473
0
        }
3474
0
    }
3475
3476
    /* Initialise stat info for passing to tap
3477
     * Note: this isn't _only_ for taps - internal code here uses it too
3478
     * also store stat info in proto_data for subdissectors
3479
     */
3480
103
    stat_info = wmem_new0(pinfo->pool, sip_info_value_t);
3481
103
    p_add_proto_data(pinfo->pool, pinfo, proto_sip, pinfo->curr_layer_num, stat_info);
3482
3483
103
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "SIP");
3484
3485
103
    if (!pinfo->flags.in_error_pkt && have_tap_listener(exported_pdu_tap)) {
3486
0
        wmem_list_frame_t *cur;
3487
0
        unsigned proto_id;
3488
0
        const char *proto_name;
3489
0
        void *tmp;
3490
3491
        /* For SIP messages with other sip messages embedded in the body, don't export those individually.
3492
         * E.g. if we are called from the mime_multipart dissector don't export the message.
3493
         */
3494
0
        cur = wmem_list_frame_prev(wmem_list_tail(pinfo->layers));
3495
0
        tmp = wmem_list_frame_data(cur);
3496
0
        proto_id = GPOINTER_TO_UINT(tmp);
3497
0
        proto_name = proto_get_protocol_filter_name(proto_id);
3498
0
        if (strcmp(proto_name, "mime_multipart") != 0) {
3499
0
            export_sip_pdu(pinfo, tvb);
3500
0
        }
3501
0
    }
3502
3503
103
    DPRINT2(("------------------------------ dissect_sip_common ------------------------------"));
3504
3505
103
    switch (line_type) {
3506
3507
103
    case REQUEST_LINE:
3508
103
        is_known_request = sip_is_known_request(tvb, pinfo, offset, token_1_len, &current_method_idx);
3509
103
        descr = is_known_request ? "Request" : "Unknown request";
3510
103
        col_add_lstr(pinfo->cinfo, COL_INFO,
3511
103
                     descr, ": ",
3512
103
                     tvb_format_text(pinfo->pool, tvb, offset, linelen - SIP2_HDR_LEN - 1),
3513
103
                     COL_ADD_LSTR_TERMINATOR);
3514
103
        DPRINT(("got %s: %s", descr,
3515
103
                tvb_format_text(pinfo->pool, tvb, offset, linelen - SIP2_HDR_LEN - 1)));
3516
103
        break;
3517
3518
0
    case STATUS_LINE:
3519
0
        descr = "Status";
3520
0
        col_add_lstr(pinfo->cinfo, COL_INFO,
3521
0
                     "Status: ",
3522
0
                     tvb_format_text(pinfo->pool, tvb, offset + SIP2_HDR_LEN + 1, linelen - SIP2_HDR_LEN - 1),
3523
0
                     COL_ADD_LSTR_TERMINATOR);
3524
0
        stat_info->reason_phrase = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset + SIP2_HDR_LEN + 5,
3525
0
                                                      linelen - (SIP2_HDR_LEN + 5),ENC_UTF_8|ENC_NA);
3526
0
        DPRINT(("got Response: %s",
3527
0
                tvb_format_text(pinfo->pool, tvb, offset + SIP2_HDR_LEN + 1, linelen - SIP2_HDR_LEN - 1)));
3528
0
        break;
3529
3530
0
    case OTHER_LINE:
3531
0
    default: /* Squelch compiler complaints */
3532
0
        descr = "Continuation";
3533
0
        col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
3534
0
        DPRINT(("got continuation"));
3535
0
        break;
3536
103
    }
3537
3538
103
    ts = proto_tree_add_item(tree, proto_sip, tvb, offset, -1, ENC_NA);
3539
103
    sip_tree = proto_item_add_subtree(ts, ett_sip);
3540
3541
103
    switch (line_type) {
3542
3543
103
    case REQUEST_LINE:
3544
103
        if (sip_tree) {
3545
103
            ti_a = proto_tree_add_item(sip_tree, hf_Request_Line, tvb,
3546
103
                        offset, linelen, ENC_UTF_8);
3547
3548
103
            reqresp_tree = proto_item_add_subtree(ti_a, ett_sip_reqresp);
3549
103
        }
3550
103
        dfilter_sip_request_line(tvb, reqresp_tree, pinfo, offset, token_1_len, linelen);
3551
103
        break;
3552
3553
0
    case STATUS_LINE:
3554
0
        if (sip_tree) {
3555
0
            ti_a = proto_tree_add_item(sip_tree, hf_sip_Status_Line, tvb,
3556
0
                        offset, linelen, ENC_UTF_8);
3557
0
            reqresp_tree = proto_item_add_subtree(ti_a, ett_sip_reqresp);
3558
0
        }
3559
0
        dfilter_sip_status_line(tvb, reqresp_tree, pinfo, linelen, offset);
3560
0
        break;
3561
3562
0
    case OTHER_LINE:
3563
0
        if (sip_tree) {
3564
0
            reqresp_tree = proto_tree_add_subtree_format(sip_tree, tvb, offset, next_offset,
3565
0
                                     ett_sip_reqresp, NULL, "%s line: %s", descr,
3566
0
                                     tvb_format_text(pinfo->pool, tvb, offset, linelen));
3567
            /* XXX: Is adding to 'reqresp_tree as intended ? Changed from original 'sip_tree' */
3568
0
            proto_tree_add_item(reqresp_tree, hf_sip_continuation, tvb, offset, -1, ENC_NA);
3569
0
        }
3570
0
        return remaining_length;
3571
103
    }
3572
3573
103
    remaining_length = remaining_length - (next_offset - offset);
3574
103
    offset = next_offset;
3575
3576
103
    body_offset = offset;
3577
3578
    /*
3579
     * Find the blank line separating the headers from the message body.
3580
     * Do this now so we can add the msg_hdr FT_STRING item with the correct
3581
     * length.
3582
     */
3583
937
    while (remaining_length > 0) {
3584
844
        int line_end_offset;
3585
844
        unsigned char c;
3586
3587
844
        linelen = tvb_find_line_end(tvb, body_offset, -1, &next_offset, false);
3588
844
        if (linelen == 0) {
3589
            /*
3590
             * This is a blank line separating the
3591
             * message header from the message body.
3592
             */
3593
10
            body_offset = next_offset;
3594
10
            break;
3595
10
        }
3596
3597
834
        line_end_offset = body_offset + linelen;
3598
834
        if(tvb_reported_length_remaining(tvb, next_offset) > 0){
3599
795
            while (tvb_offset_exists(tvb, next_offset) && ((c = tvb_get_uint8(tvb, next_offset)) == ' ' || c == '\t'))
3600
51
            {
3601
                /*
3602
                 * This line end is not a header separator.
3603
                 * It just extends the header with another line.
3604
                 * Look for next line end:
3605
                 */
3606
51
                linelen += (next_offset - line_end_offset);
3607
51
                linelen += tvb_find_line_end(tvb, next_offset, -1, &next_offset, false);
3608
51
                line_end_offset = body_offset + linelen;
3609
51
            }
3610
744
        }
3611
834
        remaining_length = remaining_length - (next_offset - body_offset);
3612
834
        body_offset = next_offset;
3613
834
    }/* End while */
3614
3615
103
    remaining_length += (body_offset - offset);
3616
3617
103
    th = proto_tree_add_item(sip_tree, hf_sip_msg_hdr, tvb, offset,
3618
103
                                 body_offset - offset, ENC_UTF_8);
3619
103
    hdr_tree = proto_item_add_subtree(th, ett_sip_hdr);
3620
3621
103
    if (have_tap_listener(sip_follow_tap))
3622
0
        tap_queue_packet(sip_follow_tap, pinfo, tvb);
3623
3624
    /*
3625
     * Process the headers - if we're not building a protocol tree,
3626
     * we just do this to find the blank line separating the
3627
     * headers from the message body.
3628
     */
3629
103
    content_length_valid = false;
3630
925
    while (remaining_length > 0) {
3631
844
        int line_end_offset;
3632
844
        int colon_offset;
3633
844
        int semi_colon_offset;
3634
844
        int parameter_offset;
3635
844
        int parameter_end_offset;
3636
844
        int parameter_len;
3637
844
        int content_type_len, content_type_parameter_str_len;
3638
844
        int header_len;
3639
844
        char *header_name;
3640
844
        dissector_handle_t ext_hdr_handle;
3641
844
        int hf_index;
3642
844
        int value_offset;
3643
844
        int sub_value_offset;
3644
844
        int comma_offset;
3645
844
        unsigned char c;
3646
844
        int value_len;
3647
844
        bool is_no_header_termination = false;
3648
844
        proto_tree *tc_uri_item_tree = NULL;
3649
844
        uri_offset_info uri_offsets;
3650
3651
844
        linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, false);
3652
844
        if (linelen == 0) {
3653
            /*
3654
             * This is a blank line separating the
3655
             * message header from the message body.
3656
             */
3657
10
            offset = next_offset;
3658
10
            break;
3659
10
        }
3660
3661
834
        line_end_offset = offset + linelen;
3662
834
        if(tvb_reported_length_remaining(tvb, next_offset) <= 0){
3663
90
            is_no_header_termination = true;
3664
744
        }else{
3665
795
            while (tvb_offset_exists(tvb, next_offset) && ((c = tvb_get_uint8(tvb, next_offset)) == ' ' || c == '\t'))
3666
51
            {
3667
                /*
3668
                 * This line end is not a header separator.
3669
                 * It just extends the header with another line.
3670
                 * Look for next line end:
3671
                 */
3672
51
                linelen += (next_offset - line_end_offset);
3673
51
                linelen += tvb_find_line_end(tvb, next_offset, -1, &next_offset, false);
3674
51
                line_end_offset = offset + linelen;
3675
51
            }
3676
744
        }
3677
834
        colon_offset = tvb_find_uint8(tvb, offset, linelen, ':');
3678
834
        if (colon_offset == -1) {
3679
            /*
3680
             * Malformed header - no colon after the name.
3681
             */
3682
175
            expert_add_info(pinfo, th, &ei_sip_header_no_colon);
3683
659
        } else {
3684
659
            header_len = colon_offset - offset;
3685
659
            header_name = (char*)tvb_get_string_enc(pinfo->pool, tvb, offset, header_len, ENC_UTF_8|ENC_NA);
3686
659
            ascii_strdown_inplace(header_name);
3687
659
            hf_index = sip_is_known_sip_header(header_name, header_len);
3688
3689
            /*
3690
             * Skip whitespace after the colon.
3691
             */
3692
659
            value_offset = tvb_skip_wsp(tvb, colon_offset + 1, line_end_offset - (colon_offset + 1));
3693
3694
659
            value_len = (int) (line_end_offset - value_offset);
3695
3696
659
            if (hf_index == -1) {
3697
189
                int *hf_ptr = NULL;
3698
189
                if (sip_custom_header_fields_hash) {
3699
0
                    hf_ptr = (int*)g_hash_table_lookup(sip_custom_header_fields_hash, header_name);
3700
0
                }
3701
189
                if (hf_ptr) {
3702
0
                    sip_proto_tree_add_string(hdr_tree, pinfo->pool, *hf_ptr, tvb, offset,
3703
0
                                              next_offset - offset, value_offset, value_len);
3704
189
                } else {
3705
189
                    proto_item *ti_c;
3706
189
                    proto_tree *ti_tree = proto_tree_add_subtree(hdr_tree, tvb,
3707
189
                                                         offset, next_offset - offset, ett_sip_ext_hdr, &ti_c,
3708
189
                                                         tvb_format_text(pinfo->pool, tvb, offset, linelen));
3709
3710
189
                    ext_hdr_handle = dissector_get_string_handle(ext_hdr_subdissector_table, header_name);
3711
189
                    if (ext_hdr_handle != NULL) {
3712
0
                        tvbuff_t *next_tvb2;
3713
0
                        next_tvb2 = tvb_new_subset_length(tvb, value_offset, value_len);
3714
0
                        dissector_try_string_with_data(ext_hdr_subdissector_table, header_name, next_tvb2, pinfo, ti_tree, true, NULL);
3715
189
                    } else {
3716
189
                        expert_add_info_format(pinfo, ti_c, &ei_sip_unrecognized_header,
3717
189
                                               "Unrecognised SIP header (%s)",
3718
189
                                               header_name);
3719
189
                    }
3720
189
                }
3721
470
            } else {
3722
470
                proto_item *sip_element_item;
3723
470
                proto_tree *sip_element_tree;
3724
3725
                /*
3726
                 * Add it to the protocol tree,
3727
                 * but display the line as is.
3728
                 */
3729
470
                switch ( hf_index ) {
3730
3731
0
                    case POS_TO :
3732
3733
                        /*if(hdr_tree)*/ {
3734
0
                            proto_item *item;
3735
3736
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
3737
0
                                               hf_header_array[hf_index], tvb,
3738
0
                                               offset, next_offset - offset,
3739
0
                                               value_offset, value_len);
3740
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
3741
3742
0
                            sip_element_tree = proto_item_add_subtree( sip_element_item,
3743
0
                                               ett_sip_element);
3744
                            /* To        =  ( "To" / "t" ) HCOLON ( name-addr
3745
                             *               / addr-spec ) *( SEMI to-param )
3746
                             */
3747
0
                            sip_uri_offset_init(&uri_offsets);
3748
0
                            if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1){
3749
0
                                display_sip_uri(tvb, sip_element_tree, pinfo, &uri_offsets, &sip_to_uri);
3750
0
                                if((uri_offsets.name_addr_start != -1) && (uri_offsets.name_addr_end != -1)){
3751
0
                                    stat_info->tap_to_addr = (char*)tvb_get_string_enc(pinfo->pool, tvb, uri_offsets.name_addr_start,
3752
0
                                        uri_offsets.name_addr_end - uri_offsets.name_addr_start + 1, ENC_UTF_8|ENC_NA);
3753
0
                                }
3754
0
                                offset = uri_offsets.name_addr_end +1;
3755
0
                            }
3756
3757
                            /* Find parameter tag if present.
3758
                             * TODO make this generic to find any interesting parameter
3759
                             * use the same method as for SIP headers ?
3760
                             */
3761
3762
0
                            parameter_offset = offset;
3763
0
                            while (parameter_offset < line_end_offset
3764
0
                                   && (tvb_strneql(tvb, parameter_offset, "tag=", 4) != 0))
3765
0
                                parameter_offset++;
3766
3767
0
                            if ( parameter_offset < line_end_offset ){ /* Tag found */
3768
0
                                parameter_offset = parameter_offset + 4;
3769
0
                                parameter_end_offset = tvb_find_uint8(tvb, parameter_offset,
3770
0
                                                                       (line_end_offset - parameter_offset), ';');
3771
0
                                if ( parameter_end_offset == -1)
3772
0
                                    parameter_end_offset = line_end_offset;
3773
0
                                parameter_len = parameter_end_offset - parameter_offset;
3774
0
                                proto_tree_add_item(sip_element_tree, hf_sip_to_tag, tvb, parameter_offset,
3775
0
                                                    parameter_len, ENC_UTF_8);
3776
0
                                item = proto_tree_add_item(sip_element_tree, hf_sip_tag, tvb, parameter_offset,
3777
0
                                                           parameter_len, ENC_UTF_8);
3778
0
                                proto_item_set_hidden(item);
3779
3780
                                /* Tag indicates in-dialog messages, in case we have a INVITE, SUBSCRIBE or REFER, mark it */
3781
0
                                switch (current_method_idx) {
3782
3783
0
                                case SIP_METHOD_INVITE:
3784
0
                                case SIP_METHOD_SUBSCRIBE:
3785
0
                                case SIP_METHOD_REFER:
3786
0
                                    col_append_str(pinfo->cinfo, COL_INFO, ", in-dialog");
3787
0
                                    break;
3788
0
                                }
3789
0
                            }
3790
0
                        } /* if hdr_tree */
3791
0
                    break;
3792
3793
0
                    case POS_FROM :
3794
0
                        /*if(hdr_tree)*/ {
3795
0
                            proto_item *item;
3796
3797
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
3798
0
                                               hf_header_array[hf_index], tvb,
3799
0
                                               offset, next_offset - offset,
3800
0
                                               value_offset, value_len);
3801
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
3802
3803
0
                            sip_element_tree = proto_item_add_subtree( sip_element_item, ett_sip_element);
3804
                            /*
3805
                             * From        =  ( "From" / "f" ) HCOLON from-spec
3806
                             * from-spec   =  ( name-addr / addr-spec )
3807
                             *                *( SEMI from-param )
3808
                             */
3809
3810
0
                            sip_uri_offset_init(&uri_offsets);
3811
0
                            if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1){
3812
0
                                display_sip_uri(tvb, sip_element_tree, pinfo, &uri_offsets, &sip_from_uri);
3813
0
                                if((uri_offsets.name_addr_start != -1) && (uri_offsets.name_addr_end != -1)){
3814
0
                                    stat_info->tap_from_addr = (char*)tvb_get_string_enc(pinfo->pool, tvb, uri_offsets.name_addr_start,
3815
0
                                        uri_offsets.name_addr_end - uri_offsets.name_addr_start + 1, ENC_UTF_8|ENC_NA);
3816
0
                                }
3817
0
                                offset = uri_offsets.name_addr_end +1;
3818
0
                            }
3819
3820
                            /* Find parameter tag if present.
3821
                             * TODO make this generic to find any interesting parameter
3822
                             * use the same method as for SIP headers ?
3823
                             */
3824
3825
0
                            parameter_offset = offset;
3826
0
                            while (parameter_offset < line_end_offset
3827
0
                                   && (tvb_strneql(tvb, parameter_offset, "tag=", 4) != 0))
3828
0
                                parameter_offset++;
3829
0
                            if ( parameter_offset < line_end_offset ){ /* Tag found */
3830
0
                                parameter_offset = parameter_offset + 4;
3831
0
                                parameter_end_offset = tvb_find_uint8(tvb, parameter_offset,
3832
0
                                                                       (line_end_offset - parameter_offset), ';');
3833
0
                                if ( parameter_end_offset == -1)
3834
0
                                    parameter_end_offset = line_end_offset;
3835
0
                                parameter_len = parameter_end_offset - parameter_offset;
3836
0
                                proto_tree_add_item(sip_element_tree, hf_sip_from_tag, tvb, parameter_offset,
3837
0
                                                    parameter_len, ENC_UTF_8);
3838
0
                                item = proto_tree_add_item(sip_element_tree, hf_sip_tag, tvb, parameter_offset,
3839
0
                                                           parameter_len, ENC_UTF_8);
3840
0
                                proto_item_set_hidden(item);
3841
0
                            }
3842
0
                        }/* hdr_tree */
3843
0
                    break;
3844
3845
0
                    case POS_P_ASSERTED_IDENTITY :
3846
0
                        if(hdr_tree)
3847
0
                        {
3848
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
3849
0
                                               hf_header_array[hf_index], tvb,
3850
0
                                               offset, next_offset - offset,
3851
0
                                               value_offset, value_len);
3852
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
3853
3854
0
                            sip_element_tree = proto_item_add_subtree( sip_element_item,
3855
0
                                               ett_sip_element);
3856
3857
                            /*
3858
                             * PAssertedID = "P-Asserted-Identity" HCOLON PAssertedID-value
3859
                             *                *(COMMA PAssertedID-value)
3860
                             * PAssertedID-value = name-addr / addr-spec
3861
                             *
3862
                             * Initialize the uri_offsets
3863
                             */
3864
0
                            sip_uri_offset_init(&uri_offsets);
3865
0
                            if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
3866
0
                                 display_sip_uri(tvb, sip_element_tree, pinfo, &uri_offsets, &sip_pai_uri);
3867
0
                        }
3868
0
                        break;
3869
0
                    case POS_P_ASSOCIATED_URI:
3870
0
                        if (hdr_tree)
3871
0
                        {
3872
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
3873
0
                                hf_header_array[hf_index], tvb,
3874
0
                                offset, next_offset - offset,
3875
0
                                value_offset, value_len);
3876
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
3877
                            /*
3878
                             * P-Associated-URI       = "P-Associated-URI" HCOLON
3879
                             *                          [p-aso-uri-spec]
3880
                             *                          *(COMMA p-aso-uri-spec)
3881
                             * p-aso-uri-spec         = name-addr *(SEMI ai-param)
3882
                             * ai-param               = generic-param
3883
                             */
3884
                            /* Skip to the end of the URI directly */
3885
0
                            semi_colon_offset = tvb_find_uint8(tvb, value_offset, line_end_offset - value_offset, '>');
3886
0
                            if (semi_colon_offset != -1) {
3887
0
                                semi_colon_offset = tvb_find_uint8(tvb, semi_colon_offset, line_end_offset - semi_colon_offset, ';');
3888
0
                                if (semi_colon_offset != -1) {
3889
0
                                    sip_element_tree = proto_item_add_subtree(sip_element_item,
3890
0
                                        ett_sip_element);
3891
                                    /* We have generic parameters */
3892
0
                                    dissect_sip_generic_parameters(tvb, sip_element_tree, pinfo, semi_colon_offset + 1, line_end_offset);
3893
0
                                }
3894
0
                            }
3895
3896
0
                        }
3897
0
                        break;
3898
0
                    case POS_HISTORY_INFO:
3899
0
                        if(hdr_tree)
3900
0
                        {
3901
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
3902
0
                                               hf_header_array[hf_index], tvb,
3903
0
                                               offset, next_offset - offset,
3904
0
                                               value_offset, value_len);
3905
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
3906
3907
0
                            sip_element_tree = proto_item_add_subtree( sip_element_item,
3908
0
                                               ett_sip_hist);
3909
0
                            dissect_sip_history_info(tvb, sip_element_tree, pinfo, value_offset, line_end_offset);
3910
0
                        }
3911
0
                        break;
3912
3913
0
                    case POS_P_CHARGING_FUNC_ADDRESSES:
3914
0
                        if(hdr_tree)
3915
0
                        {
3916
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
3917
0
                                               hf_header_array[hf_index], tvb,
3918
0
                                               offset, next_offset - offset,
3919
0
                                               value_offset, value_len);
3920
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
3921
3922
0
                            sip_element_tree = proto_item_add_subtree( sip_element_item,
3923
0
                                               ett_sip_element);
3924
0
                            dissect_sip_p_charging_func_addresses(tvb, sip_element_tree, pinfo, value_offset, line_end_offset);
3925
0
                        }
3926
0
                        break;
3927
3928
0
                    case POS_P_PREFERRED_IDENTITY :
3929
0
                        if(hdr_tree)
3930
0
                        {
3931
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
3932
0
                                               hf_header_array[hf_index], tvb,
3933
0
                                               offset, next_offset - offset,
3934
0
                                               value_offset, value_len);
3935
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
3936
3937
0
                            sip_element_tree = proto_item_add_subtree( sip_element_item,
3938
0
                                               ett_sip_element);
3939
                            /*
3940
                             * PPreferredID = "P-Preferred-Identity" HCOLON PPreferredID-value
3941
                             *                   *(COMMA PPreferredID-value)
3942
                             * PPreferredID-value = name-addr / addr-spec
3943
                             *
3944
                             * Initialize the uri_offsets
3945
                             */
3946
0
                            sip_uri_offset_init(&uri_offsets);
3947
0
                            if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
3948
0
                                 display_sip_uri(tvb, sip_element_tree, pinfo, &uri_offsets, &sip_ppi_uri);
3949
0
                        }
3950
0
                        break;
3951
3952
0
                    case POS_PERMISSION_MISSING :
3953
0
                        if(hdr_tree)
3954
0
                        {
3955
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
3956
0
                                               hf_header_array[hf_index], tvb,
3957
0
                                               offset, next_offset - offset,
3958
0
                                               value_offset, value_len);
3959
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
3960
3961
0
                            sip_element_tree = proto_item_add_subtree( sip_element_item,
3962
0
                                                                   ett_sip_element);
3963
                            /*
3964
                             * Permission-Missing  =  "Permission-Missing" HCOLON per-miss-spec
3965
                             *                        *( COMMA per-miss-spec )
3966
                             * per-miss-spec       =  ( name-addr / addr-spec )
3967
                             *                       *( SEMI generic-param )
3968
                             * Initialize the uri_offsets
3969
                             */
3970
0
                            sip_uri_offset_init(&uri_offsets);
3971
0
                            if((dissect_sip_name_addr_or_addr_spec(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1)
3972
0
                                 display_sip_uri(tvb, sip_element_tree, pinfo, &uri_offsets, &sip_pmiss_uri);
3973
0
                        }
3974
0
                        break;
3975
3976
3977
0
                    case POS_TRIGGER_CONSENT :
3978
0
                        if(hdr_tree)
3979
0
                        {
3980
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
3981
0
                                               hf_header_array[hf_index], tvb,
3982
0
                                               offset, next_offset - offset,
3983
0
                                               value_offset, value_len);
3984
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
3985
3986
0
                            sip_element_tree = proto_item_add_subtree( sip_element_item,
3987
0
                                                                        ett_sip_element);
3988
                            /*
3989
                             * Trigger-Consent     =  "Trigger-Consent" HCOLON trigger-cons-spec
3990
                             *                        *( COMMA trigger-cons-spec )
3991
                             * trigger-cons-spec   =  ( SIP-URI / SIPS-URI )
3992
                             *                        *( SEMI trigger-param )
3993
                             * trigger-param       =  target-uri / generic-param
3994
                             * target-uri          =  "target-uri" EQUAL
3995
                             *                            LDQUOT *( qdtext / quoted-pair ) RDQUOT
3996
                             * Initialize the uri_offsets
3997
                             */
3998
0
                            sip_uri_offset_init(&uri_offsets);
3999
0
                            if((dissect_sip_uri(tvb, pinfo, value_offset, line_end_offset+2, &uri_offsets)) != -1) {
4000
4001
0
                                tc_uri_item_tree = display_sip_uri(tvb, sip_element_tree, pinfo, &uri_offsets, &sip_tc_uri);
4002
0
                                if (line_end_offset > uri_offsets.uri_end) {
4003
0
                                    int hparam_offset = uri_offsets.uri_end + 1;
4004
                                    /* Is there a header parameter */
4005
0
                                    if (tvb_find_uint8(tvb, hparam_offset, 1,';')) {
4006
0
                                        while ((hparam_offset != -1 && hparam_offset < line_end_offset) )  {
4007
                                            /* Is this a target-uri ? */
4008
0
                                            hparam_offset = hparam_offset + 1;
4009
0
                                            if (tvb_strncaseeql(tvb, hparam_offset, "target-uri=\"", 12) == 0) {
4010
0
                                                int turi_start_offset = hparam_offset + 12;
4011
0
                                                int turi_end_offset   = tvb_find_uint8(tvb, turi_start_offset, -1,'\"');
4012
0
                                                if (turi_end_offset != -1)
4013
0
                                                    proto_tree_add_item(tc_uri_item_tree, hf_sip_tc_turi, tvb, turi_start_offset,(turi_end_offset - turi_start_offset),ENC_UTF_8);
4014
0
                                                else
4015
0
                                                    break; /* malformed */
4016
0
                                            }
4017
0
                                            hparam_offset = tvb_find_uint8(tvb, hparam_offset, -1,';');
4018
0
                                        }
4019
0
                                    }
4020
0
                                }
4021
0
                            }
4022
0
                        }/* hdr_tree */
4023
0
                        break;
4024
0
                    case POS_RETRY_AFTER:
4025
0
                    {
4026
                        /* Store the retry number */
4027
0
                        char *value = (char*)tvb_get_string_enc(pinfo->pool, tvb, value_offset, value_len, ENC_UTF_8 | ENC_NA);
4028
0
                        uint32_t retry;
4029
0
                        bool retry_valid = ws_strtou32(value, NULL, &retry);
4030
4031
4032
0
                        sip_element_item = proto_tree_add_uint(hdr_tree, hf_header_array[hf_index],
4033
0
                            tvb, offset, next_offset - offset,
4034
0
                            retry);
4035
4036
0
                        if (!retry_valid) {
4037
0
                            expert_add_info(pinfo, sip_element_item, &ei_sip_retry_after_invalid);
4038
0
                        }
4039
0
                    }
4040
0
                    break;
4041
0
                    case POS_CSEQ :
4042
0
                    {
4043
                        /* Store the sequence number */
4044
0
                        char *value = (char*)tvb_get_string_enc(pinfo->pool, tvb, value_offset, value_len, ENC_UTF_8|ENC_NA);
4045
4046
0
                        cseq_number = (uint32_t)strtoul(value, NULL, 10);
4047
0
                        cseq_number_set = 1;
4048
0
                        stat_info->tap_cseq_number=cseq_number;
4049
4050
                        /* Add CSeq  tree */
4051
0
                        if (hdr_tree) {
4052
0
                            sip_element_item = proto_tree_add_string(hdr_tree,
4053
0
                                                         hf_header_array[hf_index], tvb,
4054
0
                                                         offset, next_offset - offset,
4055
0
                                                         value);
4056
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4057
4058
0
                            cseq_tree = proto_item_add_subtree(sip_element_item, ett_sip_cseq);
4059
0
                        }
4060
4061
                        /* Walk past number and spaces characters to get to start
4062
                           of method name */
4063
0
                        for (sub_value_offset=0; sub_value_offset < value_len; sub_value_offset++)
4064
0
                        {
4065
0
                            if (!g_ascii_isdigit(value[sub_value_offset]))
4066
0
                            {
4067
0
                                proto_tree_add_uint(cseq_tree, hf_sip_cseq_seq_no,
4068
0
                                                    tvb, value_offset, sub_value_offset,
4069
0
                                                    cseq_number);
4070
0
                                break;
4071
0
                            }
4072
0
                        }
4073
4074
0
                        for (; sub_value_offset < value_len; sub_value_offset++)
4075
0
                        {
4076
0
                            if (g_ascii_isalpha(value[sub_value_offset]))
4077
0
                            {
4078
                                /* Have reached start of method name */
4079
0
                                break;
4080
0
                            }
4081
0
                        }
4082
4083
0
                        if (sub_value_offset == value_len)
4084
0
                        {
4085
                            /* Didn't find method name */
4086
0
                            return offset - orig_offset;
4087
0
                        }
4088
4089
                        /* Extract method name from value */
4090
0
                        strlen_to_copy = (int)value_len-sub_value_offset;
4091
0
                        if (strlen_to_copy > MAX_CSEQ_METHOD_SIZE) {
4092
                            /* Note the error in the protocol tree */
4093
0
                            proto_tree_add_string_format(hdr_tree,
4094
0
                                                             hf_header_array[hf_index], tvb,
4095
0
                                                             offset, next_offset - offset,
4096
0
                                                             value+sub_value_offset, "%s String too big: %d bytes",
4097
0
                                                             sip_headers[POS_CSEQ].name,
4098
0
                                                             strlen_to_copy);
4099
0
                            return offset - orig_offset;
4100
0
                        }
4101
0
                        else {
4102
                            /* Add CSeq method to the tree */
4103
0
                            proto_tree_add_item_ret_string(cseq_tree, hf_sip_cseq_method, tvb,
4104
0
                                                    value_offset + sub_value_offset, strlen_to_copy, ENC_UTF_8,
4105
0
                                                    pinfo->pool, (const uint8_t **)&cseq_method);
4106
0
                        }
4107
0
                    }
4108
0
                    break;
4109
4110
0
                    case POS_RACK :
4111
0
                    {
4112
0
                        char *value = (char*)tvb_get_string_enc(pinfo->pool, tvb, value_offset, value_len, ENC_UTF_8|ENC_NA);
4113
0
                        int cseq_no_offset;
4114
                        /*int cseq_method_offset;*/
4115
4116
                        /* Add RAck  tree */
4117
0
                        if (hdr_tree) {
4118
0
                            sip_element_item = proto_tree_add_string(hdr_tree,
4119
0
                                                         hf_header_array[hf_index], tvb,
4120
0
                                                         offset, next_offset - offset,
4121
0
                                                         value);
4122
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4123
4124
0
                            rack_tree = proto_item_add_subtree(sip_element_item, ett_sip_rack);
4125
0
                        }
4126
4127
                        /* RSeq number */
4128
0
                        for (sub_value_offset=0; sub_value_offset < value_len; sub_value_offset++)
4129
0
                        {
4130
0
                            if (!g_ascii_isdigit(value[sub_value_offset]))
4131
0
                            {
4132
0
                                proto_tree_add_uint(rack_tree, hf_sip_rack_rseq_no,
4133
0
                                                    tvb, value_offset, sub_value_offset,
4134
0
                                                    (uint32_t)strtoul(value, NULL, 10));
4135
0
                                break;
4136
0
                            }
4137
0
                        }
4138
4139
                        /* Get to start of CSeq number */
4140
0
                        for ( ; sub_value_offset < value_len; sub_value_offset++)
4141
0
                        {
4142
0
                            if (value[sub_value_offset] != ' ' &&
4143
0
                                value[sub_value_offset] != '\t')
4144
0
                            {
4145
0
                                break;
4146
0
                            }
4147
0
                        }
4148
0
                        cseq_no_offset = sub_value_offset;
4149
4150
                        /* CSeq number */
4151
0
                        for ( ; sub_value_offset < value_len; sub_value_offset++)
4152
0
                        {
4153
0
                            if (!g_ascii_isdigit(value[sub_value_offset]))
4154
0
                            {
4155
0
                                proto_tree_add_uint(rack_tree, hf_sip_rack_cseq_no,
4156
0
                                                    tvb, value_offset+cseq_no_offset,
4157
0
                                                    sub_value_offset-cseq_no_offset,
4158
0
                                                    (uint32_t)strtoul(value+cseq_no_offset, NULL, 10));
4159
0
                                break;
4160
0
                            }
4161
0
                        }
4162
4163
                        /* Get to start of CSeq method name */
4164
0
                        for ( ; sub_value_offset < value_len; sub_value_offset++)
4165
0
                        {
4166
0
                            if (g_ascii_isalpha(value[sub_value_offset]))
4167
0
                            {
4168
                                /* Have reached start of method name */
4169
0
                                break;
4170
0
                            }
4171
0
                        }
4172
                        /*cseq_method_offset = sub_value_offset;*/
4173
4174
0
                        if (sub_value_offset == linelen)
4175
0
                        {
4176
                            /* Didn't find method name */
4177
0
                            return offset - orig_offset;
4178
0
                        }
4179
4180
                        /* Add CSeq method to the tree */
4181
0
                        if (cseq_tree)
4182
0
                        {
4183
0
                            proto_tree_add_item(rack_tree, hf_sip_rack_cseq_method, tvb,
4184
0
                                                value_offset + sub_value_offset,
4185
0
                                                (int)value_len-sub_value_offset, ENC_UTF_8);
4186
0
                        }
4187
4188
0
                        break;
4189
0
                    }
4190
4191
10
                    case POS_CALL_ID :
4192
10
                    {
4193
10
                        call_id = (char*)tvb_get_string_enc(pinfo->pool, tvb, value_offset, value_len, ENC_UTF_8|ENC_NA);
4194
10
                        proto_item *gen_item;
4195
4196
                        /* Store the Call-id */
4197
10
                        stat_info->tap_call_id = call_id;
4198
4199
                        /* Add 'Call-id' string item to tree */
4200
10
                        sip_element_item = proto_tree_add_string(hdr_tree,
4201
10
                                                    hf_header_array[hf_index], tvb,
4202
10
                                                    offset, next_offset - offset,
4203
10
                                                    call_id);
4204
10
                        gen_item = proto_tree_add_string(hdr_tree,
4205
10
                                                    hf_sip_call_id_gen, tvb,
4206
10
                                                    offset, next_offset - offset,
4207
10
                                                    call_id);
4208
10
                        proto_item_set_generated(gen_item);
4209
10
                        if (sip_hide_generatd_call_ids) {
4210
0
                            proto_item_set_hidden(gen_item);
4211
0
                        }
4212
10
                        sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4213
10
                    }
4214
10
                    break;
4215
4216
0
                    case POS_EXPIRES :
4217
0
                        if (tvb_strneql(tvb, value_offset, "0", value_len) == 0)
4218
0
                        {
4219
0
                            expires_is_0 = 1;
4220
0
                        }
4221
4222
                        /* Add 'Expires' string item to tree */
4223
0
                        sip_proto_tree_add_uint(hdr_tree, pinfo->pool,
4224
0
                                                hf_header_array[hf_index], tvb,
4225
0
                                                offset, next_offset - offset,
4226
0
                                                value_offset, value_len);
4227
0
                    break;
4228
4229
                    /*
4230
                     * Content-Type is the same as Internet
4231
                     * media type used by other dissectors,
4232
                     * appropriate dissector found by
4233
                     * lookup in "media_type" dissector table.
4234
                     */
4235
0
                    case POS_CONTENT_TYPE :
4236
0
                        sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4237
0
                                                         hf_header_array[hf_index], tvb,
4238
0
                                                         offset, next_offset - offset,
4239
0
                                                         value_offset, value_len);
4240
0
                        sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4241
4242
0
                        content_type_len = value_len;
4243
0
                        semi_colon_offset = tvb_find_uint8(tvb, value_offset, value_len, ';');
4244
                        /* Content-Type     =  ( "Content-Type" / "c" ) HCOLON media-type
4245
                         * media-type       =  m-type SLASH m-subtype *(SEMI m-parameter)
4246
                         * SEMI    =  SWS ";" SWS ; semicolon
4247
                         * LWS  =  [*WSP CRLF] 1*WSP ; linear whitespace
4248
                         * SWS  =  [LWS] ; sep whitespace
4249
                         */
4250
0
                        if ( semi_colon_offset != -1) {
4251
0
                            int content_type_end;
4252
                            /*
4253
                             * Skip whitespace after the semicolon.
4254
                             */
4255
0
                            parameter_offset = tvb_skip_wsp(tvb, semi_colon_offset +1, value_offset + value_len - (semi_colon_offset +1));
4256
0
                            content_type_end = tvb_skip_wsp_return(tvb, semi_colon_offset-1);
4257
0
                            content_type_len = content_type_end - value_offset;
4258
0
                            content_type_parameter_str_len = value_offset + value_len - parameter_offset;
4259
0
                            content_info.media_str = (char*)tvb_get_string_enc(pinfo->pool, tvb, parameter_offset,
4260
0
                                                         content_type_parameter_str_len, ENC_UTF_8|ENC_NA);
4261
0
                        }
4262
0
                        media_type_str_lower_case = ascii_strdown_inplace(
4263
0
                            (char *)tvb_get_string_enc(pinfo->pool, tvb, value_offset, content_type_len, ENC_UTF_8|ENC_NA));
4264
4265
                        /* Debug code
4266
                        proto_tree_add_debug_text(hdr_tree, tvb, value_offset,content_type_len,
4267
                                            "media_type_str(lower cased)=%s",media_type_str_lower_case);
4268
                        */
4269
0
                    break;
4270
4271
100
                    case POS_CONTENT_LENGTH :
4272
100
                    {
4273
100
                        char *value = (char*)tvb_get_string_enc(pinfo->pool, tvb, value_offset, value_len, ENC_UTF_8|ENC_NA);
4274
100
                        content_length_valid = ws_strtou32(value, NULL, &content_length);
4275
4276
100
                        sip_element_item = proto_tree_add_uint(hdr_tree,
4277
100
                                               hf_header_array[hf_index], tvb,
4278
100
                                               offset, next_offset - offset,
4279
100
                                               content_length);
4280
100
                        sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4281
100
                        if (!content_length_valid)
4282
99
                            expert_add_info(pinfo, sip_element_item, &ei_sip_content_length_invalid);
4283
4284
100
                        break;
4285
0
                    }
4286
4287
0
                    case POS_MAX_BREADTH :
4288
0
                    case POS_MAX_FORWARDS :
4289
0
                    case POS_RSEQ :
4290
0
                        sip_proto_tree_add_uint(hdr_tree, pinfo->pool,
4291
0
                                                hf_header_array[hf_index], tvb,
4292
0
                                                offset, next_offset - offset,
4293
0
                                                value_offset, value_len);
4294
0
                        break;
4295
4296
280
                    case POS_CONTACT :
4297
                        /*
4298
                         * Contact        =  ("Contact" / "m" ) HCOLON
4299
                         *                   ( STAR / (contact-param *(COMMA contact-param)))
4300
                         * contact-param  =  (name-addr / addr-spec) *(SEMI contact-params)
4301
                         */
4302
280
                        sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4303
280
                                               hf_header_array[hf_index], tvb,
4304
280
                                               offset, next_offset - offset,
4305
280
                                               value_offset, value_len);
4306
280
                        sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4307
4308
280
                        sip_element_tree = proto_item_add_subtree( sip_element_item,
4309
280
                                               ett_sip_element);
4310
4311
                        /* value_offset points to the first non SWS character after ':' */
4312
280
                        c = tvb_get_uint8(tvb, value_offset);
4313
280
                        if (c =='*'){
4314
0
                            contact_is_star = 1;
4315
0
                            break;
4316
0
                        }
4317
4318
280
                        /*if(hdr_tree)*/ {
4319
280
                            comma_offset = value_offset;
4320
312
                            while((comma_offset = dissect_sip_contact_item(tvb, pinfo, sip_element_tree, comma_offset,
4321
312
                                    next_offset, &contacts_expires_0, &contacts_expires_unknown)) != -1)
4322
144
                            {
4323
144
                                contacts++;
4324
144
                                if(comma_offset == next_offset)
4325
112
                                {
4326
                                    /* Line End reached: Stop Parsing */
4327
112
                                    break;
4328
112
                                }
4329
4330
32
                                if(tvb_get_uint8(tvb, comma_offset) != ',')
4331
0
                                {
4332
                                    /* Undefined value reached: Stop Parsing */
4333
0
                                    break;
4334
0
                                }
4335
32
                                comma_offset++; /* skip comma */
4336
32
                            }
4337
280
                        }
4338
280
                    break;
4339
4340
0
                    case POS_AUTHORIZATION:
4341
                        /* Authorization     =  "Authorization" HCOLON credentials
4342
                         * credentials       =  ("Digest" LWS digest-response)
4343
                         *                      / other-response
4344
                         * digest-response   =  dig-resp *(COMMA dig-resp)
4345
                         * other-response    =  auth-scheme LWS auth-param
4346
                         *                      *(COMMA auth-param)
4347
                         */
4348
0
                    case POS_WWW_AUTHENTICATE:
4349
                        /* Proxy-Authenticate  =  "Proxy-Authenticate" HCOLON challenge
4350
                         * challenge           =  ("Digest" LWS digest-cln *(COMMA digest-cln))
4351
                         *                        / other-challenge
4352
                         * other-challenge     =  auth-scheme LWS auth-param
4353
                         *                        *(COMMA auth-param)
4354
                         * auth-scheme         =  token
4355
                         */
4356
0
                    case POS_PROXY_AUTHENTICATE:
4357
                        /* Proxy-Authenticate  =  "Proxy-Authenticate" HCOLON challenge
4358
                         */
4359
0
                    case POS_PROXY_AUTHORIZATION:
4360
                        /* Proxy-Authorization  =  "Proxy-Authorization" HCOLON credentials
4361
                         */
4362
0
                    case POS_AUTHENTICATION_INFO:
4363
                        /* Authentication-Info  =  "Authentication-Info" HCOLON ainfo
4364
                         *                        *(COMMA ainfo)
4365
                         * ainfo                =  nextnonce / message-qop
4366
                         *                         / response-auth / cnonce
4367
                         *                         / nonce-count
4368
                         */
4369
                        /* Add tree using whole text of line */
4370
0
                        if (hdr_tree) {
4371
0
                            proto_item *ti_c;
4372
0
                            sip_authorization_t authorization_info = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
4373
0
                            authorization_user_t * authorization_user = NULL;
4374
                            /* Add whole line as header tree */
4375
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4376
0
                                               hf_header_array[hf_index], tvb,
4377
0
                                               offset, next_offset - offset,
4378
0
                                               value_offset, value_len);
4379
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4380
4381
0
                            sip_element_tree = proto_item_add_subtree( sip_element_item,
4382
0
                                               ett_sip_element);
4383
4384
                            /* Set sip.auth as a hidden field/filter */
4385
0
                            ti_c = proto_tree_add_item(hdr_tree, hf_sip_auth, tvb,
4386
0
                                                     offset, next_offset-offset,
4387
0
                                                     ENC_UTF_8);
4388
0
                            proto_item_set_hidden(ti_c);
4389
4390
                            /* Check if we have any parameters */
4391
0
                            if ((line_end_offset - value_offset) != 0) {
4392
                                /* Authentication-Info does not begin with the scheme name */
4393
0
                                if (hf_index != POS_AUTHENTICATION_INFO)
4394
0
                                {
4395
                                    /* The first time comma_offset is "start of parameters" */
4396
0
                                    comma_offset = tvb_ws_mempbrk_pattern_uint8(tvb, value_offset, line_end_offset - value_offset, &pbrk_whitespace, NULL);
4397
0
                                    proto_tree_add_item(sip_element_tree, hf_sip_auth_scheme,
4398
0
                                        tvb, value_offset, comma_offset - value_offset,
4399
0
                                        ENC_UTF_8);
4400
0
                                } else {
4401
                                    /* The first time comma_offset is "start of parameters" */
4402
0
                                    comma_offset = value_offset;
4403
0
                                }
4404
4405
                                /* Parse each individual parameter in the line */
4406
0
                                while ((comma_offset = dissect_sip_authorization_item(tvb, pinfo, sip_element_tree, comma_offset, line_end_offset, &authorization_info)) != -1)
4407
0
                                {
4408
0
                                    if (comma_offset == line_end_offset)
4409
0
                                    {
4410
                                        /* Line End reached: Stop Parsing */
4411
0
                                        break;
4412
0
                                    }
4413
4414
0
                                    if (tvb_get_uint8(tvb, comma_offset) != ',')
4415
0
                                    {
4416
                                        /* Undefined value reached: Stop Parsing */
4417
0
                                        break;
4418
0
                                    }
4419
0
                                    comma_offset++; /* skip comma */
4420
0
                                }
4421
0
                                if ((authorization_info.response != NULL) && (global_sip_validate_authorization) &&
4422
0
                                        (authorization_info.username != NULL) && (authorization_info.realm != NULL)) { /* If there is a response, check for valid credentials */
4423
0
                                    authorization_user = sip_get_authorization(&authorization_info);
4424
0
                                    if (authorization_user) {
4425
0
                                        authorization_info.method = wmem_strdup(pinfo->pool, stat_info->request_method);
4426
0
                                        if (!sip_validate_authorization(&authorization_info, authorization_user->password)) {
4427
0
                                            proto_tree_add_expert_format(tree, pinfo, &ei_sip_authorization_invalid, tvb, offset, line_end_offset - offset, "SIP digest does not match known password %s", authorization_user->password);
4428
0
                                        }
4429
0
                                    }
4430
0
                                }
4431
0
                            } /* Check if we have any parameters */
4432
0
                        }/*hdr_tree*/
4433
0
                    break;
4434
4435
0
                    case POS_ROUTE:
4436
                        /* Add Route subtree */
4437
0
                        if (hdr_tree) {
4438
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4439
0
                                                         hf_header_array[hf_index], tvb,
4440
0
                                                         offset, next_offset - offset,
4441
0
                                                         value_offset, value_len);
4442
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4443
4444
0
                            route_tree = proto_item_add_subtree(sip_element_item, ett_sip_route);
4445
0
                            dissect_sip_route_header(tvb, route_tree, pinfo, &sip_route_uri, value_offset, line_end_offset);
4446
0
                        }
4447
0
                        break;
4448
0
                    case POS_RECORD_ROUTE:
4449
                        /* Add Record-Route subtree */
4450
0
                        if (hdr_tree) {
4451
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4452
0
                                                         hf_header_array[hf_index], tvb,
4453
0
                                                         offset, next_offset - offset,
4454
0
                                                         value_offset, value_len);
4455
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4456
4457
0
                            route_tree = proto_item_add_subtree(sip_element_item, ett_sip_route);
4458
0
                            dissect_sip_route_header(tvb, route_tree, pinfo, &sip_record_route_uri, value_offset, line_end_offset);
4459
0
                        }
4460
0
                        break;
4461
0
                    case POS_SERVICE_ROUTE:
4462
                        /* Add Service-Route subtree */
4463
0
                        if (hdr_tree) {
4464
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4465
0
                                                         hf_header_array[hf_index], tvb,
4466
0
                                                         offset, next_offset - offset,
4467
0
                                                         value_offset, value_len);
4468
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4469
4470
0
                            route_tree = proto_item_add_subtree(sip_element_item, ett_sip_route);
4471
0
                            dissect_sip_route_header(tvb, route_tree, pinfo, &sip_service_route_uri, value_offset, line_end_offset);
4472
0
                        }
4473
0
                        break;
4474
0
                    case POS_PATH:
4475
                        /* Add Path subtree */
4476
0
                        if (hdr_tree) {
4477
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4478
0
                                                         hf_header_array[hf_index], tvb,
4479
0
                                                         offset, next_offset - offset,
4480
0
                                                         value_offset, value_len);
4481
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4482
4483
0
                            route_tree = proto_item_add_subtree(sip_element_item, ett_sip_route);
4484
0
                            dissect_sip_route_header(tvb, route_tree, pinfo, &sip_path_uri, value_offset, line_end_offset);
4485
0
                        }
4486
0
                        break;
4487
45
                    case POS_VIA:
4488
                        /* Add Via subtree */
4489
45
                        if (hdr_tree) {
4490
45
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4491
45
                                                         hf_header_array[hf_index], tvb,
4492
45
                                                         offset, next_offset - offset,
4493
45
                                                         value_offset, value_len);
4494
45
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4495
4496
45
                            via_tree = proto_item_add_subtree(sip_element_item, ett_sip_via);
4497
45
                            dissect_sip_via_header(tvb, via_tree, value_offset, line_end_offset, pinfo);
4498
45
                        }
4499
45
                        break;
4500
0
                    case POS_REASON:
4501
0
                        if(hdr_tree) {
4502
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4503
0
                                                         hf_header_array[hf_index], tvb,
4504
0
                                                         offset, next_offset - offset,
4505
0
                                                         value_offset, value_len);
4506
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4507
4508
0
                            reason_tree = proto_item_add_subtree(sip_element_item, ett_sip_reason);
4509
0
                            dissect_sip_reason_header(tvb, reason_tree, pinfo, value_offset, line_end_offset);
4510
0
                        }
4511
0
                        break;
4512
10
                    case POS_CONTENT_ENCODING:
4513
                        /* Content-Encoding  =  ( "Content-Encoding" / "e" ) HCOLON
4514
                         * content-coding *(COMMA content-coding)
4515
                         */
4516
10
                        sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4517
10
                                                         hf_header_array[hf_index], tvb,
4518
10
                                                         offset, next_offset - offset,
4519
10
                                                         value_offset, value_len);
4520
10
                        sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4521
4522
10
                        content_encoding_parameter_str = ascii_strdown_inplace((char*)tvb_get_string_enc(pinfo->pool, tvb, value_offset,
4523
10
                                                         (line_end_offset-value_offset), ENC_UTF_8|ENC_NA));
4524
10
                        break;
4525
0
                    case POS_SECURITY_CLIENT:
4526
                        /* security-client  = "Security-Client" HCOLON
4527
                         *                     sec-mechanism *(COMMA sec-mechanism)
4528
                         */
4529
0
                        sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4530
0
                                                         hf_header_array[hf_index], tvb,
4531
0
                                                         offset, next_offset - offset,
4532
0
                                                         value_offset, value_len);
4533
0
                        sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4534
4535
0
                        comma_offset = tvb_find_uint8(tvb, value_offset, line_end_offset - value_offset, ',');
4536
0
                        while(comma_offset<line_end_offset){
4537
0
                            comma_offset = tvb_find_uint8(tvb, value_offset, line_end_offset - value_offset, ',');
4538
0
                            if(comma_offset == -1){
4539
0
                                comma_offset = line_end_offset;
4540
0
                            }
4541
0
                            security_client_tree = proto_item_add_subtree(sip_element_item, ett_sip_security_client);
4542
0
                            dissect_sip_sec_mechanism(tvb, pinfo, security_client_tree, value_offset, comma_offset);
4543
0
                            comma_offset = value_offset = comma_offset+1;
4544
0
                        }
4545
4546
0
                        break;
4547
0
                    case POS_SECURITY_SERVER:
4548
                        /* security-server  = "Security-Server" HCOLON
4549
                         *                     sec-mechanism *(COMMA sec-mechanism)
4550
                         */
4551
0
                        sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4552
0
                                                         hf_header_array[hf_index], tvb,
4553
0
                                                         offset, next_offset - offset,
4554
0
                                                         value_offset, value_len);
4555
0
                        sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4556
4557
0
                        comma_offset = tvb_find_uint8(tvb, value_offset, line_end_offset - value_offset, ',');
4558
0
                        while(comma_offset<line_end_offset){
4559
0
                            comma_offset = tvb_find_uint8(tvb, value_offset, line_end_offset - value_offset, ',');
4560
0
                            if(comma_offset == -1){
4561
0
                                comma_offset = line_end_offset;
4562
0
                            }
4563
0
                            security_client_tree = proto_item_add_subtree(sip_element_item, ett_sip_security_server);
4564
0
                            dissect_sip_sec_mechanism(tvb, pinfo, security_client_tree, value_offset, comma_offset);
4565
0
                            comma_offset = value_offset = comma_offset+1;
4566
0
                        }
4567
4568
0
                        break;
4569
0
                    case POS_SECURITY_VERIFY:
4570
                        /* security-verify  = "Security-Verify" HCOLON
4571
                         *                     sec-mechanism *(COMMA sec-mechanism)
4572
                         */
4573
0
                        sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4574
0
                                                         hf_header_array[hf_index], tvb,
4575
0
                                                         offset, next_offset - offset,
4576
0
                                                         value_offset, value_len);
4577
0
                        sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4578
4579
0
                        comma_offset = tvb_find_uint8(tvb, value_offset, line_end_offset - value_offset, ',');
4580
0
                        while(comma_offset<line_end_offset){
4581
0
                            comma_offset = tvb_find_uint8(tvb, value_offset, line_end_offset - value_offset, ',');
4582
0
                            if(comma_offset == -1){
4583
0
                                comma_offset = line_end_offset;
4584
0
                            }
4585
0
                            security_client_tree = proto_item_add_subtree(sip_element_item, ett_sip_security_verify);
4586
0
                            dissect_sip_sec_mechanism(tvb, pinfo, security_client_tree, value_offset, comma_offset);
4587
0
                            comma_offset = value_offset = comma_offset+1;
4588
0
                        }
4589
4590
0
                        break;
4591
0
                    case POS_SESSION_ID:
4592
0
                        if(hdr_tree) {
4593
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4594
0
                                                            hf_header_array[hf_index], tvb,
4595
0
                                                            offset, next_offset - offset,
4596
0
                                                            value_offset, value_len);
4597
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4598
0
                            session_id_tree = proto_item_add_subtree(sip_element_item, ett_sip_session_id);
4599
0
                            dissect_sip_session_id_header(tvb, session_id_tree, value_offset, line_end_offset, pinfo);
4600
0
                        }
4601
0
                        break;
4602
0
                    case POS_P_ACCESS_NETWORK_INFO:
4603
                        /* Add P-Access-Network-Info subtree */
4604
0
                        if (hdr_tree) {
4605
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4606
0
                                hf_header_array[hf_index], tvb,
4607
0
                                offset, next_offset - offset,
4608
0
                                value_offset, value_len);
4609
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4610
0
                            p_access_net_info_tree = proto_item_add_subtree(sip_element_item, ett_sip_p_access_net_info);
4611
0
                            dissect_sip_p_access_network_info_header(tvb, pinfo, p_access_net_info_tree, value_offset, line_end_offset);
4612
0
                        }
4613
0
                        break;
4614
0
                    case POS_P_CHARGING_VECTOR:
4615
0
                        if (hdr_tree) {
4616
0
                            proto_tree *p_charging_vector_tree;
4617
4618
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4619
0
                                hf_header_array[hf_index], tvb,
4620
0
                                offset, next_offset - offset,
4621
0
                                value_offset, value_len);
4622
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4623
0
                            p_charging_vector_tree = proto_item_add_subtree(sip_element_item, ett_sip_p_charging_vector);
4624
0
                            dissect_sip_p_charging_vector_header(tvb, pinfo, p_charging_vector_tree, value_offset, line_end_offset);
4625
0
                        }
4626
0
                        break;
4627
0
                    case POS_FEATURE_CAPS:
4628
0
                        if (hdr_tree) {
4629
0
                            proto_tree *feature_caps_tree;
4630
4631
0
                            sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4632
0
                                hf_header_array[hf_index], tvb,
4633
0
                                offset, next_offset - offset,
4634
0
                                value_offset, value_len);
4635
0
                            sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4636
0
                            feature_caps_tree = proto_item_add_subtree(sip_element_item, ett_sip_feature_caps);
4637
0
                            dissect_sip_p_feature_caps(tvb, feature_caps_tree, value_offset, line_end_offset);
4638
0
                        }
4639
0
                        break;
4640
25
                    default :
4641
                        /* Default case is to assume it's an FT_STRING field */
4642
25
                        sip_element_item = sip_proto_tree_add_string(hdr_tree, pinfo->pool,
4643
25
                                                         hf_header_array[hf_index], tvb,
4644
25
                                                         offset, next_offset - offset,
4645
25
                                                         value_offset, value_len);
4646
25
                        sip_proto_set_format_text(hdr_tree, pinfo->pool, sip_element_item, tvb, offset, linelen);
4647
25
                        break;
4648
470
                }/* end switch */
4649
470
            }/*if HF_index */
4650
659
        }/* if colon_offset */
4651
822
        if (is_no_header_termination == true){
4652
            /* Header not terminated by empty line CRLF */
4653
78
            proto_tree_add_expert(hdr_tree, pinfo, &ei_sip_header_not_terminated,
4654
78
                                    tvb, line_end_offset, -1);
4655
78
        }
4656
822
        remaining_length = remaining_length - (next_offset - offset);
4657
822
        offset = next_offset;
4658
822
    }/* End while */
4659
4660
91
    datalen = tvb_captured_length_remaining(tvb, offset);
4661
91
    reported_datalen = tvb_reported_length_remaining(tvb, offset);
4662
91
    if (content_length_valid) {
4663
0
        if ((unsigned)datalen > content_length)
4664
0
            datalen = content_length;
4665
0
        if ((unsigned)reported_datalen > content_length)
4666
0
            reported_datalen = content_length;
4667
0
    }
4668
4669
91
    if (!call_id) {
4670
15
        call_id = wmem_strdup(pinfo->pool, "");
4671
15
        expert_add_info(pinfo, hdr_tree, &ei_sip_call_id_invalid);
4672
        /* XXX: The hash table lookups below (setup time, request/response,
4673
         * resend) are less reliable when the mandatory Call-Id header field
4674
         * is missing.
4675
         */
4676
15
    }
4677
4678
    /* Add to info column interesting things learned from header fields. */
4679
4680
    /* for either REGISTER requests or responses, any contacts without expires
4681
     * parameter use the Expires header's value
4682
     */
4683
91
    if (expires_is_0) {
4684
        /* this may add nothing, but that's ok */
4685
0
        contacts_expires_0 += contacts_expires_unknown;
4686
0
    }
4687
4688
    /* Registration requests */
4689
91
    if (current_method_idx == SIP_METHOD_REGISTER)
4690
0
    {
4691
        /* TODO: what if there's a *-contact but also non-*-contacts?
4692
         * we should create expert info for that someday I guess
4693
         */
4694
0
        if (contact_is_star && expires_is_0)
4695
0
        {
4696
0
            col_append_str(pinfo->cinfo, COL_INFO, "  (remove all bindings)");
4697
0
        }
4698
0
        else
4699
0
        if (contacts_expires_0 > 0)
4700
0
        {
4701
0
            col_append_fstr(pinfo->cinfo, COL_INFO, "  (remove %d binding%s)",
4702
0
                contacts_expires_0, contacts_expires_0 == 1 ? "":"s");
4703
0
            if (contacts > contacts_expires_0) {
4704
0
                col_append_fstr(pinfo->cinfo, COL_INFO, " (add %d binding%s)",
4705
0
                    contacts - contacts_expires_0,
4706
0
                    (contacts - contacts_expires_0 == 1) ? "":"s");
4707
0
            }
4708
0
        }
4709
0
        else
4710
0
        if (!contacts)
4711
0
        {
4712
0
            col_append_str(pinfo->cinfo, COL_INFO, "  (fetch bindings)");
4713
0
        }
4714
0
        else
4715
0
        {
4716
0
            col_append_fstr(pinfo->cinfo, COL_INFO, "  (%d binding%s)",
4717
0
                contacts, contacts == 1 ? "":"s");
4718
0
        }
4719
0
    }
4720
4721
    /* Registration responses - this info only makes sense in 2xx responses */
4722
91
    if (line_type == STATUS_LINE && stat_info)
4723
0
    {
4724
0
        if (stat_info->response_code == 200)
4725
0
        {
4726
0
            col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)", cseq_method);
4727
0
        }
4728
0
        if ((strcmp(cseq_method, "REGISTER") == 0) &&
4729
0
            stat_info->response_code > 199 && stat_info->response_code < 300)
4730
0
        {
4731
0
            if (contacts_expires_0 > 0) {
4732
0
                col_append_fstr(pinfo->cinfo, COL_INFO, "  (removed %d binding%s)",
4733
0
                    contacts_expires_0, contacts_expires_0 == 1 ? "":"s");
4734
0
                if (contacts > contacts_expires_0) {
4735
0
                    col_append_fstr(pinfo->cinfo, COL_INFO, " (%d binding%s kept)",
4736
0
                        contacts - contacts_expires_0,
4737
0
                        (contacts - contacts_expires_0 == 1) ? "":"s");
4738
0
                }
4739
0
            } else {
4740
0
                col_append_fstr(pinfo->cinfo, COL_INFO, "  (%d binding%s)",
4741
0
                    contacts, contacts == 1 ? "":"s");
4742
0
            }
4743
0
        }
4744
0
    }
4745
4746
    /* We've finished writing to the info col for this SIP message
4747
     * Set fence in case there is more than one (SIP)message in the frame
4748
     */
4749
    /* XXX: this produces ugly output, since usually there's only one SIP
4750
     * message in a frame yet this '|' gets added at the end. Need a better
4751
     * way to do this.
4752
     */
4753
91
    col_append_str(pinfo->cinfo, COL_INFO, " | ");
4754
91
    col_set_fence(pinfo->cinfo, COL_INFO);
4755
4756
    /* Find the total setup time, Must be done before checking for resend
4757
     * As that will overwrite the "Request packet no".
4758
     */
4759
91
    if ((line_type == REQUEST_LINE)&&(strcmp(cseq_method, "ACK") == 0))
4760
0
    {
4761
0
        request_for_response = sip_find_invite(pinfo, cseq_method, call_id,
4762
0
                                                cseq_number_set, cseq_number,
4763
0
                                                &response_time);
4764
0
        stat_info->setup_time = response_time;
4765
0
    }
4766
4767
    /* For responses, try to link back to request frame */
4768
91
    if (line_type == STATUS_LINE)
4769
0
    {
4770
0
        request_for_response = sip_find_request(pinfo, cseq_method, call_id,
4771
0
                                                cseq_number_set, cseq_number,
4772
0
                                                &response_time);
4773
0
    }
4774
4775
    /* Check if this packet is a resend. */
4776
91
    resend_for_packet = sip_is_packet_resend(pinfo, cseq_method, call_id,
4777
91
                                             cseq_number_set, cseq_number,
4778
91
                                             line_type);
4779
    /* Mark whether this is a resend for the tap */
4780
91
    stat_info->resend = (resend_for_packet > 0);
4781
4782
    /* Report this packet to the tap */
4783
91
    if (!pinfo->flags.in_error_pkt)
4784
18
    {
4785
18
        tap_queue_packet(sip_tap, pinfo, stat_info);
4786
18
    }
4787
4788
91
    if (datalen > 0) {
4789
        /*
4790
         * There's a message body starting at "offset".
4791
         * Set the length of the header item.
4792
         */
4793
10
        sdp_setup_info_t setup_info = {
4794
10
            .hf_id = hf_sip_call_id_gen,
4795
10
            .add_hidden = sip_hide_generatd_call_ids,
4796
10
            .hf_type = SDP_TRACE_ID_HF_TYPE_STR,
4797
10
            .trace_id.str = wmem_strdup(wmem_file_scope(), call_id),
4798
10
        };
4799
10
        content_info.data = &setup_info;
4800
4801
10
        if(content_encoding_parameter_str != NULL &&
4802
0
            (!strncmp(content_encoding_parameter_str, "gzip", 4) ||
4803
0
             !strncmp(content_encoding_parameter_str,"deflate",7))){
4804
            /* The body is gzip:ed */
4805
0
            next_tvb = tvb_child_uncompress_zlib(tvb, tvb, offset,  datalen);
4806
0
            if (next_tvb) {
4807
0
                add_new_data_source(pinfo, next_tvb, "gunzipped data");
4808
0
                if(sip_tree) {
4809
0
                    ti_a = proto_tree_add_item(sip_tree, hf_sip_msg_body, next_tvb, 0, -1,
4810
0
                                         ENC_NA);
4811
0
                    message_body_tree = proto_item_add_subtree(ti_a, ett_sip_message_body);
4812
0
                }
4813
0
            } else {
4814
0
                next_tvb = tvb_new_subset_length(tvb, offset, reported_datalen);
4815
0
                if(sip_tree) {
4816
0
                    ti_a = proto_tree_add_item(sip_tree, hf_sip_msg_body, next_tvb, 0, -1,
4817
0
                                         ENC_NA);
4818
0
                    message_body_tree = proto_item_add_subtree(ti_a, ett_sip_message_body);
4819
0
                }
4820
0
            }
4821
10
        }else{
4822
10
            next_tvb = tvb_new_subset_length(tvb, offset, reported_datalen);
4823
10
            if(sip_tree) {
4824
10
                ti_a = proto_tree_add_item(sip_tree, hf_sip_msg_body, next_tvb, 0, -1,
4825
10
                                     ENC_NA);
4826
10
                message_body_tree = proto_item_add_subtree(ti_a, ett_sip_message_body);
4827
10
            }
4828
10
        }
4829
4830
        /* give the content type parameters to sub dissectors */
4831
10
        if ( media_type_str_lower_case != NULL ) {
4832
            /* SDP needs a transport layer to determine request/response */
4833
0
            if (!strcmp(media_type_str_lower_case, "application/sdp")) {
4834
                /* Resends don't count */
4835
0
                if (resend_for_packet == 0) {
4836
0
                    if (line_type == REQUEST_LINE) {
4837
0
                        DPRINT(("calling setup_sdp_transport() SDP_EXCHANGE_OFFER frame=%d",
4838
0
                                pinfo->num));
4839
0
                        DINDENT();
4840
0
                        setup_sdp_transport(next_tvb, pinfo, SDP_EXCHANGE_OFFER, pinfo->num, sip_delay_sdp_changes, &setup_info);
4841
0
                        DENDENT();
4842
0
                    } else if (line_type == STATUS_LINE) {
4843
0
                        if (stat_info->response_code >= 400) {
4844
0
                            DPRINT(("calling setup_sdp_transport() SDP_EXCHANGE_ANSWER_REJECT "
4845
0
                                    "request_frame=%d, this=%d",
4846
0
                                    request_for_response, pinfo->num));
4847
0
                            DINDENT();
4848
                            /* SIP client request failed, so SDP offer should fail */
4849
0
                            setup_sdp_transport(next_tvb, pinfo, SDP_EXCHANGE_ANSWER_REJECT, request_for_response, sip_delay_sdp_changes, &setup_info);
4850
0
                            DENDENT();
4851
0
                        }
4852
0
                        else if ((stat_info->response_code >= 200) && (stat_info->response_code <= 299)) {
4853
0
                            DPRINT(("calling setup_sdp_transport() SDP_EXCHANGE_ANSWER_ACCEPT "
4854
0
                                    "request_frame=%d, this=%d",
4855
0
                                    request_for_response, pinfo->num));
4856
0
                            DINDENT();
4857
                            /* SIP success request, so SDP offer should be accepted */
4858
0
                            setup_sdp_transport(next_tvb, pinfo, SDP_EXCHANGE_ANSWER_ACCEPT, request_for_response, sip_delay_sdp_changes, &setup_info);
4859
0
                            DENDENT();
4860
0
                        }
4861
0
                    }
4862
0
                } else {
4863
0
                    DPRINT(("calling setup_sdp_transport() resend_for_packet "
4864
0
                            "request_frame=%d, this=%d",
4865
0
                            request_for_response, pinfo->num));
4866
0
                    DINDENT();
4867
0
                    setup_sdp_transport_resend(pinfo->num, resend_for_packet);
4868
0
                    DENDENT();
4869
0
                }
4870
0
            }
4871
4872
            /* XXX: why is this called even if setup_sdp_transport() was called before? That will
4873
                    parse the SDP a second time, for 'application/sdp' media MIME bodies */
4874
0
            DPRINT(("calling dissector_try_string_with_data()"));
4875
0
            DINDENT();
4876
0
            found_match = dissector_try_string_with_data(media_type_dissector_table,
4877
0
                                               media_type_str_lower_case,
4878
0
                                               next_tvb, pinfo,
4879
0
                                               message_body_tree, true, &content_info);
4880
0
            DENDENT();
4881
0
            DPRINT(("done calling dissector_try_string_with_data() with found_match=%u", found_match));
4882
4883
0
            if (!found_match &&
4884
0
                !strncmp(media_type_str_lower_case, "multipart/", sizeof("multipart/")-1)) {
4885
0
                DPRINT(("calling dissector_try_string_with_data() for multipart"));
4886
0
                DINDENT();
4887
                /* Try to decode the unknown multipart subtype anyway */
4888
0
                found_match = dissector_try_string_with_data(media_type_dissector_table,
4889
0
                                                   "multipart/",
4890
0
                                                   next_tvb, pinfo,
4891
0
                                                   message_body_tree, true, &content_info);
4892
0
                DENDENT();
4893
0
                DPRINT(("done calling dissector_try_string_with_data() with found_match=%u", found_match));
4894
0
            }
4895
            /* If no match dump as text */
4896
0
        }
4897
10
        if ( found_match == 0 )
4898
10
        {
4899
10
            DPRINT(("calling dissector_try_heuristic() with found_match=0"));
4900
10
            DINDENT();
4901
10
            if (!(dissector_try_heuristic(heur_subdissector_list,
4902
10
                              next_tvb, pinfo, message_body_tree, &hdtbl_entry, NULL))) {
4903
10
                int tmp_offset = 0;
4904
126
                while (tvb_offset_exists(next_tvb, tmp_offset)) {
4905
116
                    tvb_find_line_end(next_tvb, tmp_offset, -1, &next_offset, false);
4906
116
                    linelen = next_offset - tmp_offset;
4907
116
                    proto_tree_add_format_text(message_body_tree, next_tvb,
4908
116
                                tmp_offset, linelen);
4909
116
                    tmp_offset = next_offset;
4910
116
                }/* end while */
4911
10
            }
4912
10
            DENDENT();
4913
10
        }
4914
10
        offset += datalen;
4915
10
    }
4916
4917
    /* And add the filterable field to the request/response line */
4918
91
    if (reqresp_tree)
4919
18
    {
4920
18
        proto_item *item;
4921
18
        item = proto_tree_add_boolean(reqresp_tree, hf_sip_resend, tvb, orig_offset, 0,
4922
18
                                      resend_for_packet > 0);
4923
18
        proto_item_set_generated(item);
4924
18
        if (resend_for_packet > 0)
4925
0
        {
4926
0
            item = proto_tree_add_uint(reqresp_tree, hf_sip_original_frame,
4927
0
                                       tvb, orig_offset, 0, resend_for_packet);
4928
0
            proto_item_set_generated(item);
4929
0
        }
4930
4931
18
        if (request_for_response > 0)
4932
0
        {
4933
0
            item = proto_tree_add_uint(reqresp_tree, hf_sip_matching_request_frame,
4934
0
                                       tvb, orig_offset, 0, request_for_response);
4935
0
            proto_item_set_generated(item);
4936
0
            item = proto_tree_add_uint(reqresp_tree, hf_sip_response_time,
4937
0
                                       tvb, orig_offset, 0, response_time);
4938
0
            proto_item_set_generated(item);
4939
0
            if ((line_type == STATUS_LINE)&&(strcmp(cseq_method, "BYE") == 0)){
4940
0
                item = proto_tree_add_uint(reqresp_tree, hf_sip_release_time,
4941
0
                                          tvb, orig_offset, 0, response_time);
4942
0
                proto_item_set_generated(item);
4943
0
            }
4944
0
        }
4945
18
    }
4946
4947
91
    if (ts != NULL)
4948
18
        proto_item_set_len(ts, offset - orig_offset);
4949
4950
91
    if (global_sip_raw_text)
4951
0
        tvb_raw_text_add(tvb, orig_offset, offset - orig_offset, body_offset, pinfo, tree);
4952
4953
    /* Append a brief summary to the SIP root item */
4954
91
    if (stat_info->request_method) {
4955
18
        proto_item_append_text(ts, " (%s)", stat_info->request_method);
4956
18
    }
4957
73
    else {
4958
73
        proto_item_append_text(ts, " (%u)", stat_info->response_code);
4959
73
    }
4960
91
    return offset - orig_offset;
4961
103
}
4962
4963
/* Display filter for SIP Request-Line */
4964
static void
4965
dfilter_sip_request_line(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int offset, unsigned meth_len, int linelen)
4966
103
{
4967
103
    const uint8_t   *value;
4968
103
    unsigned   parameter_len = meth_len;
4969
103
    uri_offset_info uri_offsets;
4970
4971
    /*
4972
     * We know we have the entire method; otherwise, "sip_parse_line()"
4973
     * would have returned OTHER_LINE.
4974
     * Request-Line  =  Method SP Request-URI SP SIP-Version CRLF
4975
     * SP = single space
4976
     * Request-URI    =  SIP-URI / SIPS-URI / absoluteURI
4977
     */
4978
4979
    /* get method string*/
4980
103
    proto_tree_add_item_ret_string(tree, hf_sip_Method, tvb, offset, parameter_len, ENC_ASCII | ENC_NA,
4981
103
        pinfo->pool, &value);
4982
4983
    /* Copy request method for telling tap */
4984
103
    stat_info->request_method = (char*)value;
4985
4986
103
    if (tree) {
4987
        /* build Request-URI tree*/
4988
103
        offset += parameter_len + 1;
4989
103
        linelen -= parameter_len + 1;
4990
103
        sip_uri_offset_init(&uri_offsets);
4991
        /* calc R-URI len*/
4992
103
        uri_offsets.uri_end = tvb_find_uint8(tvb, offset, linelen, ' ')-1;
4993
103
        dissect_sip_uri(tvb, pinfo, offset, offset + linelen, &uri_offsets);
4994
103
        display_sip_uri(tvb, tree, pinfo, &uri_offsets, &sip_req_uri);
4995
103
    }
4996
103
}
4997
4998
/* Display filter for SIP Status-Line */
4999
static void
5000
dfilter_sip_status_line(tvbuff_t *tvb, proto_tree *tree, packet_info *pinfo, int line_end, int offset)
5001
0
{
5002
0
    int response_code = 0;
5003
0
    bool response_code_valid;
5004
0
    proto_item* pi;
5005
0
    int diag_len;
5006
0
    tvbuff_t *next_tvb;
5007
5008
    /*
5009
     * We know we have the entire status code; otherwise,
5010
     * "sip_parse_line()" would have returned OTHER_LINE.
5011
     * We also know that we have a version string followed by a
5012
     * space at the beginning of the line, for the same reason.
5013
     */
5014
0
    offset = offset + SIP2_HDR_LEN + 1;
5015
0
    response_code_valid = ws_strtoi32((char*)tvb_get_string_enc(pinfo->pool, tvb, offset, 3,
5016
0
        ENC_UTF_8|ENC_NA), NULL, &response_code);
5017
5018
    /* Add numerical response code to tree */
5019
0
    pi = proto_tree_add_uint(tree, hf_sip_Status_Code, tvb, offset, 3, response_code);
5020
0
    if (!response_code_valid)
5021
0
        expert_add_info(pinfo, pi, &ei_sip_Status_Code_invalid);
5022
5023
    /* Add response code for sending to tap */
5024
0
    stat_info->response_code = response_code;
5025
5026
    /* Skip past the response code and possible trailing space */
5027
0
    offset = offset + 3 + 1;
5028
5029
    /* Check for diagnostics */
5030
0
    diag_len = line_end - (SIP2_HDR_LEN + 1 + 3 + 1);
5031
0
    if((diag_len) <= 0)
5032
0
        return;
5033
5034
    /* If we have a SIP diagnostics sub dissector call it */
5035
0
    if(sip_diag_handle){
5036
0
        next_tvb = tvb_new_subset_length(tvb, offset, diag_len);
5037
0
        call_dissector_only(sip_diag_handle, next_tvb, pinfo, tree, NULL);
5038
0
    }
5039
0
}
5040
5041
/* From section 4.1 of RFC 2543:
5042
 *
5043
 * Request-Line  =  Method SP Request-URI SP SIP-Version CRLF
5044
 *
5045
 * From section 5.1 of RFC 2543:
5046
 *
5047
 * Status-Line  =  SIP-version SP Status-Code SP Reason-Phrase CRLF
5048
 *
5049
 * From section 7.1 of RFC 3261:
5050
 *
5051
 * Unlike HTTP, SIP treats the version number as a literal string.
5052
 * In practice, this should make no difference.
5053
 */
5054
static line_type_t
5055
sip_parse_line(tvbuff_t *tvb, int offset, int linelen, unsigned *token_1_lenp)
5056
565
{
5057
565
    int space_offset;
5058
565
    int token_1_start;
5059
565
    unsigned token_1_len;
5060
565
    int token_2_start;
5061
565
    unsigned token_2_len;
5062
565
    int token_3_start;
5063
565
    unsigned token_3_len;
5064
565
    int colon_pos;
5065
5066
565
    token_1_start = offset;
5067
565
    space_offset = tvb_find_uint8(tvb, token_1_start, -1, ' ');
5068
565
    if ((space_offset == -1) || (space_offset == token_1_start)) {
5069
        /*
5070
         * Either there's no space in the line (which means
5071
         * the line is empty or doesn't have a token followed
5072
         * by a space; neither is valid for a request or status), or
5073
         * the first character in the line is a space (meaning
5074
         * the method is empty, which isn't valid for a request,
5075
         * or the SIP version is empty, which isn't valid for a
5076
         * status).
5077
         */
5078
358
        return OTHER_LINE;
5079
358
    }
5080
207
    token_1_len = space_offset - token_1_start;
5081
207
    token_2_start = space_offset + 1;
5082
207
    space_offset = tvb_find_uint8(tvb, token_2_start, -1, ' ');
5083
207
    if (space_offset == -1) {
5084
        /*
5085
         * There's no space after the second token, so we don't
5086
         * have a third token.
5087
         */
5088
40
        return OTHER_LINE;
5089
40
    }
5090
167
    token_2_len = space_offset - token_2_start;
5091
167
    token_3_start = space_offset + 1;
5092
167
    token_3_len = token_1_start + linelen - token_3_start;
5093
5094
167
    *token_1_lenp = token_1_len;
5095
5096
    /*
5097
     * Is the first token a version string?
5098
     */
5099
167
    if ( (strict_sip_version && (
5100
167
        token_1_len == SIP2_HDR_LEN
5101
11
        && tvb_strneql(tvb, token_1_start, SIP2_HDR, SIP2_HDR_LEN) == 0)
5102
167
    ) || (! strict_sip_version && (
5103
0
        tvb_strncaseeql(tvb, token_1_start, "SIP/", 4) == 0)
5104
167
    )) {
5105
        /*
5106
         * Yes, so this is either a Status-Line or something
5107
         * else other than a Request-Line.  To be a Status-Line,
5108
         * the second token must be a 3-digit number.
5109
         */
5110
0
        if (token_2_len != 3) {
5111
            /*
5112
             * We don't have 3-character status code.
5113
             */
5114
0
            return OTHER_LINE;
5115
0
        }
5116
0
        if (!g_ascii_isdigit(tvb_get_uint8(tvb, token_2_start)) ||
5117
0
            !g_ascii_isdigit(tvb_get_uint8(tvb, token_2_start + 1)) ||
5118
0
            !g_ascii_isdigit(tvb_get_uint8(tvb, token_2_start + 2))) {
5119
            /*
5120
             * 3 characters yes, 3 digits no.
5121
             */
5122
0
            return OTHER_LINE;
5123
0
        }
5124
0
        return STATUS_LINE;
5125
167
    } else {
5126
        /*
5127
         * No, so this is either a Request-Line or something
5128
         * other than a Status-Line.  To be a Request-Line, the
5129
         * second token must be a URI and the third token must
5130
         * be a version string.
5131
         */
5132
167
        if (token_2_len < 3) {
5133
            /*
5134
             * We don't have a URI consisting of at least 3
5135
             * characters.
5136
             */
5137
22
            return OTHER_LINE;
5138
22
        }
5139
145
        colon_pos = tvb_find_uint8(tvb, token_2_start + 1, -1, ':');
5140
145
        if (colon_pos == -1) {
5141
            /*
5142
             * There is no colon after the method, so the URI
5143
             * doesn't have a colon in it, so it's not valid.
5144
             */
5145
28
            return OTHER_LINE;
5146
28
        }
5147
117
        if (colon_pos >= token_3_start) {
5148
            /*
5149
             * The colon is in the version string, not the URI.
5150
             */
5151
6
            return OTHER_LINE;
5152
6
        }
5153
        /* XXX - Check for a proper URI prefix? */
5154
111
        if ( (strict_sip_version && (
5155
111
            token_3_len != SIP2_HDR_LEN
5156
104
            || tvb_strneql(tvb, token_3_start, SIP2_HDR, SIP2_HDR_LEN) == -1)
5157
111
        ) || (! strict_sip_version && (
5158
0
            tvb_strncaseeql(tvb, token_3_start, "SIP/", 4) == -1)
5159
103
        )) {
5160
            /*
5161
             * The version string isn't an SIP version 2.0 version
5162
             * string.
5163
             */
5164
8
            return OTHER_LINE;
5165
8
        }
5166
103
        return REQUEST_LINE;
5167
111
    }
5168
167
}
5169
5170
static bool sip_is_known_request(tvbuff_t *tvb, packet_info* pinfo, int meth_offset,
5171
                     unsigned meth_len, unsigned *meth_idx)
5172
103
{
5173
103
    unsigned i;
5174
103
    char *meth_name;
5175
5176
103
    meth_name = (char*)tvb_get_string_enc(pinfo->pool, tvb, meth_offset, meth_len, ENC_UTF_8|ENC_NA);
5177
5178
1.85k
    for (i = 1; i < array_length(sip_methods); i++) {
5179
1.75k
        if (meth_len == strlen(sip_methods[i]) &&
5180
30
            strncmp(meth_name, sip_methods[i], meth_len) == 0)
5181
0
        {
5182
0
            *meth_idx = i;
5183
0
            return true;
5184
0
        }
5185
1.75k
    }
5186
5187
103
    return false;
5188
103
}
5189
5190
/*
5191
 * Returns index of method in sip_headers
5192
 * Header namne should be in lower case
5193
 */
5194
static int sip_is_known_sip_header(char *header_name, unsigned header_len)
5195
659
{
5196
659
    unsigned pos;
5197
5198
    /* Compact name is one character long */
5199
659
    if(header_len>1){
5200
186
        pos = GPOINTER_TO_UINT(g_hash_table_lookup(sip_headers_hash, header_name));
5201
186
        if (pos!=0)
5202
0
            return pos;
5203
186
    }
5204
5205
    /* Look for compact name match */
5206
37.1k
    for (pos = 1; pos < array_length(sip_headers); pos++) {
5207
36.9k
        if (sip_headers[pos].compact_name != NULL &&
5208
6.63k
                header_len == strlen(sip_headers[pos].compact_name) &&
5209
2.87k
                g_ascii_strncasecmp(header_name, sip_headers[pos].compact_name, header_len) == 0)
5210
470
            return pos;
5211
36.9k
    }
5212
5213
189
    return -1;
5214
659
}
5215
5216
/*
5217
 * Display the entire message as raw text.
5218
 */
5219
static void
5220
tvb_raw_text_add(tvbuff_t *tvb, int offset, int length, int body_offset, packet_info* pinfo, proto_tree *tree)
5221
0
{
5222
0
    proto_tree *raw_tree;
5223
0
    proto_item *ti;
5224
0
    int next_offset, linelen, end_offset;
5225
0
    char *str;
5226
0
    tvbuff_t* body_tvb = NULL;
5227
5228
0
    ti = proto_tree_add_item(tree, proto_raw_sip, tvb, offset, length, ENC_NA);
5229
0
    raw_tree = proto_item_add_subtree(ti, ett_raw_text);
5230
5231
0
    end_offset = offset + length;
5232
5233
0
    if (body_offset < end_offset
5234
0
        && global_sip_raw_text_body_default_encoding != IANA_CS_UTF_8
5235
        /* UTF-8 compatible with ASCII */
5236
0
        && global_sip_raw_text_body_default_encoding != IANA_CS_US_ASCII)
5237
0
    {
5238
        /* Create body tvb with new character encoding */
5239
0
        uint32_t iana_charset_id = global_sip_raw_text_body_default_encoding;
5240
0
        unsigned ws_encoding_id = mibenum_charset_to_encoding((unsigned)iana_charset_id);
5241
5242
0
        if (ws_encoding_id != (ENC_NA | ENC_ASCII) && ws_encoding_id != (ENC_NA | ENC_UTF_8)) {
5243
            /* Encoding body with the new encoding */
5244
0
            char* encoding_name = val_to_str_ext(pinfo->pool, iana_charset_id,
5245
0
                &mibenum_vals_character_sets_ext, "UNKNOWN");
5246
0
            const char* data_str = (char*)tvb_get_string_enc(pinfo->pool, tvb, body_offset,
5247
0
                                                        end_offset - body_offset, ws_encoding_id);
5248
0
            size_t l = strlen(data_str);
5249
0
            body_tvb = tvb_new_child_real_data(tvb, (const uint8_t*)data_str, (unsigned)l, (int)l);
5250
0
            add_new_data_source(pinfo, body_tvb, wmem_strdup_printf(pinfo->pool, "Decoded %s text", encoding_name));
5251
0
        }
5252
0
    }
5253
5254
    /* Display the headers of SIP message as raw text */
5255
0
    while (offset < body_offset) {
5256
0
        tvb_find_line_end(tvb, offset, -1, &next_offset, false);
5257
0
        linelen = next_offset - offset;
5258
0
        if (raw_tree) {
5259
0
            if (global_sip_raw_text_without_crlf)
5260
0
                str = tvb_format_text_wsp(pinfo->pool, tvb, offset, linelen);
5261
0
            else
5262
0
                str = tvb_format_text(pinfo->pool, tvb, offset, linelen);
5263
0
            proto_tree_add_string_format(raw_tree, hf_sip_raw_line, tvb, offset, linelen,
5264
0
                             str,
5265
0
                             "%s",
5266
0
                             str);
5267
0
        }
5268
0
        offset = next_offset;
5269
0
    }
5270
5271
0
    DISSECTOR_ASSERT_HINT(offset == body_offset, "The offset must be equal to body_offset before dissect body as raw text.");
5272
5273
0
    if (body_offset < end_offset) {
5274
        /* Dissect the body of SIP message as raw text */
5275
0
        if (body_tvb) {
5276
0
            offset = 0;
5277
0
            end_offset = tvb_captured_length_remaining(body_tvb, 0);
5278
0
        } else {
5279
0
            body_tvb = tvb; /* reuse old offset and end_offset */
5280
0
        }
5281
5282
0
        while (offset < end_offset) {
5283
0
            tvb_find_line_end(body_tvb, offset, -1, &next_offset, false);
5284
0
            linelen = next_offset - offset;
5285
0
            if (raw_tree) {
5286
0
                if (global_sip_raw_text_without_crlf)
5287
0
                    str = tvb_format_text_wsp(pinfo->pool, body_tvb, offset, linelen);
5288
0
                else
5289
0
                    str = tvb_format_text(pinfo->pool, body_tvb, offset, linelen);
5290
5291
0
                proto_tree_add_string_format(raw_tree, hf_sip_raw_line, body_tvb, offset,
5292
0
                    linelen, str, "%s", str);
5293
0
            }
5294
0
            offset = next_offset;
5295
0
        }
5296
0
    }
5297
0
}
5298
5299
/* Check to see if this packet is a resent request.  Return value is the frame number
5300
   of the original frame this packet seems to be resending (0 = no resend). */
5301
unsigned sip_is_packet_resend(packet_info *pinfo,
5302
            const char *cseq_method,
5303
            char *call_id,
5304
            unsigned char cseq_number_set,
5305
            uint32_t cseq_number, line_type_t line_type)
5306
18
{
5307
18
    uint32_t cseq_to_compare = 0;
5308
18
    sip_hash_key   key;
5309
18
    sip_hash_key   *p_key = 0;
5310
18
    sip_hash_value *p_val = 0;
5311
18
    sip_frame_result_value *sip_frame_result = NULL;
5312
18
    unsigned result = 0;
5313
5314
    /* Don't consider packets that appear to be resent only because
5315
       they are e.g. returned in ICMP unreachable messages. */
5316
18
    if (pinfo->flags.in_error_pkt)
5317
0
    {
5318
0
        return 0;
5319
0
    }
5320
5321
    /* A broken packet may have no cseq number set. Don't consider it as
5322
       a resend */
5323
18
    if (!cseq_number_set)
5324
18
    {
5325
18
        return 0;
5326
18
    }
5327
5328
    /* Return any answer stored from previous dissection */
5329
0
    if (pinfo->fd->visited)
5330
0
    {
5331
0
        sip_frame_result = (sip_frame_result_value*)p_get_proto_data(wmem_file_scope(), pinfo, proto_sip, pinfo->curr_layer_num);
5332
0
        if (sip_frame_result != NULL)
5333
0
        {
5334
0
            return sip_frame_result->original_frame_num;
5335
0
        }
5336
0
        else
5337
0
        {
5338
0
            return 0;
5339
0
        }
5340
0
    }
5341
5342
    /* No packet entry found, consult global hash table */
5343
5344
    /* Prepare the key */
5345
0
    (void) g_strlcpy(key.call_id, call_id, MAX_CALL_ID_SIZE);
5346
5347
    /*  We're only using these addresses locally (for the hash lookup) so
5348
     *  there is no need to make a (g_malloc'd) copy of them.
5349
     */
5350
0
    set_address(&key.dest_address, pinfo->net_dst.type, pinfo->net_dst.len,
5351
0
            pinfo->net_dst.data);
5352
0
    set_address(&key.source_address, pinfo->net_src.type,
5353
0
            pinfo->net_src.len, pinfo->net_src.data);
5354
0
    key.dest_port = pinfo->destport;
5355
0
    if (sip_retrans_the_same_sport) {
5356
0
        key.source_port = pinfo->srcport;
5357
0
    } else {
5358
0
        key.source_port = MAGIC_SOURCE_PORT;
5359
0
    }
5360
0
    key.ptype = pinfo->ptype;
5361
5362
    /* Do the lookup */
5363
0
    p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
5364
5365
0
    if (p_val)
5366
0
    {
5367
        /* Table entry found, we'll use its value for comparison */
5368
0
        cseq_to_compare = p_val->cseq;
5369
5370
        /* First time through, must update value with current details if
5371
            cseq number has changed */
5372
0
        if (cseq_number != p_val->cseq)
5373
0
        {
5374
0
            p_val->cseq = cseq_number;
5375
0
            p_val->method = wmem_strdup(wmem_file_scope(), cseq_method);
5376
0
            p_val->transaction_state = nothing_seen;
5377
0
            p_val->frame_number = 0;
5378
0
            if (line_type == REQUEST_LINE)
5379
0
            {
5380
0
                p_val->request_time = pinfo->abs_ts;
5381
0
            }
5382
0
        }
5383
0
    }
5384
0
    else
5385
0
    {
5386
        /* Need to create a new table entry */
5387
5388
        /* Allocate a new key and value */
5389
0
        p_key = wmem_new(wmem_file_scope(), sip_hash_key);
5390
0
        p_val = wmem_new0(wmem_file_scope(), sip_hash_value);
5391
5392
        /* Fill in key and value details */
5393
0
        snprintf(p_key->call_id, MAX_CALL_ID_SIZE, "%s", call_id);
5394
0
        copy_address_wmem(wmem_file_scope(), &(p_key->dest_address), &pinfo->net_dst);
5395
0
        copy_address_wmem(wmem_file_scope(), &(p_key->source_address), &pinfo->net_src);
5396
0
        p_key->dest_port = pinfo->destport;
5397
0
        if (sip_retrans_the_same_sport) {
5398
0
            p_key->source_port = pinfo->srcport;
5399
0
        } else {
5400
0
            p_key->source_port = MAGIC_SOURCE_PORT;
5401
0
        }
5402
0
        p_key->ptype = pinfo->ptype;
5403
5404
0
        p_val->cseq = cseq_number;
5405
0
        p_val->method = wmem_strdup(wmem_file_scope(), cseq_method);
5406
0
        p_val->transaction_state = nothing_seen;
5407
0
        if (line_type == REQUEST_LINE)
5408
0
        {
5409
0
            p_val->request_time = pinfo->abs_ts;
5410
0
        }
5411
5412
        /* Add entry */
5413
0
        g_hash_table_insert(sip_hash, p_key, p_val);
5414
5415
        /* Assume have seen no cseq yet */
5416
0
        cseq_to_compare = 0;
5417
0
    }
5418
5419
5420
    /******************************************/
5421
    /* Is it a resend???                      */
5422
5423
    /* Does this look like a resent request (discount ACK, CANCEL, or a
5424
       different method from the original one) ? */
5425
5426
0
    if ((line_type == REQUEST_LINE) && (cseq_number == cseq_to_compare) &&
5427
0
        (p_val->transaction_state == request_seen) &&
5428
0
        (strcmp(cseq_method, p_val->method) == 0) &&
5429
0
        (strcmp(cseq_method, "ACK") != 0) &&
5430
0
        (strcmp(cseq_method, "CANCEL") != 0))
5431
0
    {
5432
0
        result = p_val->frame_number;
5433
0
    }
5434
5435
    /* Does this look like a resent final response ? */
5436
0
    if ((line_type == STATUS_LINE) && (cseq_number == cseq_to_compare) &&
5437
0
        (p_val->transaction_state == final_response_seen) &&
5438
0
        (strcmp(cseq_method, p_val->method) == 0) &&
5439
0
        (stat_info->response_code >= 200) &&
5440
0
        (stat_info->response_code == p_val->response_code))
5441
0
    {
5442
0
        result = p_val->frame_number;
5443
0
    }
5444
5445
    /* Update state for this entry */
5446
0
    p_val->cseq = cseq_number;
5447
5448
0
    switch (line_type)
5449
0
    {
5450
0
        case REQUEST_LINE:
5451
0
            p_val->transaction_state = request_seen;
5452
0
            if (!result)
5453
0
            {
5454
                /* This frame is the original request */
5455
0
                p_val->frame_number = pinfo->num;
5456
0
                p_val->request_time = pinfo->abs_ts;
5457
0
            }
5458
0
            break;
5459
0
        case STATUS_LINE:
5460
0
            if (stat_info->response_code >= 200)
5461
0
            {
5462
0
                p_val->response_code = stat_info->response_code;
5463
0
                p_val->transaction_state = final_response_seen;
5464
0
                if (!result)
5465
0
                {
5466
                    /* This frame is the original response */
5467
0
                    p_val->frame_number = pinfo->num;
5468
0
                }
5469
0
            }
5470
0
            else
5471
0
            {
5472
0
                p_val->transaction_state = provisional_response_seen;
5473
0
            }
5474
0
            break;
5475
0
        default:
5476
0
            break;
5477
0
    }
5478
5479
0
    sip_frame_result = (sip_frame_result_value *)p_get_proto_data(wmem_file_scope(), pinfo, proto_sip, pinfo->curr_layer_num);
5480
0
    if (sip_frame_result == NULL)
5481
0
    {
5482
0
        sip_frame_result = wmem_new0(wmem_file_scope(), sip_frame_result_value);
5483
0
        p_add_proto_data(wmem_file_scope(), pinfo, proto_sip, pinfo->curr_layer_num, sip_frame_result);
5484
0
    }
5485
5486
    /* Store return value with this packet */
5487
0
    sip_frame_result->original_frame_num = result;
5488
5489
0
    return result;
5490
0
}
5491
5492
5493
/* Check to see if this packet is a resent request.  Return value is the frame number
5494
   of the original frame this packet seems to be resending (0 = no resend). */
5495
unsigned sip_find_request(packet_info *pinfo,
5496
            const char *cseq_method,
5497
            char *call_id,
5498
            unsigned char cseq_number_set,
5499
            uint32_t cseq_number,
5500
            uint32_t *response_time)
5501
0
{
5502
0
    uint32_t cseq_to_compare = 0;
5503
0
    sip_hash_key   key;
5504
0
    sip_hash_value *p_val = 0;
5505
0
    sip_frame_result_value *sip_frame_result = NULL;
5506
0
    unsigned result = 0;
5507
0
    int seconds_between_packets;
5508
0
    int nseconds_between_packets;
5509
5510
    /* Ignore error (usually ICMP) frames */
5511
0
    if (pinfo->flags.in_error_pkt)
5512
0
    {
5513
0
        return 0;
5514
0
    }
5515
5516
    /* A broken packet may have no cseq number set. Ignore. */
5517
0
    if (!cseq_number_set)
5518
0
    {
5519
0
        return 0;
5520
0
    }
5521
5522
    /* Return any answer stored from previous dissection */
5523
0
    if (pinfo->fd->visited)
5524
0
    {
5525
0
        sip_frame_result = (sip_frame_result_value*)p_get_proto_data(wmem_file_scope(), pinfo, proto_sip, pinfo->curr_layer_num);
5526
0
        if (sip_frame_result != NULL)
5527
0
        {
5528
0
            *response_time = sip_frame_result->response_time;
5529
0
            return sip_frame_result->response_request_frame_num;
5530
0
        }
5531
0
        else
5532
0
        {
5533
0
            return 0;
5534
0
        }
5535
0
    }
5536
5537
    /* No packet entry found, consult global hash table */
5538
5539
    /* Prepare the key */
5540
0
    (void) g_strlcpy(key.call_id, call_id, MAX_CALL_ID_SIZE);
5541
5542
    /* Looking for matching request, so reverse addresses for this lookup */
5543
0
    set_address(&key.dest_address, pinfo->net_src.type, pinfo->net_src.len,
5544
0
            pinfo->net_src.data);
5545
0
    set_address(&key.source_address, pinfo->net_dst.type, pinfo->net_dst.len,
5546
0
            pinfo->net_dst.data);
5547
0
    key.dest_port = pinfo->srcport;
5548
0
    key.source_port = pinfo->destport;
5549
0
    key.ptype = pinfo->ptype;
5550
5551
    /* Do the lookup */
5552
0
    p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
5553
5554
0
    if (p_val)
5555
0
    {
5556
        /* Table entry found, we'll use its value for comparison */
5557
0
        cseq_to_compare = p_val->cseq;
5558
0
    }
5559
0
    else
5560
0
    {
5561
        /* We don't have the request */
5562
0
        return 0;
5563
0
    }
5564
5565
5566
    /**************************************************/
5567
    /* Is it a response to a request that we've seen? */
5568
0
    if ((cseq_number == cseq_to_compare) &&
5569
0
        (p_val->transaction_state == request_seen) &&
5570
0
        (strcmp(cseq_method, p_val->method) == 0))
5571
0
    {
5572
0
        result = p_val->frame_number;
5573
0
    }
5574
5575
5576
    /* Store return value with this packet */
5577
0
    sip_frame_result = (sip_frame_result_value *)p_get_proto_data(wmem_file_scope(), pinfo, proto_sip, pinfo->curr_layer_num);
5578
0
    if (sip_frame_result == NULL)
5579
0
    {
5580
        /* Allocate and set all values to zero */
5581
0
        sip_frame_result = wmem_new0(wmem_file_scope(), sip_frame_result_value);
5582
0
        p_add_proto_data(wmem_file_scope(), pinfo, proto_sip, pinfo->curr_layer_num, sip_frame_result);
5583
0
    }
5584
5585
0
    sip_frame_result->response_request_frame_num = result;
5586
5587
    /* Work out response time */
5588
0
    seconds_between_packets = (int)
5589
0
        (pinfo->abs_ts.secs - p_val->request_time.secs);
5590
0
    nseconds_between_packets =
5591
0
         pinfo->abs_ts.nsecs - p_val->request_time.nsecs;
5592
0
    sip_frame_result->response_time = (seconds_between_packets*1000) +
5593
0
                                      (nseconds_between_packets / 1000000);
5594
0
    *response_time = sip_frame_result->response_time;
5595
5596
0
    return result;
5597
0
}
5598
5599
/*
5600
 * Find the initial INVITE to calculate the total setup time
5601
 */
5602
unsigned sip_find_invite(packet_info *pinfo,
5603
            const char *cseq_method _U_,
5604
            char *call_id,
5605
            unsigned char cseq_number_set,
5606
            uint32_t cseq_number _U_,
5607
            uint32_t *response_time)
5608
0
{
5609
#if 0
5610
    uint32_t cseq_to_compare = 0;
5611
#endif
5612
0
    sip_hash_key   key;
5613
0
    sip_hash_value *p_val = 0;
5614
0
    sip_frame_result_value *sip_frame_result = NULL;
5615
0
    unsigned result = 0;
5616
0
    int seconds_between_packets;
5617
0
    int nseconds_between_packets;
5618
5619
    /* Ignore error (usually ICMP) frames */
5620
0
    if (pinfo->flags.in_error_pkt)
5621
0
    {
5622
0
        return 0;
5623
0
    }
5624
5625
    /* A broken packet may have no cseq number set. Ignore. */
5626
0
    if (!cseq_number_set)
5627
0
    {
5628
0
        return 0;
5629
0
    }
5630
5631
    /* Return any answer stored from previous dissection */
5632
0
    if (pinfo->fd->visited)
5633
0
    {
5634
0
        sip_frame_result = (sip_frame_result_value*)p_get_proto_data(wmem_file_scope(), pinfo, proto_sip, pinfo->curr_layer_num);
5635
0
        if (sip_frame_result != NULL)
5636
0
        {
5637
0
            *response_time = sip_frame_result->response_time;
5638
0
            return sip_frame_result->response_request_frame_num;
5639
0
        }
5640
0
        else
5641
0
        {
5642
0
            return 0;
5643
0
        }
5644
0
    }
5645
5646
    /* No packet entry found, consult global hash table */
5647
5648
    /* Prepare the key */
5649
0
    (void) g_strlcpy(key.call_id, call_id, MAX_CALL_ID_SIZE);
5650
5651
    /* Looking for matching INVITE */
5652
0
    set_address(&key.dest_address, pinfo->net_dst.type, pinfo->net_dst.len,
5653
0
            pinfo->net_dst.data);
5654
0
    set_address(&key.source_address, pinfo->net_src.type, pinfo->net_src.len,
5655
0
            pinfo->net_src.data);
5656
0
    key.dest_port = pinfo->destport;
5657
0
    key.source_port = pinfo->srcport;
5658
0
    key.ptype = pinfo->ptype;
5659
5660
    /* Do the lookup */
5661
0
    p_val = (sip_hash_value*)g_hash_table_lookup(sip_hash, &key);
5662
5663
0
    if (p_val)
5664
0
    {
5665
#if 0
5666
        /* Table entry found, we'll use its value for comparison */
5667
        cseq_to_compare = p_val->cseq;
5668
#endif
5669
0
    }
5670
0
    else
5671
0
    {
5672
        /* We don't have the request */
5673
0
        return 0;
5674
0
    }
5675
5676
5677
    /**************************************************/
5678
    /* Is it a response to a request that we've seen? */
5679
#if 0
5680
    if ((cseq_number == cseq_to_compare) &&
5681
        (p_val->transaction_state == request_seen) &&
5682
        (strcmp(cseq_method, p_val->method) == 0))
5683
    {
5684
        result = p_val->frame_number;
5685
    }
5686
#endif
5687
5688
0
    result = p_val->frame_number;
5689
5690
    /* Store return value with this packet */
5691
0
    sip_frame_result = (sip_frame_result_value *)p_get_proto_data(wmem_file_scope(), pinfo, proto_sip, pinfo->curr_layer_num);
5692
0
    if (sip_frame_result == NULL)
5693
0
    {
5694
        /* Allocate and set all values to zero */
5695
0
        sip_frame_result = wmem_new0(wmem_file_scope(), sip_frame_result_value);
5696
0
        p_add_proto_data(wmem_file_scope(), pinfo, proto_sip,  pinfo->curr_layer_num, sip_frame_result);
5697
0
    }
5698
5699
0
    sip_frame_result->response_request_frame_num = result;
5700
5701
    /* Work out response time */
5702
0
    seconds_between_packets = (int)
5703
0
        (pinfo->abs_ts.secs - p_val->request_time.secs);
5704
0
    nseconds_between_packets =
5705
0
         pinfo->abs_ts.nsecs - p_val->request_time.nsecs;
5706
0
    sip_frame_result->response_time = (seconds_between_packets*1000) +
5707
0
                                      (nseconds_between_packets / 1000000);
5708
0
    *response_time = sip_frame_result->response_time;
5709
5710
5711
0
    return result;
5712
0
}
5713
5714
0
static bool sip_validate_authorization(sip_authorization_t *authorization_info, char *password) {
5715
0
    char ha1[33] = {0};
5716
0
    char ha2[33] = {0};
5717
0
    char response[33] = {0};
5718
0
    gcry_md_hd_t md5_handle;
5719
0
    if ( (authorization_info->qop == NULL) ||
5720
0
        (authorization_info->username == NULL) ||
5721
0
        (authorization_info->realm == NULL) ||
5722
0
        (authorization_info->method == NULL) ||
5723
0
        (authorization_info->uri == NULL) ||
5724
0
        (authorization_info->nonce == NULL) ) {
5725
0
        return true; /* If no qop, discard */
5726
0
    }
5727
0
    if (strcmp(authorization_info->qop, "auth") ||
5728
0
        (authorization_info->nonce_count == NULL) ||
5729
0
        (authorization_info->cnonce == NULL) ||
5730
0
        (authorization_info->response == NULL) ||
5731
0
        (password == NULL)) {
5732
0
        return true; /* Obsolete or not enough information, discard */
5733
0
    }
5734
5735
0
    if (gcry_md_open(&md5_handle, GCRY_MD_MD5, 0)) {
5736
0
        return false;
5737
0
    }
5738
5739
0
    gcry_md_write(md5_handle, authorization_info->username, strlen(authorization_info->username));
5740
0
    gcry_md_putc(md5_handle, ':');
5741
0
    gcry_md_write(md5_handle, authorization_info->realm, strlen(authorization_info->realm));
5742
0
    gcry_md_putc(md5_handle, ':');
5743
0
    gcry_md_write(md5_handle, password, strlen(password));
5744
    /* Array is zeroed out so there is always a \0 at index 32 for string termination */
5745
0
    bytes_to_hexstr(ha1, gcry_md_read(md5_handle, 0), HASH_MD5_LENGTH);
5746
0
    gcry_md_reset(md5_handle);
5747
0
    gcry_md_write(md5_handle, authorization_info->method, strlen(authorization_info->method));
5748
0
    gcry_md_putc(md5_handle, ':');
5749
0
    gcry_md_write(md5_handle, authorization_info->uri, strlen(authorization_info->uri));
5750
    /* Array is zeroed out so there is always a \0 at index 32 for string termination */
5751
0
    bytes_to_hexstr(ha2, gcry_md_read(md5_handle, 0), HASH_MD5_LENGTH);
5752
0
    gcry_md_reset(md5_handle);
5753
0
    gcry_md_write(md5_handle, ha1, strlen(ha1));
5754
0
    gcry_md_putc(md5_handle, ':');
5755
0
    gcry_md_write(md5_handle, authorization_info->nonce, strlen(authorization_info->nonce));
5756
0
    gcry_md_putc(md5_handle, ':');
5757
0
    gcry_md_write(md5_handle, authorization_info->nonce_count, strlen(authorization_info->nonce_count));
5758
0
    gcry_md_putc(md5_handle, ':');
5759
0
    gcry_md_write(md5_handle, authorization_info->cnonce, strlen(authorization_info->cnonce));
5760
0
    gcry_md_putc(md5_handle, ':');
5761
0
    gcry_md_write(md5_handle, authorization_info->qop, strlen(authorization_info->qop));
5762
0
    gcry_md_putc(md5_handle, ':');
5763
0
    gcry_md_write(md5_handle, ha2, strlen(ha2));
5764
    /* Array is zeroed out so there is always a \0 at index 32 for string termination */
5765
0
    bytes_to_hexstr(response, gcry_md_read(md5_handle, 0), HASH_MD5_LENGTH);
5766
0
    gcry_md_close(md5_handle);
5767
0
    if (!strncmp(response, authorization_info->response, 32)) {
5768
0
        return true;
5769
0
    }
5770
0
    return false;
5771
0
}
5772
5773
/* TAP STAT INFO */
5774
5775
/* TODO: extra codes to be added from SIP extensions?
5776
 * https://www.iana.org/assignments/sip-parameters/sip-parameters.xhtml#sip-parameters-6
5777
 */
5778
static const value_string sip_response_code_vals[] = {
5779
    { 999, "Unknown response"}, /* Must be first */
5780
5781
    { 100, "Trying"},
5782
    { 180, "Ringing"},
5783
    { 181, "Call Is Being Forwarded"},
5784
    { 182, "Queued"},
5785
    { 183, "Session Progress"},
5786
    { 199, "Informational - Others" },
5787
5788
    { 200, "OK"},
5789
    { 202, "Accepted"},
5790
    { 204, "No Notification"},
5791
    { 299, "Success - Others"}, /* used to keep track of other Success packets */
5792
5793
    { 300, "Multiple Choices"},
5794
    { 301, "Moved Permanently"},
5795
    { 302, "Moved Temporarily"},
5796
    { 305, "Use Proxy"},
5797
    { 380, "Alternative Service"},
5798
    { 399, "Redirection - Others"},
5799
5800
    { 400, "Bad Request"},
5801
    { 401, "Unauthorized"},
5802
    { 402, "Payment Required"},
5803
    { 403, "Forbidden"},
5804
    { 404, "Not Found"},
5805
    { 405, "Method Not Allowed"},
5806
    { 406, "Not Acceptable"},
5807
    { 407, "Proxy Authentication Required"},
5808
    { 408, "Request Timeout"},
5809
    { 410, "Gone"},
5810
    { 412, "Conditional Request Failed"},
5811
    { 413, "Request Entity Too Large"},
5812
    { 414, "Request-URI Too Long"},
5813
    { 415, "Unsupported Media Type"},
5814
    { 416, "Unsupported URI Scheme"},
5815
    { 420, "Bad Extension"},
5816
    { 421, "Extension Required"},
5817
    { 422, "Session Timer Too Small"},
5818
    { 423, "Interval Too Brief"},
5819
    { 428, "Use Identity Header"},
5820
    { 429, "Provide Referrer Identity"},
5821
    { 430, "Flow Failed"},
5822
    { 433, "Anonymity Disallowed"},
5823
    { 436, "Bad Identity-Info"},
5824
    { 437, "Unsupported Certificate"},
5825
    { 438, "Invalid Identity Header"},
5826
    { 439, "First Hop Lacks Outbound Support"},
5827
    { 440, "Max-Breadth Exceeded"},
5828
    { 470, "Consent Needed"},
5829
    { 480, "Temporarily Unavailable"},
5830
    { 481, "Call/Transaction Does Not Exist"},
5831
    { 482, "Loop Detected"},
5832
    { 483, "Too Many Hops"},
5833
    { 484, "Address Incomplete"},
5834
    { 485, "Ambiguous"},
5835
    { 486, "Busy Here"},
5836
    { 487, "Request Terminated"},
5837
    { 488, "Not Acceptable Here"},
5838
    { 489, "Bad Event"},
5839
    { 491, "Request Pending"},
5840
    { 493, "Undecipherable"},
5841
    { 494, "Security Agreement Required"},
5842
    { 499, "Client Error - Others"},
5843
5844
    { 500, "Server Internal Error"},
5845
    { 501, "Not Implemented"},
5846
    { 502, "Bad Gateway"},
5847
    { 503, "Service Unavailable"},
5848
    { 504, "Server Time-out"},
5849
    { 505, "Version Not Supported"},
5850
    { 513, "Message Too Large"},
5851
    { 599, "Server Error - Others"},
5852
5853
    { 600, "Busy Everywhere"},
5854
    { 603, "Decline"},
5855
    { 604, "Does Not Exist Anywhere"},
5856
    { 606, "Not Acceptable"},
5857
    { 607, "Unwanted"},
5858
    { 608, "Rejected"},
5859
    { 699, "Global Failure - Others"},
5860
5861
    { 0, NULL}
5862
};
5863
0
#define RESPONSE_CODE_MIN 100
5864
0
#define RESPONSE_CODE_MAX 699
5865
5866
typedef enum
5867
{
5868
    REQ_RESP_METHOD_COLUMN,
5869
    COUNT_COLUMN,
5870
    RESENT_COLUMN,
5871
    MIN_SETUP_COLUMN,
5872
    AVG_SETUP_COLUMN,
5873
    MAX_SETUP_COLUMN
5874
} sip_stat_columns;
5875
5876
static stat_tap_table_item sip_stat_fields[] = {
5877
    {TABLE_ITEM_STRING, TAP_ALIGN_LEFT, "Request Method / Response Code", "%-25s"},
5878
    {TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Count", "%d"},
5879
    {TABLE_ITEM_UINT, TAP_ALIGN_RIGHT, "Resent", "%d"},
5880
    {TABLE_ITEM_FLOAT, TAP_ALIGN_RIGHT, "Min Setup (s)", "%8.2f"},
5881
    {TABLE_ITEM_FLOAT, TAP_ALIGN_RIGHT, "Avg Setup (s)", "%8.2f"},
5882
    {TABLE_ITEM_FLOAT, TAP_ALIGN_RIGHT, "Max Setup (s)", "%8.2f"},
5883
};
5884
5885
static const char *req_table_name = "SIP Requests";
5886
static const char *resp_table_name = "SIP Responses";
5887
5888
static void sip_stat_init(stat_tap_table_ui* new_stat)
5889
0
{
5890
    /* XXX Should we have a single request + response table instead? */
5891
0
    int num_fields = array_length(sip_stat_fields);
5892
0
    stat_tap_table *req_table;
5893
0
    stat_tap_table *resp_table;
5894
0
    stat_tap_table_item_type items[array_length(sip_stat_fields)];
5895
0
    unsigned i;
5896
5897
    // These values are fixed for all entries.
5898
0
    items[REQ_RESP_METHOD_COLUMN].type = TABLE_ITEM_STRING;
5899
0
    items[COUNT_COLUMN].type = TABLE_ITEM_UINT;
5900
0
    items[COUNT_COLUMN].user_data.uint_value = 0;
5901
0
    items[COUNT_COLUMN].value.uint_value = 0;
5902
0
    items[RESENT_COLUMN].type = TABLE_ITEM_UINT;
5903
0
    items[RESENT_COLUMN].value.uint_value = 0;
5904
0
    items[MIN_SETUP_COLUMN].type = TABLE_ITEM_FLOAT;
5905
0
    items[MIN_SETUP_COLUMN].user_data.uint_value = 0;
5906
0
    items[MIN_SETUP_COLUMN].value.float_value = 0.0f;
5907
0
    items[AVG_SETUP_COLUMN].type = TABLE_ITEM_FLOAT;
5908
0
    items[AVG_SETUP_COLUMN].user_data.float_value = 0.0f;
5909
0
    items[AVG_SETUP_COLUMN].value.float_value = 0.0f;
5910
0
    items[MAX_SETUP_COLUMN].type = TABLE_ITEM_FLOAT;
5911
0
    items[MAX_SETUP_COLUMN].value.float_value = 0.0f;
5912
5913
0
    req_table = stat_tap_find_table(new_stat, req_table_name);
5914
0
    if (req_table) {
5915
0
        if (new_stat->stat_tap_reset_table_cb)
5916
0
            new_stat->stat_tap_reset_table_cb(req_table);
5917
0
    }
5918
0
    else {
5919
0
        req_table = stat_tap_init_table(req_table_name, num_fields, 0, NULL);
5920
0
        stat_tap_add_table(new_stat, req_table);
5921
5922
        // For req_table, first column value is method.
5923
0
        for (i = 1; i < array_length(sip_methods); i++) {
5924
0
            items[REQ_RESP_METHOD_COLUMN].value.string_value = g_strdup(sip_methods[i]);
5925
0
            stat_tap_init_table_row(req_table, i-1, num_fields, items);
5926
0
        }
5927
0
    }
5928
5929
0
    resp_table = stat_tap_find_table(new_stat, resp_table_name);
5930
0
    if (resp_table) {
5931
0
        if (new_stat->stat_tap_reset_table_cb)
5932
0
            new_stat->stat_tap_reset_table_cb(resp_table);
5933
0
    }
5934
0
    else {
5935
0
        resp_table = stat_tap_init_table(resp_table_name, num_fields, 0, NULL);
5936
0
        stat_tap_add_table(new_stat, resp_table);
5937
5938
        // For responses entries, first column gets code and description.
5939
0
        for (i = 1; sip_response_code_vals[i].strptr; i++) {
5940
0
            unsigned response_code = sip_response_code_vals[i].value;
5941
0
            items[REQ_RESP_METHOD_COLUMN].value.string_value =
5942
0
                ws_strdup_printf("%u %s", response_code, sip_response_code_vals[i].strptr);
5943
0
            items[REQ_RESP_METHOD_COLUMN].user_data.uint_value = response_code;
5944
0
            stat_tap_init_table_row(resp_table, i-1, num_fields, items);
5945
0
        }
5946
0
    }
5947
0
}
5948
5949
static tap_packet_status
5950
sip_stat_packet(void *tapdata, packet_info *pinfo _U_, epan_dissect_t *edt _U_, const void *siv_ptr, tap_flags_t flags _U_)
5951
0
{
5952
0
    stat_data_t* stat_data = (stat_data_t*) tapdata;
5953
0
    const sip_info_value_t *info_value = (const sip_info_value_t *) siv_ptr;
5954
0
    stat_tap_table *cur_table = NULL;
5955
0
    unsigned cur_row = 0;  /* 0 = Unknown for both tables */
5956
5957
0
    if (info_value->request_method && info_value->response_code < 1) {
5958
        /* Request table */
5959
0
        stat_tap_table *req_table = stat_tap_find_table(stat_data->stat_tap_data, req_table_name);
5960
0
        stat_tap_table_item_type *item_data;
5961
0
        unsigned element;
5962
5963
0
        cur_table = req_table;
5964
0
        for (element = 0; element < req_table->num_elements; element++) {
5965
0
            item_data = stat_tap_get_field_data(req_table, element, REQ_RESP_METHOD_COLUMN);
5966
0
            if (g_ascii_strcasecmp(info_value->request_method, item_data->value.string_value) == 0) {
5967
0
                cur_row = element;
5968
0
                break;
5969
0
            }
5970
0
        }
5971
5972
0
    } else if (info_value->response_code > 0) {
5973
        /* Response table */
5974
0
        stat_tap_table *resp_table = stat_tap_find_table(stat_data->stat_tap_data, resp_table_name);
5975
0
        unsigned response_code = info_value->response_code;
5976
0
        stat_tap_table_item_type *item_data;
5977
0
        unsigned element;
5978
5979
0
        cur_table = resp_table;
5980
0
        if (response_code < RESPONSE_CODE_MIN || response_code > RESPONSE_CODE_MAX) {
5981
0
            response_code = 999;
5982
0
        } else if (!try_val_to_str(response_code, sip_response_code_vals)) {
5983
0
            response_code = ((response_code / 100) * 100) + 99;
5984
0
        }
5985
5986
0
        for (element = 0; element < resp_table->num_elements; element++) {
5987
0
            item_data = stat_tap_get_field_data(resp_table, element, REQ_RESP_METHOD_COLUMN);
5988
0
            if (item_data->user_data.uint_value == response_code) {
5989
0
                cur_row = element;
5990
0
                break;
5991
0
            }
5992
0
        }
5993
5994
0
    } else {
5995
0
        return TAP_PACKET_DONT_REDRAW;
5996
0
    }
5997
5998
0
    if (cur_table) {
5999
0
        stat_tap_table_item_type *item_data;
6000
6001
0
        item_data = stat_tap_get_field_data(cur_table, cur_row, COUNT_COLUMN);
6002
0
        item_data->value.uint_value++;
6003
0
        stat_tap_set_field_data(cur_table, cur_row, COUNT_COLUMN, item_data);
6004
6005
0
        if (info_value->resend) {
6006
0
            item_data = stat_tap_get_field_data(cur_table, cur_row, RESENT_COLUMN);
6007
0
            item_data->value.uint_value++;
6008
0
            stat_tap_set_field_data(cur_table, cur_row, RESENT_COLUMN, item_data);
6009
0
        }
6010
6011
0
        if (info_value->setup_time > 0) {
6012
0
            stat_tap_table_item_type *min_item_data = stat_tap_get_field_data(cur_table, cur_row, MIN_SETUP_COLUMN);
6013
0
            stat_tap_table_item_type *avg_item_data = stat_tap_get_field_data(cur_table, cur_row, AVG_SETUP_COLUMN);
6014
0
            stat_tap_table_item_type *max_item_data = stat_tap_get_field_data(cur_table, cur_row, MAX_SETUP_COLUMN);
6015
0
            double setup_time = (double) info_value->setup_time / 1000;
6016
0
            unsigned count;
6017
6018
0
            min_item_data->user_data.uint_value++; /* We store the setup count in MIN_SETUP_COLUMN */
6019
0
            count = min_item_data->user_data.uint_value;
6020
0
            avg_item_data->user_data.float_value += setup_time; /* We store the total setup time in AVG_SETUP_COLUMN */
6021
6022
0
            if (count <= 1) {
6023
0
                min_item_data->value.float_value = setup_time;
6024
0
                avg_item_data->value.float_value = setup_time;
6025
0
                max_item_data->value.float_value = setup_time;
6026
0
            } else {
6027
0
                if (setup_time < min_item_data->value.float_value) {
6028
0
                    min_item_data->value.float_value = setup_time;
6029
0
                }
6030
0
                avg_item_data->value.float_value = avg_item_data->user_data.float_value / count;
6031
0
                if (setup_time > max_item_data->value.float_value) {
6032
0
                    max_item_data->value.float_value = setup_time;
6033
0
                }
6034
0
            }
6035
6036
0
            stat_tap_set_field_data(cur_table, cur_row, MIN_SETUP_COLUMN, min_item_data);
6037
0
            stat_tap_set_field_data(cur_table, cur_row, AVG_SETUP_COLUMN, avg_item_data);
6038
0
            stat_tap_set_field_data(cur_table, cur_row, MAX_SETUP_COLUMN, max_item_data);
6039
0
        }
6040
0
    }
6041
6042
0
    return TAP_PACKET_REDRAW;
6043
0
}
6044
6045
static void
6046
sip_stat_reset(stat_tap_table* table)
6047
0
{
6048
0
    unsigned element;
6049
0
    stat_tap_table_item_type* item_data;
6050
6051
0
    for (element = 0; element < table->num_elements; element++)
6052
0
    {
6053
0
        item_data = stat_tap_get_field_data(table, element, COUNT_COLUMN);
6054
0
        item_data->user_data.uint_value = 0;
6055
0
        item_data->value.uint_value = 0;
6056
0
        stat_tap_set_field_data(table, element, COUNT_COLUMN, item_data);
6057
6058
0
        item_data = stat_tap_get_field_data(table, element, RESENT_COLUMN);
6059
0
        item_data->value.uint_value = 0;
6060
0
        stat_tap_set_field_data(table, element, RESENT_COLUMN, item_data);
6061
6062
0
        item_data = stat_tap_get_field_data(table, element, MIN_SETUP_COLUMN);
6063
0
        item_data->user_data.uint_value = 0;
6064
0
        item_data->value.float_value = 0.0f;
6065
0
        stat_tap_set_field_data(table, element, MIN_SETUP_COLUMN, item_data);
6066
6067
0
        item_data = stat_tap_get_field_data(table, element, AVG_SETUP_COLUMN);
6068
0
        item_data->user_data.float_value = 0.0f;
6069
0
        item_data->value.float_value = 0.0f;
6070
0
        stat_tap_set_field_data(table, element, AVG_SETUP_COLUMN, item_data);
6071
6072
0
        item_data = stat_tap_get_field_data(table, element, MAX_SETUP_COLUMN);
6073
0
        item_data->value.float_value = 0.0f;
6074
0
        stat_tap_set_field_data(table, element, MAX_SETUP_COLUMN, item_data);
6075
0
    }
6076
0
}
6077
6078
static void
6079
sip_stat_free_table_item(stat_tap_table* table _U_, unsigned row _U_, unsigned column, stat_tap_table_item_type* field_data)
6080
0
{
6081
0
    if (column != REQ_RESP_METHOD_COLUMN) return;
6082
0
    g_free((char*)field_data->value.string_value);
6083
0
    field_data->value.string_value = NULL;
6084
0
}
6085
6086
static char *sip_follow_conv_filter(epan_dissect_t *edt, packet_info *pinfo _U_, unsigned *stream _U_, unsigned *sub_stream _U_)
6087
0
{
6088
0
    char *filter = NULL;
6089
6090
    /* Extract si.Call-ID from decoded tree in edt */
6091
0
    if (edt != NULL) {
6092
0
        int hfid = proto_registrar_get_id_byname("sip.Call-ID");
6093
0
        GPtrArray *gp = proto_find_first_finfo(edt->tree, hfid);
6094
0
        if (gp != NULL && gp->len != 0) {
6095
0
            filter = ws_strdup_printf("sip.Call-ID == \"%s\"", fvalue_get_string(((field_info *)gp->pdata[0])->value));
6096
0
        }
6097
0
        g_ptr_array_free(gp, true);
6098
0
    } else {
6099
0
        filter = ws_strdup_printf("sip.Call-ID");
6100
0
    }
6101
6102
0
    return filter;
6103
0
}
6104
6105
static char *sip_follow_index_filter(unsigned stream _U_, unsigned sub_stream _U_)
6106
0
{
6107
0
    return NULL;
6108
0
}
6109
6110
static char *sip_follow_address_filter(address *src_addr _U_, address *dst_addr _U_, int src_port _U_, int dst_port _U_)
6111
0
{
6112
0
    return NULL;
6113
0
}
6114
6115
6116
/* Register the protocol with Wireshark */
6117
void proto_register_sip(void)
6118
14
{
6119
6120
    /* Setup list of header fields */
6121
14
    static hf_register_info hf[] = {
6122
6123
14
        { &hf_sip_msg_hdr,
6124
14
          { "Message Header",           "sip.msg_hdr",
6125
14
            FT_STRING, BASE_NONE|BASE_NO_DISPLAY_VALUE, NULL, 0,
6126
14
            "Message Header in SIP message", HFILL }
6127
14
        },
6128
14
        { &hf_sip_Method,
6129
14
          { "Method",      "sip.Method",
6130
14
            FT_STRING, BASE_NONE,NULL,0x0,
6131
14
            "SIP Method", HFILL }
6132
14
        },
6133
14
        { &hf_Request_Line,
6134
14
          { "Request-Line",                "sip.Request-Line",
6135
14
            FT_STRING, BASE_NONE,NULL,0x0,
6136
14
            "SIP Request-Line", HFILL }
6137
14
        },
6138
14
        { &hf_sip_ruri_display,
6139
14
          { "Request-URI display info",        "sip.r-uri.display.info",
6140
14
            FT_STRING, BASE_NONE,NULL,0x0,
6141
14
            "RFC 3261: SIP R-URI Display Info", HFILL }
6142
14
        },
6143
14
        { &hf_sip_ruri,
6144
14
          { "Request-URI",        "sip.r-uri",
6145
14
            FT_STRING, BASE_NONE,NULL,0x0,
6146
14
            "RFC 3261: SIP R-URI", HFILL }
6147
14
        },
6148
14
        { &hf_sip_ruri_user,
6149
14
          { "Request-URI User Part",      "sip.r-uri.user",
6150
14
            FT_STRING, BASE_NONE,NULL,0x0,
6151
14
            "RFC 3261: SIP R-URI User", HFILL }
6152
14
        },
6153
14
        { &hf_sip_ruri_host,
6154
14
          { "Request-URI Host Part",      "sip.r-uri.host",
6155
14
            FT_STRING, BASE_NONE,NULL,0x0,
6156
14
            "RFC 3261: SIP R-URI Host", HFILL }
6157
14
        },
6158
14
        { &hf_sip_ruri_port,
6159
14
          { "Request-URI Host Port",      "sip.r-uri.port",
6160
14
            FT_STRING, BASE_NONE,NULL,0x0,
6161
14
            "RFC 3261: SIP R-URI Port", HFILL }
6162
14
        },
6163
14
        { &hf_sip_ruri_param,
6164
14
          { "Request URI parameter",      "sip.r-uri.param",
6165
14
            FT_STRING, BASE_NONE,NULL,0x0,
6166
14
            NULL, HFILL }
6167
14
        },
6168
14
        { &hf_sip_Status_Code,
6169
14
          { "Status-Code",         "sip.Status-Code",
6170
14
            FT_UINT32, BASE_DEC,NULL,0x0,
6171
14
            "SIP Status Code", HFILL }
6172
14
        },
6173
14
        { &hf_sip_Status_Line,
6174
14
          { "Status-Line",                 "sip.Status-Line",
6175
14
            FT_STRING, BASE_NONE,NULL,0x0,
6176
14
            "SIP Status-Line", HFILL }
6177
14
        },
6178
14
        { &hf_sip_display,
6179
14
          { "SIP Display info",       "sip.display.info",
6180
14
            FT_STRING, BASE_NONE,NULL,0x0,
6181
14
            "RFC 3261: Display info", HFILL }
6182
14
        },
6183
14
        { &hf_sip_to_display,
6184
14
          { "SIP to display info",       "sip.to.display.info",
6185
14
            FT_STRING, BASE_NONE,NULL,0x0,
6186
14
            "RFC 3261: To Display info", HFILL }
6187
14
        },
6188
14
        { &hf_sip_to_addr,
6189
14
          { "SIP to address",         "sip.to.addr",
6190
14
            FT_STRING, BASE_NONE,NULL,0x0,
6191
14
            "RFC 3261: To Address", HFILL }
6192
14
        },
6193
14
        { &hf_sip_to_user,
6194
14
          { "SIP to address User Part",        "sip.to.user",
6195
14
            FT_STRING, BASE_NONE,NULL,0x0,
6196
14
            "RFC 3261: To Address User", HFILL }
6197
14
        },
6198
14
        { &hf_sip_to_host,
6199
14
          { "SIP to address Host Part",        "sip.to.host",
6200
14
            FT_STRING, BASE_NONE,NULL,0x0,
6201
14
            "RFC 3261: To Address Host", HFILL }
6202
14
        },
6203
14
        { &hf_sip_to_port,
6204
14
          { "SIP to address Host Port",        "sip.to.port",
6205
14
            FT_STRING, BASE_NONE,NULL,0x0,
6206
14
            "RFC 3261: To Address Port", HFILL }
6207
14
        },
6208
14
        { &hf_sip_to_param,
6209
14
          { "SIP To URI parameter",        "sip.to.param",
6210
14
            FT_STRING, BASE_NONE,NULL,0x0,
6211
14
            NULL, HFILL }
6212
14
        },
6213
14
        { &hf_sip_to_tag,
6214
14
          { "SIP to tag",          "sip.to.tag",
6215
14
            FT_STRING, BASE_NONE,NULL,0x0,
6216
14
            "RFC 3261: to tag", HFILL }
6217
14
        },
6218
14
        { &hf_sip_from_display,
6219
14
          { "SIP from display info",       "sip.from.display.info",
6220
14
            FT_STRING, BASE_NONE,NULL,0x0,
6221
14
            "RFC 3261: From Display info", HFILL }
6222
14
        },
6223
14
        { &hf_sip_from_addr,
6224
14
          { "SIP from address",        "sip.from.addr",
6225
14
            FT_STRING, BASE_NONE,NULL,0x0,
6226
14
            "RFC 3261: From Address", HFILL }
6227
14
        },
6228
14
        { &hf_sip_from_user,
6229
14
          { "SIP from address User Part",      "sip.from.user",
6230
14
            FT_STRING, BASE_NONE,NULL,0x0,
6231
14
            "RFC 3261: From Address User", HFILL }
6232
14
        },
6233
14
        { &hf_sip_from_host,
6234
14
          { "SIP from address Host Part",      "sip.from.host",
6235
14
            FT_STRING, BASE_NONE,NULL,0x0,
6236
14
            "RFC 3261: From Address Host", HFILL }
6237
14
        },
6238
14
        { &hf_sip_from_port,
6239
14
          { "SIP from address Host Port",      "sip.from.port",
6240
14
            FT_STRING, BASE_NONE,NULL,0x0,
6241
14
            "RFC 3261: From Address Port", HFILL }
6242
14
        },
6243
14
        { &hf_sip_from_param,
6244
14
          { "SIP From URI parameter",      "sip.from.param",
6245
14
            FT_STRING, BASE_NONE,NULL,0x0,
6246
14
            NULL, HFILL }
6247
14
        },
6248
14
        { &hf_sip_from_tag,
6249
14
          { "SIP from tag",        "sip.from.tag",
6250
14
            FT_STRING, BASE_NONE,NULL,0x0,
6251
14
            "RFC 3261: from tag", HFILL }
6252
14
        },
6253
14
        { &hf_sip_curi_display,
6254
14
          { "SIP C-URI display info",       "sip.contact.display.info",
6255
14
            FT_STRING, BASE_NONE,NULL,0x0,
6256
14
            "RFC 3261: SIP C-URI Display info", HFILL }
6257
14
        },
6258
14
        { &hf_sip_curi,
6259
14
          { "Contact URI",        "sip.contact.uri",
6260
14
            FT_STRING, BASE_NONE,NULL,0x0,
6261
14
            "RFC 3261: SIP C-URI", HFILL }
6262
14
        },
6263
14
        { &hf_sip_curi_user,
6264
14
          { "Contact URI User Part",      "sip.contact.user",
6265
14
            FT_STRING, BASE_NONE,NULL,0x0,
6266
14
            "RFC 3261: SIP C-URI User", HFILL }
6267
14
        },
6268
14
        { &hf_sip_curi_host,
6269
14
          { "Contact URI Host Part",      "sip.contact.host",
6270
14
            FT_STRING, BASE_NONE,NULL,0x0,
6271
14
            "RFC 3261: SIP C-URI Host", HFILL }
6272
14
        },
6273
14
        { &hf_sip_curi_port,
6274
14
          { "Contact URI Host Port",      "sip.contact.port",
6275
14
            FT_STRING, BASE_NONE,NULL,0x0,
6276
14
            "RFC 3261: SIP C-URI Port", HFILL }
6277
14
        },
6278
14
        { &hf_sip_curi_param,
6279
14
          { "Contact URI parameter",      "sip.contact.param",
6280
14
            FT_STRING, BASE_NONE,NULL,0x0,
6281
14
            NULL, HFILL }
6282
14
        },
6283
14
        { &hf_sip_route_display,
6284
14
          { "Route display info",       "sip.Route.display.info",
6285
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6286
14
        },
6287
14
        { &hf_sip_route,
6288
14
          { "Route URI",         "sip.Route.uri",
6289
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6290
14
        },
6291
14
        { &hf_sip_route_user,
6292
14
          { "Route Userinfo",    "sip.Route.user",
6293
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6294
14
        },
6295
14
        { &hf_sip_route_host,
6296
14
          { "Route Host Part",   "sip.Route.host",
6297
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6298
14
        },
6299
14
        { &hf_sip_route_port,
6300
14
          { "Route Host Port",   "sip.Route.port",
6301
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6302
14
        },
6303
14
        { &hf_sip_route_param,
6304
14
          { "Route URI parameter",   "sip.Route.param",
6305
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6306
14
        },
6307
14
        { &hf_sip_record_route_display,
6308
14
          { "Record-Route display info",       "sip.Record-Route.display.info",
6309
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6310
14
        },
6311
14
        { &hf_sip_record_route,
6312
14
          { "Record-Route URI",         "sip.Record-Route.uri",
6313
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6314
14
        },
6315
14
        { &hf_sip_record_route_user,
6316
14
          { "Record-Route Userinfo",    "sip.Record-Route.user",
6317
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6318
14
        },
6319
14
        { &hf_sip_record_route_host,
6320
14
          { "Record-Route Host Part",   "sip.Record-Route.host",
6321
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6322
14
        },
6323
14
        { &hf_sip_record_route_port,
6324
14
          { "Record-Route Host Port",   "sip.Record-Route.port",
6325
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6326
14
        },
6327
14
        { &hf_sip_record_route_param,
6328
14
          { "Record-Route URI parameter",   "sip.Record-Route.param",
6329
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6330
14
        },
6331
14
        { &hf_sip_service_route_display,
6332
14
          { "Service-Route display info",       "sip.Service-Route.display.info",
6333
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6334
14
        },
6335
14
        { &hf_sip_service_route,
6336
14
          { "Service-Route URI",         "sip.Service-Route.uri",
6337
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6338
14
        },
6339
14
        { &hf_sip_service_route_user,
6340
14
          { "Service-Route Userinfo",    "sip.Service-Route.user",
6341
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6342
14
        },
6343
14
        { &hf_sip_service_route_host,
6344
14
          { "Service-Route Host Part",   "sip.Service-Route.host",
6345
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6346
14
        },
6347
14
        { &hf_sip_service_route_port,
6348
14
          { "Service-Route Host Port",   "sip.Service-Route.port",
6349
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6350
14
        },
6351
14
        { &hf_sip_service_route_param,
6352
14
          { "Service-Route URI parameter",   "sip.Service-Route.param",
6353
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6354
14
        },
6355
14
        { &hf_sip_path_display,
6356
14
          { "Path URI",       "sip.Path.display.info",
6357
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6358
14
        },
6359
14
        { &hf_sip_path,
6360
14
          { "Path URI",         "sip.Path.uri",
6361
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6362
14
        },
6363
14
        { &hf_sip_path_user,
6364
14
          { "Path Userinfo",    "sip.Path.user",
6365
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6366
14
        },
6367
14
        { &hf_sip_path_host,
6368
14
          { "Path Host Part",   "sip.Path.host",
6369
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6370
14
        },
6371
14
        { &hf_sip_path_port,
6372
14
          { "Path Host Port",   "sip.Path.port",
6373
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6374
14
        },
6375
14
        { &hf_sip_path_param,
6376
14
          { "Path URI parameter",   "sip.Path.param",
6377
14
            FT_STRING, BASE_NONE,NULL,0x0,NULL,HFILL }
6378
14
        },
6379
14
        { &hf_sip_contact_param,
6380
14
          { "Contact parameter",       "sip.contact.parameter",
6381
14
            FT_STRING, BASE_NONE,NULL,0x0,
6382
14
            "RFC 3261: one contact parameter", HFILL }
6383
14
        },
6384
14
        { &hf_sip_tag,
6385
14
          { "SIP tag",         "sip.tag",
6386
14
            FT_STRING, BASE_NONE,NULL,0x0,
6387
14
            "RFC 3261: tag", HFILL }
6388
14
        },
6389
14
        { &hf_sip_pai_display,
6390
14
          { "SIP PAI display info",       "sip.pai.display.info",
6391
14
            FT_STRING, BASE_NONE,NULL,0x0,
6392
14
            "RFC 3325: P-Asserted-Identity Display info", HFILL }
6393
14
        },
6394
14
        { &hf_sip_pai_addr,
6395
14
          { "SIP PAI Address",         "sip.pai.addr",
6396
14
            FT_STRING, BASE_NONE,NULL,0x0,
6397
14
            "RFC 3325: P-Asserted-Identity Address", HFILL }
6398
14
        },
6399
14
        { &hf_sip_pai_user,
6400
14
          { "SIP PAI User Part",       "sip.pai.user",
6401
14
            FT_STRING, BASE_NONE,NULL,0x0,
6402
14
            "RFC 3325: P-Asserted-Identity User", HFILL }
6403
14
        },
6404
14
        { &hf_sip_pai_host,
6405
14
          { "SIP PAI Host Part",       "sip.pai.host",
6406
14
            FT_STRING, BASE_NONE,NULL,0x0,
6407
14
            "RFC 3325: P-Asserted-Identity Host", HFILL }
6408
14
        },
6409
14
        { &hf_sip_pai_port,
6410
14
          { "SIP PAI Host Port",       "sip.pai.port",
6411
14
            FT_STRING, BASE_NONE,NULL,0x0,
6412
14
            "RFC 3325: P-Asserted-Identity Port", HFILL }
6413
14
        },
6414
14
        { &hf_sip_pai_param,
6415
14
          { "SIP PAI URI parameter",       "sip.pai.param",
6416
14
            FT_STRING, BASE_NONE,NULL,0x0,
6417
14
            NULL, HFILL }
6418
14
        },
6419
14
        { &hf_sip_pmiss_display,
6420
14
          { "SIP PMISS display info",       "sip.pmiss.display.info",
6421
14
            FT_STRING, BASE_NONE,NULL,0x0,
6422
14
            "RFC 3325: Permission Missing Display info", HFILL }
6423
14
        },
6424
14
        { &hf_sip_pmiss_addr,
6425
14
          { "SIP PMISS Address",       "sip.pmiss.addr",
6426
14
            FT_STRING, BASE_NONE,NULL,0x0,
6427
14
            "RFC 3325: Permission Missing Address", HFILL }
6428
14
        },
6429
14
        { &hf_sip_pmiss_user,
6430
14
          { "SIP PMISS User Part",     "sip.pmiss.user",
6431
14
            FT_STRING, BASE_NONE,NULL,0x0,
6432
14
            "RFC 3325: Permission Missing User", HFILL }
6433
14
        },
6434
14
        { &hf_sip_pmiss_host,
6435
14
          { "SIP PMISS Host Part",     "sip.pmiss.host",
6436
14
            FT_STRING, BASE_NONE,NULL,0x0,
6437
14
            "RFC 3325: Permission Missing Host", HFILL }
6438
14
        },
6439
14
        { &hf_sip_pmiss_port,
6440
14
          { "SIP PMISS Host Port",     "sip.pmiss.port",
6441
14
            FT_STRING, BASE_NONE,NULL,0x0,
6442
14
            "RFC 3325: Permission Missing Port", HFILL }
6443
14
        },
6444
14
        { &hf_sip_pmiss_param,
6445
14
          { "SIP PMISS URI parameter",     "sip.pmiss.param",
6446
14
            FT_STRING, BASE_NONE,NULL,0x0,
6447
14
            NULL, HFILL }
6448
14
        },
6449
14
        { &hf_sip_ppi_display,
6450
14
          { "SIP PPI display info",       "sip.ppi.display.info",
6451
14
            FT_STRING, BASE_NONE,NULL,0x0,
6452
14
            "RFC 3325: P-Preferred-Identity Display info", HFILL }
6453
14
        },
6454
14
        { &hf_sip_ppi_addr,
6455
14
          { "SIP PPI Address",         "sip.ppi.addr",
6456
14
            FT_STRING, BASE_NONE,NULL,0x0,
6457
14
            "RFC 3325: P-Preferred-Identity Address", HFILL }
6458
14
        },
6459
14
        { &hf_sip_ppi_user,
6460
14
          { "SIP PPI User Part",       "sip.ppi.user",
6461
14
            FT_STRING, BASE_NONE,NULL,0x0,
6462
14
            "RFC 3325: P-Preferred-Identity User", HFILL }
6463
14
        },
6464
14
        { &hf_sip_ppi_host,
6465
14
          { "SIP PPI Host Part",       "sip.ppi.host",
6466
14
            FT_STRING, BASE_NONE,NULL,0x0,
6467
14
            "RFC 3325: P-Preferred-Identity Host", HFILL }
6468
14
        },
6469
14
        { &hf_sip_ppi_port,
6470
14
          { "SIP PPI Host Port",       "sip.ppi.port",
6471
14
            FT_STRING, BASE_NONE,NULL,0x0,
6472
14
            "RFC 3325: P-Preferred-Identity Port", HFILL }
6473
14
        },
6474
14
        { &hf_sip_ppi_param,
6475
14
          { "SIP PPI URI parameter",       "sip.ppi.param",
6476
14
            FT_STRING, BASE_NONE,NULL,0x0,
6477
14
            NULL, HFILL }
6478
14
        },
6479
14
        { &hf_sip_tc_display,
6480
14
          { "SIP TC display info",       "sip.tc.display.info",
6481
14
            FT_STRING, BASE_NONE,NULL,0x0,
6482
14
            "RFC 3325: Trigger Consent Display info", HFILL }
6483
14
        },
6484
14
        { &hf_sip_tc_addr,
6485
14
          { "SIP TC Address",      "sip.tc.addr",
6486
14
            FT_STRING, BASE_NONE,NULL,0x0,
6487
14
            "RFC 3325: Trigger Consent Address", HFILL }
6488
14
        },
6489
14
        { &hf_sip_tc_user,
6490
14
          { "SIP TC User Part",        "sip.tc.user",
6491
14
            FT_STRING, BASE_NONE,NULL,0x0,
6492
14
            "RFC 3325: Trigger Consent User", HFILL }
6493
14
        },
6494
14
        { &hf_sip_tc_host,
6495
14
          { "SIP TC Host Part",        "sip.tc.host",
6496
14
            FT_STRING, BASE_NONE,NULL,0x0,
6497
14
            "RFC 3325: Trigger Consent Host", HFILL }
6498
14
        },
6499
14
        { &hf_sip_tc_port,
6500
14
          { "SIP TC Host Port",        "sip.tc.port",
6501
14
            FT_STRING, BASE_NONE,NULL,0x0,
6502
14
            "RFC 3325: Trigger Consent Port", HFILL }
6503
14
        },
6504
14
        { &hf_sip_tc_param,
6505
14
          { "SIP TC URI parameter",        "sip.tc.param",
6506
14
            FT_STRING, BASE_NONE,NULL,0x0,
6507
14
            NULL, HFILL }
6508
14
        },
6509
14
        { &hf_sip_tc_turi,
6510
14
          { "SIP TC Target URI",       "sip.tc.target-uri",
6511
14
            FT_STRING, BASE_NONE,NULL,0x0,
6512
14
            "RFC 3325: Trigger Consent Target URI", HFILL }
6513
14
        },
6514
14
        { &hf_header_array[POS_ACCEPT],
6515
14
          { "Accept",      "sip.Accept",
6516
14
            FT_STRING, BASE_NONE,NULL,0x0,
6517
14
            "RFC 3261: Accept Header", HFILL }
6518
14
        },
6519
14
        { &hf_header_array[POS_ACCEPT_CONTACT],
6520
14
          { "Accept-Contact",      "sip.Accept-Contact",
6521
14
            FT_STRING, BASE_NONE,NULL,0x0,
6522
14
            "RFC 3841: Accept-Contact Header", HFILL }
6523
14
        },
6524
14
        { &hf_header_array[POS_ACCEPT_ENCODING],
6525
14
          { "Accept-Encoding",         "sip.Accept-Encoding",
6526
14
            FT_STRING, BASE_NONE,NULL,0x0,
6527
14
            "RFC 3841: Accept-Encoding Header", HFILL }
6528
14
        },
6529
14
        { &hf_header_array[POS_ACCEPT_LANGUAGE],
6530
14
          { "Accept-Language",         "sip.Accept-Language",
6531
14
            FT_STRING, BASE_NONE,NULL,0x0,
6532
14
            "RFC 3261: Accept-Language Header", HFILL }
6533
14
        },
6534
14
        { &hf_header_array[POS_ACCEPT_RESOURCE_PRIORITY],
6535
14
          { "Accept-Resource-Priority",        "sip.Accept-Resource-Priority",
6536
14
            FT_STRING, BASE_NONE,NULL,0x0,
6537
14
            "Draft: Accept-Resource-Priority Header", HFILL }
6538
14
        },
6539
14
        { &hf_header_array[POS_ADDITIONAL_IDENTITY],
6540
14
          { "Additional-Identity",        "sip.Additional-Identity",
6541
14
            FT_STRING, BASE_NONE,NULL,0x0,
6542
14
            NULL, HFILL }
6543
14
        },
6544
14
        { &hf_header_array[POS_ALERT_INFO],
6545
14
          { "Alert-Info",      "sip.Alert-Info",
6546
14
            FT_STRING, BASE_NONE,NULL,0x0,
6547
14
            "RFC 3261: Alert-Info Header", HFILL }
6548
14
        },
6549
14
        { &hf_header_array[POS_ALLOW],
6550
14
          { "Allow",       "sip.Allow",
6551
14
            FT_STRING, BASE_NONE,NULL,0x0,
6552
14
            "RFC 3261: Allow Header", HFILL }
6553
14
        },
6554
14
        { &hf_header_array[POS_ALLOW_EVENTS],
6555
14
          { "Allow-Events",        "sip.Allow-Events",
6556
14
            FT_STRING, BASE_NONE,NULL,0x0,
6557
14
            "RFC 3265: Allow-Events Header", HFILL }
6558
14
        },
6559
14
        { &hf_header_array[POS_ANSWER_MODE],
6560
14
          { "Answer-Mode",         "sip.Answer-Mode",
6561
14
            FT_STRING, BASE_NONE,NULL,0x0,
6562
14
            "RFC 5373: Answer-Mode Header", HFILL }
6563
14
        },
6564
14
        { &hf_header_array[POS_ATTESTATION_INFO],
6565
14
          { "Attestation-Info",         "sip.Attestation-Info",
6566
14
            FT_STRING, BASE_NONE,NULL,0x0,
6567
14
            NULL, HFILL }
6568
14
        },
6569
14
        { &hf_header_array[POS_AUTHENTICATION_INFO],
6570
14
          { "Authentication-Info",         "sip.Authentication-Info",
6571
14
            FT_STRING, BASE_NONE,NULL,0x0,
6572
14
            "RFC 3261: Authentication-Info Header", HFILL }
6573
14
        },
6574
14
        { &hf_header_array[POS_AUTHORIZATION],
6575
14
          { "Authorization",       "sip.Authorization",
6576
14
            FT_STRING, BASE_NONE,NULL,0x0,
6577
14
            "RFC 3261: Authorization Header", HFILL }
6578
14
        },
6579
14
        { &hf_header_array[POS_CALL_ID],
6580
14
          { "Call-ID",         "sip.Call-ID",
6581
14
            FT_STRING, BASE_NONE,NULL,0x0,
6582
14
            "RFC 3261: Call-ID Header", HFILL }
6583
14
        },
6584
14
        { &hf_header_array[POS_CALL_INFO],
6585
14
          { "Call-Info",       "sip.Call-Info",
6586
14
            FT_STRING, BASE_NONE,NULL,0x0,
6587
14
            "RFC 3261: Call-Info Header", HFILL }
6588
14
        },
6589
14
        { &hf_header_array[POS_CELLULAR_NETWORK_INFO],
6590
14
          { "Cellular-Network-Info",       "sip.Cellular-Network-Info",
6591
14
            FT_STRING, BASE_NONE,NULL,0x0,
6592
14
            NULL, HFILL }
6593
14
        },
6594
14
        { &hf_header_array[POS_CONTACT],
6595
14
          { "Contact",         "sip.Contact",
6596
14
            FT_STRING, BASE_NONE,NULL,0x0,
6597
14
            "RFC 3261: Contact Header", HFILL }
6598
14
        },
6599
14
        { &hf_header_array[POS_CONTENT_DISPOSITION],
6600
14
          { "Content-Disposition",         "sip.Content-Disposition",
6601
14
            FT_STRING, BASE_NONE,NULL,0x0,
6602
14
            "RFC 3261: Content-Disposition Header", HFILL }
6603
14
        },
6604
14
        { &hf_header_array[POS_CONTENT_ENCODING],
6605
14
          { "Content-Encoding",        "sip.Content-Encoding",
6606
14
            FT_STRING, BASE_NONE,NULL,0x0,
6607
14
            "RFC 3261: Content-Encoding Header", HFILL }
6608
14
        },
6609
14
        { &hf_header_array[POS_CONTENT_LANGUAGE],
6610
14
          { "Content-Language",        "sip.Content-Language",
6611
14
            FT_STRING, BASE_NONE,NULL,0x0,
6612
14
            "RFC 3261: Content-Language Header", HFILL }
6613
14
        },
6614
14
        { &hf_header_array[POS_CONTENT_LENGTH],
6615
14
          { "Content-Length",      "sip.Content-Length",
6616
14
            FT_UINT32, BASE_DEC,NULL,0x0,
6617
14
            "RFC 3261: Content-Length Header", HFILL }
6618
14
        },
6619
14
        { &hf_header_array[POS_CONTENT_TYPE],
6620
14
          { "Content-Type",        "sip.Content-Type",
6621
14
            FT_STRING, BASE_NONE,NULL,0x0,
6622
14
            "RFC 3261: Content-Type Header", HFILL }
6623
14
        },
6624
14
        { &hf_header_array[POS_CSEQ],
6625
14
          { "CSeq",        "sip.CSeq",
6626
14
            FT_STRING, BASE_NONE,NULL,0x0,
6627
14
            "RFC 3261: CSeq Header", HFILL }
6628
14
        },
6629
14
        { &hf_header_array[POS_DATE],
6630
14
          { "Date",        "sip.Date",
6631
14
            FT_STRING, BASE_NONE,NULL,0x0,
6632
14
            "RFC 3261: Date Header", HFILL }
6633
14
        },
6634
14
        { &hf_header_array[POS_ERROR_INFO],
6635
14
          { "Error-Info",      "sip.Error-Info",
6636
14
            FT_STRING, BASE_NONE,NULL,0x0,
6637
14
            "RFC 3261: Error-Info Header", HFILL }
6638
14
        },
6639
14
        { &hf_header_array[POS_EVENT],
6640
14
          { "Event",       "sip.Event",
6641
14
            FT_STRING, BASE_NONE,NULL,0x0,
6642
14
            "RFC 3265: Event Header", HFILL }
6643
14
        },
6644
14
        { &hf_header_array[POS_EXPIRES],
6645
14
          { "Expires",         "sip.Expires",
6646
14
            FT_UINT32, BASE_DEC,NULL,0x0,
6647
14
            "RFC 3261: Expires Header", HFILL }
6648
14
        },
6649
14
        { &hf_header_array[POS_FEATURE_CAPS],
6650
14
          { "Feature-Caps",        "sip.Feature-Caps",
6651
14
            FT_STRING, BASE_NONE,NULL,0x0,
6652
14
            "RFC 6809: Feature-Caps", HFILL }
6653
14
        },
6654
14
        { &hf_header_array[POS_FLOW_TIMER],
6655
14
          { "Flow-Timer",      "sip.Flow-Timer",
6656
14
            FT_STRING, BASE_NONE,NULL,0x0,
6657
14
            "RFC 5626: Flow-Timer", HFILL }
6658
14
        },
6659
14
        { &hf_header_array[POS_FROM],
6660
14
          { "From",        "sip.From",
6661
14
            FT_STRING, BASE_NONE,NULL,0x0,
6662
14
            "RFC 3261: From Header", HFILL }
6663
14
        },
6664
14
        { &hf_header_array[POS_GEOLOCATION],
6665
14
          { "Geolocation",         "sip.Geolocation",
6666
14
            FT_STRING, BASE_NONE,NULL,0x0,
6667
14
            NULL, HFILL }
6668
14
        },
6669
14
        { &hf_header_array[POS_GEOLOCATION_ERROR],
6670
14
          { "Geolocation-Error",       "sip.Geolocation-Error",
6671
14
            FT_STRING, BASE_NONE,NULL,0x0,
6672
14
            NULL, HFILL }
6673
14
        },
6674
14
        { &hf_header_array[POS_GEOLOCATION_ROUTING],
6675
14
          { "Geolocation-Routing",         "sip.Geolocation-Routing",
6676
14
            FT_STRING, BASE_NONE,NULL,0x0,
6677
14
            NULL, HFILL }
6678
14
        },
6679
14
        { &hf_header_array[POS_HISTORY_INFO],
6680
14
          { "History-Info",           "sip.History-Info",
6681
14
            FT_STRING, BASE_NONE,NULL,0x0,
6682
14
            "RFC 4244: Request History Information", HFILL }
6683
14
        },
6684
14
        { &hf_header_array[POS_IDENTITY],
6685
14
          { "Identity",           "sip.Identity",
6686
14
            FT_STRING, BASE_NONE,NULL,0x0,
6687
14
            "RFC 4474: Request Identity", HFILL }
6688
14
        },
6689
14
        { &hf_header_array[POS_IDENTITY_INFO],
6690
14
          { "Identity-info",          "sip.Identity-info",
6691
14
            FT_STRING, BASE_NONE,NULL,0x0,
6692
14
            "RFC 4474: Request Identity-info", HFILL }
6693
14
        },
6694
14
        { &hf_header_array[POS_INFO_PKG],
6695
14
          { "Info-Package",           "sip.Info-Package",
6696
14
            FT_STRING, BASE_NONE,NULL,0x0,
6697
14
            NULL, HFILL }
6698
14
        },
6699
14
        { &hf_header_array[POS_IN_REPLY_TO],
6700
14
          { "In-Reply-To",         "sip.In-Reply-To",
6701
14
            FT_STRING, BASE_NONE,NULL,0x0,
6702
14
            "RFC 3261: In-Reply-To Header", HFILL }
6703
14
        },
6704
14
        { &hf_header_array[POS_JOIN],
6705
14
          { "Join",        "sip.Join",
6706
14
            FT_STRING, BASE_NONE,NULL,0x0,
6707
14
            "Draft: Join Header", HFILL }
6708
14
        },
6709
14
        { &hf_header_array[POS_MAX_BREADTH],
6710
14
          { "Max-Breadth",     "sip.Max-Breadth",
6711
14
            FT_UINT32, BASE_DEC,NULL,0x0,
6712
14
            "RFC 5393: Max-Breadth Header", HFILL }
6713
14
        },
6714
14
        { &hf_header_array[POS_MAX_FORWARDS],
6715
14
          { "Max-Forwards",        "sip.Max-Forwards",
6716
14
            FT_UINT32, BASE_DEC,NULL,0x0,
6717
14
            "RFC 3261: Max-Forwards Header", HFILL }
6718
14
        },
6719
14
        { &hf_header_array[POS_MIME_VERSION],
6720
14
          { "MIME-Version",        "sip.MIME-Version",
6721
14
            FT_STRING, BASE_NONE,NULL,0x0,
6722
14
            "RFC 3261: MIME-Version Header", HFILL }
6723
14
        },
6724
14
        { &hf_header_array[POS_MIN_EXPIRES],
6725
14
          { "Min-Expires",         "sip.Min-Expires",
6726
14
            FT_STRING, BASE_NONE,NULL,0x0,
6727
14
            "RFC 3261: Min-Expires Header", HFILL }
6728
14
        },
6729
14
        { &hf_header_array[POS_MIN_SE],
6730
14
          { "Min-SE",      "sip.Min-SE",
6731
14
            FT_STRING, BASE_NONE,NULL,0x0,
6732
14
            "Draft: Min-SE Header", HFILL }
6733
14
        },
6734
14
        { &hf_header_array[POS_ORGANIZATION],
6735
14
          { "Organization",        "sip.Organization",
6736
14
            FT_STRING, BASE_NONE,NULL,0x0,
6737
14
            "RFC 3261: Organization Header", HFILL }
6738
14
        },
6739
14
        { &hf_header_array[POS_ORIGINATION_ID],
6740
14
          { "Origination-Id",        "sip.Origination-Id",
6741
14
            FT_STRING, BASE_NONE,NULL,0x0,
6742
14
            NULL, HFILL }
6743
14
        },
6744
14
        { &hf_header_array[POS_P_ACCESS_NETWORK_INFO],
6745
14
          { "P-Access-Network-Info",   "sip.P-Access-Network-Info",
6746
14
            FT_STRING, BASE_NONE,NULL,0x0,
6747
14
            "P-Access-Network-Info Header", HFILL }
6748
14
        },
6749
14
        { &hf_header_array[POS_P_ANSWER_STATE],
6750
14
          { "P-Answer-State",      "sip.P-Answer-State",
6751
14
            FT_STRING, BASE_NONE,NULL,0x0,
6752
14
            "RFC 4964: P-Answer-State Header", HFILL }
6753
14
        },
6754
14
        { &hf_header_array[POS_P_ASSERTED_IDENTITY],
6755
14
          { "P-Asserted-Identity",     "sip.P-Asserted-Identity",
6756
14
            FT_STRING, BASE_NONE,NULL,0x0,
6757
14
            "RFC 3325: P-Asserted-Identity Header", HFILL }
6758
14
        },
6759
14
        { &hf_header_array[POS_P_ASSERTED_SERV],
6760
14
          { "P-Asserted-Service",      "sip.P-Asserted-Service",
6761
14
            FT_STRING, BASE_NONE,NULL,0x0,
6762
14
            NULL, HFILL }
6763
14
        },
6764
14
        { &hf_header_array[POS_P_CHARGE_INFO],
6765
14
          { "P-Charge-Info",      "sip.P-Charge-Info",
6766
14
            FT_STRING, BASE_NONE,NULL,0x0,
6767
14
            NULL, HFILL }
6768
14
        },
6769
14
        { &hf_header_array[POS_P_ASSOCIATED_URI],
6770
14
          { "P-Associated-URI",        "sip.P-Associated-URI",
6771
14
            FT_STRING, BASE_NONE,NULL,0x0,
6772
14
            "RFC 3455: P-Associated-URI Header", HFILL }
6773
14
        },
6774
6775
14
        { &hf_header_array[POS_P_CALLED_PARTY_ID],
6776
14
          { "P-Called-Party-ID",       "sip.P-Called-Party-ID",
6777
14
            FT_STRING, BASE_NONE,NULL,0x0,
6778
14
            "RFC 3455: P-Called-Party-ID Header", HFILL }
6779
14
        },
6780
6781
14
        { &hf_header_array[POS_P_CHARGING_FUNC_ADDRESSES],
6782
14
          { "P-Charging-Function-Addresses","sip.P-Charging-Function-Addresses",
6783
14
            FT_STRING, BASE_NONE,NULL,0x0,
6784
14
            NULL, HFILL }
6785
14
        },
6786
6787
14
        { &hf_header_array[POS_P_CHARGING_VECTOR],
6788
14
          { "P-Charging-Vector",       "sip.P-Charging-Vector",
6789
14
            FT_STRING, BASE_NONE,NULL,0x0,
6790
14
            "P-Charging-Vector Header", HFILL }
6791
14
        },
6792
6793
14
        { &hf_header_array[POS_P_DCS_TRACE_PARTY_ID],
6794
14
          { "P-DCS-Trace-Party-ID",    "sip.P-DCS-Trace-Party-ID",
6795
14
            FT_STRING, BASE_NONE,NULL,0x0,
6796
14
            "P-DCS-Trace-Party-ID Header", HFILL }
6797
14
        },
6798
6799
14
        { &hf_header_array[POS_P_DCS_OSPS],
6800
14
          { "P-DCS-OSPS",          "sip.P-DCS-OSPS",
6801
14
            FT_STRING, BASE_NONE,NULL,0x0,
6802
14
            "P-DCS-OSPS Header", HFILL }
6803
14
        },
6804
6805
14
        { &hf_header_array[POS_P_DCS_BILLING_INFO],
6806
14
          { "P-DCS-Billing-Info",      "sip.P-DCS-Billing-Info",
6807
14
            FT_STRING, BASE_NONE,NULL,0x0,
6808
14
            "P-DCS-Billing-Info Header", HFILL }
6809
14
        },
6810
6811
14
        { &hf_header_array[POS_P_DCS_LAES],
6812
14
          { "P-DCS-LAES",          "sip.P-DCS-LAES",
6813
14
            FT_STRING, BASE_NONE,NULL,0x0,
6814
14
            "P-DCS-LAES Header", HFILL }
6815
14
        },
6816
6817
14
        { &hf_header_array[POS_P_DCS_REDIRECT],
6818
14
          { "P-DCS-Redirect",      "sip.P-DCS-Redirect",
6819
14
            FT_STRING, BASE_NONE,NULL,0x0,
6820
14
            "P-DCS-Redirect Header", HFILL }
6821
14
        },
6822
6823
14
        { &hf_header_array[POS_P_EARLY_MEDIA],
6824
14
          { "P-Early-Media",       "sip.P-Early-Media",
6825
14
            FT_STRING, BASE_NONE,NULL,0x0,
6826
14
            "P-Early-Media Header", HFILL }
6827
14
        },
6828
6829
14
        { &hf_header_array[POS_P_MEDIA_AUTHORIZATION],
6830
14
          { "P-Media-Authorization",   "sip.P-Media-Authorization",
6831
14
            FT_STRING, BASE_NONE,NULL,0x0,
6832
14
            "RFC 3313: P-Media-Authorization Header", HFILL }
6833
14
        },
6834
6835
14
        { &hf_header_array[POS_P_PREFERRED_IDENTITY],
6836
14
          { "P-Preferred-Identity",    "sip.P-Preferred-Identity",
6837
14
            FT_STRING, BASE_NONE,NULL,0x0,
6838
14
            "RFC 3325: P-Preferred-Identity Header", HFILL }
6839
14
        },
6840
14
        { &hf_header_array[POS_P_PREFERRED_SERV],
6841
14
          { "P-Preferred-Service",     "sip.P-Preferred-Service",
6842
14
            FT_STRING, BASE_NONE,NULL,0x0,
6843
14
            NULL, HFILL }
6844
14
        },
6845
14
        { &hf_header_array[POS_P_PROFILE_KEY],
6846
14
          { "P-Profile-Key",   "sip.P-Profile-Key",
6847
14
            FT_STRING, BASE_NONE,NULL,0x0,
6848
14
            "P-Profile-Key Header", HFILL }
6849
14
        },
6850
14
        { &hf_header_array[POS_P_REFUSED_URI_LST],
6851
14
          { "P-Refused-URI-List",      "sip.P-Refused-URI-List",
6852
14
            FT_STRING, BASE_NONE,NULL,0x0,
6853
14
            "P-Refused-URI-List Header", HFILL }
6854
14
        },
6855
14
        { &hf_header_array[POS_P_SERVED_USER],
6856
14
          { "P-Served-User",   "sip.P-Served-User",
6857
14
            FT_STRING, BASE_NONE,NULL,0x0,
6858
14
            NULL, HFILL }
6859
14
        },
6860
14
        { &hf_header_array[POS_P_USER_DATABASE],
6861
14
          { "P-User-Database",     "sip.P-User-Database",
6862
14
            FT_STRING, BASE_NONE,NULL,0x0,
6863
14
            "P-User-Database Header", HFILL }
6864
14
        },
6865
6866
14
        { &hf_header_array[POS_P_VISITED_NETWORK_ID],
6867
14
          { "P-Visited-Network-ID",    "sip.P-Visited-Network-ID",
6868
14
            FT_STRING, BASE_NONE,NULL,0x0,
6869
14
            "RFC 3455: P-Visited-Network-ID Header", HFILL }
6870
14
        },
6871
6872
14
        { &hf_header_array[POS_PATH],
6873
14
          { "Path",            "sip.Path",
6874
14
            FT_STRING, BASE_NONE,NULL,0x0,
6875
14
            "RFC 3327: Path Header", HFILL }
6876
14
        },
6877
6878
14
        { &hf_header_array[POS_PERMISSION_MISSING],
6879
14
          { "Permission-Missing",      "sip.Permission-Missing",
6880
14
            FT_STRING, BASE_NONE,NULL,0x0,
6881
14
            "RFC 5360: Permission Missing Header", HFILL }
6882
14
        },
6883
14
        { &hf_header_array[POS_POLICY_CONTACT],
6884
14
          { "Policy-Contact",      "sip.Policy_Contact",
6885
14
            FT_STRING, BASE_NONE,NULL,0x0,
6886
14
            NULL, HFILL }
6887
14
        },
6888
14
        { &hf_header_array[POS_POLICY_ID],
6889
14
          { "Policy-ID",       "sip.Policy_ID",
6890
14
            FT_STRING, BASE_NONE,NULL,0x0,
6891
14
            NULL, HFILL }
6892
14
        },
6893
14
        { &hf_header_array[POS_PRIORITY],
6894
14
          { "Priority",        "sip.Priority",
6895
14
            FT_STRING, BASE_NONE,NULL,0x0,
6896
14
            "RFC 3261: Priority Header", HFILL }
6897
14
        },
6898
14
        { &hf_header_array[POS_PRIORITY_SHARE],
6899
14
          { "Priority-Share",        "sip.Priority-Share",
6900
14
            FT_STRING, BASE_NONE,NULL,0x0,
6901
14
            NULL, HFILL }
6902
14
        },
6903
14
        { &hf_header_array[POS_PRIV_ANSWER_MODE],
6904
14
          { "Priv-Answer-mode",    "sip.Priv-Answer-mode",
6905
14
            FT_STRING, BASE_NONE,NULL,0x0,
6906
14
            NULL, HFILL }
6907
14
        },
6908
14
        { &hf_header_array[POS_PRIVACY],
6909
14
          { "Privacy",             "sip.Privacy",
6910
14
            FT_STRING, BASE_NONE,NULL,0x0,
6911
14
            "Privacy Header", HFILL }
6912
14
        },
6913
6914
14
        { &hf_header_array[POS_PROXY_AUTHENTICATE],
6915
14
          { "Proxy-Authenticate",      "sip.Proxy-Authenticate",
6916
14
            FT_STRING, BASE_NONE,NULL,0x0,
6917
14
            "RFC 3261: Proxy-Authenticate Header", HFILL }
6918
14
        },
6919
14
        { &hf_header_array[POS_PROXY_AUTHORIZATION],
6920
14
          { "Proxy-Authorization",         "sip.Proxy-Authorization",
6921
14
            FT_STRING, BASE_NONE,NULL,0x0,
6922
14
            "RFC 3261: Proxy-Authorization Header", HFILL }
6923
14
        },
6924
6925
14
        { &hf_header_array[POS_PROXY_REQUIRE],
6926
14
          { "Proxy-Require",       "sip.Proxy-Require",
6927
14
            FT_STRING, BASE_NONE,NULL,0x0,
6928
14
            "RFC 3261: Proxy-Require Header", HFILL }
6929
14
        },
6930
14
        { &hf_header_array[POS_RACK],
6931
14
          { "RAck",        "sip.RAck",
6932
14
            FT_STRING, BASE_NONE,NULL,0x0,
6933
14
            "RFC 3262: RAck Header", HFILL }
6934
14
        },
6935
14
        { &hf_header_array[POS_REASON],
6936
14
          { "Reason",          "sip.Reason",
6937
14
            FT_STRING, BASE_NONE,NULL,0x0,
6938
14
            "RFC 3326 Reason Header", HFILL }
6939
14
        },
6940
14
        { &hf_header_array[POS_REASON_PHRASE],
6941
14
          { "Reason-Phrase",           "sip.Reason-Phrase",
6942
14
            FT_STRING, BASE_NONE,NULL,0x0,
6943
14
            NULL, HFILL }
6944
14
        },
6945
14
        { &hf_header_array[POS_RECORD_ROUTE],
6946
14
          { "Record-Route",        "sip.Record-Route",
6947
14
            FT_STRING, BASE_NONE,NULL,0x0,
6948
14
            "RFC 3261: Record-Route Header", HFILL }
6949
14
        },
6950
14
        { &hf_header_array[POS_RECV_INFO],
6951
14
          { "Recv-Info",       "sip.Recv-Info",
6952
14
            FT_STRING, BASE_NONE,NULL,0x0,
6953
14
            NULL, HFILL }
6954
14
        },
6955
14
        { &hf_header_array[POS_REFER_SUB],
6956
14
          { "Refer-Sub",       "sip.Refer-Sub",
6957
14
            FT_STRING, BASE_NONE,NULL,0x0,
6958
14
            "RFC 4488: Refer-Sub Header", HFILL }
6959
14
        },
6960
14
        { &hf_header_array[POS_REFER_TO],
6961
14
          { "Refer-To",           "sip.Refer-To",
6962
14
            FT_STRING, BASE_NONE,NULL,0x0,
6963
14
            "RFC 3515: Refer-To Header", HFILL }
6964
14
        },
6965
14
        { &hf_header_array[POS_REFERRED_BY],
6966
14
          { "Referred By",      "sip.Referred-by",
6967
14
            FT_STRING, BASE_NONE,NULL,0x0,
6968
14
            "RFC 3892: Referred-by Header", HFILL }
6969
14
        },
6970
14
        { &hf_header_array[POS_REJECT_CONTACT],
6971
14
          { "Reject-Contact",         "sip.Reject-Contact",
6972
14
            FT_STRING, BASE_NONE,NULL,0x0,
6973
14
            "RFC 3841: Reject-Contact Header", HFILL }
6974
14
        },
6975
14
        { &hf_header_array[POS_RELAYED_CHARGE],
6976
14
          { "Relayed-Charge",         "sip.Relayed-Charge",
6977
14
            FT_STRING, BASE_NONE,NULL,0x0,
6978
14
            NULL, HFILL }
6979
14
        },
6980
14
        { &hf_header_array[POS_REPLACES],
6981
14
          { "Replaces",       "sip.Replaces",
6982
14
            FT_STRING, BASE_NONE,NULL,0x0,
6983
14
            "RFC 3891: Replaces Header", HFILL }
6984
14
        },
6985
14
        { &hf_header_array[POS_REPLY_TO],
6986
14
          { "Reply-To",        "sip.Reply-To",
6987
14
            FT_STRING, BASE_NONE,NULL,0x0,
6988
14
            "RFC 3261: Reply-To Header", HFILL }
6989
14
        },
6990
14
        { &hf_header_array[POS_REQUEST_DISPOSITION],
6991
14
          { "Request-Disposition",     "sip.Request-Disposition",
6992
14
            FT_STRING, BASE_NONE,NULL,0x0,
6993
14
            "RFC 3841: Request-Disposition Header", HFILL }
6994
14
        },
6995
14
        { &hf_header_array[POS_REQUIRE],
6996
14
          { "Require",        "sip.Require",
6997
14
            FT_STRING, BASE_NONE,NULL,0x0,
6998
14
            "RFC 3261: Require Header", HFILL }
6999
14
        },
7000
14
        { &hf_header_array[POS_RESOURCE_PRIORITY],
7001
14
          { "Resource-Priority",      "sip.Resource-Priority",
7002
14
            FT_STRING, BASE_NONE,NULL,0x0,
7003
14
            "Draft: Resource-Priority Header", HFILL }
7004
14
        },
7005
14
        { &hf_header_array[POS_RESOURCE_SHARE],
7006
14
          { "Resource-Share",      "sip.Resource-Share",
7007
14
            FT_STRING, BASE_NONE,NULL,0x0,
7008
14
            NULL, HFILL }
7009
14
        },
7010
14
        { &hf_header_array[POS_RESPONSE_SOURCE],
7011
14
          { "Response-Source",      "sip.Response-Source",
7012
14
            FT_STRING, BASE_NONE,NULL,0x0,
7013
14
            NULL, HFILL }
7014
14
        },
7015
14
        { &hf_header_array[POS_RESTORATION_INFO],
7016
14
          { "Restoration-Info",      "sip.Restoration-Info",
7017
14
            FT_STRING, BASE_NONE,NULL,0x0,
7018
14
            NULL, HFILL }
7019
14
        },
7020
14
        { &hf_header_array[POS_RETRY_AFTER],
7021
14
          { "Retry-After",        "sip.Retry-After",
7022
14
            FT_UINT32, BASE_DEC,NULL,0x0,
7023
14
            "RFC 3261: Retry-After Header", HFILL }
7024
14
        },
7025
14
        { &hf_header_array[POS_ROUTE],
7026
14
          { "Route",       "sip.Route",
7027
14
            FT_STRING, BASE_NONE,NULL,0x0,
7028
14
            "RFC 3261: Route Header", HFILL }
7029
14
        },
7030
14
        { &hf_header_array[POS_RSEQ],
7031
14
          { "RSeq",        "sip.RSeq",
7032
14
            FT_UINT32, BASE_DEC,NULL,0x0,
7033
14
            "RFC 3262: RSeq Header", HFILL }
7034
14
        },
7035
14
        { &hf_header_array[ POS_SECURITY_CLIENT],
7036
14
          { "Security-Client",         "sip.Security-Client",
7037
14
            FT_STRING, BASE_NONE,NULL,0x0,
7038
14
            "RFC 3329 Security-Client Header", HFILL }
7039
14
        },
7040
14
        { &hf_header_array[ POS_SECURITY_SERVER],
7041
14
          { "Security-Server",         "sip.Security-Server",
7042
14
            FT_STRING, BASE_NONE,NULL,0x0,
7043
14
            "RFC 3329 Security-Server Header", HFILL }
7044
14
        },
7045
14
        { &hf_header_array[ POS_SECURITY_VERIFY],
7046
14
          { "Security-Verify",         "sip.Security-Verify",
7047
14
            FT_STRING, BASE_NONE,NULL,0x0,
7048
14
            "RFC 3329 Security-Verify Header", HFILL }
7049
14
        },
7050
14
        { &hf_header_array[POS_SERVER],
7051
14
          { "Server",         "sip.Server",
7052
14
            FT_STRING, BASE_NONE,NULL,0x0,
7053
14
            "RFC 3261: Server Header", HFILL }
7054
14
        },
7055
14
        { &hf_header_array[POS_SERVICE_INTERACT_INFO],
7056
14
          { "Service-Interact-Info",         "sip.Service-Interact-Info",
7057
14
            FT_STRING, BASE_NONE,NULL,0x0,
7058
14
            NULL, HFILL }
7059
14
        },
7060
14
        { &hf_header_array[POS_SERVICE_ROUTE],
7061
14
          { "Service-Route",       "sip.Service-Route",
7062
14
            FT_STRING, BASE_NONE,NULL,0x0,
7063
14
            "RFC 3608: Service-Route Header", HFILL }
7064
14
        },
7065
14
        { &hf_header_array[POS_SESSION_EXPIRES],
7066
14
          { "Session-Expires",         "sip.Session-Expires",
7067
14
            FT_STRING, BASE_NONE,NULL,0x0,
7068
14
            "RFC 4028: Session-Expires Header", HFILL }
7069
14
        },
7070
14
        { &hf_header_array[POS_SESSION_ID],
7071
14
          { "Session-ID", "sip.Session-ID",
7072
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7073
14
            NULL, HFILL }
7074
14
        },
7075
14
        { &hf_header_array[POS_SIP_ETAG],
7076
14
          { "ETag",        "sip.ETag",
7077
14
            FT_STRING, BASE_NONE,NULL,0x0,
7078
14
            "RFC 3903: SIP-ETag Header", HFILL }
7079
14
        },
7080
14
        { &hf_header_array[POS_SIP_IF_MATCH],
7081
14
          { "If_Match",        "sip.If_Match",
7082
14
            FT_STRING, BASE_NONE,NULL,0x0,
7083
14
            "RFC 3903: SIP-If-Match Header", HFILL }
7084
14
        },
7085
14
        { &hf_header_array[POS_SUBJECT],
7086
14
          { "Subject",         "sip.Subject",
7087
14
            FT_STRING, BASE_NONE,NULL,0x0,
7088
14
            "RFC 3261: Subject Header", HFILL }
7089
14
        },
7090
14
        { &hf_header_array[POS_SUBSCRIPTION_STATE],
7091
14
          { "Subscription-State",      "sip.Subscription-State",
7092
14
            FT_STRING, BASE_NONE,NULL,0x0,
7093
14
            "RFC 3265: Subscription-State Header", HFILL }
7094
14
        },
7095
14
        { &hf_header_array[POS_SUPPORTED],
7096
14
          { "Supported",      "sip.Supported",
7097
14
            FT_STRING, BASE_NONE,NULL,0x0,
7098
14
            "RFC 3261: Supported Header", HFILL }
7099
14
        },
7100
14
        { &hf_header_array[POS_SUPPRESS_IF_MATCH],
7101
14
          { "Suppress-If-Match",      "sip.Suppress_If_Match",
7102
14
            FT_STRING, BASE_NONE,NULL,0x0,
7103
14
            NULL, HFILL }
7104
14
        },
7105
14
        { &hf_header_array[POS_TARGET_DIALOG],
7106
14
          { "Target-Dialog",      "sip.Target-Dialog",
7107
14
            FT_STRING, BASE_NONE,NULL,0x0,
7108
14
            "RFC 4538: Target-Dialog Header", HFILL }
7109
14
        },
7110
14
        { &hf_header_array[POS_TIMESTAMP],
7111
14
          { "Timestamp",      "sip.Timestamp",
7112
14
            FT_STRING, BASE_NONE,NULL,0x0,
7113
14
            "RFC 3261: Timestamp Header", HFILL }
7114
14
        },
7115
14
        { &hf_header_array[POS_TO],
7116
14
          { "To",         "sip.To",
7117
14
            FT_STRING, BASE_NONE,NULL,0x0,
7118
14
            "RFC 3261: To Header", HFILL }
7119
14
        },
7120
7121
14
        { &hf_header_array[POS_TRIGGER_CONSENT],
7122
14
          { "Trigger-Consent",        "sip.Trigger-Consent",
7123
14
            FT_STRING, BASE_NONE,NULL,0x0,
7124
14
            "RFC 5380: Trigger Consent", HFILL }
7125
14
        },
7126
7127
14
        { &hf_header_array[POS_UNSUPPORTED],
7128
14
          { "Unsupported",        "sip.Unsupported",
7129
14
            FT_STRING, BASE_NONE,NULL,0x0,
7130
14
            "RFC 3261: Unsupported Header", HFILL }
7131
14
        },
7132
14
        { &hf_header_array[POS_USER_AGENT],
7133
14
          { "User-Agent",         "sip.User-Agent",
7134
14
            FT_STRING, BASE_NONE,NULL,0x0,
7135
14
            "RFC 3261: User-Agent Header", HFILL }
7136
14
        },
7137
14
        { &hf_header_array[POS_VIA],
7138
14
          { "Via",        "sip.Via",
7139
14
            FT_STRING, BASE_NONE,NULL,0x0,
7140
14
            "RFC 3261: Via Header", HFILL }
7141
14
        },
7142
14
        { &hf_header_array[POS_WARNING],
7143
14
          { "Warning",        "sip.Warning",
7144
14
            FT_STRING, BASE_NONE,NULL,0x0,
7145
14
            "RFC 3261: Warning Header", HFILL }
7146
14
        },
7147
7148
14
        { &hf_header_array[POS_WWW_AUTHENTICATE],
7149
14
          { "WWW-Authenticate",       "sip.WWW-Authenticate",
7150
14
            FT_STRING, BASE_NONE,NULL,0x0,
7151
14
            "RFC 3261: WWW-Authenticate Header", HFILL }
7152
14
        },
7153
14
        { &hf_header_array[POS_DIVERSION],
7154
14
          { "Diversion",      "sip.Diversion",
7155
14
            FT_STRING, BASE_NONE,NULL,0x0,
7156
14
            "RFC 5806: Diversion Header", HFILL }
7157
14
        },
7158
14
        { &hf_header_array[POS_USER_TO_USER],
7159
14
          { "User-to-User",   "sip.uui",
7160
14
            FT_STRING, BASE_NONE,NULL,0x0,
7161
14
            "draft-johnston-sipping-cc-uui-09: User-to-User header", HFILL }
7162
14
        },
7163
14
        { &hf_sip_resend,
7164
14
          { "Resent Packet", "sip.resend",
7165
14
            FT_BOOLEAN, BASE_NONE, NULL, 0x0,
7166
14
            NULL, HFILL }
7167
14
        },
7168
14
        { &hf_sip_original_frame,
7169
14
          { "Suspected resend of frame",  "sip.resend-original",
7170
14
            FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RETRANS_PREV), 0x0,
7171
14
            "Original transmission of frame", HFILL}
7172
14
        },
7173
14
        { &hf_sip_matching_request_frame,
7174
14
          { "Request Frame",  "sip.response-request",
7175
14
            FT_FRAMENUM, BASE_NONE, NULL, 0x0,
7176
14
            NULL, HFILL}
7177
14
        },
7178
14
        { &hf_sip_response_time,
7179
14
          { "Response Time (ms)",  "sip.response-time",
7180
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
7181
14
            "Response time since original request (in milliseconds)", HFILL}
7182
14
        },
7183
14
        { &hf_sip_release_time,
7184
14
          { "Release Time (ms)",  "sip.release-time",
7185
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
7186
14
            "release time since original BYE (in milliseconds)", HFILL}
7187
14
        },
7188
14
        { &hf_sip_auth,
7189
14
          { "Authentication",  "sip.auth",
7190
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7191
14
            "SIP Authentication", HFILL}
7192
14
        },
7193
14
        { &hf_sip_auth_scheme,
7194
14
          { "Authentication Scheme",  "sip.auth.scheme",
7195
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7196
14
            "SIP Authentication Scheme", HFILL}
7197
14
        },
7198
14
        { &hf_sip_auth_digest_response,
7199
14
          { "Digest Authentication Response",  "sip.auth.digest.response",
7200
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7201
14
            "SIP Digest Authentication Response Value", HFILL}
7202
14
        },
7203
14
        { &hf_sip_auth_nc,
7204
14
          { "Nonce Count",  "sip.auth.nc",
7205
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7206
14
            "SIP Authentication Nonce count", HFILL}
7207
14
        },
7208
14
        { &hf_sip_auth_username,
7209
14
          { "Username",  "sip.auth.username",
7210
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7211
14
            "SIP Authentication Username", HFILL}
7212
14
        },
7213
14
        { &hf_sip_auth_realm,
7214
14
          { "Realm",  "sip.auth.realm",
7215
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7216
14
            "SIP Authentication Realm", HFILL}
7217
14
        },
7218
14
        { &hf_sip_auth_nonce,
7219
14
          { "Nonce Value",  "sip.auth.nonce",
7220
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7221
14
            "SIP Authentication Nonce", HFILL}
7222
14
        },
7223
14
        { &hf_sip_auth_algorithm,
7224
14
          { "Algorithm",  "sip.auth.algorithm",
7225
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7226
14
            "SIP Authentication Algorithm", HFILL}
7227
14
        },
7228
14
        { &hf_sip_auth_opaque,
7229
14
          { "Opaque Value",  "sip.auth.opaque",
7230
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7231
14
            "SIP Authentication Opaque value", HFILL}
7232
14
        },
7233
14
        { &hf_sip_auth_qop,
7234
14
          { "QOP",  "sip.auth.qop",
7235
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7236
14
            "SIP Authentication QOP", HFILL}
7237
14
        },
7238
14
        { &hf_sip_auth_cnonce,
7239
14
          { "CNonce Value",  "sip.auth.cnonce",
7240
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7241
14
            "SIP Authentication Client Nonce", HFILL}
7242
14
        },
7243
14
        { &hf_sip_auth_uri,
7244
14
          { "Authentication URI",  "sip.auth.uri",
7245
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7246
14
            "SIP Authentication URI", HFILL}
7247
14
        },
7248
14
        { &hf_sip_auth_domain,
7249
14
          { "Authentication Domain",  "sip.auth.domain",
7250
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7251
14
            "SIP Authentication Domain", HFILL}
7252
14
        },
7253
14
        { &hf_sip_auth_stale,
7254
14
          { "Stale Flag",  "sip.auth.stale",
7255
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7256
14
            "SIP Authentication Stale Flag", HFILL}
7257
14
        },
7258
14
        { &hf_sip_auth_auts,
7259
14
          { "Authentication Token",  "sip.auth.auts",
7260
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7261
14
            "SIP Authentication Token", HFILL}
7262
14
        },
7263
14
        { &hf_sip_auth_rspauth,
7264
14
          { "Response auth",  "sip.auth.rspauth",
7265
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7266
14
            "SIP Authentication Response auth", HFILL}
7267
14
        },
7268
14
        { &hf_sip_auth_nextnonce,
7269
14
          { "Next Nonce",  "sip.auth.nextnonce",
7270
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7271
14
            "SIP Authentication Next Nonce", HFILL}
7272
14
        },
7273
14
        { &hf_sip_auth_ik,
7274
14
          { "Integrity Key",  "sip.auth.ik",
7275
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7276
14
            "SIP Authentication Integrity Key", HFILL}
7277
14
        },
7278
14
        { &hf_sip_auth_ck,
7279
14
          { "Cyphering Key",  "sip.auth.ck",
7280
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7281
14
            "SIP Authentication Cyphering Key", HFILL}
7282
14
        },
7283
14
        { &hf_sip_cseq_seq_no,
7284
14
          { "Sequence Number",  "sip.CSeq.seq",
7285
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
7286
14
            "CSeq header sequence number", HFILL}
7287
14
        },
7288
14
        { &hf_sip_cseq_method,
7289
14
          { "Method",  "sip.CSeq.method",
7290
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7291
14
            "CSeq header method", HFILL}
7292
14
        },
7293
14
        { &hf_sip_via_transport,
7294
14
          { "Transport",  "sip.Via.transport",
7295
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7296
14
            "Via header Transport", HFILL}
7297
14
        },
7298
14
        { &hf_sip_via_sent_by_address,
7299
14
          { "Sent-by Address",  "sip.Via.sent-by.address",
7300
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7301
14
            "Via header Sent-by Address", HFILL}
7302
14
        },
7303
14
        { &hf_sip_via_sent_by_port,
7304
14
          { "Sent-by port",  "sip.Via.sent-by.port",
7305
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
7306
14
            "Via header Sent-by Port", HFILL}
7307
14
        },
7308
14
        { &hf_sip_via_branch,
7309
14
          { "Branch",  "sip.Via.branch",
7310
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7311
14
            "SIP Via Branch", HFILL},
7312
14
        },
7313
14
        { &hf_sip_via_maddr,
7314
14
          { "Maddr",  "sip.Via.maddr",
7315
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7316
14
            "SIP Via Maddr", HFILL},
7317
14
        },
7318
14
        { &hf_sip_via_rport,
7319
14
          { "RPort",  "sip.Via.rport",
7320
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7321
14
            "SIP Via RPort", HFILL},
7322
14
        },
7323
14
        { &hf_sip_via_received,
7324
14
          { "Received",  "sip.Via.received",
7325
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7326
14
            "SIP Via Received", HFILL},
7327
14
        },
7328
14
        { &hf_sip_via_ttl,
7329
14
          { "TTL",  "sip.Via.ttl",
7330
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7331
14
            "SIP Via TTL", HFILL}
7332
14
        },
7333
14
        { &hf_sip_via_comp,
7334
14
          { "Comp",  "sip.Via.comp",
7335
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7336
14
            "SIP Via comp", HFILL}
7337
14
        },
7338
14
        { &hf_sip_via_sigcomp_id,
7339
14
          { "Sigcomp identifier",  "sip.Via.sigcomp-id",
7340
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7341
14
            "SIP Via sigcomp identifier", HFILL}
7342
14
        },
7343
14
        { &hf_sip_via_oc,
7344
14
        { "Overload Control",  "sip.Via.oc",
7345
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7346
14
            NULL, HFILL }
7347
14
        },
7348
14
        { &hf_sip_via_oc_val,
7349
14
        { "Overload Control Value",  "sip.Via.oc_val",
7350
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
7351
14
            NULL, HFILL }
7352
14
        },
7353
14
        { &hf_sip_via_oc_validity,
7354
14
        { "Overload Control Validity",  "sip.Via.oc_validity",
7355
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7356
14
            NULL, HFILL }
7357
14
        },
7358
14
        { &hf_sip_via_oc_seq,
7359
14
        { "Overload Control Sequence",  "sip.Via.oc_seq",
7360
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7361
14
            NULL, HFILL }
7362
14
        },
7363
14
        { &hf_sip_oc_seq_timestamp,
7364
14
        { "Overload Control Sequence Time Stamp",
7365
14
            "sip.Via.oc_seq.ts",
7366
14
            FT_ABSOLUTE_TIME, ABSOLUTE_TIME_UTC, NULL, 0x0,
7367
14
            NULL, HFILL }
7368
14
        },
7369
14
        { &hf_sip_via_oc_algo,
7370
14
        { "Overload Control Algorithm",  "sip.Via.oc_algo",
7371
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7372
14
            NULL, HFILL }
7373
14
        },
7374
14
        { &hf_sip_via_be_route,
7375
14
        { "be-route",  "sip.Via.be_route",
7376
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7377
14
            NULL, HFILL }
7378
14
        },
7379
14
        { &hf_sip_p_acc_net_i_acc_type,
7380
14
           { "access-type", "sip.P-Access-Network-Info.access-type",
7381
14
             FT_STRING, BASE_NONE, NULL, 0x0,
7382
14
             "SIP P-Access-Network-Info access-type", HFILL}
7383
14
        },
7384
14
        { &hf_sip_p_acc_net_i_ucid_3gpp,
7385
14
           { "utran-cell-id-3gpp", "sip.P-Access-Network-Info.utran-cell-id-3gpp",
7386
14
             FT_STRING, BASE_NONE, NULL, 0x0,
7387
14
             "SIP P-Access-Network-Info utran-cell-id-3gpp", HFILL}
7388
14
        },
7389
14
        { &hf_sip_rack_rseq_no,
7390
14
          { "RSeq Sequence Number",  "sip.RAck.RSeq.seq",
7391
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
7392
14
            "RAck RSeq header sequence number (from prov response)", HFILL}
7393
14
        },
7394
14
        { &hf_sip_rack_cseq_no,
7395
14
          { "CSeq Sequence Number",  "sip.RAck.CSeq.seq",
7396
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
7397
14
            "RAck CSeq header sequence number (from prov response)", HFILL}
7398
14
        },
7399
14
        { &hf_sip_rack_cseq_method,
7400
14
          { "CSeq Method",  "sip.RAck.CSeq.method",
7401
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7402
14
            "RAck CSeq header method (from prov response)", HFILL}
7403
14
        },
7404
14
        { &hf_sip_reason_protocols,
7405
14
          { "Reason protocols",  "sip.reason_protocols",
7406
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7407
14
            NULL, HFILL}
7408
14
        },
7409
14
        { &hf_sip_reason_cause_q850,
7410
14
          { "Cause",  "sip.reason_cause_q850",
7411
14
            FT_UINT32, BASE_DEC_HEX|BASE_EXT_STRING, &q850_cause_code_vals_ext, 0x0,
7412
14
            NULL, HFILL}
7413
14
        },
7414
14
        { &hf_sip_reason_cause_sip,
7415
14
          { "Cause",  "sip.reason_cause_sip",
7416
14
            FT_UINT32, BASE_DEC, VALS(sip_response_code_vals), 0x0,
7417
14
            NULL, HFILL }
7418
14
        },
7419
14
        { &hf_sip_reason_cause_other,
7420
14
        { "Cause",  "sip.reason_cause_other",
7421
14
            FT_UINT32, BASE_DEC, NULL, 0x0,
7422
14
            NULL, HFILL }
7423
14
        },
7424
14
        { &hf_sip_reason_text,
7425
14
        { "Text",  "sip.reason_text",
7426
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7427
14
            NULL, HFILL }
7428
14
        },
7429
14
        { &hf_sip_msg_body,
7430
14
          { "Message Body",           "sip.msg_body",
7431
14
            FT_BYTES, BASE_NONE|BASE_NO_DISPLAY_VALUE, NULL, 0x0,
7432
14
            "Message Body in SIP message", HFILL }
7433
14
        },
7434
14
        { &hf_sip_sec_mechanism,
7435
14
          { "[Security-mechanism]",  "sip.sec_mechanism",
7436
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7437
14
            NULL, HFILL}
7438
14
        },
7439
14
        { &hf_sip_sec_mechanism_alg,
7440
14
          { "alg",  "sip.sec_mechanism.alg",
7441
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7442
14
            NULL, HFILL}
7443
14
        },
7444
14
        { &hf_sip_sec_mechanism_ealg,
7445
14
          { "ealg",  "sip.sec_mechanism.ealg",
7446
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7447
14
            NULL, HFILL}
7448
14
        },
7449
14
        { &hf_sip_sec_mechanism_prot,
7450
14
          { "prot",  "sip.sec_mechanism.prot",
7451
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7452
14
            NULL, HFILL}
7453
14
        },
7454
14
        { &hf_sip_sec_mechanism_spi_c,
7455
14
          { "spi-c",  "sip.sec_mechanism.spi_c",
7456
14
            FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
7457
14
            NULL, HFILL}
7458
14
        },
7459
14
        { &hf_sip_sec_mechanism_spi_s,
7460
14
          { "spi-s",  "sip.sec_mechanism.spi_s",
7461
14
            FT_UINT32, BASE_DEC_HEX, NULL, 0x0,
7462
14
            NULL, HFILL}
7463
14
        },
7464
14
        { &hf_sip_sec_mechanism_port1,
7465
14
          { "port1",  "sip.sec_mechanism.port1",
7466
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
7467
14
            NULL, HFILL}
7468
14
        },
7469
14
        { &hf_sip_sec_mechanism_port_c,
7470
14
          { "port-c",  "sip.sec_mechanism.port_c",
7471
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
7472
14
            NULL, HFILL}
7473
14
        },
7474
14
        { &hf_sip_sec_mechanism_port2,
7475
14
          { "port2",  "sip.sec_mechanism.port2",
7476
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
7477
14
            NULL, HFILL}
7478
14
        },
7479
14
        { &hf_sip_sec_mechanism_port_s,
7480
14
          { "port-s",  "sip.sec_mechanism.port_s",
7481
14
            FT_UINT16, BASE_DEC, NULL, 0x0,
7482
14
            NULL, HFILL}
7483
14
        },
7484
14
        { &hf_sip_session_id_sess_id,
7485
14
            { "sess-id", "sip.Session-ID.sess_id",
7486
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
7487
14
            NULL, HFILL}
7488
14
        },
7489
14
        { &hf_sip_session_id_param,
7490
14
            { "param", "sip.Session-ID.param",
7491
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7492
14
            NULL, HFILL}
7493
14
        },
7494
14
        { &hf_sip_session_id_local_uuid,
7495
14
            { "local-uuid", "sip.Session-ID.local_uuid",
7496
14
            FT_GUID, BASE_NONE, NULL, 0x0,
7497
14
            NULL, HFILL}
7498
14
        },
7499
14
        { &hf_sip_session_id_remote_uuid,
7500
14
            { "remote-uuid", "sip.Session-ID.remote_uuid",
7501
14
            FT_GUID, BASE_NONE, NULL, 0x0,
7502
14
            NULL, HFILL}
7503
14
        },
7504
14
  { &hf_sip_session_id_logme,
7505
14
           { "logme",  "sip.Session-ID.logme",
7506
14
             FT_BOOLEAN, BASE_NONE, TFS(&tfs_set_notset), 0x0,
7507
14
             NULL, HFILL}
7508
14
        },
7509
14
        { &hf_sip_continuation,
7510
14
          { "Continuation data",  "sip.continuation",
7511
14
            FT_BYTES, BASE_NONE, NULL, 0x0,
7512
14
            NULL, HFILL}
7513
14
        },
7514
14
        { &hf_sip_feature_cap,
7515
14
          { "Feature Cap",  "sip.feature_cap",
7516
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7517
14
            NULL, HFILL }
7518
14
        },
7519
14
        { &hf_sip_service_priority,
7520
14
          { "Service Priority",  "sip.service_priority",
7521
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7522
14
            NULL, HFILL }
7523
14
        },
7524
14
        { &hf_sip_icid_value,
7525
14
        { "icid-value",  "sip.icid_value",
7526
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7527
14
            NULL, HFILL }
7528
14
        },
7529
14
        { &hf_sip_icid_gen_addr,
7530
14
        { "icid-gen-addr",  "sip.icid_gen_addr",
7531
14
            FT_STRING, BASE_NONE, NULL, 0x0,
7532
14
            NULL, HFILL }
7533
14
        },
7534
14
        { &hf_sip_call_id_gen,
7535
14
        { "Generated Call-ID",         "sip.call_id_generated",
7536
14
            FT_STRING, BASE_NONE,NULL,0x0,
7537
14
            "Use to catch call id across protocols", HFILL }
7538
14
        },
7539
7540
14
    };
7541
7542
    /* raw_sip header field(s) */
7543
14
    static hf_register_info raw_hf[] = {
7544
7545
14
        { &hf_sip_raw_line,
7546
14
          { "Raw SIP Line",                "raw_sip.line",
7547
14
            FT_STRING, BASE_NONE,NULL,0x0,
7548
14
            NULL, HFILL }
7549
14
        }};
7550
7551
    /* Setup protocol subtree array */
7552
14
    static int *ett[] = {
7553
14
        &ett_sip,
7554
14
        &ett_sip_reqresp,
7555
14
        &ett_sip_hdr,
7556
14
        &ett_sip_ext_hdr,
7557
14
        &ett_sip_element,
7558
14
        &ett_sip_hist,
7559
14
        &ett_sip_uri,
7560
14
        &ett_sip_contact_item,
7561
14
        &ett_sip_message_body,
7562
14
        &ett_sip_cseq,
7563
14
        &ett_sip_via,
7564
14
        &ett_sip_reason,
7565
14
        &ett_sip_security_client,
7566
14
        &ett_sip_security_server,
7567
14
        &ett_sip_security_verify,
7568
14
        &ett_sip_rack,
7569
14
        &ett_sip_record_route,
7570
14
        &ett_sip_service_route,
7571
14
        &ett_sip_route,
7572
14
        &ett_sip_path,
7573
14
        &ett_sip_ruri,
7574
14
        &ett_sip_pai_uri,
7575
14
        &ett_sip_pmiss_uri,
7576
14
        &ett_sip_ppi_uri,
7577
14
        &ett_sip_tc_uri,
7578
14
        &ett_sip_to_uri,
7579
14
        &ett_sip_from_uri,
7580
14
        &ett_sip_curi,
7581
14
        &ett_sip_session_id,
7582
14
        &ett_sip_p_access_net_info,
7583
14
        &ett_sip_p_charging_vector,
7584
14
        &ett_sip_feature_caps,
7585
14
        &ett_sip_via_be_route
7586
14
    };
7587
14
    static int *ett_raw[] = {
7588
14
        &ett_raw_text,
7589
14
    };
7590
7591
14
    static ei_register_info ei[] = {
7592
14
        { &ei_sip_unrecognized_header, { "sip.unrecognized_header", PI_UNDECODED, PI_NOTE, "Unrecognised SIP header", EXPFILL }},
7593
14
        { &ei_sip_header_no_colon, { "sip.header_no_colon", PI_MALFORMED, PI_WARN, "Header has no colon after the name", EXPFILL }},
7594
14
        { &ei_sip_header_not_terminated, { "sip.header_not_terminated", PI_MALFORMED, PI_WARN, "Header not terminated by empty line (CRLF)", EXPFILL }},
7595
#if 0
7596
        { &ei_sip_odd_register_response, { "sip.response.unusual", PI_RESPONSE_CODE, PI_WARN, "SIP Response is unusual", EXPFILL }},
7597
#endif
7598
14
        { &ei_sip_call_id_invalid, { "sip.Call-ID.invalid", PI_PROTOCOL, PI_WARN, "Call ID is mandatory", EXPFILL }},
7599
14
        { &ei_sip_sipsec_malformed, { "sip.sec_mechanism.malformed", PI_MALFORMED, PI_WARN, "SIP Security-mechanism header malformed", EXPFILL }},
7600
14
        { &ei_sip_via_sent_by_port, { "sip.Via.sent-by.port.invalid", PI_MALFORMED, PI_NOTE, "Invalid SIP Via sent-by-port", EXPFILL }},
7601
14
        { &ei_sip_content_length_invalid, { "sip.content_length.invalid", PI_MALFORMED, PI_NOTE, "Invalid content_length", EXPFILL }},
7602
14
        { &ei_sip_retry_after_invalid, { "sip.retry_after.invalid", PI_MALFORMED, PI_NOTE, "Invalid retry_after value", EXPFILL }},
7603
14
        { &ei_sip_Status_Code_invalid, { "sip.Status-Code.invalid", PI_MALFORMED, PI_NOTE, "Invalid Status-Code", EXPFILL }},
7604
14
        { &ei_sip_authorization_invalid, { "sip.authorization.invalid", PI_PROTOCOL, PI_WARN, "Invalid authorization response for known credentials", EXPFILL }},
7605
14
        { &ei_sip_session_id_sess_id,{ "sip.Session-ID.sess_id.invalid", PI_PROTOCOL, PI_WARN, "Session ID cannot be empty", EXPFILL }}
7606
14
    };
7607
7608
14
    module_t *sip_module;
7609
14
    expert_module_t* expert_sip;
7610
14
    uat_t* sip_custom_headers_uat;
7611
14
    uat_t* sip_authorization_users_uat;
7612
7613
14
    static tap_param sip_stat_params[] = {
7614
14
      { PARAM_FILTER, "filter", "Filter", NULL, true }
7615
14
    };
7616
7617
14
    static stat_tap_table_ui sip_stat_table = {
7618
14
      REGISTER_TELEPHONY_GROUP_UNSORTED,
7619
14
      "SIP Statistics",
7620
14
      "sip",
7621
14
      "sip,stat",
7622
14
      sip_stat_init,
7623
14
      sip_stat_packet,
7624
14
      sip_stat_reset,
7625
14
      sip_stat_free_table_item,
7626
14
      NULL,
7627
14
      array_length(sip_stat_fields), sip_stat_fields,
7628
14
      array_length(sip_stat_params), sip_stat_params,
7629
14
      NULL,
7630
14
      0
7631
14
    };
7632
7633
    /* UAT for header fields */
7634
14
    static uat_field_t sip_custom_header_uat_fields[] = {
7635
14
        UAT_FLD_CSTRING(sip_custom_header_fields, header_name, "Header name", "SIP header name"),
7636
14
        UAT_FLD_CSTRING(sip_custom_header_fields, header_desc, "Field desc", "Description of the value contained in the header"),
7637
14
        UAT_END_FIELDS
7638
14
    };
7639
7640
14
    static uat_field_t sip_authorization_users_uat_fields[] = {
7641
14
        UAT_FLD_CSTRING(sip_authorization_users, username, "Username", "SIP authorization username"),
7642
14
        UAT_FLD_CSTRING(sip_authorization_users, realm, "Realm", "SIP authorization realm"),
7643
14
        UAT_FLD_CSTRING(sip_authorization_users, password, "Password", "SIP authorization password"),
7644
14
        UAT_END_FIELDS
7645
14
    };
7646
7647
        /* Register the protocol name and description */
7648
14
    proto_sip = proto_register_protocol("Session Initiation Protocol", "SIP", "sip");
7649
14
    proto_raw_sip = proto_register_protocol("Session Initiation Protocol (SIP as raw text)",
7650
14
                                            "Raw_SIP", "raw_sip");
7651
14
    sip_handle = register_dissector("sip", dissect_sip, proto_sip);
7652
14
    sip_tcp_handle = register_dissector("sip.tcp", dissect_sip_tcp, proto_sip);
7653
7654
    /* Required function calls to register the header fields and subtrees used */
7655
14
    proto_register_field_array(proto_sip, hf, array_length(hf));
7656
14
    proto_register_subtree_array(ett, array_length(ett));
7657
14
    expert_sip = expert_register_protocol(proto_sip);
7658
14
    expert_register_field_array(expert_sip, ei, array_length(ei));
7659
14
    proto_register_subtree_array(ett_raw, array_length(ett_raw));
7660
7661
    /* Register raw_sip field(s) */
7662
14
    proto_register_field_array(proto_raw_sip, raw_hf, array_length(raw_hf));
7663
7664
14
    sip_module = prefs_register_protocol(proto_sip, proto_reg_handoff_sip);
7665
7666
14
    prefs_register_uint_preference(sip_module, "tls.port",
7667
14
        "SIP TLS Port",
7668
14
        "SIP Server TLS Port",
7669
14
        10, &sip_tls_port);
7670
7671
14
    prefs_register_bool_preference(sip_module, "display_raw_text",
7672
14
        "Display raw text for SIP message",
7673
14
        "Specifies that the raw text of the "
7674
14
        "SIP message should be displayed "
7675
14
        "in addition to the dissection tree",
7676
14
        &global_sip_raw_text);
7677
7678
14
    prefs_register_bool_preference(sip_module, "display_raw_text_without_crlf",
7679
14
        "Don't show '\\r\\n' in raw SIP messages",
7680
14
        "If the raw text of the SIP message "
7681
14
        "is displayed, the trailing carriage "
7682
14
        "return and line feed are not shown",
7683
14
        &global_sip_raw_text_without_crlf);
7684
7685
14
    prefs_register_enum_preference(sip_module, "raw_text_body_default_encoding",
7686
14
        "Default charset of raw SIP messages",
7687
14
        "Display sip body of raw text by using this charset. The default is UTF-8.",
7688
14
        &global_sip_raw_text_body_default_encoding,
7689
14
        ws_supported_mibenum_vals_character_sets_ev_array, false);
7690
7691
14
    prefs_register_bool_preference(sip_module, "strict_sip_version",
7692
14
        "Enforce strict SIP version check (" SIP2_HDR ")",
7693
14
        "If enabled, only " SIP2_HDR " traffic will be dissected as SIP. "
7694
14
        "Disable it to allow SIP traffic with a different version "
7695
14
        "to be dissected as SIP.",
7696
14
        &strict_sip_version);
7697
7698
14
    prefs_register_bool_preference(sip_module, "desegment_headers",
7699
14
        "Reassemble SIP headers spanning multiple TCP segments",
7700
14
        "Whether the SIP dissector should reassemble headers "
7701
14
        "of a request spanning multiple TCP segments. "
7702
14
        "To use this option, you must also enable "
7703
14
        "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
7704
14
        &sip_desegment_headers);
7705
7706
14
    prefs_register_bool_preference(sip_module, "desegment_body",
7707
14
        "Reassemble SIP bodies spanning multiple TCP segments",
7708
14
        "Whether the SIP dissector should use the "
7709
14
        "\"Content-length:\" value, if present, to reassemble "
7710
14
        "the body of a request spanning multiple TCP segments, "
7711
14
        "and reassemble chunked data spanning multiple TCP segments. "
7712
14
        "To use this option, you must also enable "
7713
14
        "\"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
7714
14
        &sip_desegment_body);
7715
7716
14
    prefs_register_bool_preference(sip_module, "retrans_the_same_sport",
7717
14
        "Retransmissions always use the same source port",
7718
14
        "Whether retransmissions are detected coming from the same source port only.",
7719
14
        &sip_retrans_the_same_sport);
7720
7721
14
    prefs_register_bool_preference(sip_module, "delay_sdp_changes",
7722
14
        "Delay SDP changes for tracking media",
7723
14
        "Whether SIP should delay tracking the media (e.g., RTP/RTCP) until an SDP offer "
7724
14
        "is answered. If enabled, mid-dialog changes to SDP and media state only take "
7725
14
        "effect if and when an SDP offer is successfully answered; however enabling this "
7726
14
        "prevents tracking media in early-media call scenarios",
7727
14
        &sip_delay_sdp_changes);
7728
7729
14
    prefs_register_bool_preference(sip_module, "hide_generatd_call_id",
7730
14
        "Hide the generated Call Id",
7731
14
        "Whether the generated call id should be hidden(not displayed) in the tree or not.",
7732
14
        &sip_hide_generatd_call_ids);
7733
7734
    /* UAT */
7735
14
    sip_custom_headers_uat = uat_new("Custom SIP Header Fields",
7736
14
        sizeof(header_field_t),
7737
14
        "custom_sip_header_fields",
7738
14
        true,
7739
14
        &sip_custom_header_fields,
7740
14
        &sip_custom_num_header_fields,
7741
        /* specifies named fields, so affects dissection
7742
            and the set of named fields */
7743
14
        UAT_AFFECTS_DISSECTION|UAT_AFFECTS_FIELDS,
7744
14
        NULL,
7745
14
        header_fields_copy_cb,
7746
14
        header_fields_update_cb,
7747
14
        header_fields_free_cb,
7748
14
        header_fields_post_update_cb,
7749
14
        header_fields_reset_cb,
7750
14
        sip_custom_header_uat_fields
7751
14
    );
7752
7753
14
    prefs_register_uat_preference(sip_module, "custom_sip_header_fields", "Custom SIP header fields",
7754
14
        "A table to define custom SIP header for which fields can be setup and used for filtering/data extraction etc.",
7755
14
        sip_custom_headers_uat);
7756
7757
14
    prefs_register_bool_preference(sip_module, "validate_authorization",
7758
14
        "Validate SIP authorization",
7759
14
        "Validate SIP authorizations with known credentials",
7760
14
        &global_sip_validate_authorization);
7761
7762
14
    sip_authorization_users_uat = uat_new("SIP authorization users",
7763
14
        sizeof(authorization_user_t),
7764
14
        "authorization_users_sip",
7765
14
        true,
7766
14
        &sip_authorization_users,
7767
14
        &sip_authorization_num_users,
7768
        /* specifies named fields, so affects dissection
7769
            and the set of named fields */
7770
14
        UAT_AFFECTS_DISSECTION|UAT_AFFECTS_FIELDS,
7771
14
        NULL,
7772
14
        authorization_users_copy_cb,
7773
14
        authorization_users_update_cb,
7774
14
        authorization_users_free_cb,
7775
14
        NULL,
7776
14
        NULL,
7777
14
        sip_authorization_users_uat_fields
7778
14
    );
7779
7780
14
    prefs_register_uat_preference(sip_module, "authorization_users_sip", "SIP authorization users",
7781
14
        "A table to define user credentials used for validating authorization attempts",
7782
14
        sip_authorization_users_uat);
7783
7784
14
    register_init_routine(&sip_init_protocol);
7785
14
    register_cleanup_routine(&sip_cleanup_protocol);
7786
14
    heur_subdissector_list = register_heur_dissector_list_with_description("sip", "SIP message fallback", proto_sip);
7787
    /* Register for tapping */
7788
14
    sip_tap = register_tap("sip");
7789
14
    sip_follow_tap = register_tap("sip_follow");
7790
7791
14
    ext_hdr_subdissector_table = register_dissector_table("sip.hdr", "SIP Extension header", proto_sip, FT_STRING, STRING_CASE_SENSITIVE);
7792
7793
14
    register_stat_tap_table_ui(&sip_stat_table);
7794
7795
    /* compile patterns */
7796
14
    ws_mempbrk_compile(&pbrk_comma_semi, ",;");
7797
14
    ws_mempbrk_compile(&pbrk_whitespace, " \t\r\n");
7798
14
    ws_mempbrk_compile(&pbrk_param_end, ">,;? \r");
7799
14
    ws_mempbrk_compile(&pbrk_param_end_colon_brackets, ">,;? \r:[]");
7800
14
    ws_mempbrk_compile(&pbrk_header_end_dquote, "\r\n,;\"");
7801
14
    ws_mempbrk_compile(&pbrk_tab_sp_fslash, "\t /");
7802
14
    ws_mempbrk_compile(&pbrk_addr_end, "[] \t:;");
7803
14
    ws_mempbrk_compile(&pbrk_via_param_end, "\t;, ");
7804
7805
14
    register_follow_stream(proto_sip, "sip_follow", sip_follow_conv_filter, sip_follow_index_filter, sip_follow_address_filter,
7806
14
                           udp_port_to_display, follow_tvb_tap_listener, NULL, NULL);
7807
7808
14
    register_external_value_string("sip_response_code_vals", sip_response_code_vals);
7809
14
}
7810
7811
void
7812
proto_reg_handoff_sip(void)
7813
14
{
7814
14
    static unsigned saved_sip_tls_port;
7815
14
    static bool sip_prefs_initialized = false;
7816
7817
14
    if (!sip_prefs_initialized) {
7818
14
        sigcomp_handle = find_dissector_add_dependency("sigcomp", proto_sip);
7819
14
        sip_diag_handle = find_dissector("sip.diagnostic");
7820
14
        sip_uri_userinfo_handle = find_dissector("sip.uri_userinfo");
7821
14
        sip_via_branch_handle = find_dissector("sip.via_branch");
7822
14
        sip_via_be_route_handle = find_dissector("sip.via_be_route");
7823
        /* Check for a dissector to parse Reason Code texts */
7824
14
        sip_reason_code_handle = find_dissector("sip.reason_code");
7825
        /* SIP content type and internet media type used by other dissectors are the same */
7826
14
        media_type_dissector_table = find_dissector_table("media_type");
7827
7828
14
        dissector_add_uint_range_with_preference("udp.port", DEFAULT_SIP_PORT_RANGE, sip_handle);
7829
14
        dissector_add_string("media_type", "message/sip", sip_handle);
7830
14
        dissector_add_string("ws.protocol", "sip", sip_handle);  /* RFC 7118 */
7831
7832
14
        dissector_add_uint_range_with_preference("tcp.port", DEFAULT_SIP_PORT_RANGE, sip_tcp_handle);
7833
7834
14
        heur_dissector_add("udp", dissect_sip_heur, "SIP over UDP", "sip_udp", proto_sip, HEURISTIC_ENABLE);
7835
14
        heur_dissector_add("tcp", dissect_sip_tcp_heur, "SIP over TCP", "sip_tcp", proto_sip, HEURISTIC_ENABLE);
7836
14
        heur_dissector_add("sctp", dissect_sip_heur, "SIP over SCTP", "sip_sctp", proto_sip, HEURISTIC_ENABLE);
7837
14
        heur_dissector_add("stun", dissect_sip_heur, "SIP over TURN", "sip_stun", proto_sip, HEURISTIC_ENABLE);
7838
7839
14
        dissector_add_uint("acdr.tls_application_port", 5061, sip_handle);
7840
14
        dissector_add_uint("acdr.tls_application", TLS_APP_SIP, sip_handle);
7841
14
        dissector_add_string("protobuf_field", "adc.sip.ResponsePDU.body", sip_handle);
7842
14
        dissector_add_string("protobuf_field", "adc.sip.RequestPDU.body", sip_handle);
7843
7844
14
        exported_pdu_tap = find_tap_id(EXPORT_PDU_TAP_NAME_LAYER_7);
7845
7846
14
        sip_prefs_initialized = true;
7847
14
    } else {
7848
0
        ssl_dissector_delete(saved_sip_tls_port, sip_tcp_handle);
7849
0
    }
7850
    /* Set our port number for future use */
7851
14
    ssl_dissector_add(sip_tls_port, sip_tcp_handle);
7852
14
    saved_sip_tls_port = sip_tls_port;
7853
7854
14
}
7855
7856
/*
7857
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
7858
 *
7859
 * Local variables:
7860
 * c-basic-offset: 4
7861
 * tab-width: 8
7862
 * indent-tabs-mode: nil
7863
 * End:
7864
 *
7865
 * vi: set shiftwidth=4 tabstop=8 expandtab:
7866
 * :indentSize=4:tabSize=8:noTabs=true:
7867
 */