From 468c9a07f5d73524c548438840e431cf9cb4e0be Mon Sep 17 00:00:00 2001 From: hoelscher <jens.hoelscher@fh-muenster.de> Date: Mon, 16 Nov 2015 15:11:50 +0100 Subject: [PATCH] add sctp_peeloff --- gtests/net/packetdrill/run_system_call.c | 77 ++++++++++++++++++- .../tests/bsd/sctp/sctp_active_x.pkt | 19 ++++- 2 files changed, 91 insertions(+), 5 deletions(-) diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index 84a6a847..71fccfcf 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -1753,11 +1753,37 @@ static int run_syscall_connect(struct state *state, socket->script.remote.port = 0; socket->script.local.port = 0; socket->live.remote.ip = state->config->live_remote_ip; - socket->live.remote.port = htons(state->config->live_connect_port); + socket->live.remote.port = htons(state->config->live_connect_port); DEBUGP("success: setting socket to state %d\n", socket->state); return STATUS_OK; } +static int run_syscall_sctp_peeloff(struct state *state, + int script_copy_fd, + int script_new_fd, + int live_new_fd, + char **error) { + struct socket *copy_socket = NULL, *new_socket, *temp_socket; + copy_socket = find_socket_by_script_fd(state, script_copy_fd); + assert(copy_socket != NULL); + if (copy_socket->state == SOCKET_NEW) { + asprintf(error, "socket is not new"); + return STATUS_ERR; + } + new_socket = find_socket_by_script_fd(state, script_new_fd); + assert(new_socket == NULL); + new_socket = socket_new(state); + temp_socket = new_socket->next; + + memcpy(new_socket, copy_socket, sizeof(struct socket)); + new_socket->next = temp_socket; + new_socket->live.fd = live_new_fd; + new_socket->script.fd = script_new_fd; + DEBUGP("success: setting socket to state %d\n", new_socket->state); + return STATUS_OK; +} + + /**************************************************************************** * Here we have the parsing and invocation of the system calls that * we support... @@ -4792,6 +4818,11 @@ static int syscall_sctp_connectx(struct state *state, struct syscall_spec *sysca return STATUS_ERR; assoc_expr = get_arg(args, 3, error); + if (check_type(assoc_expr, EXPR_LIST, error)) + return STATUS_ERR; + if (check_arg_count(assoc_expr->value.list, 1, error)) + return STATUS_ERR; + assoc_expr = get_arg(assoc_expr->value.list, 0, error); if (check_u32_expr(assoc_expr, (u32)live_associd, "sctp_connectx assoc_id", error)) return STATUS_ERR; @@ -4803,6 +4834,46 @@ static int syscall_sctp_connectx(struct state *state, struct syscall_spec *sysca #endif } +static int syscall_sctp_peeloff(struct state *state, struct syscall_spec *syscall, + struct expression_list *args, + char **error) +{ +#if defined(__FreeBSD__) || defined(linux) + int live_fd, script_fd, result, script_new_fd; + sctp_assoc_t assoc_id; + struct expression *expr_assoc; + if (check_arg_count(args, 2, error)) + return STATUS_ERR; + if (s32_arg(args, 0, &script_fd, error)) + return STATUS_ERR; + if (to_live_fd(state, script_fd, &live_fd, error)) + return STATUS_ERR; + expr_assoc = get_arg(args, 1, error); + if (get_u32(expr_assoc, &assoc_id, error)) + return STATUS_ERR; + + //check connection Type and set assoc_id if one-to-many style socket + + begin_syscall(state, syscall); + + result = sctp_peeloff(live_fd, assoc_id); + + if (end_syscall(state, syscall, CHECK_NON_NEGATIVE, result, error)) + return STATUS_ERR; + + if (get_s32(syscall->result, &script_new_fd, error)) + return STATUS_ERR; + if (run_syscall_sctp_peeloff(state, script_fd, script_new_fd, result, error)) { + asprintf(error, "can't copy socket definition"); + return STATUS_ERR; + } + + return STATUS_OK; +#else + asprintf(error, "sctp_connectx is not supported"); + return STATUS_ERR; +#endif +} /* A dispatch table with all the system calls that we support... */ struct system_call_entry { @@ -4812,6 +4883,7 @@ struct system_call_entry { struct expression_list *args, char **error); }; + struct system_call_entry system_call_table[] = { {"socket", syscall_socket}, {"bind", syscall_bind}, @@ -4840,7 +4912,8 @@ struct system_call_entry system_call_table[] = { {"sctp_sendv", syscall_sctp_sendv}, {"sctp_recvv", syscall_sctp_recvv}, {"sctp_bindx", syscall_sctp_bindx}, - {"sctp_connectx", syscall_sctp_connectx} + {"sctp_connectx", syscall_sctp_connectx}, + {"sctp_peeloff", syscall_sctp_peeloff} }; /* Evaluate the system call arguments and invoke the system call. */ diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_active_x.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_active_x.pkt index 15af1333..44c1d95e 100644 --- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_active_x.pkt +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_active_x.pkt @@ -1,17 +1,30 @@ -+0.0 socket(..., SOCK_STREAM, IPPROTO_SCTP) = 3 + + 0.0 socket(..., SOCK_STREAM, IPPROTO_SCTP) = 3 +0.0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) +0.0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 +0.0 sctp_bindx(3, [...], 1, SCTP_BINDX_ADD_ADDR) = 0 // Check the handshake with an empty(!) cookie -+0.1 sctp_connectx(3, [...], 1, 3) = 0 ++0.1 sctp_connectx(3, [...], 1, [3]) = 0 +0.0 > sctp: INIT[flgs=0, tag=1, a_rwnd=..., os=..., is=..., tsn=1, ...] +0.1 < sctp: INIT_ACK[flgs=0, tag=2, a_rwnd=1500, os=16, is=16, tsn=1, STATE_COOKIE[len=4, val=...]] +0.0 > sctp: COOKIE_ECHO[flgs=0, len=4, val=...] +0.1 < sctp: COOKIE_ACK[flgs=0] -+0.0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0 ++0.0 sctp_sendmsg(3, ..., 1000, ..., ..., htonl(1234), SCTP_UNORDERED, 1, 0, 0) = 1000 +* > sctp: DATA[flgs=UBE, len=1016, tsn=1, sid=1, ssn=0, ppid=1234] ++0.0 < sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=1500, gaps=[], dups=[]] + ++0.0 sctp_peeloff(3, 4) = 4 + ++0.0 sctp_sendmsg(3, ..., 1000, ..., ..., htonl(1234), SCTP_UNORDERED, 1, 0, 0) = 1000 +* > sctp: DATA[flgs=UBE, len=1016, tsn=1, sid=1, ssn=0, ppid=1234] ++0.0 < sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=1500, gaps=[], dups=[]] + ++0.0 sctp_sendmsg(4, ..., 1000, ..., ..., htonl(1234), SCTP_UNORDERED, 1, 0, 0) = 1000 +* > sctp: DATA[flgs=UBE, len=1016, tsn=1, sid=1, ssn=0, ppid=1234] ++0.0 < sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=1500, gaps=[], dups=[]] +0.0 < sctp: SHUTDOWN[flgs=0, cum_tsn=0] * > sctp: SHUTDOWN_ACK[flgs=0] -- GitLab