2 * Routines for Secure Reliable Transport Protocol dissection
3 * Copyright (c) 2018 Haivision Systems Inc. <info@srtalliance.org>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 * SRT is an open source video transport protocol and technology stack
14 * that optimizes streaming performance across unpredictable networks
15 * with secure streams and easy firewall traversal, bringing the best
16 * quality live video over the worst networks.
19 * https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01
21 * Open-source implementation:
22 * https://github.com/Haivision/srt
27 #include <epan/packet.h>
28 #include <epan/expert.h>
29 #include <epan/conversation.h>
31 #include <epan/unit_strings.h>
33 #include <wsutil/array.h>
34 #include <wsutil/inet_addr.h>
37 void proto_reg_handoff_srt(void);
38 void proto_register_srt(void);
40 /* Initialize the protocol */
42 static int hf_srt_iscontrol
;
43 static int hf_srt_type
;
44 static int hf_srt_exttype
;
45 static int hf_srt_exttype_none
;
46 static int hf_srt_seqno
;
47 static int hf_srt_ack_seqno
;
48 static int hf_srt_ackno
;
49 static int hf_srt_msgno
;
50 static int hf_srt_msgno_pb
;
51 static int hf_srt_msgno_inorder
;
52 static int hf_srt_msgno_enctypes
;
53 static int hf_srt_msgno_rexmit
;
54 static int hf_srt_timestamp
;
56 static int hf_srt_addinfo
;
57 static int hf_srt_rtt
;
58 static int hf_srt_rttvar
;
59 static int hf_srt_bufavail
;
60 static int hf_srt_rate
;
61 static int hf_srt_bandwidth
;
62 static int hf_srt_rcvrate
;
65 static int hf_srt_handshake_version
;
66 static int hf_srt_handshake_type_v4
;
67 static int hf_srt_handshake_enc_field_v5
;
68 static int hf_srt_handshake_ext_field_v5
;
69 static int hf_srt_handshake_ext_field_v5_flag_hsreq
;
70 static int hf_srt_handshake_ext_field_v5_flag_kmreq
;
71 static int hf_srt_handshake_ext_field_v5_flag_config
;
72 static int hf_srt_handshake_isn
;
73 static int hf_srt_handshake_mtu
;
74 static int hf_srt_handshake_flow_window
;
75 static int hf_srt_handshake_reqtype
;
76 static int hf_srt_handshake_failure_type
;
77 static int hf_srt_handshake_id
;
78 static int hf_srt_handshake_cookie
;
79 static int hf_srt_handshake_peerip
;
80 /* SRT Handshake Extension */
81 static int hf_srt_handshake_ext_version
;
82 static int hf_srt_handshake_ext_flags
;
83 static int hf_srt_handshake_ext_flag_tsbpd_snd
;
84 static int hf_srt_handshake_ext_flag_tsbpd_rcv
;
85 static int hf_srt_handshake_ext_flag_haicrypt
;
86 static int hf_srt_handshake_ext_flag_tlpkt_drop
;
87 static int hf_srt_handshake_ext_flag_nak_report
;
88 static int hf_srt_handshake_ext_flag_rexmit
;
89 static int hf_srt_handshake_ext_flag_stream
;
91 /* Key Material (KM) */
93 static int hf_srt_km_s
;
94 static int hf_srt_km_v
;
95 static int hf_srt_km_pt
;
96 static int hf_srt_km_sign
;
97 static int hf_srt_km_resv1
;
98 static int hf_srt_km_kk
;
99 static int hf_srt_km_keki
;
100 static int hf_srt_km_cipher
;
101 static int hf_srt_km_auth
;
102 static int hf_srt_km_se
;
103 static int hf_srt_km_resv2
;
104 static int hf_srt_km_resv3
;
105 static int hf_srt_km_slen
;
106 static int hf_srt_km_klen
;
107 static int hf_srt_km_salt
;
108 static int hf_srt_km_wrap
;
110 /* HS Extension: Group */
111 static int hf_srt_hs_ext_group_id
;
112 static int hf_srt_hs_ext_group_type
;
113 static int hf_srt_hs_ext_group_flags
;
114 static int hf_srt_hs_ext_group_weight
;
116 static int hf_srt_srths_blocktype
;
117 static int hf_srt_srths_blocklen
;
118 static int hf_srt_srths_agent_latency
; // TSBPD delay
119 static int hf_srt_srths_peer_latency
; // TSBPD delay
120 static int hf_srt_srtkm_msg
;
121 static int hf_srt_srtkm_error
;
122 static int hf_srt_srths_sid
;
123 static int hf_srt_srths_congestcontrol
;
124 static int hf_srt_hs_ext_filter
;
127 static int ett_srt_handshake_ext_flags
;
128 static int ett_srt_handshake_ext_field_flags
;
130 static expert_field ei_srt_nak_seqno
;
131 static expert_field ei_srt_hs_ext_hsreq_len
;
132 static expert_field ei_srt_hs_ext_type
;
133 static expert_field ei_srt_hs_ext_group_len
;
135 static dissector_handle_t srt_udp_handle
;
138 /* This defines the firstmost bit of the packet, so it can stay this way. */
139 #define SRT_TYPE_DATA 0
140 #define SRT_TYPE_CONTROL 1
141 #define SRT_CONTROL_MASK (~0x80000000)
143 #define SRT_KM_S_MASK 0x80
144 #define SRT_KM_V_MASK 0x70
145 #define SRT_KM_PT_MASK 0x0F
146 #define SRT_KM_KK_MASK 0x03
147 #define SRT_KM_RESV1_MASK 0xFC
149 #define SRT_LOSS_SEQUENCE_FIRST 0x80000000
150 #define SRT_LOSS_SEQUENCE_MASK (~SRT_LOSS_SEQUENCE_FIRST)
154 SRT_UNDEFINED
= 0, /* initial trap representation */
157 SRT_MAGIC_CODE
= 0x4A17
160 /* Handshake Extended Field Flags */
161 #define SRT_OPT_FIELD_LEN 32
162 #define SRT_OPT_TSBPDSND (1 << 0)
163 #define SRT_OPT_TSBPDRCV (1 << 1)
164 #define SRT_OPT_HAICRYPT (1 << 2)
165 #define SRT_OPT_TLPKTDROP (1 << 3)
166 #define SRT_OPT_NAKREPORT (1 << 4)
167 #define SRT_OPT_REXMITFLG (1 << 5)
168 #define SRT_OPT_STREAM (1 << 6)
171 /* Extended Handshake Flags */
172 #define SRT_HS_V5_EXT_FIELD_LEN 16
173 #define SRT_HS_V5_EXT_FIELD_HSREQ (1 << 0)
174 #define SRT_HS_V5_EXT_FIELD_KMREQ (1 << 1)
175 #define SRT_HS_V5_EXT_FIELD_CONFIG (1 << 2)
176 #define SRT_HS_V5_EXT_FIELD_MAGIC SRT_MAGIC_CODE
178 /* Message number field and single bit flags */
179 #define SRT_MSGNO_FF_FIRST_B (2 << (32-2))
180 #define SRT_MSGNO_FF_LAST_B (1 << (32-2))
181 #define SRT_MSGNO_FF_MASK (SRT_MSGNO_FF_FIRST_B | SRT_MSGNO_FF_LAST_B)
186 /* 01: last packet of a message */
188 /* 10: first packet of a message */
190 /* 11: solo message packet */
195 #define SRT_MSGNO_INORDER (1 << (32-3)) /* 0x20000000 */
197 #define SRT_MSGNO_ENCTYPE (3 << (32-5)) /* 0x18000000 */
199 #define SRT_MSGNO_EK_NONE 0
200 #define SRT_MSGNO_EK_EVEN 1
201 #define SRT_MSGNO_EK_ODD 2
203 #define SRT_MSGNO_REXMIT (1 << (32-6)) /* 0x04000000 */
205 /* Rest of the bits are for message sequence number */
206 #define SRT_MSGNO_MSGNO_MASK 0x03ffffff
207 #define SRT_MSGNO_REXMIT_FLG 0x04000000
210 /* The message types used by SRT protocol. This is a part of SRT
211 * protocol and should never be changed.
215 UMSG_HANDSHAKE
= 0, // Connection Handshake. Control: see @a CHandShake.
216 UMSG_KEEPALIVE
= 1, // Keep-alive.
217 UMSG_ACK
= 2, // Acknowledgement. Control: past-the-end sequence number up to which packets have been received.
218 UMSG_LOSSREPORT
= 3, // Negative Acknowledgement (NACK). Control: Loss list.
219 UMSG_CGWARNING
= 4, // Congestion warning.
220 UMSG_SHUTDOWN
= 5, // Shutdown.
221 UMSG_ACKACK
= 6, // Acknowledgement of Acknowledgement. Add info: The ACK sequence number
222 UMSG_DROPREQ
= 7, // Message Drop Request. Add info: Message ID. Control Info: (first, last) number of the message.
223 UMSG_PEERERROR
= 8, // Signal from the Peer side. Add info: Error code.
224 /* ... add extra code types here */
226 UMSG_EXT
= 0x7FFF // For the use of user-defined control packets.
230 #define SRT_CMD_HSREQ 1
231 #define SRT_CMD_HSRSP 2
232 #define SRT_CMD_KMREQ 3
233 #define SRT_CMD_KMRSP 4
234 #define SRT_CMD_SID 5
235 #define SRT_CMD_CONGESTION 6
236 #define SRT_CMD_FILTER 7
237 #define SRT_CMD_GROUP 8
245 // Keep it always last
257 URQ_FAILURE_TYPES
= 1000
263 SRT_KM_S_UNSECURED
= 0, ///< No encryption
264 SRT_KM_S_SECURING
= 1, ///< Stream encrypted, exchanging Keying Material
265 SRT_KM_S_SECURED
= 2, ///< Stream encrypted, keying Material exchanged, decrypting ok.
266 SRT_KM_S_NOSECRET
= 3, ///< Stream encrypted and no secret to decrypt Keying Material
267 SRT_KM_S_BADSECRET
= 4 ///< Stream encrypted and wrong secret, cannot decrypt Keying Material
270 static const value_string srt_ctrlmsg_types
[] = {
271 {UMSG_HANDSHAKE
, "HANDSHAKE"},
272 {UMSG_KEEPALIVE
, "KEEPALIVE"},
274 {UMSG_LOSSREPORT
, "LOSSREPORT"},
275 {UMSG_CGWARNING
, "CGWARNING"},
276 {UMSG_SHUTDOWN
, "SHUTDOWN"},
277 {UMSG_ACKACK
, "ACKACK"},
278 {UMSG_DROPREQ
, "DROPREQ"},
279 {UMSG_PEERERROR
, "PEERERROR"},
285 static const value_string srt_ctrlmsg_exttypes
[] = {
286 {SRT_CMD_HSREQ
, "HSREQ"},
287 {SRT_CMD_HSRSP
, "HSRSP"},
288 {SRT_CMD_KMREQ
, "KMREQ"},
289 {SRT_CMD_KMRSP
, "KMRSP"},
290 {SRT_CMD_SID
, "SID"},
291 {SRT_CMD_CONGESTION
, "CONGESTION"},
292 {SRT_CMD_FILTER
, "FILTER"},
293 {SRT_CMD_GROUP
, "GROUP"},
298 static const value_string srt_hs_ext_group_type
[] = {
301 { 2, "Main/Backup" },
306 static const value_string srt_hsv4_socket_types
[] = {
307 {SRT_STREAM
, "SRT_STREAM"},
308 {SRT_DGRAM
, "SRT_DGRAM"},
313 static const value_string srt_handshake_enc_field
[] = {
314 {0, "PBKEYLEN not advertised"},
322 static const true_false_string srt_packet_types
= {
327 static const value_string srt_pb_types
[] = {
328 {PB_SUBSEQUENT
, "PB_SUBSEQUENT"},
329 {PB_LAST
, "PB_LAST"},
330 {PB_FIRST
, "PB_FIRST"},
331 {PB_SOLO
, "PB_SOLO"},
335 static const value_string srt_msgno_enctypes
[] = {
336 {SRT_MSGNO_EK_NONE
, "Not encrypted"},
337 {SRT_MSGNO_EK_EVEN
, "Encrypted (even key)"},
338 {SRT_MSGNO_EK_ODD
, "Encrypted (odd key)"},
342 static const true_false_string srt_msgno_rexmit
= {
343 "Retransmitted", /* 1 */
347 static const value_string srt_hs_request_types
[] = {
348 {URQ_INDUCTION
, "URQ_INDUCTION (c/l invocation)"},
349 {URQ_CONCLUSION
, "URQ_CONCLUSION"},
350 {URQ_WAVEAHAND
, "URQ_WAVEAHAND (rendezvous invocation)"},
351 {URQ_AGREEMENT
, "URQ_AGREEMENT (rendezvous finalization)"},
355 static const value_string srt_enc_kmstate
[] = {
356 {SRT_KM_S_UNSECURED
, "UNSECURED"},
357 {SRT_KM_S_SECURING
, "SECURING"},
358 {SRT_KM_S_SECURED
, "SECURED"},
359 {SRT_KM_S_NOSECRET
, "NOSECRET"},
360 {SRT_KM_S_BADSECRET
, "BADSECRET"},
367 * XXX To be added later to extract correct IPv4/IPv6 address from 16 bytes of data
368 * static void srt_tree_add_ipaddr( proto_tree *tree, const int hf, tvbuff_t *tvb, int offset)
374 #define IP_BUFFER_SIZE 64
376 static void srt_format_ip_address(char* dest
, size_t dest_size
, const char* ptr
)
378 /* Initial IPv4 check.
379 * The address is considered IPv4 if:
380 * byte[0] and byte[3] != 0
389 if (ptr
[0] != 0 && ptr
[3] != 0)
391 for (i
= 4; i
< 16; ++i
)
396 /* This is not an IP4 */
398 for (j
= 0; j
< 4; ++j
)
399 p
[j
] = g_ntohl(((uint32_t*)ptr
)[j
]);
401 ws_inet_ntop6(&ia6
, dest
, (unsigned)dest_size
);
406 // There's one small problem: the contents of the handshake
407 // goes in LITTLE ENDIAN. That's an initial problem of UDT.
408 // The address must be inverted.
410 // Here's IPv4, so invert only one l.
411 ia4
= g_ntohl(*((const uint32_t*)ptr
));
413 ws_inet_ntop4(&ia4
, dest
, (unsigned)dest_size
);
418 static void srt_format_hs_ext_hsreq(proto_tree
* tree
, tvbuff_t
* tvb
, int baseoff
)
421 uint32_t version
= 0;
422 pi
= proto_tree_add_item_ret_uint(tree
, hf_srt_handshake_ext_version
, tvb
, baseoff
, 4, ENC_BIG_ENDIAN
, &version
);
424 const int vminor
= (version
>> 8) & 0xff;
425 const int vmajor
= (version
>> 16) & 0xff;
426 const int vpatch
= version
& 0xff;
427 proto_item_append_text(pi
, " (%d.%d.%d)", vmajor
, vminor
, vpatch
);
429 static int * const ext_hs_flags
[] = {
430 &hf_srt_handshake_ext_flag_tsbpd_snd
,
431 &hf_srt_handshake_ext_flag_tsbpd_rcv
,
432 &hf_srt_handshake_ext_flag_haicrypt
,
433 &hf_srt_handshake_ext_flag_tlpkt_drop
,
434 &hf_srt_handshake_ext_flag_nak_report
,
435 &hf_srt_handshake_ext_flag_rexmit
,
436 &hf_srt_handshake_ext_flag_stream
,
440 proto_tree_add_bitmask_with_flags(tree
, tvb
, baseoff
+ 4, hf_srt_handshake_ext_flags
,
441 ett_srt_handshake_ext_flags
, ext_hs_flags
, ENC_NA
, BMT_NO_APPEND
);
443 proto_tree_add_item(tree
, hf_srt_srths_peer_latency
, tvb
, baseoff
+ 8, 2, ENC_BIG_ENDIAN
);
444 proto_tree_add_item(tree
, hf_srt_srths_agent_latency
, tvb
, baseoff
+ 10, 2, ENC_BIG_ENDIAN
);
447 static void srt_format_km(proto_tree
* tree
, tvbuff_t
* tvb
, int baseoff
, int blocklen
)
450 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
451 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
452 // |S| V | PT | Sign | Resv1 | KK|
453 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
455 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
456 // | Cipher | Auth | SE | Resv2 |
457 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
458 // | Resv3 | SLen/4 | KLen/4 |
459 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
462 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
466 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
470 proto_tree_add_item(tree
, hf_srt_km_s
, tvb
, baseoff
, 1, ENC_BIG_ENDIAN
);
471 proto_tree_add_item(tree
, hf_srt_km_v
, tvb
, baseoff
, 1, ENC_BIG_ENDIAN
);
472 proto_tree_add_item(tree
, hf_srt_km_pt
, tvb
, baseoff
, 1, ENC_BIG_ENDIAN
);
474 proto_tree_add_item(tree
, hf_srt_km_sign
, tvb
, baseoff
+ 1, 2, ENC_NA
);
476 proto_tree_add_item(tree
, hf_srt_km_resv1
, tvb
, baseoff
+ 3, 1, ENC_NA
);
478 static const value_string kk_desc
[] = {
479 { 0, "No SEK is provided - invalid KM" },
480 { 1, "Even key is provided" },
481 { 2, "Odd key is provided" },
482 { 3, "Both even and odd keys are provided"},
486 u8bits
= tvb_get_uint8(tvb
, baseoff
+ 3);
487 proto_tree_add_uint_format_value(tree
, hf_srt_km_kk
, tvb
, baseoff
+ 3, 1,
488 u8bits
, "%u (%s)", (u8bits
& SRT_KM_KK_MASK
), try_val_to_str(u8bits
& SRT_KM_KK_MASK
, kk_desc
));
490 static const value_string cipher_desc
[] = {
491 { 0, "None or KEKI indexed crypto context" },
492 { 1, "AES-ECB (reserved, not supported)" },
494 { 3, "AES-CBC (reserved, not supported)" },
498 proto_tree_add_item(tree
, hf_srt_km_keki
, tvb
, baseoff
+ 4, 4, ENC_BIG_ENDIAN
);
500 u8bits
= tvb_get_uint8(tvb
, baseoff
+ 8);
501 proto_tree_add_uint_format_value(tree
, hf_srt_km_cipher
, tvb
, baseoff
+ 8, 1,
502 u8bits
, "%u (%s)", u8bits
, try_val_to_str(u8bits
, cipher_desc
));
504 proto_tree_add_item(tree
, hf_srt_km_auth
, tvb
, baseoff
+ 9, 1, ENC_BIG_ENDIAN
);
506 static const value_string se_desc
[] = {
507 { 0, "Unspecified" },
508 { 1, "MPEG2-TS/UDP" },
509 { 2, "MPEG2-TS/SRT" },
512 u8bits
= tvb_get_uint8(tvb
, baseoff
+ 10); // km.se
513 proto_tree_add_uint_format_value(tree
, hf_srt_km_se
, tvb
, baseoff
+ 10, 1,
514 u8bits
, "%u (%s)", u8bits
, try_val_to_str(u8bits
, se_desc
));
516 proto_tree_add_item(tree
, hf_srt_km_resv2
, tvb
, baseoff
+ 11, 1, ENC_NA
);
517 proto_tree_add_item(tree
, hf_srt_km_resv3
, tvb
, baseoff
+ 12, 2, ENC_NA
);
519 u8bits
= tvb_get_uint8(tvb
, baseoff
+ 14); // km.slen
521 proto_tree_add_uint_format_value(tree
, hf_srt_km_slen
, tvb
, baseoff
+ 14, 1,
522 u8bits
, "%u (%d bytes)", u8bits
, slen
);
524 u8bits
= tvb_get_uint8(tvb
, baseoff
+ 15); // km.klen
525 proto_tree_add_uint_format_value(tree
, hf_srt_km_klen
, tvb
, baseoff
+ 15, 1,
526 u8bits
, "%u (%d bytes)", u8bits
, 4 * u8bits
);
528 proto_tree_add_item(tree
, hf_srt_km_salt
, tvb
, baseoff
+ 16, slen
, ENC_NA
);
530 const int wrap_offset
= 16 + slen
;
531 proto_tree_add_item(tree
, hf_srt_km_wrap
, tvb
, baseoff
+ wrap_offset
, blocklen
- wrap_offset
, ENC_NA
);
534 static void srt_format_kmx(proto_tree
* tree
, tvbuff_t
* tvb
, int baseoff
, int blocklen
)
538 // Error report. Format as KMX state.
539 proto_tree_add_item(tree
, hf_srt_srtkm_error
, tvb
, baseoff
, 4, ENC_NA
);
543 srt_format_km(tree
, tvb
, baseoff
, blocklen
);
547 static void srt_format_hs_ext_group(proto_tree
* tree
, tvbuff_t
* tvb
, packet_info
* pinfo
, int baseoff
, int blocklen
)
550 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
551 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
553 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
554 // | Type | Flags | Weight |
555 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
558 proto_tree_add_expert_format(tree
, pinfo
, &ei_srt_hs_ext_hsreq_len
,
559 tvb
, baseoff
, blocklen
, "Actual length is %u", blocklen
);
563 proto_tree_add_item(tree
, hf_srt_hs_ext_group_id
, tvb
, baseoff
, 4, ENC_BIG_ENDIAN
);
564 proto_tree_add_item(tree
, hf_srt_hs_ext_group_type
, tvb
, baseoff
+ 4, 1, ENC_BIG_ENDIAN
);
565 proto_tree_add_item(tree
, hf_srt_hs_ext_group_flags
, tvb
, baseoff
+ 5, 1, ENC_BIG_ENDIAN
);
566 proto_tree_add_item(tree
, hf_srt_hs_ext_group_weight
, tvb
, baseoff
+ 6, 2, ENC_BIG_ENDIAN
);
570 proto_tree_add_expert_format(tree
, pinfo
, &ei_srt_hs_ext_hsreq_len
,
571 tvb
, baseoff
, blocklen
, "Actual length is %u", blocklen
);
575 // Wireshark dissector doesn't have a possibility to format enum-collected flags.
576 static void dissect_srt_hs_ext_field(proto_tree
* tree
,
577 tvbuff_t
* tvb
, int baseoff
)
579 static const int ext_field_len
= 2;
581 const int bits
= tvb_get_ntohs(tvb
, baseoff
);
582 if (bits
== SRT_HS_V5_EXT_FIELD_MAGIC
)
584 proto_item
* pi
= proto_tree_add_item(tree
, hf_srt_handshake_ext_field_v5
,
585 tvb
, baseoff
, ext_field_len
, ENC_BIG_ENDIAN
);
586 proto_item_append_text(pi
, ": HSv5 MAGIC");
590 static int * const ext_hs_ext_field_flags
[] = {
591 &hf_srt_handshake_ext_field_v5_flag_hsreq
,
592 &hf_srt_handshake_ext_field_v5_flag_kmreq
,
593 &hf_srt_handshake_ext_field_v5_flag_config
,
597 proto_tree_add_bitmask_with_flags(tree
, tvb
, baseoff
, hf_srt_handshake_ext_field_v5
,
598 ett_srt_handshake_ext_field_flags
, ext_hs_ext_field_flags
, ENC_NA
, BMT_NO_APPEND
);
605 * UTF-8 string packed as 32 bit little endian words (what?!)
606 * https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01#section-3.2.1.3
610 * The actual size is determined by the Extension Length field,
611 * which defines the length in four byte blocks. If the actual
612 * payload is less than the declared length, the remaining bytes
615 * The content is stored as 32-bit little endian words.
617 * This means that the octets of the string are in the rather peculiar
629 * and so on, with null padding (not null termination).
631 static void format_text_reorder_32(proto_tree
* tree
, tvbuff_t
* tvb
, packet_info
*pinfo
, int hfinfo
, int baseoff
, int blocklen
)
633 wmem_strbuf_t
*sid
= wmem_strbuf_create(pinfo
->pool
);
634 for (int ii
= 0; ii
< blocklen
; ii
+= 4)
637 // Yes, this is fetching the 32-bit word as big-endian
638 // rather than little-endian.
640 // However, it's then taking the low-order byte of the
641 // result as the first octet, followed by the byte above
642 // that, followed by the byte above that, followed by
643 // the high-order byte.
645 // This is equivalent t fetching the 32-bit word as little-endian
646 // and then taking the high-order byte of the result as the
649 // And both of those implement what's described above.
651 // No, I have no idea why they chose this representation for
654 const uint32_t u
= tvb_get_ntohl(tvb
, baseoff
+ ii
);
655 wmem_strbuf_append_c(sid
, 0xFF & (u
>> 0));
656 wmem_strbuf_append_c(sid
, 0xFF & (u
>> 8));
657 wmem_strbuf_append_c(sid
, 0xFF & (u
>> 16));
658 wmem_strbuf_append_c(sid
, 0xFF & (u
>> 24));
660 if (!wmem_strbuf_utf8_validate(sid
, NULL
))
661 wmem_strbuf_utf8_make_valid(sid
);
662 proto_tree_add_string(tree
, hfinfo
, tvb
,
663 baseoff
, blocklen
, wmem_strbuf_get_str(sid
));
667 /* Code to actually dissect the packets
671 dissect_srt_control_packet(tvbuff_t
*tvb
, packet_info
* pinfo
,
672 proto_tree
*tree
, proto_item
*srt_item
)
675 uint32_t exttype
= 0;
677 proto_tree_add_item_ret_uint(tree
, hf_srt_type
, tvb
, 0, 2,
678 ENC_BIG_ENDIAN
, &type
);
680 if ( type
!= UMSG_EXT
)
681 proto_tree_add_item(tree
, hf_srt_exttype_none
, tvb
, 2, 2,
684 proto_tree_add_item_ret_uint(tree
, hf_srt_exttype
, tvb
, 2, 2,
685 ENC_BIG_ENDIAN
, &exttype
);
690 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Control/ext: %s socket: %d",
691 val_to_str(exttype
, srt_ctrlmsg_exttypes
,
692 "Unknown EXT Control Type (%d)"),
693 tvb_get_ntohl(tvb
, 12));
696 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Control: ACK %d seqno: %u socket: %d",
697 tvb_get_ntohl(tvb
, 4),
698 tvb_get_ntohl(tvb
, 16),
699 tvb_get_ntohl(tvb
, 12));
702 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Control: ACKACK %d socket: %d",
703 tvb_get_ntohl(tvb
, 4),
704 tvb_get_ntohl(tvb
, 12));
707 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Control: %s socket: %d",
708 val_to_str(type
, srt_ctrlmsg_types
,
709 "Unknown Control Type (%d)"),
710 tvb_get_ntohl(tvb
, 12));
718 proto_tree_add_item(tree
, hf_srt_ackno
, tvb
, 4, 4,
722 proto_tree_add_item(tree
, hf_srt_msgno
, tvb
, 4, 4,
726 proto_tree_add_item(tree
, hf_srt_addinfo
, tvb
, 4, 4,
730 proto_tree_add_item(tree
, hf_srt_timestamp
, tvb
, 8, 4,
732 proto_tree_add_item(tree
, hf_srt_id
, tvb
, 12, 4,
739 char ipbuf
[IP_BUFFER_SIZE
];
741 const int version
= tvb_get_ntohl(tvb
, 16);
742 const int final_length
= tvb_reported_length(tvb
);
744 int handshake_reqtype
;
746 /* This contains the handshake version (currently 4 or 5) */
747 proto_tree_add_item(tree
, hf_srt_handshake_version
, tvb
,
748 16, 4, ENC_BIG_ENDIAN
);
750 /* Version 4 embraces both HSv4 listener URQ_INDUCTION response
751 * and HSv5 caller URQ_INDUCTION request. In both these cases the
752 * value is interpreted as socket type (UDT legacy). With version 5
753 * the first message is the listener's URQ_INDUCTION response, where
754 * the layout in the type is already the MAGIC in the lower block,
755 * and ENC FLAGS in the upper block. The next caller's URQ_CONCLUSION
756 * will have SRT HS Extension block flags in the lower block.
760 proto_tree_add_item(tree
, hf_srt_handshake_type_v4
, tvb
,
761 20, 4, ENC_BIG_ENDIAN
);
765 /* Both the PBKEYLEN-ad and magic are used in HSv5 induction. */
766 proto_tree_add_item(tree
, hf_srt_handshake_enc_field_v5
, tvb
,
767 20, 2, ENC_BIG_ENDIAN
);
769 dissect_srt_hs_ext_field(tree
, tvb
, 22); /* 2 bytes */
772 proto_tree_add_item(tree
, hf_srt_handshake_isn
, tvb
,
773 24, 4, ENC_BIG_ENDIAN
);
774 proto_tree_add_item(tree
, hf_srt_handshake_mtu
, tvb
,
775 28, 4, ENC_BIG_ENDIAN
);
776 proto_tree_add_item(tree
, hf_srt_handshake_flow_window
, tvb
,
777 32, 4, ENC_BIG_ENDIAN
);
778 handshake_reqtype
= tvb_get_ntohl(tvb
, 36);
779 if (handshake_reqtype
< URQ_FAILURE_TYPES
)
781 proto_tree_add_item(tree
, hf_srt_handshake_reqtype
, tvb
,
782 36, 4, ENC_BIG_ENDIAN
);
786 static const range_string rej_codes_rvals
[] = {
787 { 0, 0, "REJ_UNKNOWN" },
788 { 1, 1, "REJ_SYSTEM" },
789 { 2, 2, "REJ_PEER" },
790 { 3, 3, "REJ_RESOURCE" },
791 { 4, 4, "REJ_ROGUE" },
792 { 5, 5, "REJ_BACKLOG" },
794 { 7, 7, "REJ_CLOSE" },
795 { 8, 8, "REJ_VERSION" },
796 { 9, 9, "REJ_RDVCOOKIE" },
797 { 10, 10, "REJ_BADSECRET" },
798 { 11, 11, "REJ_UNSECURE" },
799 { 12, 12, "REJ_MESSAGEAPI" },
800 { 13, 13, "REJ_CONGESTION" },
801 { 14, 14, "REJ_FILTER" },
802 { 15, 15, "REJ_GROUP" },
803 { 16, 16, "REJ_TIMEOUT" },
804 { 17, 17, "REJ_CRYPTO" },
805 { 18, 999, "SRT Internal Rejection Reason"},
806 { 1000, 1999, "SRT Predefined Rejection Reason"},
807 { 2000, INT32_MAX
, "User Defined Rejection Reason"},
809 { 0x00, 0x00, NULL
},
812 const int error_code
= handshake_reqtype
- URQ_FAILURE_TYPES
;
813 proto_tree_add_uint_format_value(tree
, hf_srt_handshake_failure_type
, tvb
, 36, 4, handshake_reqtype
,
814 "%d (%s)", error_code
, rval_to_str_const(error_code
, rej_codes_rvals
, "Unknown"));
817 proto_tree_add_item(tree
, hf_srt_handshake_id
, tvb
,
818 40, 4, ENC_BIG_ENDIAN
);
819 proto_tree_add_item(tree
, hf_srt_handshake_cookie
, tvb
,
820 44, 4, ENC_BIG_ENDIAN
);
822 srt_format_ip_address(ipbuf
, sizeof ipbuf
, (const char *)tvb_memdup(pinfo
->pool
, tvb
, 48, 16));
824 proto_tree_add_string(tree
, hf_srt_handshake_peerip
, tvb
,
826 if (final_length
> baselen
)
828 /* Extract SRT handshake extension blocks
829 * and increase baselen accordingly.
834 const uint16_t blockid
= tvb_get_ntohs(tvb
, begin
);
835 const uint16_t blocklen
= tvb_get_ntohs(tvb
, begin
+ 2);
837 proto_tree_add_item(tree
, hf_srt_srths_blocktype
, tvb
,
838 begin
, 2, ENC_BIG_ENDIAN
);
839 proto_tree_add_item(tree
, hf_srt_srths_blocklen
, tvb
,
840 begin
+2, 2, ENC_BIG_ENDIAN
);
842 // Shift to the payload
851 srt_format_hs_ext_hsreq(tree
, tvb
, begin
);
855 /* blocklen should be 3, that corresponds to (3 * 4) = 12 bytes.
856 * Otherwise the format is unknown.*/
857 proto_tree_add_expert_format(tree
, pinfo
, &ei_srt_hs_ext_hsreq_len
,
858 tvb
, begin
, 4 * blocklen
, "Actual length is %u",
865 // Rely on the extracted blocklen
866 srt_format_kmx(tree
, tvb
, begin
, blocklen
*4);
870 format_text_reorder_32(tree
, tvb
, pinfo
, hf_srt_srths_sid
, begin
, 4 * blocklen
);
873 case SRT_CMD_CONGESTION
:
874 format_text_reorder_32(tree
, tvb
, pinfo
, hf_srt_srths_congestcontrol
, begin
, 4 * blocklen
);
878 format_text_reorder_32(tree
, tvb
, pinfo
, hf_srt_hs_ext_filter
, begin
, 4 * blocklen
);
882 srt_format_hs_ext_group(tree
, tvb
, pinfo
, begin
, blocklen
* 4);
886 proto_tree_add_expert_format(tree
, pinfo
, &ei_srt_hs_ext_type
,
887 tvb
, begin
, 4 * blocklen
, "Ext Type value is %u",
892 /* Move the index pointer past the block and repeat. */
893 begin
+= blocklen
* 4;
895 /* OK, once one block is done, interrupt the loop. */
896 if (begin
>= final_length
)
903 proto_item_set_len(srt_item
, baselen
);
908 unsigned len
= tvb_reported_length(tvb
);
910 proto_tree_add_item(tree
, hf_srt_ack_seqno
, tvb
, 4 * 4, 4,
913 // Check for "Lite ACK" (size 4)
914 if (len
<= (4 + 1) * 4)
916 proto_item_set_len(srt_item
, (4 + 1) * 4);
920 proto_tree_add_item(tree
, hf_srt_rtt
, tvb
, (4+1)*4, 4,
922 proto_tree_add_item(tree
, hf_srt_rttvar
, tvb
, (4+2)*4, 4,
924 proto_tree_add_item(tree
, hf_srt_bufavail
, tvb
, (4+3)*4, 4,
926 /* if not a light ack, decode the rate and link capacity */
928 if (len
> (4 + 4) * 4)
930 proto_tree_add_item(tree
, hf_srt_rate
, tvb
, (4 + 4) * 4, 4, ENC_BIG_ENDIAN
);
931 proto_tree_add_item(tree
, hf_srt_bandwidth
, tvb
, (4 + 5) * 4, 4, ENC_BIG_ENDIAN
);
933 // SRT Extra data. This can be version dependent, so
934 // test the length for each field.
935 if (len
> (4 + 6) * 4)
937 proto_tree_add_item(tree
, hf_srt_rcvrate
, tvb
, (4 + 6) * 4, 4, ENC_BIG_ENDIAN
);
941 proto_item_set_len(srt_item
, (int) len
);
945 proto_item_set_len(srt_item
, (4 + 4) * 4);
952 unsigned len
= tvb_reported_length(tvb
);
953 if (len
> (4 + 0) * 4)
955 unsigned lo
= tvb_get_ntohl(tvb
, (4 + 0) * 4);
956 unsigned hi
= tvb_get_ntohl(tvb
, (4 + 1) * 4);
958 proto_tree_add_expert_format(tree
, pinfo
, &ei_srt_nak_seqno
,
959 tvb
, 16, 8, "Drop sequence range: %u-%u",
961 proto_item_set_len(srt_item
, (int) len
);
965 case UMSG_LOSSREPORT
:
967 unsigned len
= tvb_reported_length(tvb
);
971 for (pos
= 16; pos
< len
; pos
+= 4)
973 val
= tvb_get_ntohl(tvb
, pos
);
974 if (val
& SRT_LOSS_SEQUENCE_FIRST
) {
975 // Remember this as a beginning range
980 // We have either a single value, or end-range here.
981 if (prev
& SRT_LOSS_SEQUENCE_FIRST
) {
982 // Was a range. Display as range and clear the state.
983 proto_tree_add_expert_format(tree
, pinfo
, &ei_srt_nak_seqno
,
984 tvb
, pos
-4, 8, "Loss sequence range: %u-%u",
985 (prev
& SRT_LOSS_SEQUENCE_MASK
), val
);
988 // No from, so this is a freestanding loss value
989 proto_tree_add_expert_format(tree
, pinfo
, &ei_srt_nak_seqno
,
990 tvb
, pos
, 4, "Loss sequence: %u", val
);
994 // Report possible errors
997 proto_tree_add_expert_format(tree
, pinfo
, &ei_srt_nak_seqno
,
998 tvb
, pos
-4, 4, "ERROR: loss sequence range begin only: %u (%x)",
999 val
& SRT_LOSS_SEQUENCE_MASK
, val
);
1002 proto_item_set_len(srt_item
, len
);
1011 srt_format_hs_ext_hsreq(tree
, tvb
, 16);
1017 // This relies on value of HCRYPT_MSG_KM_MAX_SZ resulting from this above.
1018 // Too strongly dependent on devel API, so using explicit 104.
1019 int plen
= tvb_reported_length(tvb
) - 16;
1022 srt_format_kmx(tree
, tvb
, 16, plen
);
1032 // All other types have kinda "extra padding"
1033 proto_tree_add_item(tree
, hf_srt_addinfo
, tvb
, 16, 4, ENC_BIG_ENDIAN
);
1039 /* Code to actually dissect the packets
1041 * @return the amount of data this dissector was able to dissect
1044 dissect_srt_udp(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_tree
*parent_tree
,
1047 /* Other misc. local variables. */
1048 bool is_control
= 0;
1050 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SRT");
1051 col_clear (pinfo
->cinfo
, COL_INFO
);
1053 proto_item
*srt_item
= proto_tree_add_item(parent_tree
, proto_srt
, tvb
,
1054 0 /*start*/, -1 /*length*/, ENC_NA
);
1055 proto_tree
*tree
= proto_item_add_subtree(srt_item
, ett_srt
);
1056 proto_tree_add_item_ret_boolean(tree
, hf_srt_iscontrol
, tvb
, 0, 4, ENC_BIG_ENDIAN
, &is_control
);
1060 dissect_srt_control_packet(tvb
, pinfo
, tree
, srt_item
);
1064 /* otherwise, a data packet */
1067 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
1068 "DATA: seqno: %u msgno: #%u socket: %d %s",
1069 tvb_get_ntohl(tvb
, 0),
1070 tvb_get_ntohl(tvb
, 4) & SRT_MSGNO_MSGNO_MASK
,
1071 tvb_get_ntohl(tvb
, 12),
1072 tvb_get_ntohl(tvb
, 4) & SRT_MSGNO_REXMIT_FLG
? "R" : "");
1077 proto_tree_add_item(tree
, hf_srt_seqno
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
1079 proto_tree_add_item(tree
, hf_srt_msgno_pb
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1080 proto_tree_add_item(tree
, hf_srt_msgno_inorder
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1081 proto_tree_add_item(tree
, hf_srt_msgno_enctypes
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1082 proto_tree_add_item(tree
, hf_srt_msgno_rexmit
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1083 proto_tree_add_item(tree
, hf_srt_msgno
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1085 proto_tree_add_item(tree
, hf_srt_timestamp
, tvb
, 8, 4, ENC_BIG_ENDIAN
);
1086 proto_tree_add_item(tree
, hf_srt_id
, tvb
, 12, 4, ENC_BIG_ENDIAN
);
1090 next_tvb
= tvb_new_subset_remaining(tvb
, 16);
1091 call_data_dissector(next_tvb
, pinfo
, tree
);
1094 return tvb_reported_length(tvb
);
1099 dissect_srt_heur_udp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
1101 conversation_t
*conv
;
1103 /* Must have at least 24 captured bytes for heuristic check */
1104 if (tvb_captured_length(tvb
) < 24)
1107 /* detect handshake control packet */
1108 if (tvb_get_ntohl(tvb
, 0) != (0x80000000 | UMSG_HANDSHAKE
))
1111 /* must be version 4 or 5*/
1112 const uint32_t version
= tvb_get_ntohl(tvb
, 16);
1113 if (version
!= 4 && version
!= 5)
1116 /* SRT: must be DGRAM. STREAM is not supported in SRT */
1117 if (version
== 4 && tvb_get_ntohl(tvb
, 20) != SRT_DGRAM
)
1120 conv
= find_or_create_conversation(pinfo
);
1121 conversation_set_dissector(conv
, srt_udp_handle
);
1122 dissect_srt_udp(tvb
, pinfo
, tree
, data
);
1128 /* Register the protocol with Wireshark.
1130 * This format is required because a script is used to build the C function that
1131 * calls all the protocol registration.
1133 void proto_register_srt(void)
1135 expert_module_t
*expert_srt
;
1137 /* Setup list of header fields See Section 1.5 of README.dissector for
1139 static hf_register_info hf
[] = {
1140 {&hf_srt_iscontrol
, {
1141 "Content", "srt.iscontrol",
1143 TFS(&srt_packet_types
), 0x80000000, NULL
, HFILL
}},
1146 "Msg Type", "srt.type",
1147 FT_UINT16
, BASE_HEX
,
1148 VALS(srt_ctrlmsg_types
), 0x7fff, NULL
, HFILL
}},
1151 "Extended type", "srt.exttype",
1152 FT_UINT16
, BASE_HEX
,
1153 VALS(srt_ctrlmsg_exttypes
), 0, NULL
, HFILL
}},
1155 {&hf_srt_exttype_none
, {
1156 "(no extended type)", "srt.exttype_none",
1157 FT_UINT16
, BASE_HEX
,
1158 NULL
, 0, NULL
, HFILL
}},
1161 "Sequence Number", "srt.seqno",
1162 FT_UINT32
, BASE_DEC
,
1163 NULL
, SRT_CONTROL_MASK
, NULL
, HFILL
}},
1166 "(Unused)", "srt.addinfo",
1167 FT_UINT32
, BASE_DEC
,
1168 NULL
, 0, NULL
, HFILL
}},
1171 "Message Number", "srt.msgno",
1172 FT_UINT32
, BASE_DEC
,
1173 NULL
, SRT_MSGNO_MSGNO_MASK
, NULL
, HFILL
}},
1175 {&hf_srt_msgno_pb
, {
1176 "Packet Boundary", "srt.pb",
1177 FT_UINT32
, BASE_DEC
,
1178 VALS(srt_pb_types
), SRT_MSGNO_FF_MASK
, NULL
, HFILL
}},
1180 {&hf_srt_msgno_inorder
, {
1181 "In-Order Indicator", "srt.msg.order",
1182 FT_UINT32
, BASE_DEC
,
1183 NULL
, SRT_MSGNO_INORDER
, NULL
, HFILL
}},
1185 {&hf_srt_msgno_enctypes
, {
1186 "Encryption Status", "srt.msg.enc",
1187 FT_UINT32
, BASE_DEC
,
1188 VALS(srt_msgno_enctypes
), SRT_MSGNO_ENCTYPE
, NULL
, HFILL
}},
1190 {&hf_srt_msgno_rexmit
, {
1191 "Sent as", "srt.msg.rexmit",
1193 TFS(&srt_msgno_rexmit
), SRT_MSGNO_REXMIT
, NULL
, HFILL
}},
1195 {&hf_srt_timestamp
, {
1196 "Time Stamp", "srt.timestamp",
1197 FT_UINT32
, BASE_DEC_HEX
,
1198 NULL
, 0, NULL
, HFILL
}},
1201 "Destination Socket ID", "srt.id",
1202 FT_UINT32
, BASE_DEC
,
1203 NULL
, 0, NULL
, HFILL
}},
1205 {&hf_srt_ack_seqno
, {
1206 "ACKD_RCVLASTACK", "srt.ack_seqno",
1207 FT_UINT32
, BASE_DEC
,
1208 NULL
, 0, NULL
, HFILL
}},
1211 "Ack Number", "srt.ackno",
1212 FT_UINT32
, BASE_DEC
,
1213 NULL
, 0, NULL
, HFILL
}},
1216 "ACKD_RTT", "srt.rtt",
1217 FT_UINT32
, BASE_DEC
| BASE_UNIT_STRING
,
1218 UNS(&units_microseconds
), 0, NULL
, HFILL
}},
1221 "ACKD_RTTVAR", "srt.rttvar",
1222 FT_UINT32
, BASE_DEC
| BASE_UNIT_STRING
,
1223 UNS(&units_microseconds
), 0, NULL
, HFILL
}},
1225 {&hf_srt_bufavail
, {
1226 "ACKD_BUFFERLEFT", "srt.bufavail",
1227 FT_UINT32
, BASE_DEC
| BASE_UNIT_STRING
,
1228 UNS(&units_pkts
), 0, NULL
, HFILL
}},
1231 "ACKD_RCVSPEED", "srt.rate",
1232 FT_UINT32
, BASE_DEC
| BASE_UNIT_STRING
,
1233 UNS(&units_pkts_per_sec
), 0, NULL
, HFILL
}},
1235 {&hf_srt_bandwidth
, {
1236 "ACKD_BANDWIDTH", "srt.bw",
1237 FT_UINT32
, BASE_DEC
| BASE_UNIT_STRING
,
1238 UNS(&units_pkts_per_sec
), 0, NULL
, HFILL
}},
1241 "ACKD_RCVRATE", "srt.rcvrate",
1242 FT_UINT32
, BASE_DEC
| BASE_UNIT_STRING
,
1243 UNS(&units_byte_bytespsecond
), 0, NULL
, HFILL
}},
1245 {&hf_srt_handshake_version
, {
1246 "Handshake Version", "srt.hs.version",
1247 FT_UINT32
, BASE_DEC
,
1248 NULL
, 0, NULL
, HFILL
}},
1250 {&hf_srt_handshake_type_v4
, {
1251 "(Legacy) Socket type", "srt.hs.socktype",
1252 FT_UINT32
, BASE_DEC
,
1253 VALS(srt_hsv4_socket_types
), 0, NULL
,
1256 {&hf_srt_handshake_enc_field_v5
, {
1257 "Crypto Key Field", "srt.hs.enckeyfield",
1258 FT_UINT16
, BASE_HEX
,
1259 VALS(srt_handshake_enc_field
), 0, NULL
,
1262 {&hf_srt_handshake_ext_field_v5
, {
1263 "Extended Field", "srt.hs.extfield",
1264 FT_UINT16
, BASE_HEX
,
1268 {&hf_srt_handshake_ext_field_v5_flag_hsreq
, {
1269 "HS_EXT_FIELD_HSREQ", "srt.hs.extfield.hsreq",
1270 FT_BOOLEAN
, SRT_HS_V5_EXT_FIELD_LEN
, TFS(&tfs_set_notset
),
1271 SRT_HS_V5_EXT_FIELD_HSREQ
,
1272 "Handshake request",
1275 {&hf_srt_handshake_ext_field_v5_flag_kmreq
, {
1276 "HS_EXT_FIELD_KMREQ", "srt.hs.extfield.kmreq",
1277 FT_BOOLEAN
, SRT_HS_V5_EXT_FIELD_LEN
, TFS(&tfs_set_notset
),
1278 SRT_HS_V5_EXT_FIELD_KMREQ
,
1282 {&hf_srt_handshake_ext_field_v5_flag_config
, {
1283 "HS_EXT_FIELD_CONFIG", "srt.hs.extfield.config",
1284 FT_BOOLEAN
, SRT_HS_V5_EXT_FIELD_LEN
, TFS(&tfs_set_notset
),
1285 SRT_HS_V5_EXT_FIELD_CONFIG
,
1286 "Handshake has configuration",
1289 {&hf_srt_handshake_isn
, {
1290 "Initial Sequence Number", "srt.hs.isn",
1291 FT_UINT32
, BASE_DEC
,
1292 NULL
, 0, NULL
, HFILL
}},
1294 {&hf_srt_handshake_mtu
, {
1295 "MTU", "srt.hs.mtu",
1296 FT_UINT32
, BASE_DEC
,
1297 NULL
, 0, NULL
, HFILL
}},
1299 {&hf_srt_handshake_flow_window
, {
1300 "Flow Window", "srt.hs.flow_window",
1301 FT_UINT32
, BASE_DEC
,
1302 NULL
, 0, NULL
, HFILL
}},
1304 {&hf_srt_handshake_reqtype
, {
1305 "Handshake Type", "srt.hs.reqtype",
1307 VALS(srt_hs_request_types
), 0, NULL
, HFILL
}},
1309 {&hf_srt_handshake_failure_type
, {
1310 "Handshake FAILURE code", "srt.hs.failtype",
1311 FT_UINT32
, BASE_DEC
,
1312 NULL
, 0, NULL
, HFILL
}},
1314 {&hf_srt_handshake_id
, {
1315 "Socket ID", "srt.hs.id",
1316 FT_UINT32
, BASE_DEC
,
1317 NULL
, 0, NULL
, HFILL
}},
1319 {&hf_srt_handshake_cookie
, {
1320 "SYN Cookie", "srt.hs.cookie",
1321 FT_UINT32
, BASE_HEX
,
1322 NULL
, 0, NULL
, HFILL
}},
1324 {&hf_srt_handshake_peerip
, {
1325 /* FT_STRINGZ is used because the value
1326 * is formatted to a temporary buffer first */
1327 "Peer IP Address", "srt.hs.peerip",
1328 FT_STRINGZ
, BASE_NONE
,
1329 NULL
, 0, NULL
, HFILL
}},
1331 {&hf_srt_handshake_ext_version
, {
1332 "SRT Version", "srt.hs.version",
1333 FT_UINT32
, BASE_HEX
,
1334 NULL
, 0, NULL
, HFILL
}},
1336 {&hf_srt_handshake_ext_flags
, {
1337 /* This uses custom format by appending the flag format string,
1338 * while the value in hex is still printed. */
1339 "SRT Flags", "srt.hs.srtflags",
1340 FT_UINT32
, BASE_HEX
,
1341 NULL
, 0, NULL
, HFILL
}},
1343 {&hf_srt_handshake_ext_flag_tsbpd_snd
, {
1344 "TSBPDSND", "srt.hs.srtflags.tsbpd_snd",
1345 FT_BOOLEAN
, SRT_OPT_FIELD_LEN
, TFS(&tfs_set_notset
),
1347 "The party will be sending in TSBPD (Time Stamp Based Packet Delivery) mode",
1350 {&hf_srt_handshake_ext_flag_tsbpd_rcv
, {
1351 "TSBPDRCV", "srt.hs.srtflags.tsbpd_rcv",
1352 FT_BOOLEAN
, SRT_OPT_FIELD_LEN
, TFS(&tfs_set_notset
),
1354 "The party expects to receive in TSBPD (Time Stamp Based Packet Delivery) mode",
1357 {&hf_srt_handshake_ext_flag_haicrypt
, {
1358 "HAICRYPT", "srt.hs.srtflags.haicrypt",
1359 FT_BOOLEAN
, SRT_OPT_FIELD_LEN
, TFS(&tfs_set_notset
),
1361 "The party includes haicrypt (legacy flag)",
1364 {&hf_srt_handshake_ext_flag_tlpkt_drop
, {
1365 "TLPKTDROP", "srt.hs.srtflags.tlpkt_drop",
1366 FT_BOOLEAN
, SRT_OPT_FIELD_LEN
, TFS(&tfs_set_notset
),
1368 "The party will do the Too-Late Packet Drop",
1371 {&hf_srt_handshake_ext_flag_nak_report
, {
1372 "NAKREPORT", "srt.hs.srtflags.nak_report",
1373 FT_BOOLEAN
, SRT_OPT_FIELD_LEN
, TFS(&tfs_set_notset
),
1375 "The party will do periodic NAK reporting",
1378 {&hf_srt_handshake_ext_flag_rexmit
, {
1379 "REXMITFLG", "srt.hs.srtflags.rexmit",
1380 FT_BOOLEAN
, SRT_OPT_FIELD_LEN
, TFS(&tfs_set_notset
),
1382 "The party uses the REXMIT flag",
1385 {&hf_srt_handshake_ext_flag_stream
, {
1386 "STREAM", "srt.hs.srtflags.stream",
1387 FT_BOOLEAN
, SRT_OPT_FIELD_LEN
, TFS(&tfs_set_notset
),
1389 "The party uses stream type transmission",
1392 {&hf_srt_srths_blocktype
, {
1393 "SRT HS Extension type", "srt.hs.blocktype",
1394 FT_UINT16
, BASE_HEX
,
1395 VALS(srt_ctrlmsg_exttypes
), 0, NULL
, HFILL
}},
1397 {&hf_srt_srths_blocklen
, {
1398 "SRT HS Extension size (4-byte blocks)", "srt.hs.blocklen",
1399 FT_UINT16
, BASE_DEC
,
1400 NULL
, 0, NULL
, HFILL
}},
1402 {&hf_srt_srths_agent_latency
, {
1403 "Latency", "srt.hs.agent_latency",
1404 FT_UINT16
, BASE_DEC
| BASE_UNIT_STRING
,
1405 UNS(&units_milliseconds
), 0, NULL
, HFILL
}},
1407 {&hf_srt_srths_peer_latency
, {
1408 "Peer Latency", "srt.hs.peer_latency",
1409 FT_UINT16
, BASE_DEC
| BASE_UNIT_STRING
,
1410 UNS(&units_milliseconds
), 0, NULL
, HFILL
}},
1412 {&hf_srt_srtkm_msg
, {
1413 "KMX Message (or KM State if 4 bytes)", "srt.km.msg",
1414 FT_BYTES
, BASE_NONE
,
1415 NULL
, 0, NULL
, HFILL
}},
1417 {&hf_srt_srtkm_error
, {
1418 "KM State", "srt.km.error",
1419 FT_UINT32
, BASE_DEC
,
1420 VALS(srt_enc_kmstate
), 0, NULL
, HFILL
}},
1422 {&hf_srt_srths_sid
, {
1423 "Stream ID", "srt.hs.sid",
1424 FT_STRING
, BASE_NONE
,
1425 NULL
, 0, NULL
, HFILL
}},
1427 {&hf_srt_srths_congestcontrol
, {
1428 "Congestion Control Type", "srt.hs.congestctrl",
1429 FT_STRING
, BASE_NONE
,
1430 NULL
, 0, NULL
, HFILL
}},
1432 {&hf_srt_hs_ext_filter
, {
1433 "Packet Filter Type", "srt.hs.filter",
1434 FT_STRING
, BASE_NONE
,
1435 NULL
, 0, NULL
, HFILL
}},
1438 "Key Material", "srt.km",
1439 FT_BYTES
, BASE_NONE
,
1440 NULL
, 0, NULL
, HFILL
}},
1443 "Reserved 'S' Bit", "srt.km.s",
1444 FT_UINT8
, BASE_DEC
, NULL
,
1445 SRT_KM_S_MASK
, NULL
, HFILL
}},
1448 "KM Version", "srt.km.v",
1450 NULL
, SRT_KM_V_MASK
, NULL
,
1454 "KM Payload Type", "srt.km.pt",
1456 NULL
, SRT_KM_PT_MASK
, NULL
,
1460 "KM Signature", "srt.km.sign",
1461 FT_BYTES
, BASE_NONE
,
1465 {&hf_srt_km_resv1
, {
1466 "Reserved1", "srt.km.resv1",
1468 NULL
, SRT_KM_RESV1_MASK
, NULL
,
1472 "Encryption Keys", "srt.km.kk",
1474 NULL
, SRT_KM_KK_MASK
, NULL
,
1478 "KEK index", "srt.km.keki",
1479 FT_UINT32
, BASE_DEC
,
1483 {&hf_srt_km_cipher
, {
1484 "Cipher", "srt.km.cipher",
1490 "Auth", "srt.km.auth",
1496 "Stream Encapsulation", "srt.km.se",
1501 {&hf_srt_km_resv2
, {
1502 "Reserved2", "srt.km.resv2",
1507 { &hf_srt_km_resv3
, {
1508 "Reserved3", "srt.km.resv3",
1509 FT_UINT16
, BASE_DEC
,
1514 "Salt Length (4-byte blocks)", "srt.km.slen",
1520 "SEK Length (4-byte blocks)", "srt.km.klen",
1526 "Salt", "srt.km.salt",
1527 FT_BYTES
, BASE_NONE
,
1528 NULL
, 0, NULL
, HFILL
}},
1531 "Key wrap", "srt.km.wrap",
1532 FT_BYTES
, BASE_NONE
,
1533 NULL
, 0, NULL
, HFILL
}},
1535 {&hf_srt_hs_ext_group_id
, {
1536 "Group ID", "srt.hs_ext_group.id",
1537 FT_UINT32
, BASE_DEC
,
1538 NULL
, 0, NULL
, HFILL
}},
1540 { &hf_srt_hs_ext_group_type
, {
1541 "Group Type", "srt.hs_ext_group.type",
1543 VALS(srt_hs_ext_group_type
), 0, NULL
, HFILL
}},
1545 { &hf_srt_hs_ext_group_flags
, {
1546 "Group Flags", "srt.hs_ext_group.flags",
1548 NULL
, 0, NULL
, HFILL
}},
1550 { &hf_srt_hs_ext_group_weight
, {
1551 "Member Weight", "srt.hs_ext_group.member_weight",
1552 FT_UINT16
, BASE_DEC
,
1553 NULL
, 0, NULL
, HFILL
}}
1557 static int *ett
[] = {
1559 &ett_srt_handshake_ext_flags
,
1560 &ett_srt_handshake_ext_field_flags
1563 static ei_register_info ei
[] = {
1564 { &ei_srt_nak_seqno
,
1565 { "srt.nak_seqno", PI_SEQUENCE
, PI_NOTE
,
1566 "Missing Sequence Number(s)", EXPFILL
}},
1568 { &ei_srt_hs_ext_hsreq_len
,
1569 { "srt.hs.ext.hsreq", PI_PROTOCOL
, PI_WARN
,
1570 "Unknown HS Ext HSREQ length", EXPFILL
}},
1572 { &ei_srt_hs_ext_type
,
1573 { "srt.hs.ext.type", PI_PROTOCOL
, PI_WARN
,
1574 "Unknown HS Ext Type", EXPFILL
}},
1576 { &ei_srt_hs_ext_group_len
,
1577 { "srt.hs.ext.group", PI_PROTOCOL
, PI_WARN
,
1578 "Wrong HS Ext Group length", EXPFILL
}},
1581 proto_srt
= proto_register_protocol("SRT Protocol", "SRT", "srt");
1582 proto_register_field_array(proto_srt
, hf
, array_length(hf
));
1583 proto_register_subtree_array(ett
, array_length(ett
));
1585 expert_srt
= expert_register_protocol(proto_srt
);
1586 expert_register_field_array(expert_srt
, ei
, array_length(ei
));
1588 srt_udp_handle
= register_dissector("srt", dissect_srt_udp
, proto_srt
);
1592 void proto_reg_handoff_srt(void)
1594 /* register as heuristic dissector for UDP */
1595 heur_dissector_add("udp", dissect_srt_heur_udp
, "SRT over UDP",
1596 "srt_udp", proto_srt
, HEURISTIC_ENABLE
);
1598 /* Add a handle to the list of handles that *could* be used with this
1599 table. That list is used by the "Decode As"/"-d" code in the UI. */
1600 dissector_add_for_decode_as("udp.port", srt_udp_handle
);
1605 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1610 * indent-tabs-mode: nil
1613 * vi: set shiftwidth=4 tabstop=8 expandtab:
1614 * :indentSize=4:tabSize=8:noTabs=true: