diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index bca3df3b2360ed450acebdffd7ed10c5a8436cfd..694876727fc3a75743a4d2a8fd038a06c3226a15 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -202,6 +202,8 @@ ect0 return ECT0; ect1 return ECT1; noecn return NO_ECN; ce return CE; +iov_base return IOV_BASE; +iov_len return IOV_LEN; [.][.][.] return ELLIPSIS; assoc_value return ASSOC_VALUE; stream_id return STREAM_ID; @@ -256,6 +258,13 @@ sinfo_context return SINFO_CONTEXT; sinfo_timetolive return SINFO_TIMETOLIVE; sinfo_tsn return SINFO_TSN; sinfo_cumtsn return SINFO_CUMTSN; +pr_policy return PR_POLICY; +pr_value return PR_VALUE; +auth_keynumber return AUTH_KEYNUMBER; +sendv_flags return SENDV_FLAGS; +sendv_sndinfo return SENDV_SNDINFO; +sendv_prinfo return SENDV_PRINFO; +sendv_authinfo return SENDV_AUTHINFO; CHUNK return CHUNK; DATA return DATA; INIT return INIT; diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index d6ce691cc26dd4925893a8914185cbff69baa88e..180003aea1e11ae1451f4940821e02a01a82db87 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -498,6 +498,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> FD EVENTS REVENTS ONOFF LINGER %token <reserved> ACK ECR EOL MSS NOP SACK SACKOK TIMESTAMP VAL WIN WSCALE PRO %token <reserved> FAST_OPEN +%token <reserved> IOV_BASE IOV_LEN %token <reserved> ECT0 ECT1 CE ECT01 NO_ECN %token <reserved> IPV4 IPV6 ICMP SCTP UDP UDPLITE GRE MTU %token <reserved> MPLS LABEL TC TTL @@ -541,6 +542,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> BAD_CRC32C NULL_ %token <reserved> SINFO_STREAM SINFO_SSN SINFO_FLAGS SINFO_PPID SINFO_CONTEXT %token <reserved> SINFO_TIMETOLIVE SINFO_TSN SINFO_CUMTSN +%token <reserved> PR_POLICY PR_VALUE AUTH_KEYNUMBER SENDV_FLAGS SENDV_SNDINFO +%token <reserved> SENDV_PRINFO SENDV_AUTHINFO %token <floating> FLOAT %token <integer> INTEGER HEX_INTEGER %token <string> WORD STRING BACK_QUOTED CODE IPV4_ADDR IPV6_ADDR @@ -593,6 +596,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <expression> sctp_event se_type se_on sctp_setadaptation null %type <expression> sctp_sndrcvinfo sinfo_stream sinfo_ssn sinfo_flags sinfo_ppid sinfo_context %type <expression> sinfo_timetolive sinfo_tsn sinfo_cumtsn +%type <expression> sctp_prinfo sctp_authinfo pr_policy sctp_sendv_spa %type <errno_info> opt_errno %type <chunk_list> sctp_chunk_list_spec %type <chunk_list_item> sctp_chunk_spec @@ -2456,10 +2460,19 @@ expression | sctp_setadaptation{ $$ = $1; } -| null { +| sctp_sndrcvinfo { $$ = $1; } -| sctp_sndrcvinfo { +| sctp_prinfo { + $$ = $1; +} +| sctp_authinfo { + $$ = $1; +} +| sctp_sendv_spa { + $$ = $1; +} +| null { $$ = $1; } ; @@ -2562,6 +2575,13 @@ iovec iov_expr->iov_base = new_expression(EXPR_ELLIPSIS); iov_expr->iov_len = $4; } +| '{' IOV_BASE '=' ELLIPSIS ',' IOV_LEN '=' decimal_integer '}' { + struct iovec_expr *iov_expr = calloc(1, sizeof(struct iovec_expr)); + $$ = new_expression(EXPR_IOVEC); + $$->value.iovec = iov_expr; + iov_expr->iov_base = new_expression(EXPR_ELLIPSIS); + iov_expr->iov_len = $8; +} ; pollfd @@ -3228,6 +3248,53 @@ sctp_sndrcvinfo $$->value.sctp_sndrcvinfo->sinfo_tsn = $14; $$->value.sctp_sndrcvinfo->sinfo_cumtsn = $16; }; + +pr_policy +: PR_POLICY '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| PR_POLICY '=' INTEGER { + if (!is_valid_u16($3)) { + semantic_error("pr_policy out of range"); + } + $$ = new_integer_expression($3, "%hu"); +}; + +sctp_prinfo +: '{' pr_policy ',' PR_VALUE '=' INTEGER'}' { + $$ = new_expression(EXPR_SCTP_PRINFO); + $$->value.sctp_prinfo = calloc(1, sizeof(struct sctp_prinfo_expr)); + $$->value.sctp_prinfo->pr_policy = $2; + if (!is_valid_u32($6)) { + semantic_error("pr_value out of range"); + } + $$->value.sctp_prinfo->pr_value = new_integer_expression($6, "%u"); +} +; + +sctp_authinfo +: '{' AUTH_KEYNUMBER '=' INTEGER '}' { + $$ = new_expression(EXPR_SCTP_AUTHINFO); + $$->value.sctp_authinfo = calloc(1, sizeof(struct sctp_authinfo_expr)); + if (!is_valid_u16($4)) { + semantic_error("auth_keynumber out of range"); + } + $$->value.sctp_authinfo->auth_keynumber = new_integer_expression($4, "%hu"); +} +; + +sctp_sendv_spa +: '{' SENDV_FLAGS '=' expression ',' SENDV_SNDINFO '=' expression ',' SENDV_PRINFO '=' expression ',' SENDV_AUTHINFO '=' expression '}' { + $$ = new_expression(EXPR_SCTP_SENDV_SPA); + $$->value.sctp_sendv_spa = calloc(1, sizeof(struct sctp_sendv_spa_expr)); + $$->value.sctp_sendv_spa->sendv_flags = $4; + $$->value.sctp_sendv_spa->sendv_sndinfo = $8; + $$->value.sctp_sendv_spa->sendv_prinfo = $12; + $$->value.sctp_sendv_spa->sendv_authinfo = $16; +} +; + opt_errno : { $$ = NULL; } | WORD note { diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index 10db6470af2447668cfbcbe73ba209b211ebb128..5775c62ccdd2678407b8b70aa9b4200673f243d9 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -122,7 +122,44 @@ static int get_arg_count(struct expression_list *args) { return expression_list_length(args); } - +/* This table maps expression types to human-readable strings */ +struct expression_type_entry { + enum expression_t type; + const char *name; +}; +struct expression_type_entry expression_type_table2[] = { + { EXPR_NONE, "none" }, + { EXPR_NULL, "null" }, + { EXPR_ELLIPSIS, "ellipsis" }, + { EXPR_INTEGER, "integer" }, + { EXPR_WORD, "word" }, + { EXPR_STRING, "string" }, + { EXPR_SOCKET_ADDRESS_IPV4, "sockaddr_in" }, + { EXPR_SOCKET_ADDRESS_IPV6, "sockaddr_in6" }, + { EXPR_LINGER, "linger" }, + { EXPR_BINARY, "binary_expression" }, + { EXPR_LIST, "list" }, + { EXPR_IOVEC, "iovec" }, + { EXPR_MSGHDR, "msghdr" }, + { EXPR_POLLFD, "pollfd" }, + { EXPR_SCTP_RTOINFO, "sctp_rtoinfo"}, + { EXPR_SCTP_INITMSG, "sctp_initmsg"}, + { EXPR_SCTP_ASSOC_VALUE, "sctp_assoc_value"}, + { EXPR_SCTP_SACKINFO, "sctp_sackinfo"}, + { EXPR_SCTP_STATUS, "sctp_status"}, + { EXPR_SCTP_PADDRINFO, "sctp_paddrinfo"}, + { EXPR_SCTP_PEER_ADDR_PARAMS,"sctp_peer_addr_params"}, + { EXPR_SCTP_STREAM_VALUE, "sctp_stream_value"}, + { EXPR_SCTP_ASSOCPARAMS, "sctp_assocparams"}, + { EXPR_SCTP_EVENT, "sctp_event" }, + { EXPR_SCTP_SNDINFO, "sctp_sndinfo" }, + { EXPR_SCTP_SETADAPTATION, "sctp_setadaptation"}, + { EXPR_SCTP_SNDRCVINFO, "sctp_sndrcvinfo" }, + { EXPR_SCTP_PRINFO, "sctp_prinfo" }, + { EXPR_SCTP_AUTHINFO, "sctp_authinfo" }, + { EXPR_SCTP_SENDV_SPA, "sctp_sendv_spa" }, + { NUM_EXPR_TYPES, NULL} +}; /* Verify that the expression list has the expected number of * expressions. Returns STATUS_OK on success; on failure returns * STATUS_ERR and sets error message. @@ -3043,11 +3080,10 @@ static int syscall_sctp_sendmsg(struct state *state, struct syscall_spec *syscal result = sctp_sendmsg(live_fd, msg, (size_t)len, (struct sockaddr *) to_ptr, tolen, ppid, flags, stream_no, timetolive, context); + free(msg); if (end_syscall(state, syscall, CHECK_EXACT, result, error)) { - free(msg); return STATUS_ERR; } - free(msg); return STATUS_OK; #else asprintf(error, "sctp_sendmsg is not supported"); @@ -3294,6 +3330,207 @@ static int syscall_sctp_recvmsg(struct state *state, struct syscall_spec *syscal #endif } +int parse_expression_to_sctp_sndinfo(struct expression *expr, struct sctp_sndinfo *info, char **error) { + if (expr->type == EXPR_SCTP_SNDINFO) { + struct sctp_sndinfo_expr *sndinfo_expr = expr->value.sctp_sndinfo; + info->snd_assoc_id = 0; + if (get_u16(sndinfo_expr->snd_sid, &info->snd_sid, error)) { + return STATUS_ERR; + } + if (get_u16(sndinfo_expr->snd_flags, &info->snd_flags, error)) { + return STATUS_ERR; + } + if (get_u32(sndinfo_expr->snd_ppid, &info->snd_ppid, error)) { + return STATUS_ERR; + } + if (get_u32(sndinfo_expr->snd_context, &info->snd_context, error)) { + return STATUS_ERR; + } + } else { + return STATUS_ERR; + } + return STATUS_OK; +} + +int parse_expression_to_sctp_authinfo(struct expression *expr, struct sctp_authinfo *info, char **error) { + if (expr->type == EXPR_SCTP_AUTHINFO) { + struct sctp_authinfo_expr *auth_expr = expr->value.sctp_authinfo; + if (get_u16(auth_expr->auth_keynumber, &info->auth_keynumber, error)) { + return STATUS_ERR; + } + } else { + return STATUS_ERR; + } + return STATUS_OK; +} + +int parse_expression_to_sctp_prinfo(struct expression *expr, struct sctp_prinfo *info, char **error) { + if (expr->type == EXPR_SCTP_PRINFO) { + struct sctp_prinfo_expr *prinfo_expr = expr->value.sctp_prinfo; + if (get_u16(prinfo_expr->pr_policy, &info->pr_policy, error)) { + return STATUS_ERR; + } + if (get_u32(prinfo_expr->pr_value, &info->pr_value, error)) { + return STATUS_ERR; + } + } else { + return STATUS_ERR; + } + return STATUS_OK; +} + +int parse_expression_to_sctp_sendv_spa(struct expression *expr, struct sctp_sendv_spa *info, char **error) { + if (expr->type == EXPR_SCTP_SENDV_SPA) { + struct sctp_sendv_spa_expr *spa_expr = expr->value.sctp_sendv_spa; + if (get_u32(spa_expr->sendv_flags, &info->sendv_flags, error)) { + return STATUS_ERR; + } + if (spa_expr->sendv_sndinfo->type != EXPR_ELLIPSIS) { + if (parse_expression_to_sctp_sndinfo(spa_expr->sendv_sndinfo, &info->sendv_sndinfo, error)) + return STATUS_ERR; + } + if (spa_expr->sendv_sndinfo->type != EXPR_ELLIPSIS) { + if (parse_expression_to_sctp_prinfo(spa_expr->sendv_prinfo, &info->sendv_prinfo, error)) + return STATUS_ERR; + } + if (spa_expr->sendv_sndinfo->type != EXPR_ELLIPSIS) { + if (parse_expression_to_sctp_authinfo(spa_expr->sendv_authinfo, &info->sendv_authinfo, error)) + return STATUS_ERR; + } + } else { + return STATUS_ERR; + } + return STATUS_OK; +} + +static int syscall_sctp_sendv(struct state *state, struct syscall_spec *syscall, + struct expression_list *args, + char **error) +{ +#if defined(__FreeBSD__) + int script_fd, live_fd, iovcnt, addrcnt, result, flags; + u32 infotype, script_iovec_list_len = 0; + socklen_t infolen; + struct sockaddr *addrs; + void *info; + struct iovec *iov; + struct expression *iovec_expr_list, *iovcnt_expr, *addrs_expr, *addrcnt_expr; + struct expression *info_expr, *infolen_expr, *infotype_expr, *flags_expr; + struct sctp_sndinfo sndinfo; + struct sctp_prinfo prinfo; + struct sctp_authinfo authinfo; + struct sctp_sendv_spa spa; + + if (check_arg_count(args, 9, 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; + iovec_expr_list = get_arg(args, 1, error); + iovec_new(iovec_expr_list, &iov, &script_iovec_list_len, error); + iovcnt_expr = get_arg(args, 2, error); + if (get_s32(iovcnt_expr, &iovcnt, error)) + return STATUS_ERR; + addrs_expr = get_arg(args, 3, error); + if (addrs_expr->type == EXPR_NULL) { + addrs = NULL; + } else if (addrs_expr->type == EXPR_SOCKET_ADDRESS_IPV4 || + addrs_expr->type == EXPR_SOCKET_ADDRESS_IPV6 || + addrs_expr->type == EXPR_ELLIPSIS) { + addrs = malloc(sizeof(struct sockaddr_storage)); + get_sockstorage_arg(addrs_expr, (struct sockaddr_storage *)addrs, live_fd); + } else if (addrs_expr->type == EXPR_LIST) { + struct expression_list *addrs_expr_list = (struct expression_list *)addrs_expr->value.list; + struct expression *expr; + int addrlen = expression_list_length(addrs_expr_list); + int i = 0; + size_t size = 0; + struct sockaddr *addr_ptr; + for (i = 0; i < addrlen; i++) { + expr = get_arg(addrs_expr_list, i, error); + if (expr->type == EXPR_SOCKET_ADDRESS_IPV4) { + size += sizeof(struct sockaddr_in); + } else if (expr->type == EXPR_SOCKET_ADDRESS_IPV6) { + size += sizeof(struct sockaddr_in); + } else { + return STATUS_ERR; + } + } + addrs = malloc(size); + addr_ptr = (struct sockaddr *)addrs; + for(i = 0; i < addrlen; i++) { + expr = get_arg(addrs_expr_list, i, error); + if (expr->type == EXPR_SOCKET_ADDRESS_IPV4) { + size = sizeof(struct sockaddr_in); + memcpy(expr->value.socket_address_ipv4, addr_ptr, size); + addr_ptr = addr_ptr + sizeof(struct sockaddr_in); + } else if (expr->type == EXPR_SOCKET_ADDRESS_IPV6) { + size = sizeof(struct sockaddr_in); + memcpy(expr->value.socket_address_ipv6, addr_ptr, size); + addr_ptr = addr_ptr + sizeof(struct sockaddr_in6); + } + } + } else { + return STATUS_ERR; + } + + addrcnt_expr = get_arg(args, 4, error); + if (get_s32(addrcnt_expr, &addrcnt, error)) + return STATUS_ERR; + info_expr = get_arg(args, 5, error); + if (info_expr->type == EXPR_SCTP_SNDINFO) { + if (parse_expression_to_sctp_sndinfo(info_expr, &sndinfo, error)) + return STATUS_ERR; + info = &sndinfo; + } else if (info_expr->type == EXPR_SCTP_PRINFO) { + info = malloc(sizeof(struct sctp_prinfo)); + if (parse_expression_to_sctp_prinfo(info_expr, &prinfo, error)) + return STATUS_ERR; + info = &prinfo; + } else if (info_expr->type == EXPR_SCTP_AUTHINFO) { + if (parse_expression_to_sctp_authinfo(info_expr, &authinfo, error)) + return STATUS_ERR; + info = &authinfo; + } else if (info_expr->type == EXPR_SCTP_SENDV_SPA) { + if (parse_expression_to_sctp_sendv_spa(info_expr, &spa, error)) + return STATUS_ERR; + info = &spa; + } else if (info_expr->type == EXPR_NULL) { + info = NULL; + } else { + asprintf(error, "Bad input for info"); + return STATUS_ERR; + } + infolen_expr = get_arg(args, 6, error); + if (get_u32(infolen_expr, &infolen, error)) + return STATUS_ERR; + infotype_expr = get_arg(args, 7, error); + if (get_u32(infotype_expr, &infotype, error)) + return STATUS_ERR; + flags_expr = get_arg(args, 8, error); + if (get_s32(flags_expr, &flags, error)) + return STATUS_ERR; + + begin_syscall(state, syscall); + + result = sctp_sendv(live_fd, iov, iovcnt, addrs, addrcnt, info, infolen, infotype, flags); + + if (end_syscall(state, syscall, CHECK_EXACT, result, error)) { + free(addrs); + iovec_free(iov, script_iovec_list_len); + return STATUS_ERR; + } + free(addrs); + iovec_free(iov, script_iovec_list_len); + + return STATUS_OK; +#else + asprintf(error, "sctp_sendv is not supported"); + return STATUS_ERR; +#endif +} + /* A dispatch table with all the system calls that we support... */ struct system_call_entry { const char *name; @@ -3327,6 +3564,7 @@ struct system_call_entry system_call_table[] = { {"poll", syscall_poll}, {"sctp_sendmsg", syscall_sctp_sendmsg}, {"sctp_recvmsg", syscall_sctp_recvmsg}, + {"sctp_sendv", syscall_sctp_sendv}, }; /* Evaluate the system call arguments and invoke the system call. */ diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c index 1b766b8271d94046728e6806b95f304f37dcf008..c5b493ea7814ee168f8cbd7b47c32d1295c44864 100644 --- a/gtests/net/packetdrill/script.c +++ b/gtests/net/packetdrill/script.c @@ -79,6 +79,9 @@ struct expression_type_entry expression_type_table[] = { { EXPR_SCTP_SNDINFO, "sctp_sndinfo" }, { EXPR_SCTP_SETADAPTATION, "sctp_setadaptation"}, { EXPR_SCTP_SNDRCVINFO, "sctp_sndrcvinfo" }, + { EXPR_SCTP_PRINFO, "sctp_prinfo" }, + { EXPR_SCTP_AUTHINFO, "sctp_authinfo" }, + { EXPR_SCTP_SENDV_SPA, "sctp_sendv_spa" }, { NUM_EXPR_TYPES, NULL} }; @@ -378,6 +381,19 @@ void free_expression(struct expression *expression) free_expression(expression->value.sctp_sndrcvinfo->sinfo_tsn); free_expression(expression->value.sctp_sndrcvinfo->sinfo_cumtsn); break; + case EXPR_SCTP_PRINFO: + free_expression(expression->value.sctp_prinfo->pr_policy); + free_expression(expression->value.sctp_prinfo->pr_value); + break; + case EXPR_SCTP_AUTHINFO: + free_expression(expression->value.sctp_authinfo->auth_keynumber); + break; + case EXPR_SCTP_SENDV_SPA: + free_expression(expression->value.sctp_sendv_spa->sendv_flags); + free_expression(expression->value.sctp_sendv_spa->sendv_sndinfo); + free_expression(expression->value.sctp_sendv_spa->sendv_prinfo); + free_expression(expression->value.sctp_sendv_spa->sendv_authinfo); + break; case EXPR_WORD: assert(expression->value.string); free(expression->value.string); @@ -1031,6 +1047,94 @@ static int evaluate_sctp_sndrcvinfo_expression(struct expression *in, return STATUS_OK; } +static int evaluate_sctp_prinfo_expression(struct expression *in, + struct expression *out, + char **error) +{ + struct sctp_prinfo_expr *in_info; + struct sctp_prinfo_expr *out_info; + + assert(in->type == EXPR_SCTP_PRINFO); + assert(in->value.sctp_prinfo); + assert(out->type == EXPR_SCTP_PRINFO); + + out->value.sctp_prinfo = calloc(1, sizeof(struct sctp_prinfo_expr)); + + in_info = in->value.sctp_prinfo; + out_info = out->value.sctp_prinfo; + + if (evaluate(in_info->pr_policy, + &out_info->pr_policy, + error)) + return STATUS_ERR; + if (evaluate(in_info->pr_value, + &out_info->pr_value, + error)) + return STATUS_ERR; + + return STATUS_OK; +} + +static int evaluate_sctp_authinfo_expression(struct expression *in, + struct expression *out, + char **error) +{ + struct sctp_authinfo_expr *in_info; + struct sctp_authinfo_expr *out_info; + + assert(in->type == EXPR_SCTP_AUTHINFO); + assert(in->value.sctp_authinfo); + assert(out->type == EXPR_SCTP_AUTHINFO); + + out->value.sctp_authinfo = calloc(1, sizeof(struct sctp_authinfo_expr)); + + in_info = in->value.sctp_authinfo; + out_info = out->value.sctp_authinfo; + + if (evaluate(in_info->auth_keynumber, + &out_info->auth_keynumber, + error)) + return STATUS_ERR; + + return STATUS_OK; +} + +static int evaluate_sctp_sendv_spa_expression(struct expression *in, + struct expression *out, + char **error) +{ + struct sctp_sendv_spa_expr *in_spa; + struct sctp_sendv_spa_expr *out_spa; + + assert(in->type == EXPR_SCTP_SENDV_SPA); + assert(in->value.sctp_sendv_spa); + assert(out->type == EXPR_SCTP_SENDV_SPA); + + out->value.sctp_sendv_spa = calloc(1, sizeof(struct sctp_sendv_spa_expr)); + + in_spa = in->value.sctp_sendv_spa; + out_spa = out->value.sctp_sendv_spa; + + if (evaluate(in_spa->sendv_flags, + &out_spa->sendv_flags, + error)) + return STATUS_ERR; + if (evaluate(in_spa->sendv_sndinfo, + &out_spa->sendv_sndinfo, + error)) + return STATUS_ERR; + if (evaluate(in_spa->sendv_prinfo, + &out_spa->sendv_prinfo, + error)) + return STATUS_ERR; + if (evaluate(in_spa->sendv_authinfo, + &out_spa->sendv_authinfo, + error)) + return STATUS_ERR; + + return STATUS_OK; +} + static int evaluate(struct expression *in, struct expression **out_ptr, char **error) { @@ -1095,6 +1199,15 @@ static int evaluate(struct expression *in, case EXPR_SCTP_SNDRCVINFO: result = evaluate_sctp_sndrcvinfo_expression(in, out, error); break; + case EXPR_SCTP_PRINFO: + result = evaluate_sctp_prinfo_expression(in, out, error); + break; + case EXPR_SCTP_AUTHINFO: + result = evaluate_sctp_authinfo_expression(in, out, error); + break; + case EXPR_SCTP_SENDV_SPA: + result = evaluate_sctp_sendv_spa_expression(in, out, error); + break; case EXPR_WORD: out->type = EXPR_INTEGER; if (symbol_to_int(in->value.string, diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h index fbcf7fe705e49abb54e73dde4a944c3ec54e8e52..35de4e878fc067eb555bca949431b4b962ba5804 100644 --- a/gtests/net/packetdrill/script.h +++ b/gtests/net/packetdrill/script.h @@ -59,6 +59,9 @@ enum expression_t { EXPR_SCTP_SNDINFO, /* struct sctp_sndinfo for SCTP_DEFAULT_SNDINFO */ EXPR_SCTP_SETADAPTATION, /* struct sctp_setadaptation for SCTP_ADATTATION_LAYER */ EXPR_SCTP_SNDRCVINFO, /* struct sctp_sndrcvinfo for syscall sctp_recvmsg */ + EXPR_SCTP_PRINFO, /* struct sctp_prinfo for syscall sctp_sendv */ + EXPR_SCTP_AUTHINFO, /* struct sctp_authinfo for syscall sctp_sendv */ + EXPR_SCTP_SENDV_SPA, /* struct sctp_sendv_spa for syscall sctp_sendv */ NUM_EXPR_TYPES, }; /* Convert an expression type to a human-readable string */ @@ -91,6 +94,9 @@ struct expression { struct sctp_sndinfo_expr *sctp_sndinfo; struct sctp_setadaptation_expr *sctp_setadaptation; struct sctp_sndrcvinfo_expr *sctp_sndrcvinfo; + struct sctp_prinfo_expr *sctp_prinfo; + struct sctp_authinfo_expr *sctp_authinfo; + struct sctp_sendv_spa_expr *sctp_sendv_spa; } value; const char *format; /* the printf format for printing the value */ }; @@ -137,6 +143,7 @@ struct linger_expr { struct expression *l_onoff; struct expression *l_linger; }; + /* Parse tree for a sctp_rtoinfo struct in a [gs]etsockopt syscall. */ struct sctp_rtoinfo_expr { struct expression *srto_initial; @@ -242,6 +249,25 @@ struct sctp_sndrcvinfo_expr { struct expression *sinfo_cumtsn; }; +/* Parse tree for sctp_prinfo in sctp_sendv syscall. */ +struct sctp_prinfo_expr { + struct expression *pr_policy; + struct expression *pr_value; +}; + +/* Parse tree for sctp_authinfo in sctp_sendv syscall. */ +struct sctp_authinfo_expr { + struct expression *auth_keynumber; +}; + +/* Parse tree for sctp_sendv_spa in sctp_sendv syscall. */ +struct sctp_sendv_spa_expr { + struct expression *sendv_flags; + struct expression *sendv_sndinfo; + struct expression *sendv_prinfo; + struct expression *sendv_authinfo; +}; + /* The errno-related info from strace to summarize a system call error */ struct errno_spec { const char *errno_macro; /* errno symbol (C macro name) */ diff --git a/gtests/net/packetdrill/symbols_freebsd.c b/gtests/net/packetdrill/symbols_freebsd.c index b5454bae547d452a990c933365dc2d7d5bcbc83b..e6e4d75ccfd85fe193e9c7ee836e7a17469f0250 100644 --- a/gtests/net/packetdrill/symbols_freebsd.c +++ b/gtests/net/packetdrill/symbols_freebsd.c @@ -185,6 +185,16 @@ struct int_symbol platform_symbols_table[] = { { SCTP_SENDALL, "SCTP_SENDALL" }, { SCTP_EOR, "SCTP_EOR" }, { SCTP_SACK_IMMEDIATELY, "SCTP_SACK_IMMEDIATELY" }, + { SCTP_PR_SCTP_NONE, "SCTP_PR_SCTP_NONE" }, + { SCTP_PR_SCTP_TTL, "SCTP_PR_SCTP_TTL" }, + { SCTP_SENDV_NOINFO, "SCTP_SENDV_NOINFO" }, + { SCTP_SENDV_SNDINFO, "SCTP_SENDV_SNDINFO" }, + { SCTP_SENDV_PRINFO, "SCTP_SENDV_PRINFO" }, + { SCTP_SENDV_AUTHINFO, "SCTP_SENDV_AUTHINFO" }, + { SCTP_SENDV_SPA, "SCTP_SENDV_SPA" }, + { SCTP_SEND_SNDINFO_VALID, "SCTP_SEND_SNDINFO_VALID" }, + { SCTP_SEND_PRINFO_VALID, "SCTP_SEND_PRINFO_VALID" }, + { SCTP_SEND_AUTHINFO_VALID, "SCTP_SEND_AUTHINFO_VALID" }, /* /usr/include/netinet/tcp.h */ { TCP_NODELAY, "TCP_NODELAY" }, diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_sendv.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_sendv.pkt new file mode 100644 index 0000000000000000000000000000000000000000..f3fa658a53b094295367e4e72d6ccdcb697d8f3c --- /dev/null +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_sendv.pkt @@ -0,0 +1,72 @@ + ++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 bind(3, ..., ...) = 0 +// Check the handshake with an empty(!) cookie ++0.1 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress) ++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 + +//sctp_sendv(int sd, const struct iovec *iov, int iovcnt, struct sockaddr *addrs, int addrcnt, void *info, socklen_t infolen, unsigned int infotype, int flags); + +//test with sctp_sendv_sndinfo +//+0.0 sctp_sendv(3, [{iov_base=..., iov_len=1000}], 1, ..., 1, {snd_sid=1, snd_flags=0, snd_ppid=htonl(1234), snd_context=0}, 16, SCTP_SENDV_SNDINFO, 0) = 1000 +//+0.0 > sctp: DATA[flgs=BE, len=1016, tsn=1, sid=1, ssn=0, ppid=1234] +//+0.0 < sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=1500, gaps=[], dups=[]] + +//test with sctp_sendv_authinfo ++1.0 sctp_sendv(3, [{iov_base=..., iov_len=500}, {iov_base=..., iov_len=500}], 2, ..., 1, {auth_keynumber=123}, 2, SCTP_SENDV_AUTHINFO, 0) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=1, sid=0, ssn=0, ppid=0] ++0.0 < sctp: SACK[flgs=0, cum_tsn=1, a_rwnd=1500, gaps=[], dups=[]] + +//base test ++1.0 sctp_sendv(3, [{iov_base=..., iov_len=1000}], 1, ..., 1, NULL, 0, SCTP_SENDV_NOINFO, 0) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=2, sid=0, ssn=1, ppid=0] ++0.0 < sctp: SACK[flgs=0, cum_tsn=2, a_rwnd=1500, gaps=[], dups=[]] + +//base test ++1.0 sctp_sendv(3, [{iov_base=..., iov_len=1000}], 1, ..., 1, NULL, 0, SCTP_SENDV_NOINFO, 0) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=3, sid=0, ssn=2, ppid=0] ++0.0 < sctp: SACK[flgs=0, cum_tsn=3, a_rwnd=1500, gaps=[], dups=[]] + +//base test ++5.0 sctp_sendv(3, [{iov_base=..., iov_len=1000}], 1, ..., 1, NULL, 0, SCTP_SENDV_NOINFO, 0) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=4, sid=0, ssn=3, ppid=0] ++0.0 < sctp: SACK[flgs=0, cum_tsn=4, a_rwnd=1500, gaps=[], dups=[]] + +//TEST NULL as sockaddr ++5.0 sctp_sendv(3, [{iov_base=..., iov_len=500}], 1, NULL, 0, NULL, 0, SCTP_SENDV_NOINFO, 0) = 500 +* > sctp: DATA[flgs=BE, len=516, tsn=5, sid=0, ssn=4, ppid=0] ++0.0 < sctp: SACK[flgs=0, cum_tsn=5, a_rwnd=1500, gaps=[], dups=[]] + +//TEST with two structs iov ++5.0 sctp_sendv(3, [{iov_base=..., iov_len=500},{iov_base=..., iov_len=500}], 2, ..., 1, NULL, 0, SCTP_SENDV_NOINFO, 0) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=6, sid=0, ssn=5, ppid=0] ++0.0 < sctp: SACK[flgs=0, cum_tsn=6, a_rwnd=1500, gaps=[], dups=[]] + +//test with sctp_sendv_prinfo ++5.0 sctp_sendv(3, [{iov_base=..., iov_len=500}, {iov_base=..., iov_len=500}], 2, ..., 1, {pr_policy=0, pr_value=0}, 8, SCTP_SENDV_PRINFO, 0) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=7, sid=0, ssn=6, ppid=0] ++0.0 < sctp: SACK[flgs=0, cum_tsn=7, a_rwnd=1500, gaps=[], dups=[]] + +//test with all sctp_sendv_spainfo ++5.0 sctp_sendv(3, [{..., 500}, {..., 500}], 2, ..., 1, {sendv_flags=SCTP_SEND_SNDINFO_VALID, +sendv_sndinfo={snd_sid=2, snd_flags=0, snd_ppid=htonl(0), snd_context=0}, +sendv_prinfo={pr_policy=SCTP_PR_SCTP_TTL, pr_value=10}, +sendv_authinfo={auth_keynumber=123}}, 32, SCTP_SENDV_SPA, 0) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=8, sid=2, ssn=0, ppid=0] ++0.0 < sctp: SACK[flgs=0, cum_tsn=8, a_rwnd=1500, gaps=[], dups=[]] + +//test with struct sockaddr ++4.0 sctp_sendv(3, [{..., 1000}], 1, [{sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")}], 1, NULL, 0, SCTP_SENDV_NOINFO, 0) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=9, sid=5, ssn=0, ppid=1234] ++0.0 < sctp: SACK[flgs=0, cum_tsn=9, a_rwnd=1500, gaps=[], dups=[]] + ++0.0 close(3) = 0 ++0.0 > sctp: SHUTDOWN[flgs=0, cum_tsn=0] ++0.1 < sctp: SHUTDOWN_ACK[flgs=0] ++0.0 > sctp: SHUTDOWN_COMPLETE[flgs=0]