From 440d7827ea4b0cac2db6cd26fcaa51c12bf34487 Mon Sep 17 00:00:00 2001
From: hoelscher <jens.hoelscher@fh-muenster.de>
Date: Sun, 11 Oct 2015 20:36:17 +0200
Subject: [PATCH] Add support for sctp_sendmsg syscall

---
 gtests/net/packetdrill/parser.y          |  2 +-
 gtests/net/packetdrill/run_system_call.c | 71 ++++++++++++++++++++++++
 2 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/gtests/net/packetdrill/parser.y b/gtests/net/packetdrill/parser.y
index bb2fb56b..60607043 100644
--- a/gtests/net/packetdrill/parser.y
+++ b/gtests/net/packetdrill/parser.y
@@ -3061,7 +3061,7 @@ sctp_sndinfo
 : '{' snd_sid ',' snd_flags ',' snd_ppid ',' snd_context '}' {
 #ifdef SCTP_DEFAULT_SNDINFO
 	$$ = new_expression(EXPR_SCTP_SNDINFO);
-	$$->value.sctp_sndinfo = calloc(1, sizeof(struct 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;
diff --git a/gtests/net/packetdrill/run_system_call.c b/gtests/net/packetdrill/run_system_call.c
index 626d6926..2b7ba1aa 100644
--- a/gtests/net/packetdrill/run_system_call.c
+++ b/gtests/net/packetdrill/run_system_call.c
@@ -2971,6 +2971,76 @@ error_out:
 	return status;
 }
 
+static int syscall_sctp_sendmsg(struct state *state, struct syscall_spec *syscall,
+			struct expression_list *args, char **error)
+{
+	int result, script_fd, live_fd, len;
+	void *msg = NULL;
+	struct sockaddr_storage to;
+	socklen_t tolen;
+	u32 ppid, flags, timetolive, context;
+	u16 stream_no;
+	struct expression *sockaddr_expr, *tolen_expr, *ppid_expr, *flags_expr, *ttl_expr, *stream_no_expr, *context_expr;
+	
+	if (check_arg_count(args, 10, 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;
+	if (ellipsis_arg(args, 1, error))
+		return STATUS_ERR;
+	if (s32_arg(args, 2, &len, error))
+		return STATUS_ERR;
+	sockaddr_expr = get_arg(args, 3, error);
+	if (sockaddr_expr->type == EXPR_ELLIPSIS) {
+		socklen_t len = (socklen_t)sizeof(struct sockaddr_storage);
+		if (getpeername(live_fd, (struct sockaddr *)&to, &len)) {
+			return STATUS_ERR;
+		}
+		tolen = len;
+	} else if (sockaddr_expr->type == EXPR_SOCKET_ADDRESS_IPV4) {
+		memcpy(&to, sockaddr_expr->value.socket_address_ipv4, sizeof(struct sockaddr_in));
+	} else if (sockaddr_expr->type == EXPR_SOCKET_ADDRESS_IPV6) {
+		memcpy(&to, sockaddr_expr->value.socket_address_ipv6, sizeof(struct sockaddr_in6));
+	}
+	tolen_expr = get_arg(args, 4, error);
+	if (!(tolen_expr->type == EXPR_ELLIPSIS && sockaddr_expr->type == EXPR_ELLIPSIS)) {
+		if (get_u32(tolen_expr, &tolen, error))
+			return STATUS_ERR;
+	}
+	ppid_expr = get_arg(args, 5, error);
+	if (get_u32(ppid_expr, &ppid, error))
+		return STATUS_ERR;
+	flags_expr = get_arg(args, 6, error);
+	if (get_u32(flags_expr, &flags, error))
+		return STATUS_ERR;
+	stream_no_expr =get_arg(args, 7, error);
+	if (get_u16(stream_no_expr, &stream_no, error))
+		return STATUS_ERR;
+	ttl_expr = get_arg(args, 8, error);
+	if (get_u32(ttl_expr, &timetolive, error))
+		return STATUS_ERR;
+	context_expr = get_arg(args, 9, error);
+	if (get_u32(context_expr, &context, error))
+		return STATUS_ERR;
+
+	msg = calloc(len, 1);
+	assert(msg != NULL);	
+
+	begin_syscall(state, syscall);
+	result = sctp_sendmsg(live_fd, msg, (size_t)len, (struct sockaddr*) &to, 
+			      tolen, ppid, flags, stream_no, timetolive, context);
+
+	if (end_syscall(state, syscall, CHECK_EXACT, result, error)) {
+		free(msg);
+		return STATUS_ERR;
+	}
+
+	free(msg);
+	return STATUS_OK;
+}
+
 /* A dispatch table with all the system calls that we support... */
 struct system_call_entry {
 	const char *name;
@@ -3002,6 +3072,7 @@ struct system_call_entry system_call_table[] = {
 	{"getsockopt", syscall_getsockopt},
 	{"setsockopt", syscall_setsockopt},
 	{"poll",       syscall_poll},
+	{"sctp_sendmsg", syscall_sctp_sendmsg},
 };
 
 /* Evaluate the system call arguments and invoke the system call. */
-- 
GitLab