diff --git a/gtests/net/packetdrill/lexer.l b/gtests/net/packetdrill/lexer.l index 4cadbae7f5436d244f6479e5fb95c64902e1a442..08ff374e467d804e688f4187bf05bab67d588d58 100644 --- a/gtests/net/packetdrill/lexer.l +++ b/gtests/net/packetdrill/lexer.l @@ -164,7 +164,12 @@ sin_port return SIN_PORT; sin_addr return SIN_ADDR; msg_name return MSG_NAME; msg_iov return MSG_IOV; +msg_control return MSG_CONTROL; msg_flags return MSG_FLAGS; +cmsg_len return CMSG_LEN; +cmsg_level return CMSG_LEVEL; +cmsg_type return CMSG_TYPE; +cmsg_data return CMSG_DATA; fd return FD; events return EVENTS; revents return REVENTS; @@ -259,6 +264,7 @@ snd_sid return SND_SID; snd_flags return SND_FLAGS; snd_ppid return SND_PPID; snd_context return SND_CONTEXT; +snd_assoc_id return SND_ASSOC_ID; ssb_adaptation_ind return SSB_ADAPTATION_IND; sinfo_stream return SINFO_STREAM; sinfo_ssn return SINFO_SSN; @@ -385,6 +391,7 @@ fsn return FSN; cum_tsn return CUM_TSN; gaps return GAPS; dups return DUPS; +adaptation_code_point return ADAPTATION_CODE_POINT; PARAMETER return PARAMETER; HEARTBEAT_INFORMATION return HEARTBEAT_INFORMATION; IPV4_ADDRESS return IPV4_ADDRESS; @@ -394,6 +401,7 @@ UNRECOGNIZED_PARAMETER return UNRECOGNIZED_PARAMETER; COOKIE_PRESERVATIVE return COOKIE_PRESERVATIVE; HOSTNAME_ADDRESS return HOSTNAME_ADDRESS; SUPPORTED_ADDRESS_TYPES return SUPPORTED_ADDRESS_TYPES; +ADAPTATION_INDICATION return ADAPTATION_INDICATION; ECN_CAPABLE return ECN_CAPABLE; SUPPORTED_EXTENSIONS return SUPPORTED_EXTENSIONS; addr return ADDR; diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y index f2d3fc5deb09b0981ccb4f69fdd185ebae8b92f3..357bdc61125699e80bb7017f59f3e0bfc5fb2faa 100644 --- a/gtests/net/packetdrill/parser.y +++ b/gtests/net/packetdrill/parser.y @@ -494,7 +494,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, */ %token ELLIPSIS %token <reserved> SA_FAMILY SIN_PORT SIN_ADDR _HTONS_ _HTONL_ INET_ADDR -%token <reserved> MSG_NAME MSG_IOV MSG_FLAGS +%token <reserved> MSG_NAME MSG_IOV MSG_FLAGS MSG_CONTROL CMSG_LEN CMSG_LEVEL CMSG_TYPE CMSG_DATA %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 @@ -522,7 +522,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> PARAMETER HEARTBEAT_INFORMATION IPV4_ADDRESS IPV6_ADDRESS %token <reserved> STATE_COOKIE UNRECOGNIZED_PARAMETER COOKIE_PRESERVATIVE %token <reserved> HOSTNAME_ADDRESS SUPPORTED_ADDRESS_TYPES ECN_CAPABLE -%token <reserved> SUPPORTED_EXTENSIONS +%token <reserved> SUPPORTED_EXTENSIONS ADAPTATION_CODE_POINT ADAPTATION_INDICATION %token <reserved> ADDR INCR TYPES PARAMS %token <reserved> IPV4_TYPE IPV6_TYPE HOSTNAME_TYPE %token <reserved> CAUSE @@ -538,7 +538,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %token <reserved> SPP_FLAGS SPP_IPV6_FLOWLABEL_ SPP_DSCP_ %token <reserved> SASOC_ASOCMAXRXT SASOC_NUMBER_PEER_DESTINATIONS SASOC_PEER_RWND %token <reserved> SASOC_LOCAL_RWND SASOC_COOKIE_LIFE SE_TYPE SE_ON -%token <reserved> SND_SID SND_FLAGS SND_PPID SND_CONTEXT SSB_ADAPTATION_IND +%token <reserved> SND_SID SND_FLAGS SND_PPID SND_CONTEXT SND_ASSOC_ID SSB_ADAPTATION_IND %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 @@ -598,7 +598,8 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <expression_list> expression_list function_arguments %type <expression> expression binary_expression array %type <expression> decimal_integer hex_integer data -%type <expression> inaddr sockaddr msghdr iovec pollfd opt_revents +%type <expression> inaddr sockaddr msghdr cmsghdr cmsg_level cmsg_type cmsg_data +%type <expression> iovec pollfd opt_revents %type <expression> linger l_onoff l_linger %type <expression> sctp_status sstat_state sstat_rwnd sstat_unackdata sstat_penddata %type <expression> sstat_instrms sstat_outstrms sstat_fragmentation_point sstat_primary @@ -611,7 +612,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <expression> spinfo_address spinfo_state spinfo_cwnd spinfo_srtt spinfo_rto spinfo_mtu %type <expression> sasoc_asocmaxrxt sasoc_number_peer_destinations sasoc_peer_rwnd %type <expression> sasoc_local_rwnd sasoc_cookie_life sctp_assocparams -%type <expression> sctp_sndinfo snd_sid snd_flags snd_ppid snd_context +%type <expression> sctp_sndinfo snd_sid snd_flags snd_ppid snd_assoc_id snd_context %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 @@ -661,6 +662,7 @@ static struct tcp_option *new_tcp_fast_open_option(const char *cookie_string, %type <parameter_list_item> sctp_supported_address_types_parameter_spec %type <parameter_list_item> sctp_ecn_capable_parameter_spec %type <parameter_list_item> sctp_supported_extensions_parameter_spec +%type <parameter_list_item> sctp_adaptation_indication_parameter_spec %type <parameter_list_item> sctp_pad_parameter_spec %type <cause_list> opt_cause_list_spec sctp_cause_list_spec %type <cause_list_item> sctp_cause_spec @@ -1599,6 +1601,7 @@ sctp_parameter_spec | sctp_supported_address_types_parameter_spec { $$ = $1; } | sctp_ecn_capable_parameter_spec { $$ = $1; } | sctp_supported_extensions_parameter_spec { $$ = $1; } +| sctp_adaptation_indication_parameter_spec { $$ = $1; } | sctp_pad_parameter_spec { $$ = $1; } ; @@ -1767,6 +1770,13 @@ chunk_types_list } ; +sctp_adaptation_indication_parameter_spec +: ADAPTATION_INDICATION '[' ADAPTATION_CODE_POINT '=' INTEGER ']' { + if (!is_valid_u32($5)) + semantic_error("adaptation_indication_code ot of range"); + $$ = sctp_adaptation_indication_parameter_new($5); +}; + sctp_supported_extensions_parameter_spec : SUPPORTED_EXTENSIONS '[' TYPES '=' ELLIPSIS ']' { $$ = sctp_supported_extensions_parameter_new(NULL); @@ -2449,6 +2459,9 @@ expression | msghdr { $$ = $1; } +| cmsghdr { + $$ = $1; +} | iovec { $$ = $1; } @@ -2621,6 +2634,7 @@ data msghdr : '{' MSG_NAME '(' ELLIPSIS ')' '=' ELLIPSIS ',' MSG_IOV '(' decimal_integer ')' '=' array ',' + MSG_CONTROL '('decimal_integer ')' '=' array ',' MSG_FLAGS '=' expression '}' { struct msghdr_expr *msg_expr = calloc(1, sizeof(struct msghdr_expr)); $$ = new_expression(EXPR_MSGHDR); @@ -2629,11 +2643,60 @@ msghdr msg_expr->msg_namelen = new_expression(EXPR_ELLIPSIS); msg_expr->msg_iov = $14; msg_expr->msg_iovlen = $11; - msg_expr->msg_flags = $18; - /* TODO(ncardwell): msg_control, msg_controllen */ + msg_expr->msg_controllen= $18; + msg_expr->msg_control = $21; + msg_expr->msg_flags = $25; } ; +cmsg_level +: CMSG_LEVEL '=' INTEGER { + if (!is_valid_s32($3)) { + semantic_error("cmsg_level out of range"); + } + $$ = new_integer_expression($3, "%d"); +} +| CMSG_LEVEL '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| CMSG_LEVEL '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +cmsg_type +: CMSG_TYPE '=' INTEGER { + if (!is_valid_s32($3)) { + semantic_error("cmsg_level out of range"); + } + $$ = new_integer_expression($3, "%d"); +} +| CMSG_TYPE '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| CMSG_TYPE '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + +cmsg_data +: CMSG_DATA '=' sctp_sndinfo { $$ = $3; } +| CMSG_DATA '=' sctp_prinfo { $$ = $3; } +| CMSG_DATA '=' sctp_authinfo { $$ = $3; } +| CMSG_DATA '=' sockaddr { $$ = $3; } +; + +cmsghdr +: '{' CMSG_LEN '=' INTEGER ',' cmsg_level ',' cmsg_type ',' cmsg_data '}' { + $$ = new_expression(EXPR_CMSGHDR); + $$->value.cmsghdr = calloc(1, sizeof(struct cmsghdr_expr)); + if (!is_valid_s32($4)) { + semantic_error("cmsg_len out of range"); + } + $$->value.cmsghdr->cmsg_len = new_integer_expression($4, "%u"); + $$->value.cmsghdr->cmsg_level = $6; + $$->value.cmsghdr->cmsg_type = $8; + $$->value.cmsghdr->cmsg_data = $10; +}; + iovec : '{' data ',' decimal_integer '}' { struct iovec_expr *iov_expr = calloc(1, sizeof(struct iovec_expr)); @@ -3251,14 +3314,30 @@ snd_context | SND_CONTEXT '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } ; +snd_assoc_id +: SND_ASSOC_ID '=' INTEGER { + if (!is_valid_u32($3)) { + semantic_error("snd_assoc_id out of range"); + } + $$ = new_integer_expression($3, "%u"); +} +| SND_ASSOC_ID '=' WORD { + $$ = new_expression(EXPR_WORD); + $$->value.string = $3; +} +| SND_ASSOC_ID '=' ELLIPSIS { $$ = new_expression(EXPR_ELLIPSIS); } +; + + sctp_sndinfo -: '{' snd_sid ',' snd_flags ',' snd_ppid ',' snd_context '}' { +: '{' snd_sid ',' snd_flags ',' snd_ppid ',' snd_context ',' snd_assoc_id'}' { $$ = new_expression(EXPR_SCTP_SNDINFO); $$->value.sctp_sndinfo = calloc(1, sizeof(struct sctp_sndinfo_expr)); $$->value.sctp_sndinfo->snd_sid = $2; $$->value.sctp_sndinfo->snd_flags = $4; $$->value.sctp_sndinfo->snd_ppid = $6; $$->value.sctp_sndinfo->snd_context = $8; + $$->value.sctp_sndinfo->snd_assoc_id = $10; } ; diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c index 5c5c426c9aeb78103848f3fbf5794ffce03dcdfd..81db1ed1e57fd184ffb639809e31281694238f50 100644 --- a/gtests/net/packetdrill/run_system_call.c +++ b/gtests/net/packetdrill/run_system_call.c @@ -59,7 +59,18 @@ struct sctp_tlv { static int check_sctp_notification(struct iovec *iov, struct expression *iovec_expr, char **error); #endif - +#if defined(__FreeBSD__) +static int parse_expression_to_sctp_sndinfo(struct expression *expr, struct sctp_sndinfo *info, + char **error); +static int parse_expression_to_sctp_prinfo(struct expression *expr, struct sctp_prinfo *info, + char **error); +static int parse_expression_to_sctp_authinfo(struct expression *expr, struct sctp_authinfo *info, + char **error); +#endif +#if defined(SCTP_DEFAULT_SNDINFO) || defined(SCTP_SNDINFO) +static int check_sctp_sndinfo(struct sctp_sndinfo_expr *expr, struct sctp_sndinfo *sctp_sndinfo, + char **error); +#endif /* Provide a wrapper for the Linux gettid() system call (glibc does not). */ static pid_t gettid(void) @@ -420,6 +431,69 @@ static int get_sockstorage_arg(struct expression *arg, struct sockaddr_storage * } #endif +static int check_sockaddr(struct expression *sockaddr_expr, struct sockaddr *live_addr, char **error) { + + if (sockaddr_expr->type != EXPR_ELLIPSIS) { + struct sockaddr *script_addr; + if (sockaddr_expr->type == EXPR_SOCKET_ADDRESS_IPV4) { + script_addr = (struct sockaddr*)sockaddr_expr->value.socket_address_ipv4; + } else if (sockaddr_expr->type == EXPR_SOCKET_ADDRESS_IPV6) { + script_addr = (struct sockaddr*)sockaddr_expr->value.socket_address_ipv6; + } else { + asprintf(error, "Bad type for sockaddr"); + return STATUS_ERR; + } + if (script_addr->sa_family != live_addr->sa_family) { + asprintf(error, "sockaddr sa_family expected: %d actual: %d", + script_addr->sa_family, live_addr->sa_family); + return STATUS_ERR; + } + switch(script_addr->sa_family) { + case AF_INET: + { + struct sockaddr_in *script_sockaddr = (struct sockaddr_in*)script_addr; + struct sockaddr_in *live_sockaddr = (struct sockaddr_in*)live_addr; + if (live_sockaddr->sin_port != script_sockaddr->sin_port) { + asprintf(error, "sockaddr_in from.sinport. expected: %d actual %d", + ntohs(script_sockaddr->sin_port), ntohs(live_sockaddr->sin_port)); + return STATUS_ERR; + } + if (live_sockaddr->sin_addr.s_addr != script_sockaddr->sin_addr.s_addr) { + int len = strnlen(inet_ntoa(script_sockaddr->sin_addr), 16); + char *expected_addr = malloc(sizeof(char) * len); + memcpy(expected_addr, inet_ntoa(script_sockaddr->sin_addr), len); + asprintf(error, "sockaddr_in from.sin_addr. expected: %s actual %s", + expected_addr, inet_ntoa(live_sockaddr->sin_addr)); + free(expected_addr); + return STATUS_ERR; + } + } + break; + case AF_INET6: + { + struct sockaddr_in6 *script_sockaddr = (struct sockaddr_in6*)script_addr; + struct sockaddr_in6 *live_sockaddr = (struct sockaddr_in6*)live_addr; + if (live_sockaddr->sin6_port != script_sockaddr->sin6_port) { + asprintf(error, "sockaddr_in6 from.sinport. expected: %d actual %d", + ntohs(script_sockaddr->sin6_port), ntohs(live_sockaddr->sin6_port)); + return STATUS_ERR; + } + if (live_sockaddr->sin6_addr.s6_addr != script_sockaddr->sin6_addr.s6_addr) { + char expected_addr[INET6_ADDRSTRLEN]; + char live_addr[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &script_sockaddr->sin6_addr, expected_addr, INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, &live_sockaddr->sin6_addr, live_addr, INET6_ADDRSTRLEN); + asprintf(error, "sockaddr_in6 from.sin6_addr. expected: %s actual %s", + expected_addr, live_addr); + return STATUS_ERR; + } + } + break; + } + } + return STATUS_OK; +} + #if defined(__FreeBSD__) || defined(linux) int check_u8_expr(struct expression *expr, u8 value, char *val_name, char **error) { if (expr->type != EXPR_ELLIPSIS) { @@ -470,7 +544,7 @@ int check_s32_expr(struct expression *expr, s16 value, char *val_name, char **er } #if defined(__FreeBSD__) || defined(linux) -int check_u32_expr(struct expression *expr, u16 value, char *val_name, char **error) { +int check_u32_expr(struct expression *expr, u32 value, char *val_name, char **error) { if (expr->type != EXPR_ELLIPSIS) { u32 script_val; @@ -601,6 +675,123 @@ error_out: return status; } +/* Allocate and fill in an +cmsghdr described by the given expression. + * Return STATUS_OK if the expression is a valid cmsghdr. Otherwise + * fill in the error with a human-readable error message and return + * STATUS_ERR. + */ +static int cmsg_new(struct expression *expression, + void **cmsg_ptr, size_t *cmsg_len_ptr, char **error) +{ + struct expression_list *list; + int list_len = 0, i = 0; + size_t cmsg_size = 0; + struct cmsghdr *cmsg; + + if (check_type(expression, EXPR_LIST, error)) + return STATUS_ERR; + list = expression->value.list; + list_len = expression_list_length(list); + //calc size of cmsg in list + if (list_len == 0){ + cmsg_ptr = NULL; + return STATUS_OK; + } + for (i = 0; i < list_len; i++) { + struct expression *cmsg_expr; + cmsg_expr = get_arg(list, i, error); + switch (cmsg_expr->value.cmsghdr->cmsg_data->type) { + case EXPR_SCTP_SNDINFO: + cmsg_size += CMSG_SPACE(sizeof(struct sctp_sndinfo)); + break; + case EXPR_SCTP_PRINFO: + cmsg_size += CMSG_SPACE(sizeof(struct sctp_prinfo)); + break; + case EXPR_SCTP_AUTHINFO: + cmsg_size += CMSG_SPACE(sizeof(struct sctp_authinfo)); + break; + case EXPR_SOCKET_ADDRESS_IPV4: + cmsg_size += CMSG_SPACE(sizeof(struct in_addr)); + break; + case EXPR_SOCKET_ADDRESS_IPV6: + cmsg_size += CMSG_SPACE(sizeof(struct in6_addr)); + break; + default: + asprintf(error,"cmsg %d type not valid", i); + return STATUS_ERR; + } + } + + *cmsg_len_ptr = cmsg_size; + cmsg = calloc(1, cmsg_size); + *cmsg_ptr = (void *)cmsg; + + for (i = 0; i < list_len; i++) { + struct expression *expr; + struct cmsghdr_expr *cmsg_expr; + + expr = get_arg(list, i, error); + if(check_type(expr, EXPR_CMSGHDR, error)) + goto error_out; + cmsg_expr = expr->value.cmsghdr; + if (get_u32(cmsg_expr->cmsg_len, &cmsg->cmsg_len, error)) + goto error_out; + if (get_s32(cmsg_expr->cmsg_level, &cmsg->cmsg_level, error)) + goto error_out; + if (get_s32(cmsg_expr->cmsg_type, &cmsg->cmsg_type, error)) + goto error_out; + + switch(cmsg_expr->cmsg_data->type) { + case EXPR_SCTP_SNDINFO: { + struct sctp_sndinfo info; + if (parse_expression_to_sctp_sndinfo(cmsg_expr->cmsg_data, &info, error)) { + goto error_out; + } + memcpy(CMSG_DATA(cmsg), &info, sizeof(struct sctp_sndinfo)); + cmsg = (struct cmsghdr *) ((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_sndinfo))); + break; + } + case EXPR_SCTP_PRINFO: { + struct sctp_prinfo info; + if (parse_expression_to_sctp_prinfo(cmsg_expr->cmsg_data, &info, error)) { + goto error_out; + } + memcpy(CMSG_DATA(cmsg), &info, sizeof(struct sctp_prinfo)); + cmsg = (struct cmsghdr *) ((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_prinfo))); + break; + } + case EXPR_SCTP_AUTHINFO: { + struct sctp_authinfo info; + if (parse_expression_to_sctp_authinfo(cmsg_expr->cmsg_data, &info, error)) { + goto error_out; + } + memcpy(CMSG_DATA(cmsg), &info, sizeof(struct sctp_authinfo)); + cmsg = (struct cmsghdr *) ((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_authinfo))); + break; + } + case EXPR_SOCKET_ADDRESS_IPV4: + memcpy(CMSG_DATA(cmsg), &cmsg_expr->cmsg_data->value.socket_address_ipv4->sin_addr, sizeof(struct in_addr)); + cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in_addr))); + break; + case EXPR_SOCKET_ADDRESS_IPV6: + memcpy(CMSG_DATA(cmsg), &cmsg_expr->cmsg_data->value.socket_address_ipv6->sin6_addr, sizeof(struct in6_addr)); + cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in6_addr))); + break; + default: + asprintf(error,"cmsg.cmsg_data %d type not valid", i); + goto error_out; + } + } + + return STATUS_OK; +error_out: + free(*cmsg_ptr); + *cmsg_ptr = NULL; + *cmsg_len_ptr = 0; + return STATUS_ERR; +} + /* Free all the space used by the given msghdr. */ static void msghdr_free(struct msghdr *msg, size_t iov_len) { @@ -622,6 +813,7 @@ static int msghdr_new(struct expression *expression, struct msghdr_expr *msg_expr; /* input expression from script */ socklen_t name_len = sizeof(struct sockaddr_storage); struct msghdr *msg = NULL; /* live output */ + size_t cmsg_len = 0; if (check_type(expression, EXPR_MSGHDR, error)) goto error_out; @@ -659,14 +851,29 @@ static int msghdr_new(struct expression *expression, goto error_out; } + if (msg_expr->msg_control != NULL) { + if (cmsg_new(msg_expr->msg_control, &msg->msg_control, &cmsg_len, error)) + goto error_out; + } + + if (msg_expr->msg_controllen != NULL) { + if (get_u32(msg_expr->msg_controllen, &msg->msg_controllen, error)) + goto error_out; + } + + if (msg->msg_controllen != cmsg_len) { + asprintf(error, + "msg_controllen %u does not match %u size of cmsghdr array", + msg->msg_controllen, cmsg_len); + goto error_out; + } + if (msg_expr->msg_flags != NULL) { if (get_s32(msg_expr->msg_flags, &s32_val, error)) goto error_out; msg->msg_flags = s32_val; } - /* TODO(ncardwell): msg_control, msg_controllen */ - status = STATUS_OK; error_out: @@ -1679,6 +1886,105 @@ static int syscall_sendto(struct state *state, struct syscall_spec *syscall, return status; } +static int check_cmsghdr(struct expression *expr_list, struct msghdr *msg, char **error) { + struct expression_list *list; + struct expression *cmsg_expr; + struct cmsghdr *cmsg_ptr; + int cnt=0; + + assert(expr_list->type == EXPR_LIST); + + list = expr_list->value.list; + for (cmsg_ptr = CMSG_FIRSTHDR(msg); cmsg_ptr != NULL; cmsg_ptr = CMSG_NXTHDR(msg, cmsg_ptr)) { + cmsg_expr = get_arg(list, cnt, error); + if (cmsg_expr->type != EXPR_ELLIPSIS) { + struct cmsghdr_expr *expr; + expr = cmsg_expr->value.cmsghdr; + if (check_u32_expr(expr->cmsg_len, cmsg_ptr->cmsg_len, + "cmsghdr.cmsg_len", error)) + return STATUS_ERR; + if (check_s32_expr(expr->cmsg_level, cmsg_ptr->cmsg_level, + "cmsghdr.cmsg_level", error)) + return STATUS_ERR; + if (check_s32_expr(expr->cmsg_type, cmsg_ptr->cmsg_type, + "cmsghdr.cmsg_type", error)) + return STATUS_ERR; + + if (expr->cmsg_data->type == EXPR_ELLIPSIS) { + continue; + } + switch(cmsg_ptr->cmsg_type) { +#ifdef SCTP_SNDINFO + case SCTP_SNDINFO: + if (check_sctp_sndinfo(expr->cmsg_data->value.sctp_sndinfo, + (struct sctp_sndinfo *) CMSG_DATA(cmsg_ptr), + error)) { + return STATUS_ERR; + } + break; +#endif +#ifdef SCTP_PRINFO + case SCTP_PRINFO: + if (check_u16_expr(expr->cmsg_data->value.sctp_prinfo->pr_policy, + ((struct sctp_prinfo *)CMSG_DATA(cmsg_ptr))->pr_policy, + "prinfo.pr_policy", error)) + return STATUS_ERR; + if (check_u32_expr(expr->cmsg_data->value.sctp_prinfo->pr_value, + ((struct sctp_prinfo *)CMSG_DATA(cmsg_ptr))->pr_value, + "prinfo.pr_value", error)) + return STATUS_ERR; + break; +#endif +#ifdef SCTP_AUTHINFO + case SCTP_AUTHINFO: + if (check_u16_expr(expr->cmsg_data->value.sctp_authinfo->auth_keynumber, + ((struct sctp_authinfo *)CMSG_DATA(cmsg_ptr))->auth_keynumber, + "authinfo.auth_keynumber", error)) + return STATUS_ERR; + break; +#endif +#ifdef SCTP_DSTADDRV4 + case SCTP_DSTADDRV4: + if (expr->cmsg_data->type != EXPR_ELLIPSIS) { + struct sockaddr_in *addr = expr->cmsg_data->value.socket_address_ipv4; + struct in_addr *cmsg_addr = (struct in_addr *) CMSG_DATA(cmsg_ptr); + if (addr->sin_addr.s_addr != cmsg_addr->s_addr) { + asprintf(error, "cmsg_data for SCTP_DSTADDRV4: expected: %s actual: %s", + inet_ntoa(addr->sin_addr), + inet_ntoa(*cmsg_addr)); + return STATUS_ERR; + } + } + break; +#endif +#ifdef SCTP_DSTADDRV6 + case SCTP_DSTADDRV6: + if (expr->cmsg_data->type != EXPR_ELLIPSIS) { + struct sockaddr_in6 *addr = expr->cmsg_data->value.socket_address_ipv6; + struct in6_addr *cmsg_addr = (struct in6_addr *) CMSG_DATA(cmsg_ptr); + if (memcmp(&addr->sin6_addr, cmsg_addr, sizeof(struct in6_addr))) { + char expected_addr[INET6_ADDRSTRLEN]; + char live_addr[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &addr->sin6_addr, expected_addr, INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, cmsg_addr, live_addr, INET6_ADDRSTRLEN); + asprintf(error, "sockaddr_in6 from.sin6_addr. expected: %s actual %s", + expected_addr, live_addr); + return STATUS_ERR; + } + + } + break; +#endif + default: + asprintf(error, "can't check cmsg type"); + return STATUS_ERR; + } + } + cnt++; + } + return STATUS_OK; +} + static int syscall_sendmsg(struct state *state, struct syscall_spec *syscall, struct expression_list *args, char **error) { @@ -1714,10 +2020,13 @@ static int syscall_sendmsg(struct state *state, struct syscall_spec *syscall, } begin_syscall(state, syscall); - + result = sendmsg(live_fd, msg, flags); - status = end_syscall(state, syscall, CHECK_EXACT, result, error); + if (end_syscall(state, syscall, CHECK_EXACT, result, error)) + goto error_out; + + status = check_cmsghdr(msg_expression->value.msghdr->msg_control, msg, error); error_out: msghdr_free(msg, iov_len); @@ -2143,7 +2452,8 @@ static int check_sctp_event_subscribe(struct sctp_event_subscribe_expr *expr, return STATUS_OK; } #endif -#ifdef SCTP_DEFAULT_SNDINFO + +#if defined(SCTP_DEFAULT_SNDINFO) || defined(SCTP_SNDINFO) static int check_sctp_sndinfo(struct sctp_sndinfo_expr *expr, struct sctp_sndinfo *sctp_sndinfo, char **error) @@ -2169,6 +2479,9 @@ static int check_sctp_sndinfo(struct sctp_sndinfo_expr *expr, if (check_u32_expr(expr->snd_context, sctp_sndinfo->snd_context, "sctp_sndinfo.snd_context", error)) return STATUS_ERR; + if (check_u32_expr(expr->snd_assoc_id, sctp_sndinfo->snd_assoc_id, + "sctp_sndinfo.snd_assoc_id", error)) + return STATUS_ERR; return STATUS_OK; } @@ -2330,7 +2643,12 @@ static int syscall_getsockopt(struct state *state, struct syscall_spec *syscall, case EXPR_SCTP_SNDINFO: live_optval = malloc(sizeof(struct sctp_sndinfo)); live_optlen = sizeof(struct sctp_sndinfo); - ((struct sctp_sndinfo *)live_optval)->snd_assoc_id = 0; + if (get_u32(val_expression->value.sctp_sndinfo->snd_assoc_id, + &((struct sctp_sndinfo *)live_optval)->snd_assoc_id, + error)) { + free(live_optval); + return STATUS_ERR; + } break; #endif #ifdef SCTP_ADAPTATION_LAYER @@ -2714,7 +3032,6 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, #endif #ifdef SCTP_DEFAULT_SNDINFO case EXPR_SCTP_SNDINFO: - sndinfo.snd_assoc_id = 0; if (get_u16(val_expression->value.sctp_sndinfo->snd_sid, &sndinfo.snd_sid, error)) { return STATUS_ERR; @@ -2731,6 +3048,10 @@ static int syscall_setsockopt(struct state *state, struct syscall_spec *syscall, &sndinfo.snd_context, error)) { return STATUS_ERR; } + if (get_u32(val_expression->value.sctp_sndinfo->snd_assoc_id, + &sndinfo.snd_assoc_id, error)) { + return STATUS_ERR; + } optval = &sndinfo; break; #endif @@ -2981,68 +3302,6 @@ static int check_sctp_sndrcvinfo(struct sctp_sndrcvinfo_expr *expr, return STATUS_OK; } -static int check_sockaddr(struct expression *sockaddr_expr, struct sockaddr *live_addr, char **error) { - - if (sockaddr_expr->type != EXPR_ELLIPSIS) { - struct sockaddr *script_addr; - if (sockaddr_expr->type == EXPR_SOCKET_ADDRESS_IPV4) { - script_addr = (struct sockaddr*)sockaddr_expr->value.socket_address_ipv4; - } else if (sockaddr_expr->type == EXPR_SOCKET_ADDRESS_IPV6) { - script_addr = (struct sockaddr*)sockaddr_expr->value.socket_address_ipv6; - } else { - asprintf(error, "Bad type for sockaddr"); - return STATUS_ERR; - } - if (script_addr->sa_family != live_addr->sa_family) { - asprintf(error, "sockaddr sa_family expected: %d actual: %d", - script_addr->sa_family, live_addr->sa_family); - return STATUS_ERR; - } - switch(script_addr->sa_family) { - case AF_INET: - { - struct sockaddr_in *script_sockaddr = (struct sockaddr_in*)script_addr; - struct sockaddr_in *live_sockaddr = (struct sockaddr_in*)live_addr; - if (live_sockaddr->sin_port != script_sockaddr->sin_port) { - asprintf(error, "sockaddr_in from.sinport. expected: %d actual %d", - ntohs(script_sockaddr->sin_port), ntohs(live_sockaddr->sin_port)); - return STATUS_ERR; - } - if (live_sockaddr->sin_addr.s_addr != script_sockaddr->sin_addr.s_addr) { - int len = strnlen(inet_ntoa(script_sockaddr->sin_addr), 16); - char *expected_addr = malloc(sizeof(char) * len); - memcpy(expected_addr, inet_ntoa(script_sockaddr->sin_addr), len); - asprintf(error, "sockaddr_in from.sin_addr. expected: %s actual %s", - expected_addr, inet_ntoa(live_sockaddr->sin_addr)); - free(expected_addr); - return STATUS_ERR; - } - } - break; - case AF_INET6: - { - struct sockaddr_in6 *script_sockaddr = (struct sockaddr_in6*)script_addr; - struct sockaddr_in6 *live_sockaddr = (struct sockaddr_in6*)live_addr; - if (live_sockaddr->sin6_port != script_sockaddr->sin6_port) { - asprintf(error, "sockaddr_in6 from.sinport. expected: %d actual %d", - ntohs(script_sockaddr->sin6_port), ntohs(live_sockaddr->sin6_port)); - return STATUS_ERR; - } - if (live_sockaddr->sin6_addr.s6_addr != script_sockaddr->sin6_addr.s6_addr) { - char expected_addr[INET6_ADDRSTRLEN]; - char live_addr[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, &script_sockaddr->sin6_addr, expected_addr, INET6_ADDRSTRLEN); - inet_ntop(AF_INET6, &live_sockaddr->sin6_addr, live_addr, INET6_ADDRSTRLEN); - asprintf(error, "sockaddr_in6 from.sin6_addr. expected: %s actual %s", - expected_addr, live_addr); - return STATUS_ERR; - } - } - break; - } - } - return STATUS_OK; -} #endif static int syscall_sctp_recvmsg(struct state *state, struct syscall_spec *syscall, @@ -3127,7 +3386,6 @@ static int syscall_sctp_recvmsg(struct state *state, struct syscall_spec *syscal static 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; } @@ -3140,6 +3398,9 @@ static int parse_expression_to_sctp_sndinfo(struct expression *expr, struct sctp if (get_u32(sndinfo_expr->snd_context, &info->snd_context, error)) { return STATUS_ERR; } + if (get_u32(sndinfo_expr->snd_assoc_id, &info->snd_assoc_id, error)) { + return STATUS_ERR; + } } else { return STATUS_ERR; } @@ -3792,7 +4053,6 @@ static int check_sctp_notification(struct iovec *iov, return STATUS_ERR; break; case EXPR_ELLIPSIS: - printf("check Ellipsis\n"); break; default: asprintf(error, "Bad type for iov_base. Can't check type %s", diff --git a/gtests/net/packetdrill/script.c b/gtests/net/packetdrill/script.c index 336374356ad389bd00034b6d481c417767d348d8..58604198be75911c62d284e264349820ee1ca0da 100644 --- a/gtests/net/packetdrill/script.c +++ b/gtests/net/packetdrill/script.c @@ -65,6 +65,7 @@ struct expression_type_entry expression_type_table[] = { { EXPR_LIST, "list" }, { EXPR_IOVEC, "iovec" }, { EXPR_MSGHDR, "msghdr" }, + { EXPR_CMSGHDR, "cmsghdr"}, { EXPR_POLLFD, "pollfd" }, { EXPR_SCTP_RTOINFO, "sctp_rtoinfo"}, { EXPR_SCTP_INITMSG, "sctp_initmsg"}, @@ -394,6 +395,7 @@ void free_expression(struct expression *expression) free_expression(expression->value.sctp_sndinfo->snd_flags); free_expression(expression->value.sctp_sndinfo->snd_ppid); free_expression(expression->value.sctp_sndinfo->snd_context); + free_expression(expression->value.sctp_sndinfo->snd_assoc_id); break; case EXPR_SCTP_SETADAPTATION: free_expression(expression->value.sctp_setadaptation->ssb_adaptation_ind); @@ -563,8 +565,16 @@ void free_expression(struct expression *expression) free_expression(expression->value.msghdr->msg_namelen); free_expression(expression->value.msghdr->msg_iov); free_expression(expression->value.msghdr->msg_iovlen); + free_expression(expression->value.msghdr->msg_control); + free_expression(expression->value.msghdr->msg_controllen); free_expression(expression->value.msghdr->msg_flags); break; + case EXPR_CMSGHDR: + free_expression(expression->value.cmsghdr->cmsg_len); + free_expression(expression->value.cmsghdr->cmsg_level); + free_expression(expression->value.cmsghdr->cmsg_type); + free_expression(expression->value.cmsghdr->cmsg_data); + break; case EXPR_POLLFD: assert(expression->value.pollfd); free_expression(expression->value.pollfd->fd); @@ -656,6 +666,33 @@ static int evaluate_iovec_expression(struct expression *in, return STATUS_OK; } +static int evaluate_cmsghdr_expression(struct expression *in, + struct expression *out, char **error) +{ + struct cmsghdr_expr *in_cmsg; + struct cmsghdr_expr *out_cmsg; + + assert(in->type == EXPR_CMSGHDR); + assert(in->value.msghdr); + assert(out->type == EXPR_CMSGHDR); + + out->value.cmsghdr = calloc(1, sizeof(struct cmsghdr_expr)); + + in_cmsg = in->value.cmsghdr; + out_cmsg = out->value.cmsghdr; + + if (evaluate(in_cmsg->cmsg_len, &out_cmsg->cmsg_len, error)) + return STATUS_ERR; + if (evaluate(in_cmsg->cmsg_level, &out_cmsg->cmsg_level, error)) + return STATUS_ERR; + if (evaluate(in_cmsg->cmsg_type, &out_cmsg->cmsg_type, error)) + return STATUS_ERR; + if (evaluate(in_cmsg->cmsg_data, &out_cmsg->cmsg_data, error)) + return STATUS_ERR; + + return STATUS_OK; +} + static int evaluate_msghdr_expression(struct expression *in, struct expression *out, char **error) { @@ -679,6 +716,10 @@ static int evaluate_msghdr_expression(struct expression *in, return STATUS_ERR; if (evaluate(in_msg->msg_iovlen, &out_msg->msg_iovlen, error)) return STATUS_ERR; + if (evaluate(in_msg->msg_control, &out_msg->msg_control, error)) + return STATUS_ERR; + if (evaluate(in_msg->msg_controllen, &out_msg->msg_controllen,error)) + return STATUS_ERR; if (evaluate(in_msg->msg_flags, &out_msg->msg_flags, error)) return STATUS_ERR; @@ -1159,6 +1200,10 @@ static int evaluate_sctp_sndinfo_expression(struct expression *in, &out_sndinfo->snd_context, error)) return STATUS_ERR; + if (evaluate(in_sndinfo->snd_assoc_id, + &out_sndinfo->snd_assoc_id, + error)) + return STATUS_ERR; return STATUS_OK; } @@ -2065,6 +2110,9 @@ static int evaluate(struct expression *in, case EXPR_MSGHDR: result = evaluate_msghdr_expression(in, out, error); break; + case EXPR_CMSGHDR: + result = evaluate_cmsghdr_expression(in, out, error); + break; case EXPR_POLLFD: result = evaluate_pollfd_expression(in, out, error); break; diff --git a/gtests/net/packetdrill/script.h b/gtests/net/packetdrill/script.h index bb60524ff45952a372108df958fdfbef5f63567a..5dccd49ca7b55432e1c8cf326e6f04379d471f6d 100644 --- a/gtests/net/packetdrill/script.h +++ b/gtests/net/packetdrill/script.h @@ -45,6 +45,7 @@ enum expression_t { EXPR_LIST, /* list of expressions */ EXPR_IOVEC, /* expression tree for an iovec struct */ EXPR_MSGHDR, /* expression tree for a msghdr struct */ + EXPR_CMSGHDR, /* expression tree for a cmsghdr struct */ EXPR_POLLFD, /* expression tree for a pollfd struct */ EXPR_SCTP_RTOINFO, /* struct sctp_rtoinfo for SCTP_RTOINFO */ EXPR_SCTP_INITMSG, /* struct sctp_initmsg for SCTP_INITMSG */ @@ -95,6 +96,7 @@ struct expression { struct expression_list *list; struct iovec_expr *iovec; struct msghdr_expr *msghdr; + struct cmsghdr_expr *cmsghdr; struct pollfd_expr *pollfd; struct sctp_rtoinfo_expr *sctp_rtoinfo; struct sctp_initmsg_expr *sctp_initmsg; @@ -158,9 +160,19 @@ struct msghdr_expr { struct expression *msg_namelen; struct expression *msg_iov; struct expression *msg_iovlen; + struct expression *msg_control; + struct expression *msg_controllen; struct expression *msg_flags; }; +/* Parse tree for a cmsghdr struct in a struct msghdr. */ +struct cmsghdr_expr { + struct expression *cmsg_len; + struct expression *cmsg_level; + struct expression *cmsg_type; + struct expression *cmsg_data; +}; + /* Parse tree for a pollfd struct in a poll syscall. */ struct pollfd_expr { struct expression *fd; /* file descriptor */ @@ -274,6 +286,7 @@ struct sctp_sndinfo_expr { struct expression *snd_flags; struct expression *snd_ppid; struct expression *snd_context; + struct expression *snd_assoc_id; }; /* Parse tree for sctp_setadaptation struct in [gs]etsockopt syscall. */ diff --git a/gtests/net/packetdrill/sctp.h b/gtests/net/packetdrill/sctp.h index dc9d2051513aca263324290f056af93ef26bfb98..0c737cf6ea67070986509d8604b8a7925e43e24e 100644 --- a/gtests/net/packetdrill/sctp.h +++ b/gtests/net/packetdrill/sctp.h @@ -244,8 +244,10 @@ struct sctp_pad_chunk { #define SCTP_ECN_CAPABLE_PARAMETER_TYPE 0x8000 #define SCTP_SUPPORTED_EXTENSIONS_PARAMETER_TYPE 0x8008 #define SCTP_PAD_PARAMETER_TYPE 0x8005 +#define SCTP_Set_Primary_Address 0xc004 +#define SCTP_ADAPTATION_INDICATION_PARAMETER_TYPE 0xc006 -#define MAX_SCTP_PARAMETER_BYTES 0xffff +#define MAX_SCTP_PARAMETER_BYTES 0xffff struct sctp_parameter { __be16 type; @@ -318,6 +320,12 @@ struct sctp_pad_parameter { __be16 padding_data[]; } __packed; +struct sctp_adaptation_indication_parameter { + __be16 type; + __be16 length; + __be32 adaptation_code_point; +} __packed; + #define SCTP_INVALID_STREAM_IDENTIFIER_CAUSE_CODE 0x0001 #define SCTP_MISSING_MANDATORY_PARAMETER_CAUSE_CODE 0x0002 #define SCTP_STALE_COOKIE_ERROR_CAUSE_CODE 0x0003 diff --git a/gtests/net/packetdrill/sctp_chunk_to_string.c b/gtests/net/packetdrill/sctp_chunk_to_string.c index 8dc2ca83547de2a6f006d252430c66093c944937..027873a947c3b8b21fa4eec314a20a63a29a1ee2 100644 --- a/gtests/net/packetdrill/sctp_chunk_to_string.c +++ b/gtests/net/packetdrill/sctp_chunk_to_string.c @@ -338,6 +338,27 @@ static int sctp_unknown_parameter_to_string( return STATUS_OK; } +static int sctp_adaptation_indication_parameter_to_string( + FILE *s, + struct sctp_adaptation_indication_parameter *parameter, + char **error) +{ + u16 length; + + length = ntohs(parameter->length); + if (length < sizeof(struct sctp_adaptation_indication_parameter)) { + asprintf(error, "PARAMETER too short (type=0x%04x, length=%u)", + ntohs(parameter->type), length); + return STATUS_ERR; + } + fputs("ADAPTATION_INDICATION[", s); + fprintf(s, "type=0x%04x, ", ntohs(parameter->type)); + fprintf(s, "len=%hu, ", ntohs(parameter->length)); + fprintf(s, "val=%u", ntohl(parameter->adaptation_code_point)); + fputs("]", s); + return STATUS_OK; +} + static int sctp_parameter_to_string(FILE *s, struct sctp_parameter *parameter, char **error) @@ -394,6 +415,10 @@ static int sctp_parameter_to_string(FILE *s, result = sctp_pad_parameter_to_string(s, (struct sctp_pad_parameter *)parameter, error); break; + case SCTP_ADAPTATION_INDICATION_PARAMETER_TYPE: + result = sctp_adaptation_indication_parameter_to_string(s, + (struct sctp_adaptation_indication_parameter *)parameter, error); + break; default: result = sctp_unknown_parameter_to_string(s, parameter, error); break; diff --git a/gtests/net/packetdrill/sctp_packet.c b/gtests/net/packetdrill/sctp_packet.c index 70f81259f54ced9e77c0898e8284e4a2c2cf8d49..5ddca4a72b388f1d5488bd6dd00a9e19e97d0f71 100644 --- a/gtests/net/packetdrill/sctp_packet.c +++ b/gtests/net/packetdrill/sctp_packet.c @@ -1611,6 +1611,33 @@ sctp_supported_extensions_parameter_new(struct sctp_byte_list *list) parameter_length, flags); } +struct sctp_parameter_list_item * +sctp_adaptation_indication_parameter_new(s64 val) +{ + u32 flags; + struct sctp_adaptation_indication_parameter *parameter; + u16 parameter_length; + + flags = 0; + parameter_length = sizeof(struct sctp_adaptation_indication_parameter); + + parameter = malloc(parameter_length); + assert(parameter != NULL); + memset(parameter, 0, parameter_length); + + parameter->type = htons(SCTP_ADAPTATION_INDICATION_PARAMETER_TYPE); + parameter->length = htons(parameter_length); + if (val == -1) { + parameter->adaptation_code_point = htonl(0); + flags |= FLAG_PARAMETER_VALUE_NOCHECK; + } else { + assert(is_valid_u32(val)); + parameter->adaptation_code_point = htonl((u32)val); + } + return sctp_parameter_list_item_new((struct sctp_parameter *)parameter, + parameter_length, flags); +} + struct sctp_parameter_list_item * sctp_pad_parameter_new(s64 len, u8 *padding) { diff --git a/gtests/net/packetdrill/sctp_packet.h b/gtests/net/packetdrill/sctp_packet.h index c32e8d9d6878ed480890735478ec254c21483741..b492ebc736cb5e504e079ac981e59d1f3b933639 100644 --- a/gtests/net/packetdrill/sctp_packet.h +++ b/gtests/net/packetdrill/sctp_packet.h @@ -340,6 +340,9 @@ sctp_ecn_capable_parameter_new(void); struct sctp_parameter_list_item * sctp_pad_parameter_new(s64 len, u8 *padding); +struct sctp_parameter_list_item * +sctp_adaptation_indication_parameter_new(s64 val); + struct sctp_parameter_list_item * sctp_supported_extensions_parameter_new(struct sctp_byte_list *list); diff --git a/gtests/net/packetdrill/symbols_freebsd.c b/gtests/net/packetdrill/symbols_freebsd.c index 9b0bc90bc370a39d4290c88fcd923801218762ad..b8d5288ba0690bbab275a8ebdce2e20e5ccc7cc0 100644 --- a/gtests/net/packetdrill/symbols_freebsd.c +++ b/gtests/net/packetdrill/symbols_freebsd.c @@ -82,6 +82,7 @@ struct int_symbol platform_symbols_table[] = { { SCTP_RTOINFO, "SCTP_RTOINFO" }, { SCTP_ASSOCINFO, "SCTP_ASSOCINFO" }, { SCTP_INITMSG, "SCTP_INITMSG" }, + { SCTP_INIT, "SCTP_INIT" }, { SCTP_NODELAY, "SCTP_NODELAY" }, { SCTP_ADAPTATION_LAYER, "SCTP_ADAPTATION_LAYER" }, { SCTP_MAXSEG, "SCTP_MAXSEG" }, @@ -221,6 +222,11 @@ struct int_symbol platform_symbols_table[] = { { SCTP_ADDR_UNREACHABLE, "SCTP_ADDR_UNREACHABLE" }, { SCTP_ADDR_REMOVED, "SCTP_ADDR_REMOVED" }, { SCTP_ADDR_MADE_PRIM, "SCTP_ADDR_MADE_PRIM" }, + { SCTP_SNDINFO, "SCTP_SNDINFO" }, + { SCTP_PRINFO, "SCTP_PRINFO" }, + { SCTP_AUTHINFO, "SCTP_AUTHINFO" }, + { SCTP_DSTADDRV4, "SCTP_DSTADDRV4" }, + { SCTP_DSTADDRV6, "SCTP_DSTADDRV6" }, /* /usr/include/netinet/tcp.h */ { TCP_NODELAY, "TCP_NODELAY" }, { TCP_MAXSEG, "TCP_MAXSEG" }, diff --git a/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_adaptation_event.pkt b/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_adaptation_event.pkt index e5b5e282881bb8babb97e8ed423b50a7583ac14f..282b383885d289485e3e1b9d225fd6387131e6bf 100644 --- a/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_adaptation_event.pkt +++ b/gtests/net/packetdrill/tests/bsd/sctp/notifications/sctp_adaptation_event.pkt @@ -2,14 +2,26 @@ +0.0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR) +0.0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0 // Check the handshake with an empty(!) cookie -+0.1 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress) ++0.0 bind(3, ..., ...) = 0 ++0.0 listen(3, 1) = 0 + +// Enable Event notification +0.0 setsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_ADAPTATION_INDICATION, se_on=1}, 8) = 0 +0.0 getsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_ADAPTATION_INDICATION, se_on=1}, [8]) = 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=1, is=1, tsn=1, STATE_COOKIE[len=4, val=...]] -+0.0 > sctp: COOKIE_ECHO[flgs=0, len=4, val=...] -+0.1 < sctp: COOKIE_ACK[flgs=0] + +// Send Adaptation Indication with Init chunk ++0.0 < sctp: INIT[flgs=0, tag=1, a_rwnd=1500, os=1, is=1, tsn=0, + ECN_CAPABLE[], + ADAPTATION_INDICATION[adaptation_code_point=3], + COOKIE_PRESERVATIVE[incr=12345], + SUPPORTED_ADDRESS_TYPES[types=[IPv4]]] + +* > sctp: INIT_ACK[flgs=0, tag=2, a_rwnd=..., os=..., is=..., tsn=10, ...] ++0.0 < sctp: COOKIE_ECHO[flgs=0, len=..., val=...] +* > sctp: COOKIE_ACK[flgs=0] + ++0.0 accept(3, ..., ...) = 4 //TODO: Packetdrill does not support Path reconfiguration, after that update this test -+0.0 sctp_recvv(3, [{iov_base={sai_type=SCTP_ADAPTATION_INDICATION, sai_flags=0, sai_length=16, sai_adaptation_ind=0, sai_assoc_id=...}, -iov_len=1000}], 1, ..., 20, NULL, [0], [SCTP_RECVV_NOINFO],[MSG_NOTIFICATION|MSG_EOR]) = 21 ++0.0 sctp_recvv(4, [{iov_base={sai_type=SCTP_ADAPTATION_INDICATION, sai_flags=0, sai_length=16, sai_adaptation_ind=3, sai_assoc_id=...}, +iov_len=1000}], 1, ..., 20, NULL, [0], [SCTP_RECVV_NOINFO],[MSG_NOTIFICATION|MSG_EOR]) = 16 diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt index 2b9f57a45ab668a1797af277c6744b7bd6fe6933..a33a6d1950fec9df17d13a79b78dd047d694a1fb 100644 --- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_get_socket_options.pkt @@ -115,14 +115,14 @@ sasoc_cookie_life=...}, [20]) = 0 +0 setsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_SHUTDOWN_EVENT, se_on=1}, 8) = 0 +0 getsockopt(3, IPPROTO_SCTP, SCTP_EVENT, {se_type=SCTP_SHUTDOWN_EVENT, se_on=1}, [8]) = 0 -+0 setsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=0, snd_ppid=htonl(1), snd_context=1}, 16) = 0 -+0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=0, snd_ppid=htonl(1), snd_context=1}, [16]) = 0 -+0 setsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=SCTP_UNORDERED, snd_ppid=htonl(2), snd_context=2}, 16) = 0 -+0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=SCTP_UNORDERED, snd_ppid=htonl(2), snd_context=2}, [16]) = 0 -+0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=SCTP_UNORDERED, snd_ppid=htonl(2), snd_context=...}, [16]) = 0 -+0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=SCTP_UNORDERED, snd_ppid=..., snd_context=2}, [16]) = 0 -+0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=..., snd_ppid=htonl(2), snd_context=2}, [16]) = 0 -+0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=..., snd_flags=SCTP_UNORDERED, snd_ppid=htonl(2), snd_context=2}, [16]) = 0 ++0 setsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=0, snd_ppid=htonl(1), snd_context=1, snd_assoc_id=0}, 16) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=0, snd_ppid=htonl(1), snd_context=1, snd_assoc_id=0}, [16]) = 0 ++0 setsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=SCTP_UNORDERED, snd_ppid=htonl(2), snd_context=2, snd_assoc_id=0}, 16) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=SCTP_UNORDERED, snd_ppid=htonl(2), snd_context=2, snd_assoc_id=0}, [16]) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=SCTP_UNORDERED, snd_ppid=htonl(2), snd_context=..., snd_assoc_id=0}, [16]) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=SCTP_UNORDERED, snd_ppid=..., snd_context=2, snd_assoc_id=0},[16]) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=0, snd_flags=..., snd_ppid=htonl(2), snd_context=2, snd_assoc_id=0}, [16]) = 0 ++0 getsockopt(3, IPPROTO_SCTP, SCTP_DEFAULT_SNDINFO, {snd_sid=..., snd_flags=SCTP_UNORDERED, snd_ppid=htonl(2), snd_context=2, snd_assoc_id=0}, [16]) = 0 +0 setsockopt(3, IPPROTO_SCTP, SCTP_ADAPTATION_LAYER, {ssb_adaptation_ind=2}, 4) = 0 +0 getsockopt(3, IPPROTO_SCTP, SCTP_ADAPTATION_LAYER, {ssb_adaptation_ind=2}, [4]) = 0 diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sctp_sendv.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sctp_sendv.pkt index 114a476808ae46fa799c0b32ea28b879eb416d27..b5dbb6f097c0a049c4684c5c3dda42f80115b8f8 100644 --- a/gtests/net/packetdrill/tests/bsd/sctp/sctp_sendv.pkt +++ b/gtests/net/packetdrill/tests/bsd/sctp/sctp_sendv.pkt @@ -50,14 +50,15 @@ //test with all sctp_sendv_spainfo +1.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_sndinfo={snd_sid=2, snd_flags=0, snd_ppid=htonl(0), snd_context=0, snd_assoc_id=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 sctp_sendv_sndinfo -+1.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 ++1.0 sctp_sendv(3, [{iov_base=..., iov_len=1000}], 1, ..., 1, {snd_sid=1, snd_flags=0, snd_ppid=htonl(1234), snd_context=0, snd_assoc_id=0}, 16, SCTP_SENDV_SNDINFO, 0) += 1000 * > sctp: DATA[flgs=BE, len=1016, tsn=9, sid=1, ssn=0, ppid=1234] +0.0 < sctp: SACK[flgs=0, cum_tsn=9, a_rwnd=1500, gaps=[], dups=[]] diff --git a/gtests/net/packetdrill/tests/bsd/sctp/sendmsg.pkt b/gtests/net/packetdrill/tests/bsd/sctp/sendmsg.pkt new file mode 100644 index 0000000000000000000000000000000000000000..a8639456fbb6e3f9dabfc4af97b4943a111bee9b --- /dev/null +++ b/gtests/net/packetdrill/tests/bsd/sctp/sendmsg.pkt @@ -0,0 +1,70 @@ + ++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 +//sendmsg(sd, msghdr, flags) + ++1.0 sendmsg(3, {msg_name(...)=..., msg_iov(1)=[{iov_base=..., iov_len=1000}], msg_control(0)=[], msg_flags=0}, 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 sendmsg(3, {msg_name(...)=..., msg_iov(1)=[{iov_base=..., iov_len=1000}], msg_control(28)= + [{cmsg_len=28, cmsg_level=IPPROTO_SCTP, cmsg_type=SCTP_SNDINFO, cmsg_data= + {snd_sid=2, snd_flags=0, snd_ppid=htonl(3), snd_context=2, snd_assoc_id=0} + }], + msg_flags=0}, 0) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=2, sid=2, ssn=0, ppid=3] ++0.0 < sctp: SACK[flgs=0, cum_tsn=2, a_rwnd=1500, gaps=[], dups=[]] + +// test with 2 cmsg ++1.0 sendmsg(3, {msg_name(...)=..., msg_iov(1)=[{iov_base=..., iov_len=1000}], msg_control(44)= + [{cmsg_len=28, cmsg_level=IPPROTO_SCTP, cmsg_type=SCTP_SNDINFO, cmsg_data= + {snd_sid=2, snd_flags=0, snd_ppid=htonl(4), snd_context=2, snd_assoc_id=0} + },{cmsg_len=16, cmsg_level=IPPROTO_SCTP, cmsg_type=SCTP_DSTADDRV4, cmsg_data= + {sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")} + }], + msg_flags=0}, 0) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=3, sid=2, ssn=1, ppid=4] ++0.0 < sctp: SACK[flgs=0, cum_tsn=3, a_rwnd=1500, gaps=[], dups=[]] + +// test with 2 cmsg ++1.0 sendmsg(3, {msg_name(...)=..., msg_iov(1)=[{iov_base=..., iov_len=1000}], msg_control(64)= + [{cmsg_len=28, cmsg_level=IPPROTO_SCTP, cmsg_type=SCTP_SNDINFO, cmsg_data= + {snd_sid=2, snd_flags=0, snd_ppid=htonl(5), snd_context=2, snd_assoc_id=0} + },{cmsg_len=16, cmsg_level=IPPROTO_SCTP, cmsg_type=SCTP_DSTADDRV4, cmsg_data= + {sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")} + },{cmsg_len=18, cmsg_level=IPPROTO_SCTP, cmsg_type=SCTP_PRINFO, cmsg_data= + {pr_policy=SCTP_PR_SCTP_TTL, pr_value=30} + }], + msg_flags=0}, 0) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=4, sid=2, ssn=2, ppid=5] ++0.0 < sctp: SACK[flgs=0, cum_tsn=4, a_rwnd=1500, gaps=[], dups=[]] + +// test with 2 cmsg ++1.0 sendmsg(3, {msg_name(...)=..., msg_iov(1)=[{iov_base=..., iov_len=1000}], msg_control(80)= + [{cmsg_len=28, cmsg_level=IPPROTO_SCTP, cmsg_type=SCTP_SNDINFO, cmsg_data= + {snd_sid=2, snd_flags=0, snd_ppid=htonl(6), snd_context=2, snd_assoc_id=0} + },{cmsg_len=16, cmsg_level=IPPROTO_SCTP, cmsg_type=SCTP_DSTADDRV4, cmsg_data= + {sa_family=AF_INET, sin_port=htons(8080), sin_addr=inet_addr("192.0.2.1")} + },{cmsg_len=18, cmsg_level=IPPROTO_SCTP, cmsg_type=SCTP_PRINFO, cmsg_data= + {pr_policy=SCTP_PR_SCTP_TTL, pr_value=30} + },{cmsg_len=14, cmsg_level=IPPROTO_SCTP, cmsg_type=SCTP_AUTHINFO, cmsg_data= + {auth_keynumber=123} + }], + msg_flags=0}, 0) = 1000 +* > sctp: DATA[flgs=BE, len=1016, tsn=5, sid=2, ssn=3, ppid=6] ++0.0 < sctp: SACK[flgs=0, cum_tsn=5, 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]