xref: /aosp_15_r20/external/webrtc/net/dcsctp/packet/sctp_packet_test.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 #include "net/dcsctp/packet/sctp_packet.h"
11 
12 #include <cstdint>
13 #include <utility>
14 #include <vector>
15 
16 #include "api/array_view.h"
17 #include "net/dcsctp/common/internal_types.h"
18 #include "net/dcsctp/common/math.h"
19 #include "net/dcsctp/packet/chunk/abort_chunk.h"
20 #include "net/dcsctp/packet/chunk/cookie_ack_chunk.h"
21 #include "net/dcsctp/packet/chunk/data_chunk.h"
22 #include "net/dcsctp/packet/chunk/init_chunk.h"
23 #include "net/dcsctp/packet/chunk/sack_chunk.h"
24 #include "net/dcsctp/packet/error_cause/error_cause.h"
25 #include "net/dcsctp/packet/error_cause/user_initiated_abort_cause.h"
26 #include "net/dcsctp/packet/parameter/parameter.h"
27 #include "net/dcsctp/packet/tlv_trait.h"
28 #include "net/dcsctp/public/dcsctp_options.h"
29 #include "net/dcsctp/testing/testing_macros.h"
30 #include "rtc_base/gunit.h"
31 #include "test/gmock.h"
32 
33 namespace dcsctp {
34 namespace {
35 using ::testing::SizeIs;
36 
37 constexpr VerificationTag kVerificationTag = VerificationTag(0x12345678);
38 
TEST(SctpPacketTest,DeserializeSimplePacketFromCapture)39 TEST(SctpPacketTest, DeserializeSimplePacketFromCapture) {
40   /*
41   Stream Control Transmission Protocol, Src Port: 5000 (5000), Dst Port: 5000
42     (5000) Source port: 5000 Destination port: 5000 Verification tag: 0x00000000
43       [Association index: 1]
44       Checksum: 0xaa019d33 [unverified]
45       [Checksum Status: Unverified]
46       INIT chunk (Outbound streams: 1000, inbound streams: 1000)
47           Chunk type: INIT (1)
48           Chunk flags: 0x00
49           Chunk length: 90
50           Initiate tag: 0x0eddca08
51           Advertised receiver window credit (a_rwnd): 131072
52           Number of outbound streams: 1000
53           Number of inbound streams: 1000
54           Initial TSN: 1426601527
55           ECN parameter
56               Parameter type: ECN (0x8000)
57               Parameter length: 4
58           Forward TSN supported parameter
59               Parameter type: Forward TSN supported (0xc000)
60               Parameter length: 4
61           Supported Extensions parameter (Supported types: FORWARD_TSN, AUTH,
62             ASCONF, ASCONF_ACK, RE_CONFIG) Parameter type: Supported Extensions
63   (0x8008) Parameter length: 9 Supported chunk type: FORWARD_TSN (192) Supported
64   chunk type: AUTH (15) Supported chunk type: ASCONF (193) Supported chunk type:
65   ASCONF_ACK (128) Supported chunk type: RE_CONFIG (130) Parameter padding:
66   000000 Random parameter Parameter type: Random (0x8002) Parameter length: 36
67               Random number: c5a86155090e6f420050634cc8d6b908dfd53e17c99cb143…
68           Requested HMAC Algorithm parameter (Supported HMACs: SHA-1)
69               Parameter type: Requested HMAC Algorithm (0x8004)
70               Parameter length: 6
71               HMAC identifier: SHA-1 (1)
72               Parameter padding: 0000
73           Authenticated Chunk list parameter (Chunk types to be authenticated:
74             ASCONF_ACK, ASCONF) Parameter type: Authenticated Chunk list
75   (0x8003) Parameter length: 6 Chunk type: ASCONF_ACK (128) Chunk type: ASCONF
76   (193) Chunk padding: 0000
77   */
78 
79   uint8_t data[] = {
80       0x13, 0x88, 0x13, 0x88, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x01, 0x9d, 0x33,
81       0x01, 0x00, 0x00, 0x5a, 0x0e, 0xdd, 0xca, 0x08, 0x00, 0x02, 0x00, 0x00,
82       0x03, 0xe8, 0x03, 0xe8, 0x55, 0x08, 0x36, 0x37, 0x80, 0x00, 0x00, 0x04,
83       0xc0, 0x00, 0x00, 0x04, 0x80, 0x08, 0x00, 0x09, 0xc0, 0x0f, 0xc1, 0x80,
84       0x82, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0x24, 0xc5, 0xa8, 0x61, 0x55,
85       0x09, 0x0e, 0x6f, 0x42, 0x00, 0x50, 0x63, 0x4c, 0xc8, 0xd6, 0xb9, 0x08,
86       0xdf, 0xd5, 0x3e, 0x17, 0xc9, 0x9c, 0xb1, 0x43, 0x28, 0x4e, 0xaf, 0x64,
87       0x68, 0x2a, 0xc2, 0x97, 0x80, 0x04, 0x00, 0x06, 0x00, 0x01, 0x00, 0x00,
88       0x80, 0x03, 0x00, 0x06, 0x80, 0xc1, 0x00, 0x00};
89 
90   ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket packet, SctpPacket::Parse(data));
91   EXPECT_EQ(packet.common_header().source_port, 5000);
92   EXPECT_EQ(packet.common_header().destination_port, 5000);
93   EXPECT_EQ(packet.common_header().verification_tag, VerificationTag(0));
94   EXPECT_EQ(packet.common_header().checksum, 0xaa019d33);
95 
96   EXPECT_THAT(packet.descriptors(), SizeIs(1));
97   EXPECT_EQ(packet.descriptors()[0].type, InitChunk::kType);
98   ASSERT_HAS_VALUE_AND_ASSIGN(InitChunk init,
99                               InitChunk::Parse(packet.descriptors()[0].data));
100   EXPECT_EQ(init.initial_tsn(), TSN(1426601527));
101 }
102 
TEST(SctpPacketTest,DeserializePacketWithTwoChunks)103 TEST(SctpPacketTest, DeserializePacketWithTwoChunks) {
104   /*
105   Stream Control Transmission Protocol, Src Port: 1234 (1234),
106     Dst Port: 4321 (4321)
107       Source port: 1234
108       Destination port: 4321
109       Verification tag: 0x697e3a4e
110       [Association index: 3]
111       Checksum: 0xc06e8b36 [unverified]
112       [Checksum Status: Unverified]
113       COOKIE_ACK chunk
114           Chunk type: COOKIE_ACK (11)
115           Chunk flags: 0x00
116           Chunk length: 4
117       SACK chunk (Cumulative TSN: 2930332242, a_rwnd: 131072,
118         gaps: 0, duplicate TSNs: 0)
119           Chunk type: SACK (3)
120           Chunk flags: 0x00
121           Chunk length: 16
122           Cumulative TSN ACK: 2930332242
123           Advertised receiver window credit (a_rwnd): 131072
124           Number of gap acknowledgement blocks: 0
125           Number of duplicated TSNs: 0
126   */
127 
128   uint8_t data[] = {0x04, 0xd2, 0x10, 0xe1, 0x69, 0x7e, 0x3a, 0x4e,
129                     0xc0, 0x6e, 0x8b, 0x36, 0x0b, 0x00, 0x00, 0x04,
130                     0x03, 0x00, 0x00, 0x10, 0xae, 0xa9, 0x52, 0x52,
131                     0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
132 
133   ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket packet, SctpPacket::Parse(data));
134   EXPECT_EQ(packet.common_header().source_port, 1234);
135   EXPECT_EQ(packet.common_header().destination_port, 4321);
136   EXPECT_EQ(packet.common_header().verification_tag,
137             VerificationTag(0x697e3a4eu));
138   EXPECT_EQ(packet.common_header().checksum, 0xc06e8b36u);
139 
140   EXPECT_THAT(packet.descriptors(), SizeIs(2));
141   EXPECT_EQ(packet.descriptors()[0].type, CookieAckChunk::kType);
142   EXPECT_EQ(packet.descriptors()[1].type, SackChunk::kType);
143   ASSERT_HAS_VALUE_AND_ASSIGN(
144       CookieAckChunk cookie_ack,
145       CookieAckChunk::Parse(packet.descriptors()[0].data));
146   ASSERT_HAS_VALUE_AND_ASSIGN(SackChunk sack,
147                               SackChunk::Parse(packet.descriptors()[1].data));
148 }
149 
TEST(SctpPacketTest,DeserializePacketWithWrongChecksum)150 TEST(SctpPacketTest, DeserializePacketWithWrongChecksum) {
151   /*
152   Stream Control Transmission Protocol, Src Port: 5000 (5000),
153     Dst Port: 5000 (5000)
154       Source port: 5000
155       Destination port: 5000
156       Verification tag: 0x0eddca08
157       [Association index: 1]
158       Checksum: 0x2a81f531 [unverified]
159       [Checksum Status: Unverified]
160       SACK chunk (Cumulative TSN: 1426601536, a_rwnd: 131072,
161         gaps: 0, duplicate TSNs: 0)
162           Chunk type: SACK (3)
163           Chunk flags: 0x00
164           Chunk length: 16
165           Cumulative TSN ACK: 1426601536
166           Advertised receiver window credit (a_rwnd): 131072
167           Number of gap acknowledgement blocks: 0
168           Number of duplicated TSNs: 0
169   */
170 
171   uint8_t data[] = {0x13, 0x88, 0x13, 0x88, 0x0e, 0xdd, 0xca, 0x08, 0x2a, 0x81,
172                     0xf5, 0x31, 0x03, 0x00, 0x00, 0x10, 0x55, 0x08, 0x36, 0x40,
173                     0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
174 
175   EXPECT_FALSE(SctpPacket::Parse(data).has_value());
176 }
177 
TEST(SctpPacketTest,DeserializePacketDontValidateChecksum)178 TEST(SctpPacketTest, DeserializePacketDontValidateChecksum) {
179   /*
180   Stream Control Transmission Protocol, Src Port: 5000 (5000),
181     Dst Port: 5000 (5000)
182       Source port: 5000
183       Destination port: 5000
184       Verification tag: 0x0eddca08
185       [Association index: 1]
186       Checksum: 0x2a81f531 [unverified]
187       [Checksum Status: Unverified]
188       SACK chunk (Cumulative TSN: 1426601536, a_rwnd: 131072,
189         gaps: 0, duplicate TSNs: 0)
190           Chunk type: SACK (3)
191           Chunk flags: 0x00
192           Chunk length: 16
193           Cumulative TSN ACK: 1426601536
194           Advertised receiver window credit (a_rwnd): 131072
195           Number of gap acknowledgement blocks: 0
196           Number of duplicated TSNs: 0
197   */
198 
199   uint8_t data[] = {0x13, 0x88, 0x13, 0x88, 0x0e, 0xdd, 0xca, 0x08, 0x2a, 0x81,
200                     0xf5, 0x31, 0x03, 0x00, 0x00, 0x10, 0x55, 0x08, 0x36, 0x40,
201                     0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
202 
203   ASSERT_HAS_VALUE_AND_ASSIGN(
204       SctpPacket packet,
205       SctpPacket::Parse(data, /*disable_checksum_verification=*/true));
206   EXPECT_EQ(packet.common_header().source_port, 5000);
207   EXPECT_EQ(packet.common_header().destination_port, 5000);
208   EXPECT_EQ(packet.common_header().verification_tag,
209             VerificationTag(0x0eddca08u));
210   EXPECT_EQ(packet.common_header().checksum, 0x2a81f531u);
211 }
212 
TEST(SctpPacketTest,SerializeAndDeserializeSingleChunk)213 TEST(SctpPacketTest, SerializeAndDeserializeSingleChunk) {
214   SctpPacket::Builder b(kVerificationTag, {});
215   InitChunk init(/*initiate_tag=*/VerificationTag(123), /*a_rwnd=*/456,
216                  /*nbr_outbound_streams=*/65535,
217                  /*nbr_inbound_streams=*/65534, /*initial_tsn=*/TSN(789),
218                  /*parameters=*/Parameters());
219 
220   b.Add(init);
221   std::vector<uint8_t> serialized = b.Build();
222 
223   ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket packet, SctpPacket::Parse(serialized));
224 
225   EXPECT_EQ(packet.common_header().verification_tag, kVerificationTag);
226 
227   ASSERT_THAT(packet.descriptors(), SizeIs(1));
228   EXPECT_EQ(packet.descriptors()[0].type, InitChunk::kType);
229 
230   ASSERT_HAS_VALUE_AND_ASSIGN(InitChunk deserialized,
231                               InitChunk::Parse(packet.descriptors()[0].data));
232   EXPECT_EQ(deserialized.initiate_tag(), VerificationTag(123));
233   EXPECT_EQ(deserialized.a_rwnd(), 456u);
234   EXPECT_EQ(deserialized.nbr_outbound_streams(), 65535u);
235   EXPECT_EQ(deserialized.nbr_inbound_streams(), 65534u);
236   EXPECT_EQ(deserialized.initial_tsn(), TSN(789));
237 }
238 
TEST(SctpPacketTest,SerializeAndDeserializeThreeChunks)239 TEST(SctpPacketTest, SerializeAndDeserializeThreeChunks) {
240   SctpPacket::Builder b(kVerificationTag, {});
241   b.Add(SackChunk(/*cumulative_tsn_ack=*/TSN(999), /*a_rwnd=*/456,
242                   {SackChunk::GapAckBlock(2, 3)},
243                   /*duplicate_tsns=*/{TSN(1), TSN(2), TSN(3)}));
244   b.Add(DataChunk(TSN(123), StreamID(456), SSN(789), PPID(9090),
245                   /*payload=*/{1, 2, 3, 4, 5},
246                   /*options=*/{}));
247   b.Add(DataChunk(TSN(124), StreamID(654), SSN(987), PPID(909),
248                   /*payload=*/{5, 4, 3, 3, 1},
249                   /*options=*/{}));
250 
251   std::vector<uint8_t> serialized = b.Build();
252 
253   ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket packet, SctpPacket::Parse(serialized));
254 
255   EXPECT_EQ(packet.common_header().verification_tag, kVerificationTag);
256 
257   ASSERT_THAT(packet.descriptors(), SizeIs(3));
258   EXPECT_EQ(packet.descriptors()[0].type, SackChunk::kType);
259   EXPECT_EQ(packet.descriptors()[1].type, DataChunk::kType);
260   EXPECT_EQ(packet.descriptors()[2].type, DataChunk::kType);
261 
262   ASSERT_HAS_VALUE_AND_ASSIGN(SackChunk sack,
263                               SackChunk::Parse(packet.descriptors()[0].data));
264   EXPECT_EQ(sack.cumulative_tsn_ack(), TSN(999));
265   EXPECT_EQ(sack.a_rwnd(), 456u);
266 
267   ASSERT_HAS_VALUE_AND_ASSIGN(DataChunk data1,
268                               DataChunk::Parse(packet.descriptors()[1].data));
269   EXPECT_EQ(data1.tsn(), TSN(123));
270 
271   ASSERT_HAS_VALUE_AND_ASSIGN(DataChunk data2,
272                               DataChunk::Parse(packet.descriptors()[2].data));
273   EXPECT_EQ(data2.tsn(), TSN(124));
274 }
275 
TEST(SctpPacketTest,ParseAbortWithEmptyCause)276 TEST(SctpPacketTest, ParseAbortWithEmptyCause) {
277   SctpPacket::Builder b(kVerificationTag, {});
278   b.Add(AbortChunk(
279       /*filled_in_verification_tag=*/true,
280       Parameters::Builder().Add(UserInitiatedAbortCause("")).Build()));
281 
282   ASSERT_HAS_VALUE_AND_ASSIGN(SctpPacket packet, SctpPacket::Parse(b.Build()));
283 
284   EXPECT_EQ(packet.common_header().verification_tag, kVerificationTag);
285 
286   ASSERT_THAT(packet.descriptors(), SizeIs(1));
287   EXPECT_EQ(packet.descriptors()[0].type, AbortChunk::kType);
288 
289   ASSERT_HAS_VALUE_AND_ASSIGN(AbortChunk abort,
290                               AbortChunk::Parse(packet.descriptors()[0].data));
291   ASSERT_HAS_VALUE_AND_ASSIGN(
292       UserInitiatedAbortCause cause,
293       abort.error_causes().get<UserInitiatedAbortCause>());
294   EXPECT_EQ(cause.upper_layer_abort_reason(), "");
295 }
296 
TEST(SctpPacketTest,DetectPacketWithZeroSizeChunk)297 TEST(SctpPacketTest, DetectPacketWithZeroSizeChunk) {
298   uint8_t data[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0x0a, 0x0a, 0x0a, 0x5c,
299                     0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00};
300 
301   EXPECT_FALSE(SctpPacket::Parse(data, true).has_value());
302 }
303 
TEST(SctpPacketTest,ReturnsCorrectSpaceAvailableToStayWithinMTU)304 TEST(SctpPacketTest, ReturnsCorrectSpaceAvailableToStayWithinMTU) {
305   DcSctpOptions options;
306   options.mtu = 1191;
307 
308   SctpPacket::Builder builder(VerificationTag(123), options);
309 
310   // Chunks will be padded to an even 4 bytes, so the maximum packet size should
311   // be rounded down.
312   const size_t kMaxPacketSize = RoundDownTo4(options.mtu);
313   EXPECT_EQ(kMaxPacketSize, 1188u);
314 
315   const size_t kSctpHeaderSize = 12;
316   EXPECT_EQ(builder.bytes_remaining(), kMaxPacketSize - kSctpHeaderSize);
317   EXPECT_EQ(builder.bytes_remaining(), 1176u);
318 
319   // Add a smaller packet first.
320   DataChunk::Options data_options;
321 
322   std::vector<uint8_t> payload1(183);
323   builder.Add(
324       DataChunk(TSN(1), StreamID(1), SSN(0), PPID(53), payload1, data_options));
325 
326   size_t chunk1_size = RoundUpTo4(DataChunk::kHeaderSize + payload1.size());
327   EXPECT_EQ(builder.bytes_remaining(),
328             kMaxPacketSize - kSctpHeaderSize - chunk1_size);
329   EXPECT_EQ(builder.bytes_remaining(), 976u);  // Hand-calculated.
330 
331   std::vector<uint8_t> payload2(957);
332   builder.Add(
333       DataChunk(TSN(1), StreamID(1), SSN(0), PPID(53), payload2, data_options));
334 
335   size_t chunk2_size = RoundUpTo4(DataChunk::kHeaderSize + payload2.size());
336   EXPECT_EQ(builder.bytes_remaining(),
337             kMaxPacketSize - kSctpHeaderSize - chunk1_size - chunk2_size);
338   EXPECT_EQ(builder.bytes_remaining(), 0u);  // Hand-calculated.
339 }
340 
341 }  // namespace
342 }  // namespace dcsctp
343