Squashed 'third_party/lksctp-tools/' content from commit 200eca7f1
Change-Id: I8f7575513f114b205178cac5c6b3706f3d725cb5
git-subtree-dir: third_party/lksctp-tools
git-subtree-split: 200eca7f1419b1ae53958b51e8551f7e7f6cd467
diff --git a/src/testlib/Makefile.am b/src/testlib/Makefile.am
new file mode 100644
index 0000000..b949611
--- /dev/null
+++ b/src/testlib/Makefile.am
@@ -0,0 +1,12 @@
+# Include these two in all the Makefile.am's!!!
+include $(top_srcdir)/Makefile.vars
+include $(top_srcdir)/Makefile.rules
+
+include $(top_srcdir)/Makefile.dirs
+
+# General compilation flags
+AM_CPPFLAGS = -I$(top_builddir)/src/include
+
+noinst_LTLIBRARIES = libsctputil.la
+libsctputil_la_SOURCES = sctputil.c sctputil.h
+libsctputil_la_LDFLAGS =
diff --git a/src/testlib/sctputil.c b/src/testlib/sctputil.c
new file mode 100644
index 0000000..24f305a
--- /dev/null
+++ b/src/testlib/sctputil.c
@@ -0,0 +1,417 @@
+/* SCTP kernel Implementation
+ * (C) Copyright IBM Corp. 2001, 2003
+ * Copyright (C) 1999 Cisco
+ * Copyright (C) 1999-2000 Motorola
+ # Copyright (C) 2001 Nokia
+ * Copyright (C) 2001 La Monte H.P. Yarroll
+ *
+ * The SCTP implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * The SCTP implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email address(es):
+ * lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *
+ * Or submit a bug report through the following website:
+ * http://www.sf.net/projects/lksctp
+ *
+ * Any bugs reported to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ *
+ * Written or modified by:
+ * La Monte H.P. Yarroll <piggy@acm.org>
+ * Narasimha Budihal <narsi@refcode.org>
+ * Karl Knutson <karl@athena.chicago.il.us>
+ * Jon Grimm <jgrimm@us.ibm.com>
+ * Daisy Chang <daisyc@us.ibm.com>
+ * Sridhar Samudrala <sri@us.ibm.com>
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <malloc.h>
+#include <netinet/sctp.h>
+#include <sctputil.h>
+
+/* This function prints the cmsg data. */
+void
+test_print_cmsg(sctp_cmsg_t type, sctp_cmsg_data_t *data)
+{
+ switch(type) {
+ case SCTP_INIT:
+ printf("INIT\n");
+ printf(" sinit_num_ostreams %d\n",
+ data->init.sinit_num_ostreams);
+ printf(" sinit_max_instreams %d\n",
+ data->init.sinit_max_instreams);
+ printf(" sinit_max_attempts %d\n",
+ data->init.sinit_max_attempts);
+ printf(" sinit_max_init_timeo %d\n",
+ data->init.sinit_max_init_timeo);
+
+ break;
+ case SCTP_SNDRCV:
+ printf("SNDRCV\n");
+ printf(" sinfo_stream %u\n", data->sndrcv.sinfo_stream);
+ printf(" sinfo_ssn %u\n", data->sndrcv.sinfo_ssn);
+ printf(" sinfo_flags 0x%x\n", data->sndrcv.sinfo_flags);
+ printf(" sinfo_ppid %u\n", data->sndrcv.sinfo_ppid);
+ printf(" sinfo_context %x\n", data->sndrcv.sinfo_context);
+ printf(" sinfo_tsn %u\n", data->sndrcv.sinfo_tsn);
+ printf(" sinfo_cumtsn %u\n", data->sndrcv.sinfo_cumtsn);
+ printf(" sinfo_assoc_id %u\n", data->sndrcv.sinfo_assoc_id);
+
+ break;
+
+ default:
+ printf("UNKNOWN CMSG: %d\n", type);
+ break;
+ }
+}
+
+/* This function prints the message. */
+void
+test_print_message(int sk, struct msghdr *msg, size_t msg_len)
+{
+ sctp_cmsg_data_t *data;
+ struct cmsghdr *cmsg;
+ int i;
+ int done = 0;
+ char save;
+ union sctp_notification *sn;
+
+ for (cmsg = CMSG_FIRSTHDR(msg);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR(msg, cmsg)) {
+ data = (sctp_cmsg_data_t *)CMSG_DATA(cmsg);
+ test_print_cmsg(cmsg->cmsg_type, data);
+ }
+
+ if (!(MSG_NOTIFICATION & msg->msg_flags)) {
+ int index = 0;
+ /* Make sure that everything is printable and that we
+ * are NUL terminated...
+ */
+ printf("DATA(%lu): ", msg_len);
+ while ( msg_len > 0 ) {
+ char *text;
+ int len;
+
+ text = msg->msg_iov[index].iov_base;
+ len = msg->msg_iov[index].iov_len;
+
+ save = text[msg_len-1];
+ if ( len > msg_len ) {
+ text[(len = msg_len) - 1] = '\0';
+ }
+
+ if ( (msg_len -= len) > 0 ) { index++; }
+
+ for (i = 0; i < len - 1; ++i) {
+ if (!isprint(text[i])) text[i] = '.';
+ }
+
+ printf("%s", text);
+ text[msg_len-1] = save;
+
+ if ( (done = !strcmp(text, "exit")) ) { break; }
+ }
+ } else {
+ printf("NOTIFICATION: ");
+ sn = (union sctp_notification *)msg->msg_iov[0].iov_base;
+ switch (sn->sn_header.sn_type) {
+ case SCTP_ASSOC_CHANGE:
+ switch (sn->sn_assoc_change.sac_state) {
+ case SCTP_COMM_UP:
+ printf("ASSOC_CHANGE - COMM_UP");
+ break;
+ case SCTP_COMM_LOST:
+ printf("ASSOC_CHANGE - COMM_LOST");
+ break;
+ case SCTP_RESTART:
+ printf("ASSOC_CHANGE - RESTART");
+ break;
+ case SCTP_SHUTDOWN_COMP:
+ printf("ASSOC_CHANGE - SHUTDOWN_COMP");
+ break;
+ case SCTP_CANT_STR_ASSOC:
+ printf("ASSOC_CHANGE - CANT_STR_ASSOC");
+ break;
+ default:
+ printf("ASSOC_CHANGE - UNEXPECTED(%d)",
+ sn->sn_assoc_change.sac_state);
+ break;
+ }
+ break;
+ default:
+ printf("%d", sn->sn_header.sn_type);
+ break;
+ }
+ }
+
+ printf("\n");
+}
+
+/* Check if a buf/msg_flags matches a notification, its type, and possibly an
+ * additional field in the corresponding notification structure.
+ */
+void
+test_check_buf_notification(void *buf, int datalen, int msg_flags,
+ int expected_datalen, uint16_t expected_sn_type,
+ uint32_t expected_additional)
+{
+ union sctp_notification *sn;
+
+ if (!(msg_flags & MSG_NOTIFICATION))
+ tst_brkm(TBROK, tst_exit, "Got a datamsg, expecting "
+ "notification");
+
+ if (expected_datalen <= 0)
+ return;
+
+ if (datalen != expected_datalen)
+ tst_brkm(TBROK, tst_exit, "Got a notification of unexpected "
+ "length:%d, expected length:%d", datalen,
+ expected_datalen);
+
+ sn = (union sctp_notification *)buf;
+ if (sn->sn_header.sn_type != expected_sn_type)
+ tst_brkm(TBROK, tst_exit, "Unexpected notification:%d"
+ "expected:%d", sn->sn_header.sn_type,
+ expected_sn_type);
+
+ switch(sn->sn_header.sn_type){
+ case SCTP_ASSOC_CHANGE:
+ if (sn->sn_assoc_change.sac_state != expected_additional)
+ tst_brkm(TBROK, tst_exit, "Unexpected sac_state:%d "
+ "expected:%d", sn->sn_assoc_change.sac_state,
+ expected_additional);
+ break;
+ default:
+ break;
+ }
+}
+
+/* Check if a message matches a notification, its type, and possibly an
+ * additional field in the corresponding notification structure.
+ */
+void
+test_check_msg_notification(struct msghdr *msg, int datalen,
+ int expected_datalen, uint16_t expected_sn_type,
+ uint32_t expected_additional)
+{
+ test_check_buf_notification(msg->msg_iov[0].iov_base, datalen,
+ msg->msg_flags, expected_datalen,
+ expected_sn_type, expected_additional);
+}
+
+/* Check if a buf/msg_flags/sinfo corresponds to data, its length, msg_flags,
+ * stream and ppid.
+ */
+void
+test_check_buf_data(void *buf, int datalen, int msg_flags,
+ struct sctp_sndrcvinfo *sinfo, int expected_datalen,
+ int expected_msg_flags, uint16_t expected_stream,
+ uint32_t expected_ppid)
+{
+ if (msg_flags & MSG_NOTIFICATION)
+ tst_brkm(TBROK, tst_exit, "Got a notification, expecting a"
+ "datamsg");
+
+ if (expected_datalen <= 0)
+ return;
+
+ if (datalen != expected_datalen)
+ tst_brkm(TBROK, tst_exit, "Got a datamsg of unexpected "
+ "length:%d, expected length:%d", datalen,
+ expected_datalen);
+
+ if ((msg_flags & ~0x80000000) != expected_msg_flags)
+ tst_brkm(TBROK, tst_exit, "Unexpected msg_flags:0x%x "
+ "expecting:0x%x", msg_flags, expected_msg_flags);
+
+ if ((0 == expected_stream) && (0 == expected_ppid))
+ return;
+
+ if (!sinfo)
+ tst_brkm(TBROK, tst_exit, "Null sinfo, but expected "
+ "stream:%d expected ppid:%d", expected_stream,
+ expected_ppid);
+
+ if (sinfo->sinfo_stream != expected_stream)
+ tst_brkm(TBROK, tst_exit, "stream mismatch: expected:%x "
+ "got:%x", expected_stream, sinfo->sinfo_stream);
+ if (sinfo->sinfo_ppid != expected_ppid)
+ tst_brkm(TBROK, tst_exit, "ppid mismatch: expected:%x "
+ "got:%x\n", expected_ppid, sinfo->sinfo_ppid);
+}
+
+/* Check if a message corresponds to data, its length, msg_flags, stream and
+ * ppid.
+ */
+void
+test_check_msg_data(struct msghdr *msg, int datalen, int expected_datalen,
+ int expected_msg_flags, uint16_t expected_stream,
+ uint32_t expected_ppid)
+{
+ struct cmsghdr *cmsg = NULL;
+ struct sctp_sndrcvinfo *sinfo = NULL;
+
+ /* Receive auxiliary data in msgh. */
+ for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
+ cmsg = CMSG_NXTHDR(msg, cmsg)){
+ if (IPPROTO_SCTP == cmsg->cmsg_level &&
+ SCTP_SNDRCV == cmsg->cmsg_type)
+ break;
+ } /* for( all cmsgs) */
+
+ if ((!cmsg) ||
+ (cmsg->cmsg_len < CMSG_LEN(sizeof(struct sctp_sndrcvinfo))))
+ sinfo = NULL;
+ else
+ sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
+
+ test_check_buf_data(msg->msg_iov[0].iov_base, datalen, msg->msg_flags,
+ sinfo, expected_datalen, expected_msg_flags,
+ expected_stream, expected_ppid);
+
+}
+
+
+/* Allocate a buffer of requested len and fill in with data. */
+void *
+test_build_msg(int len)
+{
+ int i = len - 1;
+ int n;
+ unsigned char msg[] =
+ "012345678901234567890123456789012345678901234567890";
+ char *msg_buf, *p;
+
+ msg_buf = (char *)malloc(len);
+ if (!msg_buf)
+ tst_brkm(TBROK, tst_exit, "malloc failed");
+
+ p = msg_buf;
+
+ do {
+ n = ((i > 50)?50:i);
+ memcpy(p, msg, ((i > 50)?50:i));
+ p += n;
+ i -= n;
+ } while (i > 0);
+
+ msg_buf[len-1] = '\0';
+
+ return(msg_buf);
+}
+
+/* Enable ASSOC_CHANGE and SNDRCVINFO notifications. */
+void test_enable_assoc_change(int fd)
+{
+ struct sctp_event_subscribe subscribe;
+
+ memset(&subscribe, 0, sizeof(subscribe));
+ subscribe.sctp_data_io_event = 1;
+ subscribe.sctp_association_event = 1;
+ test_setsockopt(fd, SCTP_EVENTS, (char *)&subscribe,
+ sizeof(subscribe));
+}
+
+static int cmp_addr(sockaddr_storage_t *addr1, sockaddr_storage_t *addr2)
+{
+ if (addr1->sa.sa_family != addr2->sa.sa_family)
+ return 0;
+ switch (addr1->sa.sa_family) {
+ case AF_INET6:
+ if (addr1->v6.sin6_port != addr2->v6.sin6_port)
+ return -1;
+ return memcmp(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr,
+ sizeof(addr1->v6.sin6_addr));
+ case AF_INET:
+ if (addr1->v4.sin_port != addr2->v4.sin_port)
+ return 0;
+ return memcmp(&addr1->v4.sin_addr, &addr2->v4.sin_addr,
+ sizeof(addr1->v4.sin_addr));
+ default:
+ tst_brkm(TBROK, tst_exit, "invalid address type %d",
+ addr1->sa.sa_family);
+ return -1;
+ }
+}
+
+/* Test peer addresses for association. */
+int test_peer_addr(int sk, sctp_assoc_t asoc, sockaddr_storage_t *peers, int count)
+{
+ struct sockaddr *addrs;
+ int error, i, j;
+ struct sockaddr *sa_addr;
+ socklen_t addrs_size = 0;
+ void *addrbuf;
+ char *found = (char *) malloc(count);
+ memset(found, 0, count);
+
+ error = sctp_getpaddrs(sk, asoc, &addrs);
+ if (-1 == error) {
+ tst_brkm(TBROK, tst_exit, "sctp_getpaddrs: %s", strerror(errno));
+ return error;
+ }
+ if (error != count) {
+ sctp_freepaddrs(addrs);
+ tst_brkm(TBROK, tst_exit, "peer count %d mismatch, expected %d",
+ error, count);
+ }
+ addrbuf = addrs;
+ for (i = 0; i < count; i++) {
+ sa_addr = (struct sockaddr *)addrbuf;
+ switch (sa_addr->sa_family) {
+ case AF_INET:
+ addrs_size += sizeof(struct sockaddr_in);
+ addrbuf += sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ addrs_size += sizeof(struct sockaddr_in6);
+ addrbuf += sizeof(struct sockaddr_in6);
+ break;
+ default:
+ errno = EINVAL;
+ sctp_freepaddrs(addrs);
+ tst_brkm(TBROK, tst_exit, "sctp_getpaddrs: %s", strerror(errno));
+ return -1;
+ }
+ for (j = 0; j < count; j++) {
+ if (cmp_addr((sockaddr_storage_t *)sa_addr,
+ &peers[j]) == 0) {
+ found[j] = 1;
+ }
+ }
+ }
+ for (j = 0; j < count; j++) {
+ if (found[j] == 0) {
+ tst_brkm(TBROK, tst_exit, "peer address %d not found", j);
+ }
+ }
+ sctp_freepaddrs(addrs);
+ free(found);
+ return 0;
+}
diff --git a/src/testlib/sctputil.h b/src/testlib/sctputil.h
new file mode 100644
index 0000000..9dbabd4
--- /dev/null
+++ b/src/testlib/sctputil.h
@@ -0,0 +1,358 @@
+/* SCTP kernel Implementation
+ * (C) Copyright IBM Corp. 2001, 2003
+ * Copyright (c) 1999-2000 Cisco, Inc.
+ * Copyright (c) 1999-2001 Motorola, Inc.
+ * Copyright (c) 2001 Intel Corp.
+ * Copyright (c) 2001 Nokia, Inc.
+ * Copyright (c) 2001 La Monte H.P. Yarroll
+ *
+ * The SCTP implementation is free software;
+ * you can redistribute it and/or modify it under the terms of
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * The SCTP implementation is distributed in the hope that it
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Please send any bug reports or fixes you make to the
+ * email address(es):
+ * lksctp developers <lksctp-developers@lists.sourceforge.net>
+ *
+ * Or submit a bug report through the following website:
+ * http://www.sf.net/projects/lksctp
+ *
+ * Any bugs reported to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ *
+ * Written or modified by:
+ * La Monte H.P. Yarroll <piggy@acm.org>
+ * Karl Knutson <karl@athena.chicago.il.us>
+ * Randall Stewart <randall@stewart.chicago.il.us>
+ * Ken Morneau <kmorneau@cisco.com>
+ * Qiaobing Xie <qxie1@motorola.com>
+ * Daisy Chang <daisyc@us.ibm.com>
+ * Jon Grimm <jgrimm@us.ibm.com>
+ * Sridhar Samudrala <samudrala@us.ibm.com>
+ * Hui Huang <hui.huang@nokia.com>
+ */
+
+#ifndef __sctputil_h__
+#define __sctputil_h__
+
+#ifdef LTP
+#include <test.h>
+#include <usctest.h>
+#endif
+
+#include <string.h>
+
+typedef union {
+ struct sockaddr_in v4;
+ struct sockaddr_in6 v6;
+ struct sockaddr sa;
+} sockaddr_storage_t;
+
+
+#define REALLY_BIG 65536
+
+/* Literal defines. */
+#ifdef PROT_SOCK
+#define SCTP_TESTPORT_1 PROT_SOCK
+#else
+#define SCTP_TESTPORT_1 1024
+#endif
+#define SCTP_TESTPORT_2 (SCTP_TESTPORT_1+1)
+
+#define SCTP_IP_BCAST htonl(0xffffffff)
+#define SCTP_IP_LOOPBACK htonl(0x7f000001)
+
+/* These are stolen from <netinet/in.h>. */
+#define SCTP_IN6ADDR_ANY_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }
+#define SCTP_IN6ADDR_LOOPBACK_INIT { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1 } } }
+
+/* Display an IPv4 address in readable format. */
+#define NIPQUAD(addr) \
+ ((unsigned char *)&addr)[0], \
+ ((unsigned char *)&addr)[1], \
+ ((unsigned char *)&addr)[2], \
+ ((unsigned char *)&addr)[3]
+
+/* Display an IPv6 address in readable format. */
+#define NIP6(addr) \
+ ntohs((addr).s6_addr16[0]), \
+ ntohs((addr).s6_addr16[1]), \
+ ntohs((addr).s6_addr16[2]), \
+ ntohs((addr).s6_addr16[3]), \
+ ntohs((addr).s6_addr16[4]), \
+ ntohs((addr).s6_addr16[5]), \
+ ntohs((addr).s6_addr16[6]), \
+ ntohs((addr).s6_addr16[7])
+
+#define DUMP_CORE { \
+ char *diediedie = 0; \
+ printf("DUMP_CORE %s: %d\n", __FILE__, __LINE__);\
+ *diediedie = 0; \
+}
+
+#ifndef LTP
+enum {
+ TPASS,
+ TINFO,
+};
+
+extern char *TCID;
+extern int TST_TOTAL;
+extern int TST_CNT;
+
+#define tst_brkm(a1, a2, whatever...) \
+ { \
+ printf("%s %2d BROK : ", TCID, ++TST_CNT); \
+ printf(whatever); \
+ printf("\n"); \
+ DUMP_CORE \
+ }
+#define tst_resm(a1, whatever...) \
+ { \
+ printf("%s %2d %s : ", TCID, \
+ (a1 == TPASS)?++TST_CNT:0, \
+ (a1 == TPASS)?"PASS":"INFO"); \
+ printf(whatever); \
+ printf("\n"); \
+ }
+#endif
+
+static inline int test_socket(int domain, int type, int protocol)
+{
+ int sk = socket(domain, type, protocol);
+ if (-1 == sk)
+ tst_brkm(TBROK, tst_exit, "socket: %s", strerror(errno));
+ return sk;
+}
+
+static inline int test_bind(int sk, struct sockaddr *addr, socklen_t addrlen)
+{
+ int error = bind(sk, addr, addrlen);
+ if (-1 == error)
+ tst_brkm(TBROK, tst_exit, "bind: %s", strerror(errno));
+ return error;
+}
+
+static inline int test_bindx_add(int sk, struct sockaddr *addr, int count)
+{
+ int error = sctp_bindx(sk, addr, count, SCTP_BINDX_ADD_ADDR);
+ if (-1 == error)
+ tst_brkm(TBROK, tst_exit, "bindx (add): %s", strerror(errno));
+ return error;
+}
+
+static inline int test_listen(int sk, int backlog)
+{
+ int error = listen(sk, backlog);
+ if (-1 == error)
+ tst_brkm(TBROK, tst_exit, "listen: %s", strerror(errno));
+ return error;
+}
+
+static inline int test_connect(int sk, struct sockaddr *addr, socklen_t addrlen)
+{
+ int error = connect(sk, addr, addrlen);
+ if (-1 == error)
+ tst_brkm(TBROK, tst_exit, "connect: %s", strerror(errno));
+ return error;
+}
+
+static inline int test_connectx(int sk, struct sockaddr *addr, int count)
+{
+ int error = sctp_connectx(sk, addr, count, NULL);
+ if (-1 == error)
+ tst_brkm(TBROK, tst_exit, "connectx: %s", strerror(errno));
+ return error;
+}
+
+static inline int test_accept(int sk, struct sockaddr *addr, socklen_t *addrlen)
+{
+ int error = accept(sk, addr, addrlen);
+ if (-1 == error)
+ tst_brkm(TBROK, tst_exit, "accept: %s", strerror(errno));
+ return error;
+}
+
+static inline int test_send(int sk, const void *msg, size_t len, int flags)
+{
+ int error = send(sk, msg, len, flags);
+ if (len != error)
+ tst_brkm(TBROK, tst_exit, "send: error:%d errno:%d",
+ error, errno);
+ return error;
+}
+
+static inline int test_sendto(int sk, const void *msg, size_t len, int flags,
+ const struct sockaddr *to, socklen_t tolen)
+{
+ int error = sendto(sk, msg, len, flags, to, tolen);
+ if (len != error)
+ tst_brkm(TBROK, tst_exit, "sendto: error:%d errno:%d",
+ error, errno);
+ return error;
+}
+
+static inline int test_sendmsg(int sk, const struct msghdr *msg, int flags,
+ int msglen)
+{
+ int error = sendmsg(sk, msg, flags);
+ if (msglen != error)
+ tst_brkm(TBROK, tst_exit, "sendmsg: error:%d errno:%d",
+ error, errno);
+ return error;
+}
+
+static inline int test_recv(int sk, void *buf, size_t len, int flags)
+{
+ int error = recv(sk, buf, len, flags);
+ if (-1 == error)
+ tst_brkm(TBROK, tst_exit, "recv: %s", strerror(errno));
+ return error;
+}
+
+static inline int test_recvmsg(int sk, struct msghdr *msg, int flags)
+{
+ int error = recvmsg(sk, msg, flags);
+ if (-1 == error)
+ tst_brkm(TBROK, tst_exit, "recvmsg: %s", strerror(errno));
+ return error;
+}
+
+static inline int test_shutdown(int sk, int how)
+{
+ int error = shutdown(sk, how);
+ if (-1 == error)
+ tst_brkm(TBROK, tst_exit, "shutdown: %s", strerror(errno));
+ return error;
+}
+
+static inline int test_getsockopt(int sk, int optname, void *optval,
+ socklen_t *optlen)
+{
+ int error = getsockopt(sk, SOL_SCTP, optname, optval, optlen);
+ if (error)
+ tst_brkm(TBROK, tst_exit, "getsockopt(%d): %s", optname,
+ strerror(errno));
+ return error;
+}
+
+static inline int test_setsockopt(int sk, int optname, const void *optval,
+ socklen_t optlen)
+{
+ int error = setsockopt(sk, SOL_SCTP, optname, optval, optlen);
+ if (error)
+ tst_brkm(TBROK, tst_exit, "setsockopt(%d): %s", optname,
+ strerror(errno));
+ return error;
+}
+
+static inline int test_sctp_peeloff(int sk, sctp_assoc_t assoc_id)
+{
+ int error = sctp_peeloff(sk, assoc_id);
+ if (-1 == error)
+ tst_brkm(TBROK, tst_exit, "sctp_peeloff: %s", strerror(errno));
+ return error;
+}
+
+static inline int test_sctp_sendmsg(int s, const void *msg, size_t len,
+ struct sockaddr *to, socklen_t tolen,
+ uint32_t ppid, uint32_t flags,
+ uint16_t stream_no, uint32_t timetolive,
+ uint32_t context)
+{
+ int error = sctp_sendmsg(s, msg, len, to, tolen, ppid, flags, stream_no,
+ timetolive, context);
+ if (len != error)
+ tst_brkm(TBROK, tst_exit, "sctp_sendmsg: error:%d errno:%d",
+ error, errno);
+ return error;
+}
+
+static inline int test_sctp_send(int s, const void *msg, size_t len,
+ const struct sctp_sndrcvinfo *sinfo,
+ int flags)
+{
+ int error = sctp_send(s, msg, len, sinfo, flags);
+ if (len != error)
+ tst_brkm(TBROK, tst_exit, "sctp_send: error:%d errno:%d",
+ error, errno);
+ return error;
+}
+
+#ifdef HAVE_SCTP_SENDV
+static inline int test_sctp_sendv(int s, const struct iovec *iov, int iovcnt,
+ struct sockaddr *addrs, int addrcnt,
+ void *info, socklen_t infolen,
+ unsigned int infotype, int flags)
+{
+ int error = sctp_sendv(s, iov, iovcnt, addrs, addrcnt, info, infolen,
+ infotype, flags);
+ int i, tlen = 0;
+
+ for (i = 0; i < iovcnt; i++)
+ tlen += iov->iov_len;
+
+ if (tlen != error)
+ tst_brkm(TBROK, tst_exit, "sctp_sendv: error:%d errno:%d",
+ error, errno);
+ return error;
+}
+#endif
+
+static inline int test_sctp_recvmsg(int sk, void *msg, size_t len,
+ struct sockaddr *from, socklen_t *fromlen,
+ struct sctp_sndrcvinfo *sinfo,
+ int *msg_flags)
+{
+ int error = sctp_recvmsg(sk, msg, len, from, fromlen, sinfo, msg_flags);
+ if (-1 == error)
+ tst_brkm(TBROK, tst_exit, "sctp_recvmsg: %s", strerror(errno));
+ return error;
+}
+
+#ifdef HAVE_SCTP_SENDV
+static inline int test_sctp_recvv(int s, const struct iovec *iov, int iovlen,
+ struct sockaddr *from, socklen_t *fromlen,
+ void *info, socklen_t *infolen,
+ unsigned int *infotype, int *flags)
+{
+ int error = sctp_recvv(s, iov, iovlen, from, fromlen, info, infolen,
+ infotype, flags);
+ if (-1 == error)
+ tst_brkm(TBROK, tst_exit, "sctp_recvmsg: %s", strerror(errno));
+ return error;
+}
+#endif
+
+static inline void *test_malloc(size_t size)
+{
+ void *buf = malloc(size);
+ if (NULL == buf)
+ tst_brkm(TBROK, tst_exit, "malloc failed");
+ return buf;
+}
+
+void test_check_msg_notification(struct msghdr *, int, int, uint16_t, uint32_t);
+void test_check_buf_notification(void *, int, int, int, uint16_t, uint32_t);
+void test_check_msg_data(struct msghdr *, int, int, int, uint16_t, uint32_t);
+void test_check_buf_data(void *, int, int, struct sctp_sndrcvinfo *, int, int,
+ uint16_t, uint32_t);
+void *test_build_msg(int);
+void test_enable_assoc_change(int);
+void test_print_message(int sk, struct msghdr *msg, size_t msg_len);
+int test_peer_addr(int sk, sctp_assoc_t asoc, sockaddr_storage_t *peers, int count);
+
+#endif /* __sctputil_h__ */