From 943cc8f9eb76c28e1eff5e856350a0ca7acc4905 Mon Sep 17 00:00:00 2001 From: Julian Cordes <julian.cordes@gmail.com> Date: Sun, 3 Jan 2016 02:46:33 +0100 Subject: [PATCH] fixes for support of generic init messages. --- gtests/net/packetdrill/packet.c | 5 + gtests/net/packetdrill/run_packet.c | 213 ++++++++++-------- gtests/net/packetdrill/sctp_packet.c | 9 +- .../tests/bsd/sctp/sctp_generic_passive.pkt | 16 ++ 4 files changed, 147 insertions(+), 96 deletions(-) create mode 100644 gtests/net/packetdrill/tests/bsd/sctp/sctp_generic_passive.pkt diff --git a/gtests/net/packetdrill/packet.c b/gtests/net/packetdrill/packet.c index a5edfebe..406e3465 100644 --- a/gtests/net/packetdrill/packet.c +++ b/gtests/net/packetdrill/packet.c @@ -177,6 +177,11 @@ static struct packet *packet_copy_with_headroom(struct packet *old_packet, packet->udplite = offset_ptr(old_base, new_base, old_packet->udplite); packet->icmpv4 = offset_ptr(old_base, new_base, old_packet->icmpv4); packet->icmpv6 = offset_ptr(old_base, new_base, old_packet->icmpv6); + + if (old_packet->chunk_list == NULL) { + packet->chunk_list = NULL; + return packet; + } /* Go through the SCTP specific lists */ for (old_chunk_item = old_packet->chunk_list->first; diff --git a/gtests/net/packetdrill/run_packet.c b/gtests/net/packetdrill/run_packet.c index 6d7b021b..caede856 100644 --- a/gtests/net/packetdrill/run_packet.c +++ b/gtests/net/packetdrill/run_packet.c @@ -191,7 +191,7 @@ static struct socket *handle_listen_for_script_packet( */ struct config *config = state->config; struct socket *socket = state->socket_under_test; /* shortcut */ - struct sctp_init_chunk *init; + u32 initiate_tag, initial_tsn; struct sctp_chunk_list_item *item; bool match = (direction == DIRECTION_INBOUND); @@ -210,17 +210,42 @@ static struct socket *handle_listen_for_script_packet( } if (!match) return NULL; - + if (packet->sctp != NULL) { - assert(packet->chunk_list != NULL); - item = packet->chunk_list->first; - if ((item != NULL) && - (item->chunk->type == SCTP_INIT_CHUNK_TYPE)) { - init = (struct sctp_init_chunk *)item->chunk; - } else { - return NULL; + if (packet->chunk_list != NULL) { + item = packet->chunk_list->first; + if ((item != NULL) && + (item->chunk->type == SCTP_INIT_CHUNK_TYPE)) { + struct sctp_init_chunk *init = (struct sctp_init_chunk *)item->chunk; + initiate_tag = ntohl(init->initiate_tag); + initial_tsn = ntohl(init->initial_tsn); + } else { + return NULL; + } + } + else { + if (packet->flags & FLAGS_SCTP_GENERIC_PACKET) { + u8 *sctp_chunk_start = (u8 *) (packet->sctp + 1); + if (sctp_chunk_start[0] == SCTP_INIT_CHUNK_TYPE) { + u8 *initiate_tag_start = (u8 *) (sctp_chunk_start + 4); + u8 *initial_tsn_start = (u8 *) (sctp_chunk_start + 16); + initiate_tag = initiate_tag_start[3] << 24 | initiate_tag_start[2] << 16 | initiate_tag_start[1] << 8 | initiate_tag_start[0]; + initial_tsn = initial_tsn_start[3] << 24 | initial_tsn_start[2] << 16 | initial_tsn_start[1] << 8 | initial_tsn_start[0]; + initiate_tag = ntohl(initiate_tag); + initial_tsn = ntohl(initial_tsn); + } + else { + return NULL; + } + } + else { + return NULL; + } } } + else { + DEBUGP("packet->sctp == NULL"); + } /* Create a child passive socket for this incoming SYN packet. * Any further packets in the test script will be directed to @@ -241,8 +266,8 @@ static struct socket *handle_listen_for_script_packet( if (packet->tcp != NULL) { socket->script.remote_isn = ntohl(packet->tcp->seq); } else { - socket->script.remote_initiate_tag = ntohl(init->initiate_tag); - socket->script.remote_initial_tsn = ntohl(init->initial_tsn); + socket->script.remote_initiate_tag = initiate_tag; + socket->script.remote_initial_tsn = initial_tsn; } socket->script.fd = -1; @@ -256,8 +281,8 @@ static struct socket *handle_listen_for_script_packet( if (packet->tcp != NULL) { socket->live.remote_isn = ntohl(packet->tcp->seq); } else { - socket->live.remote_initiate_tag = ntohl(init->initiate_tag); - socket->live.remote_initial_tsn = ntohl(init->initial_tsn); + socket->live.remote_initiate_tag = initiate_tag; + socket->live.remote_initial_tsn = initial_tsn; } socket->live.fd = -1; @@ -2508,93 +2533,95 @@ static int do_inbound_script_packet( } } if (packet->sctp) { - for (item = packet->chunk_list->first; - item != NULL; - item = item->next) { - switch (item->chunk->type) { - case SCTP_INIT_ACK_CHUNK_TYPE: - if (socket->state == SOCKET_ACTIVE_INIT_SENT) { - init_ack = (struct sctp_init_ack_chunk *)item->chunk; - DEBUGP("Moving socket in SOCKET_ACTIVE_INIT_ACK_RECEIVED\n"); - socket->state = SOCKET_ACTIVE_INIT_ACK_RECEIVED; - socket->script.remote_initiate_tag = ntohl(init_ack->initiate_tag); - socket->script.remote_initial_tsn = ntohl(init_ack->initial_tsn); - socket->live.remote_initiate_tag = ntohl(init_ack->initiate_tag); - socket->live.remote_initial_tsn = ntohl(init_ack->initial_tsn); - DEBUGP("remote_initiate_tag 0x%08x, remote_initial_tsn 0x%08x\n", ntohl(init_ack->initiate_tag), ntohl(init_ack->initial_tsn)); - } - break; - case SCTP_COOKIE_ECHO_CHUNK_TYPE: - if (item->flags & FLAG_CHUNK_VALUE_NOCHECK) { - temp_offset = socket->prepared_cookie_echo_length - item->length; - assert(packet->ip_bytes + temp_offset <= packet->buffer_bytes); - memmove((u8 *)item->chunk + item->length + temp_offset, - (u8 *)item->chunk + item->length, - packet_end(packet) - ((u8 *)item->chunk + item->length)); - memcpy(item->chunk, - socket->prepared_cookie_echo, - socket->prepared_cookie_echo_length); - item->length = socket->prepared_cookie_echo_length; - packet->buffer_bytes += temp_offset; - packet->ip_bytes += temp_offset; - if (packet->ipv4) { - packet->ipv4->tot_len = htons(ntohs(packet->ipv4->tot_len) + temp_offset); - } - if (packet->ipv6) { - packet->ipv6->payload_len = htons(ntohs(packet->ipv6->payload_len) + temp_offset); + if (packet->chunk_list != NULL) { + for (item = packet->chunk_list->first; + item != NULL; + item = item->next) { + switch (item->chunk->type) { + case SCTP_INIT_ACK_CHUNK_TYPE: + if (socket->state == SOCKET_ACTIVE_INIT_SENT) { + init_ack = (struct sctp_init_ack_chunk *)item->chunk; + DEBUGP("Moving socket in SOCKET_ACTIVE_INIT_ACK_RECEIVED\n"); + socket->state = SOCKET_ACTIVE_INIT_ACK_RECEIVED; + socket->script.remote_initiate_tag = ntohl(init_ack->initiate_tag); + socket->script.remote_initial_tsn = ntohl(init_ack->initial_tsn); + socket->live.remote_initiate_tag = ntohl(init_ack->initiate_tag); + socket->live.remote_initial_tsn = ntohl(init_ack->initial_tsn); + DEBUGP("remote_initiate_tag 0x%08x, remote_initial_tsn 0x%08x\n", ntohl(init_ack->initiate_tag), ntohl(init_ack->initial_tsn)); } - for (i = 0; i < PACKET_MAX_HEADERS; i++) { - if ((packet->ipv4 != NULL && packet->headers[i].h.ipv4 == packet->ipv4) || - (packet->ipv6 != NULL && packet->headers[i].h.ipv6 == packet->ipv6)) { - break; + break; + case SCTP_COOKIE_ECHO_CHUNK_TYPE: + if (item->flags & FLAG_CHUNK_VALUE_NOCHECK) { + temp_offset = socket->prepared_cookie_echo_length - item->length; + assert(packet->ip_bytes + temp_offset <= packet->buffer_bytes); + memmove((u8 *)item->chunk + item->length + temp_offset, + (u8 *)item->chunk + item->length, + packet_end(packet) - ((u8 *)item->chunk + item->length)); + memcpy(item->chunk, + socket->prepared_cookie_echo, + socket->prepared_cookie_echo_length); + item->length = socket->prepared_cookie_echo_length; + packet->buffer_bytes += temp_offset; + packet->ip_bytes += temp_offset; + if (packet->ipv4) { + packet->ipv4->tot_len = htons(ntohs(packet->ipv4->tot_len) + temp_offset); } + if (packet->ipv6) { + packet->ipv6->payload_len = htons(ntohs(packet->ipv6->payload_len) + temp_offset); + } + for (i = 0; i < PACKET_MAX_HEADERS; i++) { + if ((packet->ipv4 != NULL && packet->headers[i].h.ipv4 == packet->ipv4) || + (packet->ipv6 != NULL && packet->headers[i].h.ipv6 == packet->ipv6)) { + break; + } + } + assert(packet->headers[i + 1].type == HEADER_SCTP); + packet->headers[i].total_bytes += temp_offset; + packet->headers[i + 1].total_bytes += temp_offset; + offset += temp_offset; } - assert(packet->headers[i + 1].type == HEADER_SCTP); - packet->headers[i].total_bytes += temp_offset; - packet->headers[i + 1].total_bytes += temp_offset; - offset += temp_offset; - } - if (((packet->flags & FLAGS_SCTP_BAD_CRC32C) == 0) && - (((packet->flags & FLAGS_SCTP_EXPLICIT_TAG) == 0) || - ((ntohl(packet->sctp->v_tag) == socket->script.local_initiate_tag) && - (socket->script.local_initiate_tag != 0)))) { - socket->state = SOCKET_PASSIVE_COOKIE_ECHO_RECEIVED; - } - break; - case SCTP_HEARTBEAT_ACK_CHUNK_TYPE: - if (item->flags & FLAG_CHUNK_VALUE_NOCHECK) { - temp_offset = socket->prepared_heartbeat_ack_length - item->length; - assert(packet->ip_bytes + temp_offset <= packet->buffer_bytes); - memmove((u8 *)item->chunk + item->length + temp_offset, - (u8 *)item->chunk + item->length, - packet_end(packet) - ((u8 *)item->chunk + item->length)); - memcpy(item->chunk, - socket->prepared_heartbeat_ack, - socket->prepared_heartbeat_ack_length); - item->length = socket->prepared_heartbeat_ack_length; - packet->buffer_bytes += temp_offset; - packet->ip_bytes += temp_offset; - if (packet->ipv4) { - packet->ipv4->tot_len = htons(ntohs(packet->ipv4->tot_len) + temp_offset); - } - if (packet->ipv6) { - packet->ipv6->payload_len = htons(ntohs(packet->ipv6->payload_len) + temp_offset); + if (((packet->flags & FLAGS_SCTP_BAD_CRC32C) == 0) && + (((packet->flags & FLAGS_SCTP_EXPLICIT_TAG) == 0) || + ((ntohl(packet->sctp->v_tag) == socket->script.local_initiate_tag) && + (socket->script.local_initiate_tag != 0)))) { + socket->state = SOCKET_PASSIVE_COOKIE_ECHO_RECEIVED; } - for (i = 0; i < PACKET_MAX_HEADERS; i++) { - if ((packet->ipv4 != NULL && packet->headers[i].h.ipv4 == packet->ipv4) || - (packet->ipv6 != NULL && packet->headers[i].h.ipv6 == packet->ipv6)) { - break; + break; + case SCTP_HEARTBEAT_ACK_CHUNK_TYPE: + if (item->flags & FLAG_CHUNK_VALUE_NOCHECK) { + temp_offset = socket->prepared_heartbeat_ack_length - item->length; + assert(packet->ip_bytes + temp_offset <= packet->buffer_bytes); + memmove((u8 *)item->chunk + item->length + temp_offset, + (u8 *)item->chunk + item->length, + packet_end(packet) - ((u8 *)item->chunk + item->length)); + memcpy(item->chunk, + socket->prepared_heartbeat_ack, + socket->prepared_heartbeat_ack_length); + item->length = socket->prepared_heartbeat_ack_length; + packet->buffer_bytes += temp_offset; + packet->ip_bytes += temp_offset; + if (packet->ipv4) { + packet->ipv4->tot_len = htons(ntohs(packet->ipv4->tot_len) + temp_offset); + } + if (packet->ipv6) { + packet->ipv6->payload_len = htons(ntohs(packet->ipv6->payload_len) + temp_offset); + } + for (i = 0; i < PACKET_MAX_HEADERS; i++) { + if ((packet->ipv4 != NULL && packet->headers[i].h.ipv4 == packet->ipv4) || + (packet->ipv6 != NULL && packet->headers[i].h.ipv6 == packet->ipv6)) { + break; + } } + assert(packet->headers[i + 1].type == HEADER_SCTP); + packet->headers[i].total_bytes += temp_offset; + packet->headers[i + 1].total_bytes += temp_offset; + offset += temp_offset; } - assert(packet->headers[i + 1].type == HEADER_SCTP); - packet->headers[i].total_bytes += temp_offset; - packet->headers[i + 1].total_bytes += temp_offset; - offset += temp_offset; + break; + default: + item->chunk = (struct sctp_chunk *)((char *)item->chunk + offset); + break; } - break; - default: - item->chunk = (struct sctp_chunk *)((char *)item->chunk + offset); - break; } } } diff --git a/gtests/net/packetdrill/sctp_packet.c b/gtests/net/packetdrill/sctp_packet.c index 0f5c66fd..8b743399 100644 --- a/gtests/net/packetdrill/sctp_packet.c +++ b/gtests/net/packetdrill/sctp_packet.c @@ -1254,8 +1254,11 @@ void sctp_chunk_list_free(struct sctp_chunk_list *list) { struct sctp_chunk_list_item *current_item, *next_item; - - assert(list != NULL); + + if (list == NULL) { + return; + } + current_item = list->first; while (current_item != NULL) { next_item = current_item->next; @@ -2683,7 +2686,7 @@ new_sctp_generic_packet(int address_family, sctp_chunk_start[i] = item->byte; } - packet->chunk_list = sctp_chunk_list_new(); + packet->chunk_list = NULL; packet->ip_bytes = ip_bytes; return packet; } \ No newline at end of file diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_generic_passive.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_generic_passive.pkt new file mode 100644 index 00000000..d296713a --- /dev/null +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_generic_passive.pkt @@ -0,0 +1,16 @@ ++0.0 socket(..., SOCK_STREAM, IPPROTO_SCTP) = 3 +// Check the handshake with en empty(!) cookie ++0.0 bind(3, ..., ...) = 0 ++0.0 listen(3, 1) = 0 ++0.0 < sctp: [0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x05, 0xDC, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01] +//+0.0 < sctp: INIT[flgs=0, tag=1, a_rwnd=1500, os=1, is=1, tsn=1] ++0.0 > sctp: INIT_ACK[flgs=0, tag=2, a_rwnd=..., os=..., is=..., tsn=1, ...] ++0.1 < sctp: COOKIE_ECHO[flgs=0, len=..., val=...] ++0.0 > sctp: COOKIE_ACK[flgs=0] ++0.0 accept(3, ..., ...) = 4 +// Tear down the association ++1.0 < sctp: SHUTDOWN[flgs=0, cum_tsn=0] ++0.0 > sctp: SHUTDOWN_ACK[flgs=0] ++0.0 < sctp: SHUTDOWN_COMPLETE[flgs=0] ++0.0 close(4) = 0 ++0.0 close(3) = 0 -- GitLab