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>
35 #include <wsutil/str_util.h>
38 void proto_reg_handoff_srt(void);
39 void proto_register_srt(void);
41 /* Initialize the protocol */
43 static int hf_srt_iscontrol
;
44 static int hf_srt_type
;
45 static int hf_srt_exttype
;
46 static int hf_srt_exttype_none
;
47 static int hf_srt_seqno
;
48 static int hf_srt_ack_seqno
;
49 static int hf_srt_ackno
;
50 static int hf_srt_msgno
;
51 static int hf_srt_msgno_pb
;
52 static int hf_srt_msgno_inorder
;
53 static int hf_srt_msgno_enctypes
;
54 static int hf_srt_msgno_rexmit
;
55 static int hf_srt_timestamp
;
57 static int hf_srt_addinfo
;
58 static int hf_srt_rtt
;
59 static int hf_srt_rttvar
;
60 static int hf_srt_bufavail
;
61 static int hf_srt_rate
;
62 static int hf_srt_bandwidth
;
63 static int hf_srt_rcvrate
;
66 static int hf_srt_handshake_version
;
67 static int hf_srt_handshake_type_v4
;
68 static int hf_srt_handshake_enc_field_v5
;
69 static int hf_srt_handshake_ext_field_v5
;
70 static int hf_srt_handshake_ext_field_v5_flag_hsreq
;
71 static int hf_srt_handshake_ext_field_v5_flag_kmreq
;
72 static int hf_srt_handshake_ext_field_v5_flag_config
;
73 static int hf_srt_handshake_isn
;
74 static int hf_srt_handshake_mtu
;
75 static int hf_srt_handshake_flow_window
;
76 static int hf_srt_handshake_reqtype
;
77 static int hf_srt_handshake_failure_type
;
78 static int hf_srt_handshake_id
;
79 static int hf_srt_handshake_cookie
;
80 static int hf_srt_handshake_peerip
;
81 /* SRT Handshake Extension */
82 static int hf_srt_handshake_ext_version
;
83 static int hf_srt_handshake_ext_flags
;
84 static int hf_srt_handshake_ext_flag_tsbpd_snd
;
85 static int hf_srt_handshake_ext_flag_tsbpd_rcv
;
86 static int hf_srt_handshake_ext_flag_haicrypt
;
87 static int hf_srt_handshake_ext_flag_tlpkt_drop
;
88 static int hf_srt_handshake_ext_flag_nak_report
;
89 static int hf_srt_handshake_ext_flag_rexmit
;
90 static int hf_srt_handshake_ext_flag_stream
;
92 /* Key Material (KM) */
94 static int hf_srt_km_s
;
95 static int hf_srt_km_v
;
96 static int hf_srt_km_pt
;
97 static int hf_srt_km_sign
;
98 static int hf_srt_km_resv1
;
99 static int hf_srt_km_kk
;
100 static int hf_srt_km_keki
;
101 static int hf_srt_km_cipher
;
102 static int hf_srt_km_auth
;
103 static int hf_srt_km_se
;
104 static int hf_srt_km_resv2
;
105 static int hf_srt_km_resv3
;
106 static int hf_srt_km_slen
;
107 static int hf_srt_km_klen
;
108 static int hf_srt_km_salt
;
109 static int hf_srt_km_wrap
;
111 /* HS Extension: Group */
112 static int hf_srt_hs_ext_group_id
;
113 static int hf_srt_hs_ext_group_type
;
114 static int hf_srt_hs_ext_group_flags
;
115 static int hf_srt_hs_ext_group_weight
;
117 static int hf_srt_srths_blocktype
;
118 static int hf_srt_srths_blocklen
;
119 static int hf_srt_srths_agent_latency
; // TSBPD delay
120 static int hf_srt_srths_peer_latency
; // TSBPD delay
121 static int hf_srt_srtkm_msg
;
122 static int hf_srt_srtkm_error
;
123 static int hf_srt_srths_sid
;
124 static int hf_srt_srths_congestcontrol
;
125 static int hf_srt_hs_ext_filter
;
128 static int ett_srt_handshake_ext_flags
;
129 static int ett_srt_handshake_ext_field_flags
;
131 static expert_field ei_srt_nak_seqno
;
132 static expert_field ei_srt_hs_ext_hsreq_len
;
133 static expert_field ei_srt_hs_ext_type
;
134 static expert_field ei_srt_hs_ext_group_len
;
136 static dissector_handle_t srt_udp_handle
;
139 /* This defines the firstmost bit of the packet, so it can stay this way. */
140 #define SRT_TYPE_DATA 0
141 #define SRT_TYPE_CONTROL 1
142 #define SRT_CONTROL_MASK (~0x80000000)
144 #define SRT_KM_S_MASK 0x80
145 #define SRT_KM_V_MASK 0x70
146 #define SRT_KM_PT_MASK 0x0F
147 #define SRT_KM_KK_MASK 0x03
148 #define SRT_KM_RESV1_MASK 0xFC
150 #define SRT_LOSS_SEQUENCE_FIRST 0x80000000
151 #define SRT_LOSS_SEQUENCE_MASK (~SRT_LOSS_SEQUENCE_FIRST)
155 SRT_UNDEFINED
= 0, /* initial trap representation */
158 SRT_MAGIC_CODE
= 0x4A17
161 /* Handshake Extended Field Flags */
162 #define SRT_OPT_FIELD_LEN 32
163 #define SRT_OPT_TSBPDSND (1 << 0)
164 #define SRT_OPT_TSBPDRCV (1 << 1)
165 #define SRT_OPT_HAICRYPT (1 << 2)
166 #define SRT_OPT_TLPKTDROP (1 << 3)
167 #define SRT_OPT_NAKREPORT (1 << 4)
168 #define SRT_OPT_REXMITFLG (1 << 5)
169 #define SRT_OPT_STREAM (1 << 6)
172 /* Extended Handshake Flags */
173 #define SRT_HS_V5_EXT_FIELD_LEN 16
174 #define SRT_HS_V5_EXT_FIELD_HSREQ (1 << 0)
175 #define SRT_HS_V5_EXT_FIELD_KMREQ (1 << 1)
176 #define SRT_HS_V5_EXT_FIELD_CONFIG (1 << 2)
177 #define SRT_HS_V5_EXT_FIELD_MAGIC SRT_MAGIC_CODE
179 /* Message number field and single bit flags */
180 #define SRT_MSGNO_FF_FIRST_B (2 << (32-2))
181 #define SRT_MSGNO_FF_LAST_B (1 << (32-2))
182 #define SRT_MSGNO_FF_MASK (SRT_MSGNO_FF_FIRST_B | SRT_MSGNO_FF_LAST_B)
187 /* 01: last packet of a message */
189 /* 10: first packet of a message */
191 /* 11: solo message packet */
196 #define SRT_MSGNO_INORDER (1 << (32-3)) /* 0x20000000 */
198 #define SRT_MSGNO_ENCTYPE (3 << (32-5)) /* 0x18000000 */
200 #define SRT_MSGNO_EK_NONE 0
201 #define SRT_MSGNO_EK_EVEN 1
202 #define SRT_MSGNO_EK_ODD 2
204 #define SRT_MSGNO_REXMIT (1 << (32-6)) /* 0x04000000 */
206 /* Rest of the bits are for message sequence number */
207 #define SRT_MSGNO_MSGNO_MASK 0x03ffffff
208 #define SRT_MSGNO_REXMIT_FLG 0x04000000
211 /* The message types used by SRT protocol. This is a part of SRT
212 * protocol and should never be changed.
216 UMSG_HANDSHAKE
= 0, // Connection Handshake. Control: see @a CHandShake.
217 UMSG_KEEPALIVE
= 1, // Keep-alive.
218 UMSG_ACK
= 2, // Acknowledgement. Control: past-the-end sequence number up to which packets have been received.
219 UMSG_LOSSREPORT
= 3, // Negative Acknowledgement (NACK). Control: Loss list.
220 UMSG_CGWARNING
= 4, // Congestion warning.
221 UMSG_SHUTDOWN
= 5, // Shutdown.
222 UMSG_ACKACK
= 6, // Acknowledgement of Acknowledgement. Add info: The ACK sequence number
223 UMSG_DROPREQ
= 7, // Message Drop Request. Add info: Message ID. Control Info: (first, last) number of the message.
224 UMSG_PEERERROR
= 8, // Signal from the Peer side. Add info: Error code.
225 /* ... add extra code types here */
227 UMSG_EXT
= 0x7FFF // For the use of user-defined control packets.
231 #define SRT_CMD_HSREQ 1
232 #define SRT_CMD_HSRSP 2
233 #define SRT_CMD_KMREQ 3
234 #define SRT_CMD_KMRSP 4
235 #define SRT_CMD_SID 5
236 #define SRT_CMD_CONGESTION 6
237 #define SRT_CMD_FILTER 7
238 #define SRT_CMD_GROUP 8
246 // Keep it always last
258 URQ_FAILURE_TYPES
= 1000
264 SRT_KM_S_UNSECURED
= 0, ///< No encryption
265 SRT_KM_S_SECURING
= 1, ///< Stream encrypted, exchanging Keying Material
266 SRT_KM_S_SECURED
= 2, ///< Stream encrypted, keying Material exchanged, decrypting ok.
267 SRT_KM_S_NOSECRET
= 3, ///< Stream encrypted and no secret to decrypt Keying Material
268 SRT_KM_S_BADSECRET
= 4 ///< Stream encrypted and wrong secret, cannot decrypt Keying Material
271 static const value_string srt_ctrlmsg_types
[] = {
272 {UMSG_HANDSHAKE
, "HANDSHAKE"},
273 {UMSG_KEEPALIVE
, "KEEPALIVE"},
275 {UMSG_LOSSREPORT
, "LOSSREPORT"},
276 {UMSG_CGWARNING
, "CGWARNING"},
277 {UMSG_SHUTDOWN
, "SHUTDOWN"},
278 {UMSG_ACKACK
, "ACKACK"},
279 {UMSG_DROPREQ
, "DROPREQ"},
280 {UMSG_PEERERROR
, "PEERERROR"},
286 static const value_string srt_ctrlmsg_exttypes
[] = {
287 {SRT_CMD_HSREQ
, "HSREQ"},
288 {SRT_CMD_HSRSP
, "HSRSP"},
289 {SRT_CMD_KMREQ
, "KMREQ"},
290 {SRT_CMD_KMRSP
, "KMRSP"},
291 {SRT_CMD_SID
, "SID"},
292 {SRT_CMD_CONGESTION
, "CONGESTION"},
293 {SRT_CMD_FILTER
, "FILTER"},
294 {SRT_CMD_GROUP
, "GROUP"},
299 static const value_string srt_hs_ext_group_type
[] = {
302 { 2, "Main/Backup" },
307 static const value_string srt_hsv4_socket_types
[] = {
308 {SRT_STREAM
, "SRT_STREAM"},
309 {SRT_DGRAM
, "SRT_DGRAM"},
314 static const value_string srt_handshake_enc_field
[] = {
315 {0, "PBKEYLEN not advertised"},
323 static const true_false_string srt_packet_types
= {
328 static const value_string srt_pb_types
[] = {
329 {PB_SUBSEQUENT
, "PB_SUBSEQUENT"},
330 {PB_LAST
, "PB_LAST"},
331 {PB_FIRST
, "PB_FIRST"},
332 {PB_SOLO
, "PB_SOLO"},
336 static const value_string srt_msgno_enctypes
[] = {
337 {SRT_MSGNO_EK_NONE
, "Not encrypted"},
338 {SRT_MSGNO_EK_EVEN
, "Encrypted (even key)"},
339 {SRT_MSGNO_EK_ODD
, "Encrypted (odd key)"},
343 static const true_false_string srt_msgno_rexmit
= {
344 "Retransmitted", /* 1 */
348 static const value_string srt_hs_request_types
[] = {
349 {URQ_INDUCTION
, "URQ_INDUCTION (c/l invocation)"},
350 {URQ_CONCLUSION
, "URQ_CONCLUSION"},
351 {URQ_WAVEAHAND
, "URQ_WAVEAHAND (rendezvous invocation)"},
352 {URQ_AGREEMENT
, "URQ_AGREEMENT (rendezvous finalization)"},
356 static const value_string srt_enc_kmstate
[] = {
357 {SRT_KM_S_UNSECURED
, "UNSECURED"},
358 {SRT_KM_S_SECURING
, "SECURING"},
359 {SRT_KM_S_SECURED
, "SECURED"},
360 {SRT_KM_S_NOSECRET
, "NOSECRET"},
361 {SRT_KM_S_BADSECRET
, "BADSECRET"},
368 * XXX To be added later to extract correct IPv4/IPv6 address from 16 bytes of data
369 * static void srt_tree_add_ipaddr( proto_tree *tree, const int hf, tvbuff_t *tvb, int offset)
375 #define IP_BUFFER_SIZE 64
377 static void srt_format_ip_address(char* dest
, size_t dest_size
, const char* ptr
)
379 /* Initial IPv4 check.
380 * The address is considered IPv4 if:
381 * byte[0] and byte[3] != 0
390 if (ptr
[0] != 0 && ptr
[3] != 0)
392 for (i
= 4; i
< 16; ++i
)
397 /* This is not an IP4 */
399 for (j
= 0; j
< 4; ++j
)
400 p
[j
] = g_ntohl(((uint32_t*)ptr
)[j
]);
402 ws_inet_ntop6(&ia6
, dest
, (unsigned)dest_size
);
407 // There's one small problem: the contents of the handshake
408 // goes in LITTLE ENDIAN. That's an initial problem of UDT.
409 // The address must be inverted.
411 // Here's IPv4, so invert only one l.
412 ia4
= g_ntohl(*((const uint32_t*)ptr
));
414 ws_inet_ntop4(&ia4
, dest
, (unsigned)dest_size
);
419 static void srt_format_hs_ext_hsreq(proto_tree
* tree
, tvbuff_t
* tvb
, int baseoff
)
422 uint32_t version
= 0;
423 pi
= proto_tree_add_item_ret_uint(tree
, hf_srt_handshake_ext_version
, tvb
, baseoff
, 4, ENC_BIG_ENDIAN
, &version
);
425 const int vminor
= (version
>> 8) & 0xff;
426 const int vmajor
= (version
>> 16) & 0xff;
427 const int vpatch
= version
& 0xff;
428 proto_item_append_text(pi
, " (%d.%d.%d)", vmajor
, vminor
, vpatch
);
430 static int * const ext_hs_flags
[] = {
431 &hf_srt_handshake_ext_flag_tsbpd_snd
,
432 &hf_srt_handshake_ext_flag_tsbpd_rcv
,
433 &hf_srt_handshake_ext_flag_haicrypt
,
434 &hf_srt_handshake_ext_flag_tlpkt_drop
,
435 &hf_srt_handshake_ext_flag_nak_report
,
436 &hf_srt_handshake_ext_flag_rexmit
,
437 &hf_srt_handshake_ext_flag_stream
,
441 proto_tree_add_bitmask_with_flags(tree
, tvb
, baseoff
+ 4, hf_srt_handshake_ext_flags
,
442 ett_srt_handshake_ext_flags
, ext_hs_flags
, ENC_NA
, BMT_NO_APPEND
);
444 proto_tree_add_item(tree
, hf_srt_srths_peer_latency
, tvb
, baseoff
+ 8, 2, ENC_BIG_ENDIAN
);
445 proto_tree_add_item(tree
, hf_srt_srths_agent_latency
, tvb
, baseoff
+ 10, 2, ENC_BIG_ENDIAN
);
448 static void srt_format_km(proto_tree
* tree
, tvbuff_t
* tvb
, int baseoff
, int blocklen
)
451 // 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
452 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
453 // |S| V | PT | Sign | Resv1 | KK|
454 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
456 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
457 // | Cipher | Auth | SE | Resv2 |
458 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
459 // | Resv3 | SLen/4 | KLen/4 |
460 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
463 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
467 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
471 proto_tree_add_item(tree
, hf_srt_km_s
, tvb
, baseoff
, 1, ENC_BIG_ENDIAN
);
472 proto_tree_add_item(tree
, hf_srt_km_v
, tvb
, baseoff
, 1, ENC_BIG_ENDIAN
);
473 proto_tree_add_item(tree
, hf_srt_km_pt
, tvb
, baseoff
, 1, ENC_BIG_ENDIAN
);
475 proto_tree_add_item(tree
, hf_srt_km_sign
, tvb
, baseoff
+ 1, 2, ENC_NA
);
477 proto_tree_add_item(tree
, hf_srt_km_resv1
, tvb
, baseoff
+ 3, 1, ENC_NA
);
479 static const value_string kk_desc
[] = {
480 { 0, "No SEK is provided - invalid KM" },
481 { 1, "Even key is provided" },
482 { 2, "Odd key is provided" },
483 { 3, "Both even and odd keys are provided"},
487 u8bits
= tvb_get_uint8(tvb
, baseoff
+ 3);
488 proto_tree_add_uint_format_value(tree
, hf_srt_km_kk
, tvb
, baseoff
+ 3, 1,
489 u8bits
, "%u (%s)", (u8bits
& SRT_KM_KK_MASK
), try_val_to_str(u8bits
& SRT_KM_KK_MASK
, kk_desc
));
491 static const value_string cipher_desc
[] = {
492 { 0, "None or KEKI indexed crypto context" },
493 { 1, "AES-ECB (reserved, not supported)" },
495 { 3, "AES-CBC (reserved, not supported)" },
499 proto_tree_add_item(tree
, hf_srt_km_keki
, tvb
, baseoff
+ 4, 4, ENC_BIG_ENDIAN
);
501 u8bits
= tvb_get_uint8(tvb
, baseoff
+ 8);
502 proto_tree_add_uint_format_value(tree
, hf_srt_km_cipher
, tvb
, baseoff
+ 8, 1,
503 u8bits
, "%u (%s)", u8bits
, try_val_to_str(u8bits
, cipher_desc
));
505 proto_tree_add_item(tree
, hf_srt_km_auth
, tvb
, baseoff
+ 9, 1, ENC_BIG_ENDIAN
);
507 static const value_string se_desc
[] = {
508 { 0, "Unspecified" },
509 { 1, "MPEG2-TS/UDP" },
510 { 2, "MPEG2-TS/SRT" },
513 u8bits
= tvb_get_uint8(tvb
, baseoff
+ 10); // km.se
514 proto_tree_add_uint_format_value(tree
, hf_srt_km_se
, tvb
, baseoff
+ 10, 1,
515 u8bits
, "%u (%s)", u8bits
, try_val_to_str(u8bits
, se_desc
));
517 proto_tree_add_item(tree
, hf_srt_km_resv2
, tvb
, baseoff
+ 11, 1, ENC_NA
);
518 proto_tree_add_item(tree
, hf_srt_km_resv3
, tvb
, baseoff
+ 12, 2, ENC_NA
);
520 u8bits
= tvb_get_uint8(tvb
, baseoff
+ 14); // km.slen
522 proto_tree_add_uint_format_value(tree
, hf_srt_km_slen
, tvb
, baseoff
+ 14, 1,
523 u8bits
, "%u (%d bytes)", u8bits
, slen
);
525 u8bits
= tvb_get_uint8(tvb
, baseoff
+ 15); // km.klen
526 proto_tree_add_uint_format_value(tree
, hf_srt_km_klen
, tvb
, baseoff
+ 15, 1,
527 u8bits
, "%u (%d bytes)", u8bits
, 4 * u8bits
);
529 proto_tree_add_item(tree
, hf_srt_km_salt
, tvb
, baseoff
+ 16, slen
, ENC_NA
);
531 const int wrap_offset
= 16 + slen
;
532 proto_tree_add_item(tree
, hf_srt_km_wrap
, tvb
, baseoff
+ wrap_offset
, blocklen
- wrap_offset
, ENC_NA
);
535 static void srt_format_kmx(proto_tree
* tree
, tvbuff_t
* tvb
, int baseoff
, int blocklen
)
539 // Error report. Format as KMX state.
540 proto_tree_add_item(tree
, hf_srt_srtkm_error
, tvb
, baseoff
, 4, ENC_NA
);
544 srt_format_km(tree
, tvb
, baseoff
, blocklen
);
548 static void srt_format_hs_ext_group(proto_tree
* tree
, tvbuff_t
* tvb
, packet_info
* pinfo
, int baseoff
, int blocklen
)
551 // 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
552 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
554 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
555 // | Type | Flags | Weight |
556 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
559 proto_tree_add_expert_format(tree
, pinfo
, &ei_srt_hs_ext_hsreq_len
,
560 tvb
, baseoff
, blocklen
, "Actual length is %u", blocklen
);
564 proto_tree_add_item(tree
, hf_srt_hs_ext_group_id
, tvb
, baseoff
, 4, ENC_BIG_ENDIAN
);
565 proto_tree_add_item(tree
, hf_srt_hs_ext_group_type
, tvb
, baseoff
+ 4, 1, ENC_BIG_ENDIAN
);
566 proto_tree_add_item(tree
, hf_srt_hs_ext_group_flags
, tvb
, baseoff
+ 5, 1, ENC_BIG_ENDIAN
);
567 proto_tree_add_item(tree
, hf_srt_hs_ext_group_weight
, tvb
, baseoff
+ 6, 2, ENC_BIG_ENDIAN
);
571 proto_tree_add_expert_format(tree
, pinfo
, &ei_srt_hs_ext_hsreq_len
,
572 tvb
, baseoff
, blocklen
, "Actual length is %u", blocklen
);
576 // Wireshark dissector doesn't have a possibility to format enum-collected flags.
577 static void dissect_srt_hs_ext_field(proto_tree
* tree
,
578 tvbuff_t
* tvb
, int baseoff
)
580 static const int ext_field_len
= 2;
582 const int bits
= tvb_get_ntohs(tvb
, baseoff
);
583 if (bits
== SRT_HS_V5_EXT_FIELD_MAGIC
)
585 proto_item
* pi
= proto_tree_add_item(tree
, hf_srt_handshake_ext_field_v5
,
586 tvb
, baseoff
, ext_field_len
, ENC_BIG_ENDIAN
);
587 proto_item_append_text(pi
, ": HSv5 MAGIC");
591 static int * const ext_hs_ext_field_flags
[] = {
592 &hf_srt_handshake_ext_field_v5_flag_hsreq
,
593 &hf_srt_handshake_ext_field_v5_flag_kmreq
,
594 &hf_srt_handshake_ext_field_v5_flag_config
,
598 proto_tree_add_bitmask_with_flags(tree
, tvb
, baseoff
, hf_srt_handshake_ext_field_v5
,
599 ett_srt_handshake_ext_field_flags
, ext_hs_ext_field_flags
, ENC_NA
, BMT_NO_APPEND
);
606 * UTF-8 string packed as 32 bit little endian words (what?!)
607 * https://datatracker.ietf.org/doc/html/draft-sharabayko-srt-01#section-3.2.1.3
611 * The actual size is determined by the Extension Length field,
612 * which defines the length in four byte blocks. If the actual
613 * payload is less than the declared length, the remaining bytes
616 * The content is stored as 32-bit little endian words.
618 * This means that the octets of the string are in the rather peculiar
630 * and so on, with null padding (not null termination).
632 static void format_text_reorder_32(proto_tree
* tree
, tvbuff_t
* tvb
, packet_info
*pinfo
, int hfinfo
, int baseoff
, int blocklen
)
634 wmem_strbuf_t
*sid
= wmem_strbuf_create(pinfo
->pool
);
637 for (int ii
= 0; ii
< blocklen
; ii
+= 4)
640 // Yes, this is fetching the 32-bit word as big-endian
641 // rather than little-endian.
643 // However, it's then taking the low-order byte of the
644 // result as the first octet, followed by the byte above
645 // that, followed by the byte above that, followed by
646 // the high-order byte.
648 // This is equivalent t fetching the 32-bit word as little-endian
649 // and then taking the high-order byte of the result as the
652 // And both of those implement what's described above.
654 // No, I have no idea why they chose this representation for
657 const uint32_t u
= tvb_get_ntohl(tvb
, baseoff
+ ii
);
658 wmem_strbuf_append_c(sid
, 0xFF & (u
>> 0));
659 wmem_strbuf_append_c(sid
, 0xFF & (u
>> 8));
660 wmem_strbuf_append_c(sid
, 0xFF & (u
>> 16));
661 wmem_strbuf_append_c(sid
, 0xFF & (u
>> 24));
663 if (!wmem_strbuf_utf8_validate(sid
, NULL
))
664 wmem_strbuf_utf8_make_valid(sid
);
665 str
= wmem_strbuf_get_str(sid
);
666 len
= wmem_strbuf_get_len(sid
);
667 while (len
> 0 && str
[len
-1] == '\0')
669 proto_tree_add_string(tree
, hfinfo
, tvb
, baseoff
, blocklen
,
670 format_text(pinfo
->pool
, str
, len
));
674 /* Code to actually dissect the packets
678 dissect_srt_control_packet(tvbuff_t
*tvb
, packet_info
* pinfo
,
679 proto_tree
*tree
, proto_item
*srt_item
)
682 uint32_t exttype
= 0;
684 proto_tree_add_item_ret_uint(tree
, hf_srt_type
, tvb
, 0, 2,
685 ENC_BIG_ENDIAN
, &type
);
687 if ( type
!= UMSG_EXT
)
688 proto_tree_add_item(tree
, hf_srt_exttype_none
, tvb
, 2, 2,
691 proto_tree_add_item_ret_uint(tree
, hf_srt_exttype
, tvb
, 2, 2,
692 ENC_BIG_ENDIAN
, &exttype
);
697 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Control/ext: %s socket: %d",
698 val_to_str(exttype
, srt_ctrlmsg_exttypes
,
699 "Unknown EXT Control Type (%d)"),
700 tvb_get_ntohl(tvb
, 12));
703 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Control: ACK %d seqno: %u socket: %d",
704 tvb_get_ntohl(tvb
, 4),
705 tvb_get_ntohl(tvb
, 16),
706 tvb_get_ntohl(tvb
, 12));
709 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Control: ACKACK %d socket: %d",
710 tvb_get_ntohl(tvb
, 4),
711 tvb_get_ntohl(tvb
, 12));
714 col_add_fstr(pinfo
->cinfo
, COL_INFO
, "Control: %s socket: %d",
715 val_to_str(type
, srt_ctrlmsg_types
,
716 "Unknown Control Type (%d)"),
717 tvb_get_ntohl(tvb
, 12));
725 proto_tree_add_item(tree
, hf_srt_ackno
, tvb
, 4, 4,
729 proto_tree_add_item(tree
, hf_srt_msgno
, tvb
, 4, 4,
733 proto_tree_add_item(tree
, hf_srt_addinfo
, tvb
, 4, 4,
737 proto_tree_add_item(tree
, hf_srt_timestamp
, tvb
, 8, 4,
739 proto_tree_add_item(tree
, hf_srt_id
, tvb
, 12, 4,
746 char ipbuf
[IP_BUFFER_SIZE
];
748 const int version
= tvb_get_ntohl(tvb
, 16);
749 const int final_length
= tvb_reported_length(tvb
);
751 int handshake_reqtype
;
753 /* This contains the handshake version (currently 4 or 5) */
754 proto_tree_add_item(tree
, hf_srt_handshake_version
, tvb
,
755 16, 4, ENC_BIG_ENDIAN
);
757 /* Version 4 embraces both HSv4 listener URQ_INDUCTION response
758 * and HSv5 caller URQ_INDUCTION request. In both these cases the
759 * value is interpreted as socket type (UDT legacy). With version 5
760 * the first message is the listener's URQ_INDUCTION response, where
761 * the layout in the type is already the MAGIC in the lower block,
762 * and ENC FLAGS in the upper block. The next caller's URQ_CONCLUSION
763 * will have SRT HS Extension block flags in the lower block.
767 proto_tree_add_item(tree
, hf_srt_handshake_type_v4
, tvb
,
768 20, 4, ENC_BIG_ENDIAN
);
772 /* Both the PBKEYLEN-ad and magic are used in HSv5 induction. */
773 proto_tree_add_item(tree
, hf_srt_handshake_enc_field_v5
, tvb
,
774 20, 2, ENC_BIG_ENDIAN
);
776 dissect_srt_hs_ext_field(tree
, tvb
, 22); /* 2 bytes */
779 proto_tree_add_item(tree
, hf_srt_handshake_isn
, tvb
,
780 24, 4, ENC_BIG_ENDIAN
);
781 proto_tree_add_item(tree
, hf_srt_handshake_mtu
, tvb
,
782 28, 4, ENC_BIG_ENDIAN
);
783 proto_tree_add_item(tree
, hf_srt_handshake_flow_window
, tvb
,
784 32, 4, ENC_BIG_ENDIAN
);
785 handshake_reqtype
= tvb_get_ntohl(tvb
, 36);
786 if (handshake_reqtype
< URQ_FAILURE_TYPES
)
788 proto_tree_add_item(tree
, hf_srt_handshake_reqtype
, tvb
,
789 36, 4, ENC_BIG_ENDIAN
);
793 static const range_string rej_codes_rvals
[] = {
794 { 0, 0, "REJ_UNKNOWN" },
795 { 1, 1, "REJ_SYSTEM" },
796 { 2, 2, "REJ_PEER" },
797 { 3, 3, "REJ_RESOURCE" },
798 { 4, 4, "REJ_ROGUE" },
799 { 5, 5, "REJ_BACKLOG" },
801 { 7, 7, "REJ_CLOSE" },
802 { 8, 8, "REJ_VERSION" },
803 { 9, 9, "REJ_RDVCOOKIE" },
804 { 10, 10, "REJ_BADSECRET" },
805 { 11, 11, "REJ_UNSECURE" },
806 { 12, 12, "REJ_MESSAGEAPI" },
807 { 13, 13, "REJ_CONGESTION" },
808 { 14, 14, "REJ_FILTER" },
809 { 15, 15, "REJ_GROUP" },
810 { 16, 16, "REJ_TIMEOUT" },
811 { 17, 17, "REJ_CRYPTO" },
812 { 18, 999, "SRT Internal Rejection Reason"},
813 { 1000, 1999, "SRT Predefined Rejection Reason"},
814 { 2000, INT32_MAX
, "User Defined Rejection Reason"},
816 { 0x00, 0x00, NULL
},
819 const int error_code
= handshake_reqtype
- URQ_FAILURE_TYPES
;
820 proto_tree_add_uint_format_value(tree
, hf_srt_handshake_failure_type
, tvb
, 36, 4, handshake_reqtype
,
821 "%d (%s)", error_code
, rval_to_str_const(error_code
, rej_codes_rvals
, "Unknown"));
824 proto_tree_add_item(tree
, hf_srt_handshake_id
, tvb
,
825 40, 4, ENC_BIG_ENDIAN
);
826 proto_tree_add_item(tree
, hf_srt_handshake_cookie
, tvb
,
827 44, 4, ENC_BIG_ENDIAN
);
829 srt_format_ip_address(ipbuf
, sizeof ipbuf
, (const char *)tvb_memdup(pinfo
->pool
, tvb
, 48, 16));
831 proto_tree_add_string(tree
, hf_srt_handshake_peerip
, tvb
,
833 if (final_length
> baselen
)
835 /* Extract SRT handshake extension blocks
836 * and increase baselen accordingly.
841 const uint16_t blockid
= tvb_get_ntohs(tvb
, begin
);
842 const uint16_t blocklen
= tvb_get_ntohs(tvb
, begin
+ 2);
844 proto_tree_add_item(tree
, hf_srt_srths_blocktype
, tvb
,
845 begin
, 2, ENC_BIG_ENDIAN
);
846 proto_tree_add_item(tree
, hf_srt_srths_blocklen
, tvb
,
847 begin
+2, 2, ENC_BIG_ENDIAN
);
849 // Shift to the payload
858 srt_format_hs_ext_hsreq(tree
, tvb
, begin
);
862 /* blocklen should be 3, that corresponds to (3 * 4) = 12 bytes.
863 * Otherwise the format is unknown.*/
864 proto_tree_add_expert_format(tree
, pinfo
, &ei_srt_hs_ext_hsreq_len
,
865 tvb
, begin
, 4 * blocklen
, "Actual length is %u",
872 // Rely on the extracted blocklen
873 srt_format_kmx(tree
, tvb
, begin
, blocklen
*4);
877 format_text_reorder_32(tree
, tvb
, pinfo
, hf_srt_srths_sid
, begin
, 4 * blocklen
);
880 case SRT_CMD_CONGESTION
:
881 format_text_reorder_32(tree
, tvb
, pinfo
, hf_srt_srths_congestcontrol
, begin
, 4 * blocklen
);
885 format_text_reorder_32(tree
, tvb
, pinfo
, hf_srt_hs_ext_filter
, begin
, 4 * blocklen
);
889 srt_format_hs_ext_group(tree
, tvb
, pinfo
, begin
, blocklen
* 4);
893 proto_tree_add_expert_format(tree
, pinfo
, &ei_srt_hs_ext_type
,
894 tvb
, begin
, 4 * blocklen
, "Ext Type value is %u",
899 /* Move the index pointer past the block and repeat. */
900 begin
+= blocklen
* 4;
902 /* OK, once one block is done, interrupt the loop. */
903 if (begin
>= final_length
)
910 proto_item_set_len(srt_item
, baselen
);
915 unsigned len
= tvb_reported_length(tvb
);
917 proto_tree_add_item(tree
, hf_srt_ack_seqno
, tvb
, 4 * 4, 4,
920 // Check for "Lite ACK" (size 4)
921 if (len
<= (4 + 1) * 4)
923 proto_item_set_len(srt_item
, (4 + 1) * 4);
927 proto_tree_add_item(tree
, hf_srt_rtt
, tvb
, (4+1)*4, 4,
929 proto_tree_add_item(tree
, hf_srt_rttvar
, tvb
, (4+2)*4, 4,
931 proto_tree_add_item(tree
, hf_srt_bufavail
, tvb
, (4+3)*4, 4,
933 /* if not a light ack, decode the rate and link capacity */
935 if (len
> (4 + 4) * 4)
937 proto_tree_add_item(tree
, hf_srt_rate
, tvb
, (4 + 4) * 4, 4, ENC_BIG_ENDIAN
);
938 proto_tree_add_item(tree
, hf_srt_bandwidth
, tvb
, (4 + 5) * 4, 4, ENC_BIG_ENDIAN
);
940 // SRT Extra data. This can be version dependent, so
941 // test the length for each field.
942 if (len
> (4 + 6) * 4)
944 proto_tree_add_item(tree
, hf_srt_rcvrate
, tvb
, (4 + 6) * 4, 4, ENC_BIG_ENDIAN
);
948 proto_item_set_len(srt_item
, (int) len
);
952 proto_item_set_len(srt_item
, (4 + 4) * 4);
959 unsigned len
= tvb_reported_length(tvb
);
960 if (len
> (4 + 0) * 4)
962 unsigned lo
= tvb_get_ntohl(tvb
, (4 + 0) * 4);
963 unsigned hi
= tvb_get_ntohl(tvb
, (4 + 1) * 4);
965 proto_tree_add_expert_format(tree
, pinfo
, &ei_srt_nak_seqno
,
966 tvb
, 16, 8, "Drop sequence range: %u-%u",
968 proto_item_set_len(srt_item
, (int) len
);
972 case UMSG_LOSSREPORT
:
974 unsigned len
= tvb_reported_length(tvb
);
978 for (pos
= 16; pos
< len
; pos
+= 4)
980 val
= tvb_get_ntohl(tvb
, pos
);
981 if (val
& SRT_LOSS_SEQUENCE_FIRST
) {
982 // Remember this as a beginning range
987 // We have either a single value, or end-range here.
988 if (prev
& SRT_LOSS_SEQUENCE_FIRST
) {
989 // Was a range. Display as range and clear the state.
990 proto_tree_add_expert_format(tree
, pinfo
, &ei_srt_nak_seqno
,
991 tvb
, pos
-4, 8, "Loss sequence range: %u-%u",
992 (prev
& SRT_LOSS_SEQUENCE_MASK
), val
);
995 // No from, so this is a freestanding loss value
996 proto_tree_add_expert_format(tree
, pinfo
, &ei_srt_nak_seqno
,
997 tvb
, pos
, 4, "Loss sequence: %u", val
);
1001 // Report possible errors
1004 proto_tree_add_expert_format(tree
, pinfo
, &ei_srt_nak_seqno
,
1005 tvb
, pos
-4, 4, "ERROR: loss sequence range begin only: %u (%x)",
1006 val
& SRT_LOSS_SEQUENCE_MASK
, val
);
1009 proto_item_set_len(srt_item
, len
);
1018 srt_format_hs_ext_hsreq(tree
, tvb
, 16);
1024 // This relies on value of HCRYPT_MSG_KM_MAX_SZ resulting from this above.
1025 // Too strongly dependent on devel API, so using explicit 104.
1026 int plen
= tvb_reported_length(tvb
) - 16;
1029 srt_format_kmx(tree
, tvb
, 16, plen
);
1039 // All other types have kinda "extra padding"
1040 proto_tree_add_item(tree
, hf_srt_addinfo
, tvb
, 16, 4, ENC_BIG_ENDIAN
);
1046 /* Code to actually dissect the packets
1048 * @return the amount of data this dissector was able to dissect
1051 dissect_srt_udp(tvbuff_t
*tvb
, packet_info
* pinfo
, proto_tree
*parent_tree
,
1054 /* Other misc. local variables. */
1055 bool is_control
= 0;
1057 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "SRT");
1058 col_clear (pinfo
->cinfo
, COL_INFO
);
1060 proto_item
*srt_item
= proto_tree_add_item(parent_tree
, proto_srt
, tvb
,
1061 0 /*start*/, -1 /*length*/, ENC_NA
);
1062 proto_tree
*tree
= proto_item_add_subtree(srt_item
, ett_srt
);
1063 proto_tree_add_item_ret_boolean(tree
, hf_srt_iscontrol
, tvb
, 0, 4, ENC_BIG_ENDIAN
, &is_control
);
1067 dissect_srt_control_packet(tvb
, pinfo
, tree
, srt_item
);
1071 /* otherwise, a data packet */
1074 col_add_fstr(pinfo
->cinfo
, COL_INFO
,
1075 "DATA: seqno: %u msgno: #%u socket: %d %s",
1076 tvb_get_ntohl(tvb
, 0),
1077 tvb_get_ntohl(tvb
, 4) & SRT_MSGNO_MSGNO_MASK
,
1078 tvb_get_ntohl(tvb
, 12),
1079 tvb_get_ntohl(tvb
, 4) & SRT_MSGNO_REXMIT_FLG
? "R" : "");
1084 proto_tree_add_item(tree
, hf_srt_seqno
, tvb
, 0, 4, ENC_BIG_ENDIAN
);
1086 proto_tree_add_item(tree
, hf_srt_msgno_pb
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1087 proto_tree_add_item(tree
, hf_srt_msgno_inorder
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1088 proto_tree_add_item(tree
, hf_srt_msgno_enctypes
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1089 proto_tree_add_item(tree
, hf_srt_msgno_rexmit
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1090 proto_tree_add_item(tree
, hf_srt_msgno
, tvb
, 4, 4, ENC_BIG_ENDIAN
);
1092 proto_tree_add_item(tree
, hf_srt_timestamp
, tvb
, 8, 4, ENC_BIG_ENDIAN
);
1093 proto_tree_add_item(tree
, hf_srt_id
, tvb
, 12, 4, ENC_BIG_ENDIAN
);
1097 next_tvb
= tvb_new_subset_remaining(tvb
, 16);
1098 call_data_dissector(next_tvb
, pinfo
, tree
);
1101 return tvb_reported_length(tvb
);
1106 dissect_srt_heur_udp(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
1108 conversation_t
*conv
;
1110 /* Must have at least 24 captured bytes for heuristic check */
1111 if (tvb_captured_length(tvb
) < 24)
1114 /* detect handshake control packet */
1115 if (tvb_get_ntohl(tvb
, 0) != (0x80000000 | UMSG_HANDSHAKE
))
1118 /* must be version 4 or 5*/
1119 const uint32_t version
= tvb_get_ntohl(tvb
, 16);
1120 if (version
!= 4 && version
!= 5)
1123 /* SRT: must be DGRAM. STREAM is not supported in SRT */
1124 if (version
== 4 && tvb_get_ntohl(tvb
, 20) != SRT_DGRAM
)
1127 conv
= find_or_create_conversation(pinfo
);
1128 conversation_set_dissector(conv
, srt_udp_handle
);
1129 dissect_srt_udp(tvb
, pinfo
, tree
, data
);
1135 /* Register the protocol with Wireshark.
1137 * This format is required because a script is used to build the C function that
1138 * calls all the protocol registration.
1140 void proto_register_srt(void)
1142 expert_module_t
*expert_srt
;
1144 /* Setup list of header fields See Section 1.5 of README.dissector for
1146 static hf_register_info hf
[] = {
1147 {&hf_srt_iscontrol
, {
1148 "Content", "srt.iscontrol",
1150 TFS(&srt_packet_types
), 0x80000000, NULL
, HFILL
}},
1153 "Msg Type", "srt.type",
1154 FT_UINT16
, BASE_HEX
,
1155 VALS(srt_ctrlmsg_types
), 0x7fff, NULL
, HFILL
}},
1158 "Extended type", "srt.exttype",
1159 FT_UINT16
, BASE_HEX
,
1160 VALS(srt_ctrlmsg_exttypes
), 0, NULL
, HFILL
}},
1162 {&hf_srt_exttype_none
, {
1163 "(no extended type)", "srt.exttype_none",
1164 FT_UINT16
, BASE_HEX
,
1165 NULL
, 0, NULL
, HFILL
}},
1168 "Sequence Number", "srt.seqno",
1169 FT_UINT32
, BASE_DEC
,
1170 NULL
, SRT_CONTROL_MASK
, NULL
, HFILL
}},
1173 "(Unused)", "srt.addinfo",
1174 FT_UINT32
, BASE_DEC
,
1175 NULL
, 0, NULL
, HFILL
}},
1178 "Message Number", "srt.msgno",
1179 FT_UINT32
, BASE_DEC
,
1180 NULL
, SRT_MSGNO_MSGNO_MASK
, NULL
, HFILL
}},
1182 {&hf_srt_msgno_pb
, {
1183 "Packet Boundary", "srt.pb",
1184 FT_UINT32
, BASE_DEC
,
1185 VALS(srt_pb_types
), SRT_MSGNO_FF_MASK
, NULL
, HFILL
}},
1187 {&hf_srt_msgno_inorder
, {
1188 "In-Order Indicator", "srt.msg.order",
1189 FT_UINT32
, BASE_DEC
,
1190 NULL
, SRT_MSGNO_INORDER
, NULL
, HFILL
}},
1192 {&hf_srt_msgno_enctypes
, {
1193 "Encryption Status", "srt.msg.enc",
1194 FT_UINT32
, BASE_DEC
,
1195 VALS(srt_msgno_enctypes
), SRT_MSGNO_ENCTYPE
, NULL
, HFILL
}},
1197 {&hf_srt_msgno_rexmit
, {
1198 "Sent as", "srt.msg.rexmit",
1200 TFS(&srt_msgno_rexmit
), SRT_MSGNO_REXMIT
, NULL
, HFILL
}},
1202 {&hf_srt_timestamp
, {
1203 "Time Stamp", "srt.timestamp",
1204 FT_UINT32
, BASE_DEC_HEX
,
1205 NULL
, 0, NULL
, HFILL
}},
1208 "Destination Socket ID", "srt.id",
1209 FT_UINT32
, BASE_DEC
,
1210 NULL
, 0, NULL
, HFILL
}},
1212 {&hf_srt_ack_seqno
, {
1213 "ACKD_RCVLASTACK", "srt.ack_seqno",
1214 FT_UINT32
, BASE_DEC
,
1215 NULL
, 0, NULL
, HFILL
}},
1218 "Ack Number", "srt.ackno",
1219 FT_UINT32
, BASE_DEC
,
1220 NULL
, 0, NULL
, HFILL
}},
1223 "ACKD_RTT", "srt.rtt",
1224 FT_UINT32
, BASE_DEC
| BASE_UNIT_STRING
,
1225 UNS(&units_microseconds
), 0, NULL
, HFILL
}},
1228 "ACKD_RTTVAR", "srt.rttvar",
1229 FT_UINT32
, BASE_DEC
| BASE_UNIT_STRING
,
1230 UNS(&units_microseconds
), 0, NULL
, HFILL
}},
1232 {&hf_srt_bufavail
, {
1233 "ACKD_BUFFERLEFT", "srt.bufavail",
1234 FT_UINT32
, BASE_DEC
| BASE_UNIT_STRING
,
1235 UNS(&units_pkts
), 0, NULL
, HFILL
}},
1238 "ACKD_RCVSPEED", "srt.rate",
1239 FT_UINT32
, BASE_DEC
| BASE_UNIT_STRING
,
1240 UNS(&units_pkts_per_sec
), 0, NULL
, HFILL
}},
1242 {&hf_srt_bandwidth
, {
1243 "ACKD_BANDWIDTH", "srt.bw",
1244 FT_UINT32
, BASE_DEC
| BASE_UNIT_STRING
,
1245 UNS(&units_pkts_per_sec
), 0, NULL
, HFILL
}},
1248 "ACKD_RCVRATE", "srt.rcvrate",
1249 FT_UINT32
, BASE_DEC
| BASE_UNIT_STRING
,
1250 UNS(&units_byte_bytespsecond
), 0, NULL
, HFILL
}},
1252 {&hf_srt_handshake_version
, {
1253 "Handshake Version", "srt.hs.version",
1254 FT_UINT32
, BASE_DEC
,
1255 NULL
, 0, NULL
, HFILL
}},
1257 {&hf_srt_handshake_type_v4
, {
1258 "(Legacy) Socket type", "srt.hs.socktype",
1259 FT_UINT32
, BASE_DEC
,
1260 VALS(srt_hsv4_socket_types
), 0, NULL
,
1263 {&hf_srt_handshake_enc_field_v5
, {
1264 "Crypto Key Field", "srt.hs.enckeyfield",
1265 FT_UINT16
, BASE_HEX
,
1266 VALS(srt_handshake_enc_field
), 0, NULL
,
1269 {&hf_srt_handshake_ext_field_v5
, {
1270 "Extended Field", "srt.hs.extfield",
1271 FT_UINT16
, BASE_HEX
,
1275 {&hf_srt_handshake_ext_field_v5_flag_hsreq
, {
1276 "HS_EXT_FIELD_HSREQ", "srt.hs.extfield.hsreq",
1277 FT_BOOLEAN
, SRT_HS_V5_EXT_FIELD_LEN
, TFS(&tfs_set_notset
),
1278 SRT_HS_V5_EXT_FIELD_HSREQ
,
1279 "Handshake request",
1282 {&hf_srt_handshake_ext_field_v5_flag_kmreq
, {
1283 "HS_EXT_FIELD_KMREQ", "srt.hs.extfield.kmreq",
1284 FT_BOOLEAN
, SRT_HS_V5_EXT_FIELD_LEN
, TFS(&tfs_set_notset
),
1285 SRT_HS_V5_EXT_FIELD_KMREQ
,
1289 {&hf_srt_handshake_ext_field_v5_flag_config
, {
1290 "HS_EXT_FIELD_CONFIG", "srt.hs.extfield.config",
1291 FT_BOOLEAN
, SRT_HS_V5_EXT_FIELD_LEN
, TFS(&tfs_set_notset
),
1292 SRT_HS_V5_EXT_FIELD_CONFIG
,
1293 "Handshake has configuration",
1296 {&hf_srt_handshake_isn
, {
1297 "Initial Sequence Number", "srt.hs.isn",
1298 FT_UINT32
, BASE_DEC
,
1299 NULL
, 0, NULL
, HFILL
}},
1301 {&hf_srt_handshake_mtu
, {
1302 "MTU", "srt.hs.mtu",
1303 FT_UINT32
, BASE_DEC
,
1304 NULL
, 0, NULL
, HFILL
}},
1306 {&hf_srt_handshake_flow_window
, {
1307 "Flow Window", "srt.hs.flow_window",
1308 FT_UINT32
, BASE_DEC
,
1309 NULL
, 0, NULL
, HFILL
}},
1311 {&hf_srt_handshake_reqtype
, {
1312 "Handshake Type", "srt.hs.reqtype",
1314 VALS(srt_hs_request_types
), 0, NULL
, HFILL
}},
1316 {&hf_srt_handshake_failure_type
, {
1317 "Handshake FAILURE code", "srt.hs.failtype",
1318 FT_UINT32
, BASE_DEC
,
1319 NULL
, 0, NULL
, HFILL
}},
1321 {&hf_srt_handshake_id
, {
1322 "Socket ID", "srt.hs.id",
1323 FT_UINT32
, BASE_DEC
,
1324 NULL
, 0, NULL
, HFILL
}},
1326 {&hf_srt_handshake_cookie
, {
1327 "SYN Cookie", "srt.hs.cookie",
1328 FT_UINT32
, BASE_HEX
,
1329 NULL
, 0, NULL
, HFILL
}},
1331 {&hf_srt_handshake_peerip
, {
1332 /* FT_STRINGZ is used because the value
1333 * is formatted to a temporary buffer first */
1334 "Peer IP Address", "srt.hs.peerip",
1335 FT_STRINGZ
, BASE_NONE
,
1336 NULL
, 0, NULL
, HFILL
}},
1338 {&hf_srt_handshake_ext_version
, {
1339 "SRT Version", "srt.hs.version",
1340 FT_UINT32
, BASE_HEX
,
1341 NULL
, 0, NULL
, HFILL
}},
1343 {&hf_srt_handshake_ext_flags
, {
1344 /* This uses custom format by appending the flag format string,
1345 * while the value in hex is still printed. */
1346 "SRT Flags", "srt.hs.srtflags",
1347 FT_UINT32
, BASE_HEX
,
1348 NULL
, 0, NULL
, HFILL
}},
1350 {&hf_srt_handshake_ext_flag_tsbpd_snd
, {
1351 "TSBPDSND", "srt.hs.srtflags.tsbpd_snd",
1352 FT_BOOLEAN
, SRT_OPT_FIELD_LEN
, TFS(&tfs_set_notset
),
1354 "The party will be sending in TSBPD (Time Stamp Based Packet Delivery) mode",
1357 {&hf_srt_handshake_ext_flag_tsbpd_rcv
, {
1358 "TSBPDRCV", "srt.hs.srtflags.tsbpd_rcv",
1359 FT_BOOLEAN
, SRT_OPT_FIELD_LEN
, TFS(&tfs_set_notset
),
1361 "The party expects to receive in TSBPD (Time Stamp Based Packet Delivery) mode",
1364 {&hf_srt_handshake_ext_flag_haicrypt
, {
1365 "HAICRYPT", "srt.hs.srtflags.haicrypt",
1366 FT_BOOLEAN
, SRT_OPT_FIELD_LEN
, TFS(&tfs_set_notset
),
1368 "The party includes haicrypt (legacy flag)",
1371 {&hf_srt_handshake_ext_flag_tlpkt_drop
, {
1372 "TLPKTDROP", "srt.hs.srtflags.tlpkt_drop",
1373 FT_BOOLEAN
, SRT_OPT_FIELD_LEN
, TFS(&tfs_set_notset
),
1375 "The party will do the Too-Late Packet Drop",
1378 {&hf_srt_handshake_ext_flag_nak_report
, {
1379 "NAKREPORT", "srt.hs.srtflags.nak_report",
1380 FT_BOOLEAN
, SRT_OPT_FIELD_LEN
, TFS(&tfs_set_notset
),
1382 "The party will do periodic NAK reporting",
1385 {&hf_srt_handshake_ext_flag_rexmit
, {
1386 "REXMITFLG", "srt.hs.srtflags.rexmit",
1387 FT_BOOLEAN
, SRT_OPT_FIELD_LEN
, TFS(&tfs_set_notset
),
1389 "The party uses the REXMIT flag",
1392 {&hf_srt_handshake_ext_flag_stream
, {
1393 "STREAM", "srt.hs.srtflags.stream",
1394 FT_BOOLEAN
, SRT_OPT_FIELD_LEN
, TFS(&tfs_set_notset
),
1396 "The party uses stream type transmission",
1399 {&hf_srt_srths_blocktype
, {
1400 "SRT HS Extension type", "srt.hs.blocktype",
1401 FT_UINT16
, BASE_HEX
,
1402 VALS(srt_ctrlmsg_exttypes
), 0, NULL
, HFILL
}},
1404 {&hf_srt_srths_blocklen
, {
1405 "SRT HS Extension size (4-byte blocks)", "srt.hs.blocklen",
1406 FT_UINT16
, BASE_DEC
,
1407 NULL
, 0, NULL
, HFILL
}},
1409 {&hf_srt_srths_agent_latency
, {
1410 "Latency", "srt.hs.agent_latency",
1411 FT_UINT16
, BASE_DEC
| BASE_UNIT_STRING
,
1412 UNS(&units_milliseconds
), 0, NULL
, HFILL
}},
1414 {&hf_srt_srths_peer_latency
, {
1415 "Peer Latency", "srt.hs.peer_latency",
1416 FT_UINT16
, BASE_DEC
| BASE_UNIT_STRING
,
1417 UNS(&units_milliseconds
), 0, NULL
, HFILL
}},
1419 {&hf_srt_srtkm_msg
, {
1420 "KMX Message (or KM State if 4 bytes)", "srt.km.msg",
1421 FT_BYTES
, BASE_NONE
,
1422 NULL
, 0, NULL
, HFILL
}},
1424 {&hf_srt_srtkm_error
, {
1425 "KM State", "srt.km.error",
1426 FT_UINT32
, BASE_DEC
,
1427 VALS(srt_enc_kmstate
), 0, NULL
, HFILL
}},
1429 {&hf_srt_srths_sid
, {
1430 "Stream ID", "srt.hs.sid",
1431 FT_STRING
, BASE_NONE
,
1432 NULL
, 0, NULL
, HFILL
}},
1434 {&hf_srt_srths_congestcontrol
, {
1435 "Congestion Control Type", "srt.hs.congestctrl",
1436 FT_STRING
, BASE_NONE
,
1437 NULL
, 0, NULL
, HFILL
}},
1439 {&hf_srt_hs_ext_filter
, {
1440 "Packet Filter Type", "srt.hs.filter",
1441 FT_STRING
, BASE_NONE
,
1442 NULL
, 0, NULL
, HFILL
}},
1445 "Key Material", "srt.km",
1446 FT_BYTES
, BASE_NONE
,
1447 NULL
, 0, NULL
, HFILL
}},
1450 "Reserved 'S' Bit", "srt.km.s",
1451 FT_UINT8
, BASE_DEC
, NULL
,
1452 SRT_KM_S_MASK
, NULL
, HFILL
}},
1455 "KM Version", "srt.km.v",
1457 NULL
, SRT_KM_V_MASK
, NULL
,
1461 "KM Payload Type", "srt.km.pt",
1463 NULL
, SRT_KM_PT_MASK
, NULL
,
1467 "KM Signature", "srt.km.sign",
1468 FT_BYTES
, BASE_NONE
,
1472 {&hf_srt_km_resv1
, {
1473 "Reserved1", "srt.km.resv1",
1475 NULL
, SRT_KM_RESV1_MASK
, NULL
,
1479 "Encryption Keys", "srt.km.kk",
1481 NULL
, SRT_KM_KK_MASK
, NULL
,
1485 "KEK index", "srt.km.keki",
1486 FT_UINT32
, BASE_DEC
,
1490 {&hf_srt_km_cipher
, {
1491 "Cipher", "srt.km.cipher",
1497 "Auth", "srt.km.auth",
1503 "Stream Encapsulation", "srt.km.se",
1508 {&hf_srt_km_resv2
, {
1509 "Reserved2", "srt.km.resv2",
1514 { &hf_srt_km_resv3
, {
1515 "Reserved3", "srt.km.resv3",
1516 FT_UINT16
, BASE_DEC
,
1521 "Salt Length (4-byte blocks)", "srt.km.slen",
1527 "SEK Length (4-byte blocks)", "srt.km.klen",
1533 "Salt", "srt.km.salt",
1534 FT_BYTES
, BASE_NONE
,
1535 NULL
, 0, NULL
, HFILL
}},
1538 "Key wrap", "srt.km.wrap",
1539 FT_BYTES
, BASE_NONE
,
1540 NULL
, 0, NULL
, HFILL
}},
1542 {&hf_srt_hs_ext_group_id
, {
1543 "Group ID", "srt.hs_ext_group.id",
1544 FT_UINT32
, BASE_DEC
,
1545 NULL
, 0, NULL
, HFILL
}},
1547 { &hf_srt_hs_ext_group_type
, {
1548 "Group Type", "srt.hs_ext_group.type",
1550 VALS(srt_hs_ext_group_type
), 0, NULL
, HFILL
}},
1552 { &hf_srt_hs_ext_group_flags
, {
1553 "Group Flags", "srt.hs_ext_group.flags",
1555 NULL
, 0, NULL
, HFILL
}},
1557 { &hf_srt_hs_ext_group_weight
, {
1558 "Member Weight", "srt.hs_ext_group.member_weight",
1559 FT_UINT16
, BASE_DEC
,
1560 NULL
, 0, NULL
, HFILL
}}
1564 static int *ett
[] = {
1566 &ett_srt_handshake_ext_flags
,
1567 &ett_srt_handshake_ext_field_flags
1570 static ei_register_info ei
[] = {
1571 { &ei_srt_nak_seqno
,
1572 { "srt.nak_seqno", PI_SEQUENCE
, PI_NOTE
,
1573 "Missing Sequence Number(s)", EXPFILL
}},
1575 { &ei_srt_hs_ext_hsreq_len
,
1576 { "srt.hs.ext.hsreq", PI_PROTOCOL
, PI_WARN
,
1577 "Unknown HS Ext HSREQ length", EXPFILL
}},
1579 { &ei_srt_hs_ext_type
,
1580 { "srt.hs.ext.type", PI_PROTOCOL
, PI_WARN
,
1581 "Unknown HS Ext Type", EXPFILL
}},
1583 { &ei_srt_hs_ext_group_len
,
1584 { "srt.hs.ext.group", PI_PROTOCOL
, PI_WARN
,
1585 "Wrong HS Ext Group length", EXPFILL
}},
1588 proto_srt
= proto_register_protocol("SRT Protocol", "SRT", "srt");
1589 proto_register_field_array(proto_srt
, hf
, array_length(hf
));
1590 proto_register_subtree_array(ett
, array_length(ett
));
1592 expert_srt
= expert_register_protocol(proto_srt
);
1593 expert_register_field_array(expert_srt
, ei
, array_length(ei
));
1595 srt_udp_handle
= register_dissector("srt", dissect_srt_udp
, proto_srt
);
1599 void proto_reg_handoff_srt(void)
1601 /* register as heuristic dissector for UDP */
1602 heur_dissector_add("udp", dissect_srt_heur_udp
, "SRT over UDP",
1603 "srt_udp", proto_srt
, HEURISTIC_ENABLE
);
1605 /* Add a handle to the list of handles that *could* be used with this
1606 table. That list is used by the "Decode As"/"-d" code in the UI. */
1607 dissector_add_for_decode_as("udp.port", srt_udp_handle
);
1612 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1617 * indent-tabs-mode: nil
1620 * vi: set shiftwidth=4 tabstop=8 expandtab:
1621 * :indentSize=4:tabSize=8:noTabs=true: