From fb0b574abd545d0362b0e9e318a0487c12c64f96 Mon Sep 17 00:00:00 2001 From: Yuxuan Luo Date: Tue, 5 Jul 2022 14:58:27 -0400 Subject: [PATCH] SCTP: Support RE-CONFIG chunk Add support for printing RE-CONFIG chunk based on RFC6525 section3.1. Prints all optional parameters when `-vv` is set. Example: [RE-CONFIG] [OUT SSN RESET: REQ SEQ:, RES SEQ:, Last TSN:, SID 0 1] --- print-sctp.c | 246 ++++++++++++++++++++++++++++++++++++ tests/sctp-re-config-v.out | 32 +++++ tests/sctp-re-config-vv.out | 50 ++++++++ tests/sctp-re-config.out | 16 +++ tests/sctp-re-config.pcap | Bin 0 -> 2064 bytes 5 files changed, 344 insertions(+) create mode 100644 tests/sctp-re-config-v.out create mode 100644 tests/sctp-re-config-vv.out create mode 100644 tests/sctp-re-config.out create mode 100644 tests/sctp-re-config.pcap diff --git a/print-sctp.c b/print-sctp.c index 2a81c1c314..9b334fd9bc 100644 --- a/print-sctp.c +++ b/print-sctp.c @@ -112,6 +112,7 @@ #define SCTP_ECN_CWR 0x0d #define SCTP_SHUTDOWN_COMPLETE 0x0e #define SCTP_I_DATA 0x40 +#define SCTP_RE_CONFIG 0x82 #define SCTP_FORWARD_CUM_TSN 0xc0 #define SCTP_RELIABLE_CNTL 0xc1 #define SCTP_I_FORWARD_TSN 0xc2 @@ -133,6 +134,7 @@ static const struct tok sctp_chunkid_str[] = { { SCTP_ECN_CWR, "ECN CWR" }, { SCTP_SHUTDOWN_COMPLETE, "SHUTDOWN COMPLETE" }, { SCTP_I_DATA, "I-DATA" }, + { SCTP_RE_CONFIG, "RE-CONFIG" }, { SCTP_FORWARD_CUM_TSN, "FOR CUM TSN" }, { SCTP_RELIABLE_CNTL, "REL CTRL" }, { SCTP_I_FORWARD_TSN, "I-FORWARD-FSN" }, @@ -151,6 +153,14 @@ static const struct tok sctp_chunkid_str[] = { /* I-Forward-TSN Specific Flag */ #define SCTP_I_FORWARD_UNORDERED 0x01 +/* RE-CONFIG Parameters */ +#define OUT_SSN_RESET 13 +#define IN_SSN_RESET 14 +#define SSN_TSN_RESET 15 +#define RE_CONFIG_RES 16 +#define ADD_OUT_STREAM_REQ 17 +#define ADD_IN_STREAM_REQ 18 + #define SCTP_ADDRMAX 60 #define CHAN_HP 6704 @@ -374,6 +384,33 @@ struct sctpIForwardEntry{ nd_uint32_t MID; }; +/* RE-CONFIG Parameters */ +struct sctpReConfigHdr{ + nd_uint16_t param_type; + nd_uint16_t param_len; +}; + +struct outGoingSSNReset{ + nd_uint32_t re_config_req; + nd_uint32_t re_config_res; + nd_uint32_t last_assigned_TSN; +}; + +struct inGoingSSNReset{ + nd_uint32_t re_config_req; +}; + +struct reConfigRes{ + nd_uint32_t res_seq_num; + nd_uint32_t result; +}; + +struct addStreamReq{ + nd_uint32_t res_seq_num; + nd_uint16_t num_new_stream; + nd_uint16_t reserved; +}; + struct sctpUnifiedDatagram{ struct sctpChunkDesc uh; struct sctpDataPart dp; @@ -390,6 +427,27 @@ struct sctpCWR{ nd_uint32_t TSN_reduced_at; }; +/* RE-CONFIG Parameters */ +static const struct tok RE_CONFIG_parameters[] = { + { OUT_SSN_RESET, "OUT SSN RESET" }, + { IN_SSN_RESET, "IN SSN RESET" }, + { SSN_TSN_RESET, "SSN/TSN Reset" }, + { RE_CONFIG_RES, "RESP" }, + { ADD_OUT_STREAM_REQ, "ADD OUT STREAM"}, + { ADD_IN_STREAM_REQ, "ADD IN STREAM" }, + { 0, NULL } +}; + +static const struct tok results[] = { + { 0, "Success - Nothing to do" }, + { 1, "Success - Performed" }, + { 2, "Denied" }, + { 3, "Error - Wrong SSN" }, + { 4, "Error - Request already in progress" }, + { 5, "Error - Bad Sequence Number" }, + { 6, "In progress" }, +}; + static const struct tok ForCES_channels[] = { { CHAN_HP, "ForCES HP" }, { CHAN_MP, "ForCES MP" }, @@ -868,6 +926,194 @@ sctp_print(netdissect_options *ndo, ND_PRINT("\n\t\t[dup TSN #%u: %u] ", tsnNo+1, GET_BE_U_4(dupTSN)); } + break; + } + case SCTP_RE_CONFIG: + { + const struct sctpReConfigHdr *param; + uint16_t param_len, type; + uint8_t padding_len; + + sctpPacketLengthRemaining -= chunkLengthRemaining; + + while (0 != chunkLengthRemaining) { + /* it's a padding if the remaining length is less than 4 */ + if (sizeof(uint32_t) >= chunkLengthRemaining) { + chunkLengthRemaining = 0; + break; + } + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*param)); + param = (const struct sctpReConfigHdr*)bp; + param_len = GET_BE_U_2(param->param_len); + type = GET_BE_U_2(param->param_type); + padding_len = param_len % 4; + + ND_PRINT("[%s", tok2str(RE_CONFIG_parameters, NULL, type)); + + param_len -= sizeof(*param); + chunkLengthRemaining -= sizeof(*param); + bp += sizeof(*param); + if (ndo->ndo_vflag < 2) { /* if verbose level < 2, stop and skip */ + ND_PRINT("]"); + + ND_ICHECKMSG_U("chunk length", chunkLengthRemaining, <, param_len); + bp += param_len; + chunkLengthRemaining -= param_len; + /* it's a parameter padding if there are more parameters in the remaining length */ + if (chunkLengthRemaining > 4) + bp += padding_len; + + continue; + } + + switch (type) { + case OUT_SSN_RESET: + { + uint16_t stream_num = 0; + const struct outGoingSSNReset *content; + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content)); + + content = (const struct outGoingSSNReset*) bp; + ND_PRINT(": REQ SEQ: %u, ", GET_BE_U_4(content->re_config_req)); + ND_PRINT("RES SEQ: %u, ", GET_BE_U_4(content->re_config_res)); + ND_PRINT("Last TSN: %u, ", GET_BE_U_4(content->last_assigned_TSN)); + + bp += sizeof(*content); + param_len -= sizeof(*content); + chunkLengthRemaining -= sizeof(*content); + + ND_PRINT("SID"); + while (0 != param_len) { + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(stream_num)); + stream_num = GET_BE_U_2(bp); + ND_PRINT(" %u", stream_num); + + bp += sizeof(stream_num); + param_len -= sizeof(stream_num); + chunkLengthRemaining -= sizeof(stream_num); + } + ND_PRINT("]"); + + break; + } + case IN_SSN_RESET: + { + uint16_t stream_num = 0; + const struct inGoingSSNReset *content; + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content)); + + content = (const struct inGoingSSNReset*) bp; + ND_PRINT(": REQ SEQ: %u, ", GET_BE_U_4(content->re_config_req)); + + bp += sizeof(*content); + param_len -= sizeof(*content); + chunkLengthRemaining -= sizeof(*content); + + ND_PRINT("SID"); + while (0 != param_len) { + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(stream_num)); + stream_num = GET_BE_U_2(bp); + ND_PRINT(" %u", stream_num); + + bp += sizeof(stream_num); + param_len -= sizeof(stream_num); + chunkLengthRemaining -= sizeof(stream_num); + } + ND_PRINT("]"); + + break; + } + case SSN_TSN_RESET: + { + const struct inGoingSSNReset *content; + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content)); + + content = (const struct inGoingSSNReset*) bp; + ND_PRINT(": REQ SEQ: %u]", GET_BE_U_4(content->re_config_req)); + + bp += sizeof(*content); + chunkLengthRemaining -= sizeof(*content); + + break; + } + case RE_CONFIG_RES: + { + uint32_t optional = 0; + const size_t optional_size = sizeof(optional); + const struct reConfigRes *content; + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content)); + + content = (const struct reConfigRes*) bp; + ND_PRINT(": REQ SEQ: %u, ", GET_BE_U_4(content->res_seq_num)); + ND_PRINT("REQ: %s", tok2str(results, NULL, GET_BE_U_4(content->result))); + + bp += sizeof(*content); + param_len -= sizeof(*content); + chunkLengthRemaining -= sizeof(*content); + + if (0 == param_len) { + ND_PRINT("]"); + break; + } + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, optional_size); + optional = GET_BE_U_4(bp); + ND_PRINT(", Sender's TSN: %u", optional); + + bp += optional_size; + param_len -= optional_size; + chunkLengthRemaining -= optional_size; + + if (0 == param_len) { + ND_PRINT("]"); + break; + } + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, optional_size); + optional = GET_BE_U_4(bp); + ND_PRINT(", Receiver's Next TSN: %u] ", optional); + + bp += optional_size; + param_len -= optional_size; + chunkLengthRemaining -= optional_size; + + break; + } + case ADD_OUT_STREAM_REQ: + case ADD_IN_STREAM_REQ: + { + const struct addStreamReq *content; + + ND_ICHECKMSG_ZU("chunk length", chunkLengthRemaining, <, sizeof(*content)); + + content = (const struct addStreamReq*) bp; + ND_PRINT(": REQ SEQ: %u, ", GET_BE_U_4(content->res_seq_num)); + ND_PRINT("No. of new streams: %u] ", GET_BE_U_2(content->num_new_stream)); + + bp += sizeof(*content); + param_len -= sizeof(*content); + chunkLengthRemaining -= sizeof(*content); + + break; + } + default: + { + bp += chunkLengthRemaining; + chunkLengthRemaining = 0; + break; + } + } + + /* it's a parameter padding if there are more parameters in the remaining length */ + if (chunkLengthRemaining > 4) + bp += padding_len; + } + break; } default : diff --git a/tests/sctp-re-config-v.out b/tests/sctp-re-config-v.out new file mode 100644 index 0000000000..5fd03b85b4 --- /dev/null +++ b/tests/sctp-re-config-v.out @@ -0,0 +1,32 @@ + 1 15:56:38.595332 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 92) + 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [INIT] [init tag: 2670115933] [rwnd: 106496] [OS: 10] [MIS: 65535] [init TSN: 1593007960] + 2 15:56:38.595368 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 348) + 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [INIT ACK] [init tag: 2082750980] [rwnd: 106496] [OS: 5] [MIS: 5] [init TSN: 2238062072] + 3 15:56:38.595379 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 296) + 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [COOKIE ECHO] + 4 15:56:38.595392 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 36) + 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [COOKIE ACK] + 5 15:56:38.595416 IP (tos 0x2,ECT(0), ttl 64, id 1, offset 0, flags [DF], proto SCTP (132), length 76) + 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [RE-CONFIG] [OUT SSN RESET][IN SSN RESET] + 6 15:56:38.595421 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 76) + 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [RE-CONFIG] [RESP], (2) [RE-CONFIG] [OUT SSN RESET] + 7 15:56:38.595426 IP (tos 0x2,ECT(0), ttl 64, id 2, offset 0, flags [DF], proto SCTP (132), length 48) + 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [RE-CONFIG] [RESP] + 8 15:56:38.595434 IP (tos 0x2,ECT(0), ttl 64, id 3, offset 0, flags [DF], proto SCTP (132), length 60) + 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [DATA] (B)(E) [TSN: 1593007960] [SID: 0] [SSEQ 0] [PPID 0x0] + 9 15:56:38.595440 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 48) + 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [SACK] [cum ack 1593007960] [a_rwnd 106486] [#gap acks 0] [#dup tsns 0] + 10 15:56:40.359603 IP (tos 0x2,ECT(0), ttl 64, id 4, offset 0, flags [DF], proto SCTP (132), length 92) + 192.168.5.1.58384 > 192.168.5.4.36297: sctp (1) [HB REQ] + 11 15:56:40.359631 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 92) + 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [HB ACK] + 12 15:56:42.055670 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 92) + 192.168.5.2.36297 > 192.168.5.3.58384: sctp (1) [HB REQ] + 13 15:56:42.055866 IP (tos 0x2,ECT(0), ttl 64, id 5, offset 0, flags [DF], proto SCTP (132), length 92) + 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [HB ACK] + 14 15:56:51.811692 IP (tos 0x2,ECT(0), ttl 64, id 6, offset 0, flags [DF], proto SCTP (132), length 40) + 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [SHUTDOWN] + 15 15:56:51.811707 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 36) + 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [SHUTDOWN ACK] + 16 15:56:51.811712 IP (tos 0x2,ECT(0), ttl 64, id 7, offset 0, flags [DF], proto SCTP (132), length 36) + 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [SHUTDOWN COMPLETE] diff --git a/tests/sctp-re-config-vv.out b/tests/sctp-re-config-vv.out new file mode 100644 index 0000000000..aa3f14fa90 --- /dev/null +++ b/tests/sctp-re-config-vv.out @@ -0,0 +1,50 @@ + 1 15:56:38.595332 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 92) + 192.168.5.1.58384 > 192.168.5.2.36297: sctp + 1) [INIT] [init tag: 2670115933] [rwnd: 106496] [OS: 10] [MIS: 65535] [init TSN: 1593007960] + 2 15:56:38.595368 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 348) + 192.168.5.2.36297 > 192.168.5.1.58384: sctp + 1) [INIT ACK] [init tag: 2082750980] [rwnd: 106496] [OS: 5] [MIS: 5] [init TSN: 2238062072] + 3 15:56:38.595379 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 296) + 192.168.5.1.58384 > 192.168.5.2.36297: sctp + 1) [COOKIE ECHO] + 4 15:56:38.595392 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 36) + 192.168.5.2.36297 > 192.168.5.1.58384: sctp + 1) [COOKIE ACK] + 5 15:56:38.595416 IP (tos 0x2,ECT(0), ttl 64, id 1, offset 0, flags [DF], proto SCTP (132), length 76) + 192.168.5.1.58384 > 192.168.5.2.36297: sctp + 1) [RE-CONFIG] [OUT SSN RESET: REQ SEQ: 1593007960, RES SEQ: 2238062071, Last TSN: 1593007959, SID 0 1 2 3][IN SSN RESET: REQ SEQ: 1593007961, SID 0 1 2 3] + 6 15:56:38.595421 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 76) + 192.168.5.2.36297 > 192.168.5.1.58384: sctp + 1) [RE-CONFIG] [RESP: REQ SEQ: 1593007960, REQ: Success - Performed] + 2) [RE-CONFIG] [OUT SSN RESET: REQ SEQ: 2238062072, RES SEQ: 1593007961, Last TSN: 2238062071, SID 0 1 2 3] + 7 15:56:38.595426 IP (tos 0x2,ECT(0), ttl 64, id 2, offset 0, flags [DF], proto SCTP (132), length 48) + 192.168.5.1.58384 > 192.168.5.2.36297: sctp + 1) [RE-CONFIG] [RESP: REQ SEQ: 2238062072, REQ: Success - Performed] + 8 15:56:38.595434 IP (tos 0x2,ECT(0), ttl 64, id 3, offset 0, flags [DF], proto SCTP (132), length 60) + 192.168.5.1.58384 > 192.168.5.2.36297: sctp + 1) [DATA] (B)(E) [TSN: 1593007960] [SID: 0] [SSEQ 0] [PPID 0x0] [Payload: + 0x0000: 7265 7365 7420 492f 4f00 reset.I/O.] + 9 15:56:38.595440 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 48) + 192.168.5.2.36297 > 192.168.5.1.58384: sctp + 1) [SACK] [cum ack 1593007960] [a_rwnd 106486] [#gap acks 0] [#dup tsns 0] + 10 15:56:40.359603 IP (tos 0x2,ECT(0), ttl 64, id 4, offset 0, flags [DF], proto SCTP (132), length 92) + 192.168.5.1.58384 > 192.168.5.4.36297: sctp + 1) [HB REQ] + 11 15:56:40.359631 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 92) + 192.168.5.2.36297 > 192.168.5.1.58384: sctp + 1) [HB ACK] + 12 15:56:42.055670 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 92) + 192.168.5.2.36297 > 192.168.5.3.58384: sctp + 1) [HB REQ] + 13 15:56:42.055866 IP (tos 0x2,ECT(0), ttl 64, id 5, offset 0, flags [DF], proto SCTP (132), length 92) + 192.168.5.1.58384 > 192.168.5.2.36297: sctp + 1) [HB ACK] + 14 15:56:51.811692 IP (tos 0x2,ECT(0), ttl 64, id 6, offset 0, flags [DF], proto SCTP (132), length 40) + 192.168.5.1.58384 > 192.168.5.2.36297: sctp + 1) [SHUTDOWN] + 15 15:56:51.811707 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto SCTP (132), length 36) + 192.168.5.2.36297 > 192.168.5.1.58384: sctp + 1) [SHUTDOWN ACK] + 16 15:56:51.811712 IP (tos 0x2,ECT(0), ttl 64, id 7, offset 0, flags [DF], proto SCTP (132), length 36) + 192.168.5.1.58384 > 192.168.5.2.36297: sctp + 1) [SHUTDOWN COMPLETE] diff --git a/tests/sctp-re-config.out b/tests/sctp-re-config.out new file mode 100644 index 0000000000..c6efff4236 --- /dev/null +++ b/tests/sctp-re-config.out @@ -0,0 +1,16 @@ + 1 15:56:38.595332 IP 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [INIT] [init tag: 2670115933] [rwnd: 106496] [OS: 10] [MIS: 65535] [init TSN: 1593007960] + 2 15:56:38.595368 IP 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [INIT ACK] [init tag: 2082750980] [rwnd: 106496] [OS: 5] [MIS: 5] [init TSN: 2238062072] + 3 15:56:38.595379 IP 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [COOKIE ECHO] + 4 15:56:38.595392 IP 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [COOKIE ACK] + 5 15:56:38.595416 IP 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [RE-CONFIG] [OUT SSN RESET][IN SSN RESET] + 6 15:56:38.595421 IP 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [RE-CONFIG] [RESP], (2) [RE-CONFIG] [OUT SSN RESET] + 7 15:56:38.595426 IP 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [RE-CONFIG] [RESP] + 8 15:56:38.595434 IP 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [DATA] (B)(E) [TSN: 1593007960] [SID: 0] [SSEQ 0] [PPID 0x0] + 9 15:56:38.595440 IP 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [SACK] [cum ack 1593007960] [a_rwnd 106486] [#gap acks 0] [#dup tsns 0] + 10 15:56:40.359603 IP 192.168.5.1.58384 > 192.168.5.4.36297: sctp (1) [HB REQ] + 11 15:56:40.359631 IP 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [HB ACK] + 12 15:56:42.055670 IP 192.168.5.2.36297 > 192.168.5.3.58384: sctp (1) [HB REQ] + 13 15:56:42.055866 IP 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [HB ACK] + 14 15:56:51.811692 IP 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [SHUTDOWN] + 15 15:56:51.811707 IP 192.168.5.2.36297 > 192.168.5.1.58384: sctp (1) [SHUTDOWN ACK] + 16 15:56:51.811712 IP 192.168.5.1.58384 > 192.168.5.2.36297: sctp (1) [SHUTDOWN COMPLETE] diff --git a/tests/sctp-re-config.pcap b/tests/sctp-re-config.pcap new file mode 100644 index 0000000000000000000000000000000000000000..080651411fe5448d41b8503852ff21bb6b86a633 GIT binary patch literal 2064 zcmeH|Pe@cz6vn^z=8f|*v)P0u87>BKAtWsO<@0iR}$o1xdAc1-T8)cOYoLb0QT z6}KeK1&`4X=x!OU9L&AE`TgRZx{1~j%3{8}qfbZLuQJLlu=S~^xXA2u1lI0eU)>+e zl%2eM_vzT48!g@gb)Bc)&m@g^)0wILO#$0yu0ucH{)?lI{4Gk@#rY9BUrU&@#e1$* zW%qper(`Ye%bqK@saS~ru8Og8eiL+YBgfJfpI>ml>v?nTLmU(*?dNx;bpxiT(8RB$ zE#3z-LKB7fOSgUK0jjYIrE=$Z`sdgmq=*I`9u&jR`QhALVx6&(9I-ZLV~tO_#Y&Q& ze?{tclfd~pA