Skip to content
Snippets Groups Projects
Commit 9c0a0d1f authored by Michael Tüxen's avatar Michael Tüxen
Browse files

Relax constraints when describing INIT or INIT-ACK chunks.

When specifying INIT or INIT-ACK chunks allow the tag and the tsn
field to be omitted (meaning tag=... or tsn=... is allowed).
parent 2e934bd7
No related branches found
No related tags found
No related merge requests found
...@@ -951,7 +951,8 @@ opt_shutdown_complete_flags ...@@ -951,7 +951,8 @@ opt_shutdown_complete_flags
; ;
opt_tag opt_tag
: TAG '=' INTEGER { : TAG '=' ELLIPSIS { $$ = -1; }
| TAG '=' INTEGER {
if (!is_valid_u32($3)) { if (!is_valid_u32($3)) {
semantic_error("tag value out of range"); semantic_error("tag value out of range");
} }
...@@ -1098,23 +1099,11 @@ sctp_data_chunk_spec ...@@ -1098,23 +1099,11 @@ sctp_data_chunk_spec
sctp_init_chunk_spec sctp_init_chunk_spec
: INIT '[' opt_flags ',' opt_tag ',' opt_a_rwnd ',' opt_os ',' opt_is ',' opt_tsn opt_parameter_list_spec ']' { : INIT '[' opt_flags ',' opt_tag ',' opt_a_rwnd ',' opt_os ',' opt_is ',' opt_tsn opt_parameter_list_spec ']' {
if ($5 == -1) {
semantic_error("tag value must be specified");
}
if ($13 == -1) {
semantic_error("tsn value must be specified");
}
$$ = sctp_init_chunk_new($3, $5, $7, $9, $11, $13, $14); $$ = sctp_init_chunk_new($3, $5, $7, $9, $11, $13, $14);
} }
sctp_init_ack_chunk_spec sctp_init_ack_chunk_spec
: INIT_ACK '[' opt_flags ',' opt_tag ',' opt_a_rwnd ',' opt_os ',' opt_is ',' opt_tsn opt_parameter_list_spec ']' { : INIT_ACK '[' opt_flags ',' opt_tag ',' opt_a_rwnd ',' opt_os ',' opt_is ',' opt_tsn opt_parameter_list_spec ']' {
if ($5 == -1) {
semantic_error("tag value must be specified");
}
if ($13 == -1) {
semantic_error("tsn value must be specified");
}
$$ = sctp_init_ack_chunk_new($3, $5, $7, $9, $11, $13, $14); $$ = sctp_init_ack_chunk_new($3, $5, $7, $9, $11, $13, $14);
} }
......
...@@ -1153,10 +1153,11 @@ static int verify_init_chunk(struct sctp_init_chunk *actual_chunk, ...@@ -1153,10 +1153,11 @@ static int verify_init_chunk(struct sctp_init_chunk *actual_chunk,
assert(ntohs(actual_chunk->length) >= sizeof(struct sctp_init_chunk)); assert(ntohs(actual_chunk->length) >= sizeof(struct sctp_init_chunk));
parameters_length = ntohs(actual_chunk->length) - sizeof(struct sctp_init_chunk); parameters_length = ntohs(actual_chunk->length) - sizeof(struct sctp_init_chunk);
if (check_field("sctp_init_chunk_tag", if ((flags & FLAG_INIT_CHUNK_TAG_NOCHECK ? STATUS_OK :
ntohl(script_chunk->initiate_tag), check_field("sctp_init_chunk_tag",
ntohl(actual_chunk->initiate_tag), ntohl(script_chunk->initiate_tag),
error) || ntohl(actual_chunk->initiate_tag),
error)) ||
(flags & FLAG_INIT_CHUNK_A_RWND_NOCHECK ? STATUS_OK : (flags & FLAG_INIT_CHUNK_A_RWND_NOCHECK ? STATUS_OK :
check_field("sctp_init_chunk_a_rwnd", check_field("sctp_init_chunk_a_rwnd",
ntohl(script_chunk->a_rwnd), ntohl(script_chunk->a_rwnd),
...@@ -1172,10 +1173,11 @@ static int verify_init_chunk(struct sctp_init_chunk *actual_chunk, ...@@ -1172,10 +1173,11 @@ static int verify_init_chunk(struct sctp_init_chunk *actual_chunk,
ntohs(script_chunk->is), ntohs(script_chunk->is),
ntohs(actual_chunk->is), ntohs(actual_chunk->is),
error)) || error)) ||
check_field("sctp_init_chunk_tsn", (flags & FLAG_INIT_CHUNK_TSN_NOCHECK? STATUS_OK :
ntohl(script_chunk->initial_tsn), check_field("sctp_init_chunk_tsn",
ntohl(actual_chunk->initial_tsn), ntohl(script_chunk->initial_tsn),
error) || ntohl(actual_chunk->initial_tsn),
error)) ||
(flags & FLAG_INIT_CHUNK_OPT_PARAM_NOCHECK? STATUS_OK : (flags & FLAG_INIT_CHUNK_OPT_PARAM_NOCHECK? STATUS_OK :
verify_sctp_parameters(actual_chunk->parameter, verify_sctp_parameters(actual_chunk->parameter,
parameters_length, parameters_length,
...@@ -1190,10 +1192,11 @@ static int verify_init_ack_chunk(struct sctp_init_ack_chunk *actual_chunk, ...@@ -1190,10 +1192,11 @@ static int verify_init_ack_chunk(struct sctp_init_ack_chunk *actual_chunk,
struct sctp_init_ack_chunk *script_chunk, struct sctp_init_ack_chunk *script_chunk,
u32 flags, char **error) u32 flags, char **error)
{ {
if (check_field("sctp_init_ack_chunk_tag", if ((flags & FLAG_INIT_ACK_CHUNK_TAG_NOCHECK ? STATUS_OK :
ntohl(script_chunk->initiate_tag), check_field("sctp_init_ack_chunk_tag",
ntohl(actual_chunk->initiate_tag), ntohl(script_chunk->initiate_tag),
error) || ntohl(actual_chunk->initiate_tag),
error)) ||
(flags & FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK ? STATUS_OK : (flags & FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK ? STATUS_OK :
check_field("sctp_init_ack_chunk_a_rwnd", check_field("sctp_init_ack_chunk_a_rwnd",
ntohl(script_chunk->a_rwnd), ntohl(script_chunk->a_rwnd),
...@@ -1209,10 +1212,11 @@ static int verify_init_ack_chunk(struct sctp_init_ack_chunk *actual_chunk, ...@@ -1209,10 +1212,11 @@ static int verify_init_ack_chunk(struct sctp_init_ack_chunk *actual_chunk,
ntohs(script_chunk->is), ntohs(script_chunk->is),
ntohs(actual_chunk->is), ntohs(actual_chunk->is),
error)) || error)) ||
check_field("sctp_init_ack_chunk_tsn", (flags & FLAG_INIT_ACK_CHUNK_TSN_NOCHECK? STATUS_OK :
ntohl(script_chunk->initial_tsn), check_field("sctp_init_ack_chunk_tsn",
ntohl(actual_chunk->initial_tsn), ntohl(script_chunk->initial_tsn),
error)) { ntohl(actual_chunk->initial_tsn),
error))) {
return STATUS_ERR; return STATUS_ERR;
} }
/* FIXME: Validate parameters */ /* FIXME: Validate parameters */
......
...@@ -282,7 +282,12 @@ sctp_init_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn, ...@@ -282,7 +282,12 @@ sctp_init_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn,
chunk->flags = (u8)flgs; chunk->flags = (u8)flgs;
} }
chunk->length = htons(chunk_length); chunk->length = htons(chunk_length);
chunk->initiate_tag = htonl((u32)tag); if (tag == -1) {
chunk->initiate_tag = htonl(0);
flags |= FLAG_INIT_CHUNK_TAG_NOCHECK;
} else {
chunk->initiate_tag = htonl((u32)tag);
}
if (a_rwnd == -1) { if (a_rwnd == -1) {
chunk->a_rwnd = htonl(0); chunk->a_rwnd = htonl(0);
flags |= FLAG_INIT_CHUNK_A_RWND_NOCHECK; flags |= FLAG_INIT_CHUNK_A_RWND_NOCHECK;
...@@ -301,7 +306,12 @@ sctp_init_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn, ...@@ -301,7 +306,12 @@ sctp_init_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn,
} else { } else {
chunk->is = htons((u16)is); chunk->is = htons((u16)is);
} }
chunk->initial_tsn = htonl((u32)tsn); if (tsn == -1) {
chunk->initial_tsn = htonl(0);
flags |= FLAG_INIT_CHUNK_TSN_NOCHECK;
} else {
chunk->initial_tsn = htonl((u32)tsn);
}
offset = 0; offset = 0;
for (item = list->first; item != NULL; item = item->next) { for (item = list->first; item != NULL; item = item->next) {
parameter_padding_length = item->length % 4; parameter_padding_length = item->length % 4;
...@@ -355,26 +365,36 @@ sctp_init_ack_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn, ...@@ -355,26 +365,36 @@ sctp_init_ack_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn,
chunk->flags = (u8)flgs; chunk->flags = (u8)flgs;
} }
chunk->length = htons(chunk_length); chunk->length = htons(chunk_length);
chunk->initiate_tag = htonl((u32)tag); if (tag == -1) {
chunk->initiate_tag = htonl(0);
flags |= FLAG_INIT_ACK_CHUNK_TAG_NOCHECK;
} else {
chunk->initiate_tag = htonl((u32)tag);
}
if (a_rwnd == -1) { if (a_rwnd == -1) {
chunk->a_rwnd = htonl(0); chunk->a_rwnd = htonl(0);
flags |= FLAG_INIT_CHUNK_A_RWND_NOCHECK; flags |= FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK;
} else { } else {
chunk->a_rwnd = htonl((u32)a_rwnd); chunk->a_rwnd = htonl((u32)a_rwnd);
} }
if (os == -1) { if (os == -1) {
chunk->os = htons(0); chunk->os = htons(0);
flags |= FLAG_INIT_CHUNK_OS_NOCHECK; flags |= FLAG_INIT_ACK_CHUNK_OS_NOCHECK;
} else { } else {
chunk->os = htons((u16)os); chunk->os = htons((u16)os);
} }
if (is == -1) { if (is == -1) {
chunk->is = htons(0); chunk->is = htons(0);
flags |= FLAG_INIT_CHUNK_IS_NOCHECK; flags |= FLAG_INIT_ACK_CHUNK_IS_NOCHECK;
} else { } else {
chunk->is = htons((u16)is); chunk->is = htons((u16)is);
} }
chunk->initial_tsn = htonl((u32)tsn); if (tsn == -1) {
chunk->initial_tsn = htonl(0);
flags |= FLAG_INIT_ACK_CHUNK_TSN_NOCHECK;
} else {
chunk->initial_tsn = htonl((u32)tsn);
}
offset = 0; offset = 0;
for (item = list->first; item != NULL; item = item->next) { for (item = list->first; item != NULL; item = item->next) {
parameter_padding_length = item->length % 4; parameter_padding_length = item->length % 4;
...@@ -1379,6 +1399,11 @@ new_sctp_packet(int address_family, ...@@ -1379,6 +1399,11 @@ new_sctp_packet(int address_family,
} }
break; break;
case SCTP_INIT_CHUNK_TYPE: case SCTP_INIT_CHUNK_TYPE:
if (chunk_item->flags & FLAG_INIT_CHUNK_TAG_NOCHECK) {
asprintf(error,
"TAG must be specified for inbound packets");
return NULL;
}
if (chunk_item->flags & FLAG_INIT_CHUNK_A_RWND_NOCHECK) { if (chunk_item->flags & FLAG_INIT_CHUNK_A_RWND_NOCHECK) {
asprintf(error, asprintf(error,
"A_RWND must be specified for inbound packets"); "A_RWND must be specified for inbound packets");
...@@ -1401,6 +1426,11 @@ new_sctp_packet(int address_family, ...@@ -1401,6 +1426,11 @@ new_sctp_packet(int address_family,
} }
break; break;
case SCTP_INIT_ACK_CHUNK_TYPE: case SCTP_INIT_ACK_CHUNK_TYPE:
if (chunk_item->flags & FLAG_INIT_ACK_CHUNK_TAG_NOCHECK) {
asprintf(error,
"TAG must be specified for inbound packets");
return NULL;
}
if (chunk_item->flags & FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK) { if (chunk_item->flags & FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK) {
asprintf(error, asprintf(error,
"A_RWND must be specified for inbound packets"); "A_RWND must be specified for inbound packets");
......
...@@ -130,19 +130,23 @@ sctp_chunk_list_item_new(struct sctp_chunk *chunk, u32 length, u32 flags, ...@@ -130,19 +130,23 @@ sctp_chunk_list_item_new(struct sctp_chunk *chunk, u32 length, u32 flags,
struct sctp_chunk_list_item * struct sctp_chunk_list_item *
sctp_data_chunk_new(s64 flgs, s64 len, s64 tsn, s64 sid, s64 ssn, s64 ppid); sctp_data_chunk_new(s64 flgs, s64 len, s64 tsn, s64 sid, s64 ssn, s64 ppid);
#define FLAG_INIT_CHUNK_A_RWND_NOCHECK 0x00000100 #define FLAG_INIT_CHUNK_TAG_NOCHECK 0x00000100
#define FLAG_INIT_CHUNK_OS_NOCHECK 0x00000200 #define FLAG_INIT_CHUNK_A_RWND_NOCHECK 0x00000200
#define FLAG_INIT_CHUNK_IS_NOCHECK 0x00000400 #define FLAG_INIT_CHUNK_OS_NOCHECK 0x00000400
#define FLAG_INIT_CHUNK_OPT_PARAM_NOCHECK 0x00000800 #define FLAG_INIT_CHUNK_IS_NOCHECK 0x00000800
#define FLAG_INIT_CHUNK_TSN_NOCHECK 0x00001000
#define FLAG_INIT_CHUNK_OPT_PARAM_NOCHECK 0x00002000
struct sctp_chunk_list_item * struct sctp_chunk_list_item *
sctp_init_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn, sctp_init_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn,
struct sctp_parameter_list *parameters); struct sctp_parameter_list *parameters);
#define FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK 0x00000100 #define FLAG_INIT_ACK_CHUNK_TAG_NOCHECK 0x00000100
#define FLAG_INIT_ACK_CHUNK_OS_NOCHECK 0x00000200 #define FLAG_INIT_ACK_CHUNK_A_RWND_NOCHECK 0x00000200
#define FLAG_INIT_ACK_CHUNK_IS_NOCHECK 0x00000400 #define FLAG_INIT_ACK_CHUNK_OS_NOCHECK 0x00000400
#define FLAG_INIT_ACK_CHUNK_OPT_PARAM_NOCHECK 0x00000800 #define FLAG_INIT_ACK_CHUNK_IS_NOCHECK 0x00000800
#define FLAG_INIT_ACK_CHUNK_TSN_NOCHECK 0x00001000
#define FLAG_INIT_ACK_CHUNK_OPT_PARAM_NOCHECK 0x00002000
struct sctp_chunk_list_item * struct sctp_chunk_list_item *
sctp_init_ack_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn, sctp_init_ack_chunk_new(s64 flgs, s64 tag, s64 a_rwnd, s64 os, s64 is, s64 tsn,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment