Fuzzer integration (#356)

* Cleanup of merge error

* Refactor fuzzing options

* merge upcall with unconnected

* Update CMAKE files

* sync

* disable prints, enable features

* move setsockopt call

* checkout master

* revert compiler options

* Revert compiler options

* Do not dump packets to file by default

* add sanitizer blacklist entries

* update black list, rename programs

* revert experimental changes

* add mutex timeout

* sync

* sync

* sync

* sync

* sync

* cleanup

* compile fix for gcc

* fuzzer sync

* sync

* sync

* sync

* sync

* sync

* sync

* sync

* sync

* sync

* Rever temporary fix

* compilefix

* improve directory handling

* be more verbose (#312)

* Improve and of ICMP messages on Windows.

When an ICMP message is received on Windows 10 for a UDP socket,
WSAECONNRESET is reported as an error. In this case, just read
again.

Thanks to nxrighthere for reporting the issue and helping to
nail it down.

This fixes #309.

* Fix broken links, Make URLs' protocols consistent (#315)

Two Links missed leading `http(s)://` and were broken.
All links to `tools.ietf.org` now consistently use https.

* Backport https://svnweb.freebsd.org/base?view=revision&revision=340783

* Improve input validation for the IPPROTO_SCTP level socket options
SCTP_CONNECT_X and SCTP_CONNECT_X_DELAYED.

* Allow sending on demand SCTP HEARTBEATS only in the ESTABLISHED state.

* Fix cross-build linux->mingw (#320)

* sync

* sync

* sync

* sync

* sync

* cmake cleanup

* sync

* sync

* sync

* sync

* revert changes

* Sync

* sync

* bugfix

* bugfix

* sync

* sync

* sync

* sync

* sync

* sync

* sync

* sync

* sync

* sync

* sync

* sync

* sync

* sync

* sync

* Improve RNG for fuzzing

* sync

* fuzzer_connected

* Sync

* sync

* sync

* sync

* sync

* Sync

* sync

* chain.sh removed

* sync

* sync
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b381c13..dfc2fb6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -77,6 +77,12 @@
 
 option(sctp_sanitizer_memory "Compile with memory sanitizer" 0)
 
+option(sctp_build_fuzzer "Compile in clang fuzzing mode" 0)
+if (sctp_build_fuzzer)
+	add_definitions(-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=fuzzer-no-link")
+endif ()
+
 if (sctp_sanitizer_address AND sctp_sanitizer_memory)
 	message(FATAL_ERROR "Can not compile with both sanitizer options")
 endif ()
@@ -212,12 +218,17 @@
 	endif ()
 
 	if (sctp_sanitizer_address)
-		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer -g")
+		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address,undefined,signed-integer-overflow -fno-sanitize-recover=all -fsanitize-address-use-after-scope ")
 	endif ()
 
 	if (sctp_sanitizer_memory)
-		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory -fno-omit-frame-pointer -g -fsanitize-memory-track-origins")
+		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins -fPIE")
 	endif ()
+
+	if (sctp_sanitizer_address OR sctp_sanitizer_memory)
+		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer -fsanitize-coverage=edge,indirect-calls,trace-cmp,trace-div,trace-gep")
+	endif ()
+
 endif ()
 
 # SETTINGS FOR VISUAL STUDIO COMPILER
@@ -258,3 +269,7 @@
 if (sctp_build_programs)
 	add_subdirectory(programs)
 endif ()
+
+if (sctp_build_fuzzer)
+	add_subdirectory(fuzzer)
+endif ()
diff --git a/fuzzer/CMakeLists.txt b/fuzzer/CMakeLists.txt
new file mode 100644
index 0000000..c2b3427
--- /dev/null
+++ b/fuzzer/CMakeLists.txt
@@ -0,0 +1,93 @@
+#
+# Copyright (C) 2015-2019 Felix Weinrank
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the project nor the names of its contributors
+#    may be used to endorse or promote products derived from this software
+#    without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+#project(usrsctp-fuzzer C)
+
+#################################################
+# INCLUDE MODULES
+#################################################
+
+include(CheckIncludeFile)
+
+
+#################################################
+# CHECK INCLUDES
+#################################################
+
+include_directories(${CMAKE_SOURCE_DIR}/usrsctplib)
+
+
+#################################################
+# OS DEPENDENT
+#################################################
+
+if (CMAKE_SYSTEM_NAME MATCHES "Linux")
+	add_definitions(-D_GNU_SOURCE)
+endif ()
+
+if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
+	add_definitions(-D__APPLE_USE_RFC_2292)
+endif ()
+
+#################################################
+# COMPILER FLAGS
+#################################################
+
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-gnu-zero-variadic-macro-arguments")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=fuzzer")
+
+
+#################################################
+# PROGRAMS
+#################################################
+
+# if in fuzzing mode, only build the fuzzer
+configure_file(crashtest.py crashtest.py COPYONLY)
+configure_file(fuzzer_unconnected.sh fuzzer_unconnected.sh COPYONLY)
+configure_file(fuzzer_connected.sh fuzzer_connected.sh COPYONLY)
+
+list(APPEND check_programs
+	fuzzer_unconnected.c
+	fuzzer_connected.c
+)
+
+foreach (source_file ${check_programs})
+	get_filename_component(source_file_we ${source_file} NAME_WE)
+	add_executable(
+		${source_file_we}
+		${source_file}
+	)
+
+	target_link_libraries(
+		${source_file_we}
+		usrsctp-static
+	)
+endforeach ()
+
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000000 b/fuzzer/CORPUS_CONNECTED/tsctp-000000
new file mode 100644
index 0000000..5f4b76f
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000000
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000001 b/fuzzer/CORPUS_CONNECTED/tsctp-000001
new file mode 100644
index 0000000..f3f91d4
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000001
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000002 b/fuzzer/CORPUS_CONNECTED/tsctp-000002
new file mode 100644
index 0000000..869584a
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000002
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000003 b/fuzzer/CORPUS_CONNECTED/tsctp-000003
new file mode 100644
index 0000000..d1dcf30
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000003
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000004 b/fuzzer/CORPUS_CONNECTED/tsctp-000004
new file mode 100644
index 0000000..cf48b7c
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000004
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000005 b/fuzzer/CORPUS_CONNECTED/tsctp-000005
new file mode 100644
index 0000000..7663ed1
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000005
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000006 b/fuzzer/CORPUS_CONNECTED/tsctp-000006
new file mode 100644
index 0000000..68612f5
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000006
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000007 b/fuzzer/CORPUS_CONNECTED/tsctp-000007
new file mode 100644
index 0000000..a257514
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000007
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000008 b/fuzzer/CORPUS_CONNECTED/tsctp-000008
new file mode 100644
index 0000000..9bab1d9
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000008
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000009 b/fuzzer/CORPUS_CONNECTED/tsctp-000009
new file mode 100644
index 0000000..5c66cd4
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000009
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000010 b/fuzzer/CORPUS_CONNECTED/tsctp-000010
new file mode 100644
index 0000000..f1a5f41
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000010
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000011 b/fuzzer/CORPUS_CONNECTED/tsctp-000011
new file mode 100644
index 0000000..d7354b5
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000011
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000012 b/fuzzer/CORPUS_CONNECTED/tsctp-000012
new file mode 100644
index 0000000..e17aa3d
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000012
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000013 b/fuzzer/CORPUS_CONNECTED/tsctp-000013
new file mode 100644
index 0000000..4f80bf7
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000013
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000014 b/fuzzer/CORPUS_CONNECTED/tsctp-000014
new file mode 100644
index 0000000..0eef0b9
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000014
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000015 b/fuzzer/CORPUS_CONNECTED/tsctp-000015
new file mode 100644
index 0000000..b6c31ae
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000015
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000016 b/fuzzer/CORPUS_CONNECTED/tsctp-000016
new file mode 100644
index 0000000..509437a
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000016
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000017 b/fuzzer/CORPUS_CONNECTED/tsctp-000017
new file mode 100644
index 0000000..c7674e2
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000017
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000018 b/fuzzer/CORPUS_CONNECTED/tsctp-000018
new file mode 100644
index 0000000..482769e
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000018
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000019 b/fuzzer/CORPUS_CONNECTED/tsctp-000019
new file mode 100644
index 0000000..622af61
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000019
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000020 b/fuzzer/CORPUS_CONNECTED/tsctp-000020
new file mode 100644
index 0000000..7074c9f
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000020
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000021 b/fuzzer/CORPUS_CONNECTED/tsctp-000021
new file mode 100644
index 0000000..1b2990f
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000021
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000022 b/fuzzer/CORPUS_CONNECTED/tsctp-000022
new file mode 100644
index 0000000..2ccb150
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000022
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000023 b/fuzzer/CORPUS_CONNECTED/tsctp-000023
new file mode 100644
index 0000000..dd56535
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000023
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000024 b/fuzzer/CORPUS_CONNECTED/tsctp-000024
new file mode 100644
index 0000000..9108b6c
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000024
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000025 b/fuzzer/CORPUS_CONNECTED/tsctp-000025
new file mode 100644
index 0000000..6ee1c5b
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000025
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000026 b/fuzzer/CORPUS_CONNECTED/tsctp-000026
new file mode 100644
index 0000000..503dd8e
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000026
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000027 b/fuzzer/CORPUS_CONNECTED/tsctp-000027
new file mode 100644
index 0000000..bd689bc
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000027
Binary files differ
diff --git a/fuzzer/CORPUS_CONNECTED/tsctp-000028 b/fuzzer/CORPUS_CONNECTED/tsctp-000028
new file mode 100644
index 0000000..d1e11ef
--- /dev/null
+++ b/fuzzer/CORPUS_CONNECTED/tsctp-000028
Binary files differ
diff --git a/fuzzer/crashtest.py b/fuzzer/crashtest.py
new file mode 100755
index 0000000..d9c3fe6
--- /dev/null
+++ b/fuzzer/crashtest.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+import glob
+import subprocess
+import os
+
+reportdir = "reports/"
+fuzzer = "./fuzzer_connected"
+
+class bcolors:
+	HEADER = '\033[95m'
+	OKBLUE = '\033[94m'
+	OKGREEN = '\033[92m'
+	WARNING = '\033[93m'
+	FAIL = '\033[91m'
+	ENDC = '\033[0m'
+	BOLD = '\033[1m'
+	UNDERLINE = '\033[4m'
+
+
+print("Testing crashfiles")
+
+FNULL = open(os.devnull, "w")
+crashfiles = []
+crashfiles.extend(glob.glob("crash-*"))
+crashfiles.extend(glob.glob("timeout-*"))
+
+if not os.path.exists(reportdir):
+	os.makedirs(reportdir)
+
+num_files = len(crashfiles)
+filecounter = 1
+for filename in crashfiles:
+	filename_report = '{}{}{}'.format(reportdir, filename, '.report')
+	reportfile = open(filename_report, "w")
+	fuzzer_retval = subprocess.call([fuzzer, "-timeout=6", filename], stdout=reportfile, stderr=reportfile)
+	if fuzzer_retval == 0:
+		print(bcolors.FAIL, "[", filecounter, "/", num_files, "]", filename,"- not reproducable", bcolors.ENDC)
+		reportfile.close()
+		os.remove(filename_report)
+	else:
+		print(bcolors.OKGREEN, "[", filecounter, "/", num_files, "]", filename, "- reproducable", bcolors.ENDC)
+		reportfile.write("\n>> HEXDUMP <<\n\n")
+		reportfile.flush()
+		subprocess.call(["hexdump", "-Cv", filename], stdout=reportfile)
+
+	filecounter = filecounter + 1
diff --git a/fuzzer/fuzzer_connected.c b/fuzzer/fuzzer_connected.c
new file mode 100644
index 0000000..ab04983
--- /dev/null
+++ b/fuzzer/fuzzer_connected.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2017-2019 Felix Weinrank
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.	IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/time.h>
+#include <usrsctp.h>
+
+//#define FUZZ_VERBOSE
+
+static const char *init_ack = "\x13\x89\xe7\xd0\xef\x38\x12\x25\x00\x00\x00\x00\x02\x00\x01\x4c" \
+"\x20\x0f\x67\x0d\x00\x02\x00\x00\x00\x04\x00\x04\xbd\xf0\x8d\x18" \
+"\xc0\x00\x00\x04\x80\x08\x00\x09\xc0\x0f\xc1\x80\x82\x00\x00\x00" \
+"\x80\x02\x00\x24\xfd\x30\xc7\x17\x34\x27\x17\x1c\xa2\xc6\x78\x20" \
+"\x62\xc3\xa1\x3f\xb6\x86\x92\x42\xc5\x0b\xb6\x36\xd7\xf6\xf4\x19" \
+"\xee\xd3\xc9\x1e\x80\x04\x00\x06\x00\x01\x00\x00\x80\x03\x00\x06" \
+"\x80\xc1\x00\x00\x00\x07\x00\xf4\x4b\x41\x4d\x45\x2d\x42\x53\x44" \
+"\x20\x31\x2e\x31\x00\x00\x00\x00\x25\xfa\x5e\x5d\x00\x00\x00\x00" \
+"\xe6\xc3\x0a\x00\x00\x00\x00\x00\x60\xea\x00\x00\x54\x6f\x2d\xff" \
+"\xd1\x7f\x68\x2a\x00\x00\x00\x01\x20\x0f\x67\x0d\x80\x3b\x00\x00" \
+"\xc0\x60\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00" \
+"\x80\x3b\x00\x00\xc0\x60\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
+"\x04\x00\x00\x00\x00\x00\x00\x00\x13\x88\x13\x88\x00\x00\x01\x00" \
+"\x01\x01\x01\x00\x00\x00\x00\x00\x01\x00\x00\x14\x01\x00\x00\x00" \
+"\x00\x00\x20\x00\x00\x08\x00\x08\x00\x00\x00\x01\x02\x00\x01\x4c" \
+"\x20\x0f\x67\x0d\x00\x02\x00\x00\x00\x04\x00\x04\xbd\xf0\x8d\x18" \
+"\xc0\x00\x00\x04\x80\x08\x00\x09\xc0\x0f\xc1\x80\x82\x00\x00\x00" \
+"\x80\x02\x00\x24\xfd\x30\xc7\x17\x34\x27\x17\x1c\xa2\xc6\x78\x20" \
+"\x62\xc3\xa1\x3f\xb6\x86\x92\x42\xc5\x0b\xb6\x36\xd7\xf6\xf4\x19" \
+"\xee\xd3\xc9\x1e\x80\x04\x00\x06\x00\x01\x00\x00\x80\x03\x00\x06" \
+"\x80\xc1\x00\x00\x41\xc3\xed\x62\x2c\x1c\x3c\x03\x41\x6d\x17\xc8" \
+"\xd8\x64\xff\xe2\x25\xd6\x81\x9e";
+
+static const char *cookie_ack = "\x13\x89\xe7\xd0\xef\x38\x12\x25\x00\x00\x00\x00\x0b\x00\x00\x04";
+static const char *common_header = "\x13\x89\xe7\xd0\xef\x38\x12\x25\x00\x00\x00\x00";
+
+#ifdef FUZZ_VERBOSE
+static char *dump_buf;
+void
+debug_printf(const char *format, ...)
+{
+	static struct timeval time_main;
+
+	va_list ap;
+	struct timeval time_now;
+	struct timeval time_delta;
+
+	if (time_main.tv_sec == 0  && time_main.tv_usec == 0) {
+		gettimeofday(&time_main, NULL);
+	}
+
+	gettimeofday(&time_now, NULL);
+	timersub(&time_now, &time_main, &time_delta);
+
+	fprintf(stderr, "[%u.%03u] ", (unsigned int) time_delta.tv_sec, (unsigned int) time_delta.tv_usec / 1000);
+
+	va_start(ap, format);
+	vprintf(format, ap);
+	va_end(ap);
+}
+#else
+void
+debug_printf(const char *format, ...)
+{
+}
+#endif
+
+
+static int
+conn_output(void *addr, void *buf, size_t length, uint8_t tos, uint8_t set_df)
+{
+#ifdef FUZZ_VERBOSE
+	if ((dump_buf = usrsctp_dumppacket(buf, length, SCTP_DUMP_OUTBOUND)) != NULL) {
+		fprintf(stderr, "%s", dump_buf);
+		usrsctp_freedumpbuffer(dump_buf);
+	}
+#endif
+	return (0);
+}
+
+
+static void
+handle_upcall(struct socket *sock, void *arg, int flgs)
+{
+	debug_printf("handle_upcall() called - implement logic!\n");
+}
+
+
+int
+initialize_fuzzer(void) {
+#ifdef FUZZ_VERBOSE
+	usrsctp_init(0, conn_output, debug_printf);
+#else
+	usrsctp_init(0, conn_output, NULL);
+#endif
+	usrsctp_enable_crc32c_offload();
+	/* set up a connected UDP socket */
+#ifdef SCTP_DEBUG
+	usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL);
+#endif
+	usrsctp_register_address((void *)1);
+	debug_printf("usrsctp initialized\n");
+	return 1;
+}
+
+
+int
+LLVMFuzzerTestOneInput(const uint8_t* data, size_t data_size)
+{
+	static int initialized;
+	char *pktbuf;
+	struct sockaddr_conn sconn;
+	struct socket *socket_client;
+	struct linger so_linger;
+	struct sctp_event event;
+	unsigned long i;
+	uint16_t event_types[] = {
+		SCTP_ASSOC_CHANGE,
+		SCTP_PEER_ADDR_CHANGE,
+		SCTP_SEND_FAILED_EVENT,
+		SCTP_REMOTE_ERROR,
+		SCTP_SHUTDOWN_EVENT,
+		SCTP_ADAPTATION_INDICATION,
+		SCTP_PARTIAL_DELIVERY_EVENT
+	};
+
+	if (!initialized) {
+		initialized = initialize_fuzzer();
+	}
+
+	if ((socket_client = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, 0)) == NULL) {
+		perror("usrsctp_socket");
+		exit(EXIT_FAILURE);
+	}
+
+	usrsctp_set_non_blocking(socket_client, 1);
+
+	so_linger.l_onoff = 1;
+	so_linger.l_linger = 0;
+	if (usrsctp_setsockopt(socket_client, SOL_SOCKET, SO_LINGER, &so_linger, sizeof(struct linger)) < 0) {
+		perror("usrsctp_setsockopt 1");
+		exit(EXIT_FAILURE);
+	}
+
+	memset(&event, 0, sizeof(event));
+	event.se_assoc_id = SCTP_FUTURE_ASSOC;
+	event.se_on = 1;
+	for (i = 0; i < sizeof(event_types)/sizeof(uint16_t); i++) {
+		event.se_type = event_types[i];
+		if (usrsctp_setsockopt(socket_client, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(event)) < 0) {
+			perror("setsockopt SCTP_EVENT socket_client");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	usrsctp_set_upcall(socket_client, handle_upcall, NULL);
+
+	memset(&sconn, 0, sizeof(struct sockaddr_conn));
+	sconn.sconn_family = AF_CONN;
+#ifdef HAVE_SCONN_LEN
+	sconn.sconn_len = sizeof(struct sockaddr_conn);
+#endif
+	sconn.sconn_port = htons(5001);
+	sconn.sconn_addr = (void *)1;
+	if (usrsctp_connect(socket_client, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) {
+		if (errno != EINPROGRESS) {
+			perror("usrsctp_connect");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+#ifdef FUZZ_VERBOSE
+	if ((dump_buf = usrsctp_dumppacket(init_ack, 344, SCTP_DUMP_INBOUND)) != NULL) {
+		fprintf(stderr, "%s", dump_buf);
+		usrsctp_freedumpbuffer(dump_buf);
+	}
+#endif
+	usrsctp_conninput((void *)1, init_ack, 344, 0);
+
+#ifdef FUZZ_VERBOSE
+	if ((dump_buf = usrsctp_dumppacket(cookie_ack, 16, SCTP_DUMP_INBOUND)) != NULL) {
+		fprintf(stderr, "%s", dump_buf);
+		usrsctp_freedumpbuffer(dump_buf);
+	}
+#endif
+	usrsctp_conninput((void *)1, cookie_ack, 16, 0);
+
+	// concat common header and fuzzer input
+	pktbuf = malloc(data_size + 12);
+	memcpy(pktbuf, common_header, 12);
+	memcpy(pktbuf + 12, data, data_size);
+
+#ifdef FUZZ_VERBOSE
+	debug_printf(">>>> INJECTING\n");
+	if ((dump_buf = usrsctp_dumppacket(pktbuf, data_size + 12, SCTP_DUMP_INBOUND)) != NULL) {
+		fprintf(stderr, "%s", dump_buf);
+		usrsctp_freedumpbuffer(dump_buf);
+	}
+#endif
+	usrsctp_conninput((void *)1, pktbuf, data_size + 12, 0);
+
+	usrsctp_close(socket_client);
+	free(pktbuf);
+	return (0);
+}
+
+
diff --git a/fuzzer/fuzzer_connected.sh b/fuzzer/fuzzer_connected.sh
new file mode 100755
index 0000000..b591bb9
--- /dev/null
+++ b/fuzzer/fuzzer_connected.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+export ASAN_OPTIONS=abort_on_error=1:disable_core=0:unmap_shadow_on_exit=1:disable_coredump=0
+ulimit -c unlimited
+mkdir -p CORPUS_CONNECTED
+./fuzzer_connected -jobs=32 -timeout=10 -max_len=4086 CORPUS_CONNECTED
diff --git a/fuzzer/fuzzer_unconnected.c b/fuzzer/fuzzer_unconnected.c
new file mode 100644
index 0000000..2cc353f
--- /dev/null
+++ b/fuzzer/fuzzer_unconnected.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2017-2019 Felix Weinrank
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.	IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <usrsctp.h>
+
+#define FUZZ_FAST 1
+
+struct sockaddr_conn sconn;
+struct socket *s_l;
+
+static int
+conn_output(void *addr, void *buf, size_t length, uint8_t tos, uint8_t set_df)
+{
+#if 0
+	char *dump_buf;
+	if ((dump_buf = usrsctp_dumppacket(buf, length, SCTP_DUMP_OUTBOUND)) != NULL) {
+		fprintf(stderr, "%s", dump_buf);
+		usrsctp_freedumpbuffer(dump_buf);
+	}
+#endif
+	return (0);
+}
+
+static void
+handle_upcall(struct socket *sock, void *arg, int flgs)
+{
+	fprintf(stderr, "Listening socket established, implement logic!\n");
+	exit(EXIT_FAILURE);
+}
+
+int
+init_fuzzer(void) {
+	static uint8_t initialized = 0;
+	struct sctp_event event;
+	uint16_t event_types[] = {
+		SCTP_ASSOC_CHANGE,
+		SCTP_PEER_ADDR_CHANGE,
+		SCTP_SEND_FAILED_EVENT,
+		SCTP_REMOTE_ERROR,
+		SCTP_SHUTDOWN_EVENT,
+		SCTP_ADAPTATION_INDICATION,
+		SCTP_PARTIAL_DELIVERY_EVENT};
+	unsigned long i;
+
+#if defined(FUZZ_FAST)
+	if (initialized) {
+		return 0;
+	}
+#endif
+
+	usrsctp_init(0, conn_output, NULL);
+	usrsctp_enable_crc32c_offload();
+	/* set up a connected UDP socket */
+#ifdef SCTP_DEBUG
+	usrsctp_sysctl_set_sctp_debug_on(SCTP_DEBUG_ALL);
+#endif
+	usrsctp_register_address((void *)1);
+
+	if ((s_l = usrsctp_socket(AF_CONN, SOCK_STREAM, IPPROTO_SCTP, NULL, NULL, 0, 0)) == NULL) {
+		perror("usrsctp_socket");
+		exit(EXIT_FAILURE);
+	}
+	usrsctp_set_non_blocking(s_l, 1);
+
+	/* Bind the server side. */
+	memset(&sconn, 0, sizeof(struct sockaddr_conn));
+	sconn.sconn_family = AF_CONN;
+#ifdef HAVE_SCONN_LEN
+	sconn.sconn_len = sizeof(struct sockaddr_conn);
+#endif
+	sconn.sconn_port = htons(5001);
+	sconn.sconn_addr = (void *)1;
+	if (usrsctp_bind(s_l, (struct sockaddr *)&sconn, sizeof(struct sockaddr_conn)) < 0) {
+		perror("usrsctp_bind");
+		exit(EXIT_FAILURE);
+	}
+
+	memset(&event, 0, sizeof(event));
+	event.se_assoc_id = SCTP_FUTURE_ASSOC;
+	event.se_on = 1;
+	for (i = 0; i < sizeof(event_types)/sizeof(uint16_t); i++) {
+		event.se_type = event_types[i];
+		if (usrsctp_setsockopt(s_l, IPPROTO_SCTP, SCTP_EVENT, &event, sizeof(event)) < 0) {
+			perror("setsockopt SCTP_EVENT s_l");
+			exit(EXIT_FAILURE);
+		}
+	}
+
+	/* Make server side passive... */
+	if (usrsctp_listen(s_l, 1) < 0) {
+		perror("usrsctp_listen");
+		exit(EXIT_FAILURE);
+	}
+
+	usrsctp_set_upcall(s_l, handle_upcall, NULL);
+
+	initialized = 1;
+
+	return (0);
+}
+
+int
+LLVMFuzzerTestOneInput(const uint8_t* data, size_t data_size)
+{
+	init_fuzzer();
+	usrsctp_conninput((void *)1, data, data_size, 0);
+
+#if !defined(FUZZ_FAST)
+	usrsctp_close(s_l);
+	while (usrsctp_finish() != 0) {
+		//sleep(1);
+	}
+#endif
+
+	return (0);
+}
+
+
diff --git a/fuzzer/fuzzer_unconnected.sh b/fuzzer/fuzzer_unconnected.sh
new file mode 100755
index 0000000..d9efd52
--- /dev/null
+++ b/fuzzer/fuzzer_unconnected.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+export ASAN_OPTIONS=abort_on_error=1:disable_core=0:unmap_shadow_on_exit=1:disable_coredump=0
+ulimit -c unlimited
+mkdir -p CORPUS_UNCONNECTED
+./fuzzer_unconnected -jobs=32 -timeout=10 -max_len=4086 CORPUS_UNCONNECTED
diff --git a/fuzzer/text2pcap.sh b/fuzzer/text2pcap.sh
new file mode 100644
index 0000000..0c46c3b
--- /dev/null
+++ b/fuzzer/text2pcap.sh
@@ -0,0 +1 @@
+text2pcap -n -l 248 -D -t "%H:%M:%S." fuzzer.log fuzzer.pcapng
diff --git a/programs/CMakeLists.txt b/programs/CMakeLists.txt
index 45c772b..d9b89d8 100644
--- a/programs/CMakeLists.txt
+++ b/programs/CMakeLists.txt
@@ -65,7 +65,7 @@
 
 	if (CMAKE_C_COMPILER_ID MATCHES "GNU")
 		message(STATUS "MSYS / MINGW + GCC")
-		set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   -Wno-format")
+		set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-format")
 	endif ()
 endif ()
 
diff --git a/programs/programs_helper.c b/programs/programs_helper.c
index 0325a81..0119f30 100644
--- a/programs/programs_helper.c
+++ b/programs/programs_helper.c
@@ -47,7 +47,7 @@
 	gettimeofday(&time_now, NULL);
 	timersub(&time_now, &time_main, &time_delta);
 
-	printf("[%u.%03u] ", (unsigned int) time_delta.tv_sec, (unsigned int) time_delta.tv_usec / 1000);
+	fprintf(stderr, "[%u.%03u] ", (unsigned int) time_delta.tv_sec, (unsigned int) time_delta.tv_usec / 1000);
 
 	va_start(ap, format);
 	vprintf(format, ap);
diff --git a/usrsctplib/CMakeLists.txt b/usrsctplib/CMakeLists.txt
index 3194e25..2d95610 100644
--- a/usrsctplib/CMakeLists.txt
+++ b/usrsctplib/CMakeLists.txt
@@ -59,13 +59,13 @@
 
 if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
 	add_definitions(-U__FreeBSD__)
-	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}     -Wno-address-of-packed-member")
+	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-address-of-packed-member")
 endif ()
 
 if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
 	add_definitions(-U__APPLE__)
 	add_definitions(-D__APPLE_USE_RFC_2292)
-	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}     -Wno-address-of-packed-member -Wno-deprecated-declarations")
+	set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-address-of-packed-member -Wno-deprecated-declarations")
 endif ()
 
 if (CMAKE_SYSTEM_NAME MATCHES "DragonFly")
@@ -80,6 +80,11 @@
 	add_definitions(-U__OpenBSD__)
 endif ()
 
+#################################################
+# MISC
+#################################################
+
+
 
 #################################################
 # LIBRARY FILES
diff --git a/usrsctplib/netinet/sctp_usrreq.c b/usrsctplib/netinet/sctp_usrreq.c
index 5ff7a2a..dd5929d 100755
--- a/usrsctplib/netinet/sctp_usrreq.c
+++ b/usrsctplib/netinet/sctp_usrreq.c
@@ -92,11 +92,19 @@
 	sctp_init_sysctls();
 #if defined(__Userspace__)
 #if defined(__Userspace_os_Windows) || defined(__Userspace_os_NaCl)
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+	srand(0);
+#else
 	srand((unsigned int)time(NULL));
+#endif
+#else
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+	srandom(0);
 #else
 	srandom(getpid()); /* so inp->sctp_ep.random_numbers are truly random... */
 #endif
 #endif
+#endif
 #if defined(__Panda__)
 	sctp_sendspace = SB_MAX;
 	sctp_recvspace = SB_MAX;
diff --git a/usrsctplib/user_environment.c b/usrsctplib/user_environment.c
index 767c4ba..cb77a22 100755
--- a/usrsctplib/user_environment.c
+++ b/usrsctplib/user_environment.c
@@ -64,6 +64,14 @@
  * provide _some_ kind of randomness. This should only be used
  * inside other RNG's, like arc4random(9).
  */
+#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+static int
+read_random_phony(void *buf, int count)
+{
+	memset(buf, 'A', count);
+	return (count);
+}
+#else
 #if defined(__Userspace_os_FreeBSD) || defined(__Userspace_os_Darwin)
 static int
 read_random_phony(void *buf, int count)
@@ -92,6 +100,7 @@
 	return (count);
 }
 #endif
+#endif
 
 static int (*read_func)(void *, int) = read_random_phony;