summaryrefslogtreecommitdiffstats
path: root/src/server
diff options
context:
space:
mode:
Diffstat (limited to 'src/server')
-rw-r--r--src/server/net.c37
-rw-r--r--src/server/rpc.c11
-rw-r--r--src/server/rpc.h1
-rw-r--r--src/server/server.c39
4 files changed, 84 insertions, 4 deletions
diff --git a/src/server/net.c b/src/server/net.c
index c7d34de..c11a78a 100644
--- a/src/server/net.c
+++ b/src/server/net.c
@@ -69,6 +69,9 @@ void net_updateGlobalSentStatsFromClient(dnbd3_client_t * const client)
static inline bool recv_request_header(int sock, dnbd3_request_t *request)
{
ssize_t ret, fails = 0;
+#ifdef AFL_MODE
+ sock = 0;
+#endif
// Read request header from socket
while ( ( ret = recv( sock, request, sizeof(*request), MSG_WAITALL ) ) != sizeof(*request) ) {
if ( errno == EINTR && ++fails < 10 ) continue;
@@ -93,6 +96,9 @@ static inline bool recv_request_header(int sock, dnbd3_request_t *request)
static inline bool recv_request_payload(int sock, uint32_t size, serialized_buffer_t *payload)
{
+#ifdef AFL_MODE
+ sock = 0;
+#endif
if ( size == 0 ) {
logadd( LOG_ERROR, "Called recv_request_payload() to receive 0 bytes" );
return false;
@@ -169,7 +175,11 @@ void* net_handleNewConnection(void *clientPtr)
// Await data from client. Since this is a fresh connection, we expect data right away
sock_setTimeout( client->sock, _clientTimeout );
do {
+#ifdef AFL_MODE
+ const int ret = (int)recv( 0, &request, sizeof(request), MSG_WAITALL );
+#else
const int ret = (int)recv( client->sock, &request, sizeof(request), MSG_WAITALL );
+#endif
// It's expected to be a real dnbd3 client
// Check request for validity. This implicitly dictates that all HTTP requests are more than 16 bytes...
if ( ret != (int)sizeof(request) ) {
@@ -408,7 +418,32 @@ void* net_handleNewConnection(void *clientPtr)
realBytes = image->realFilesize - offset;
}
while ( done < realBytes ) {
-#ifdef __linux__
+#ifdef AFL_MODE
+ char buf[1000];
+ size_t cnt = realBytes - done;
+ if ( cnt > 1000 ) {
+ cnt = 1000;
+ }
+ const ssize_t ret = pread( image_file, buf, cnt, offset );
+ if ( ret <= 0 ) {
+ const int err = errno;
+ if ( lock ) pthread_mutex_unlock( &client->sendMutex );
+ if ( ret == -1 ) {
+ if ( err != EPIPE && err != ECONNRESET && err != ESHUTDOWN
+ && err != EAGAIN && err != EWOULDBLOCK ) {
+ logadd( LOG_DEBUG1, "sendfile to %s failed (image to net. sent %d/%d, errno=%d)",
+ client->hostName, (int)done, (int)realBytes, err );
+ }
+ if ( err == EBADF || err == EFAULT || err == EINVAL || err == EIO ) {
+ logadd( LOG_INFO, "Disabling %s:%d", image->name, image->rid );
+ image->working = false;
+ }
+ }
+ goto exit_client_cleanup;
+ }
+ write( client->sock, buf, ret );
+ done += ret;
+#elif defined(__linux__)
const ssize_t ret = sendfile( client->sock, image_file, &foffset, realBytes - done );
if ( ret <= 0 ) {
const int err = errno;
diff --git a/src/server/rpc.c b/src/server/rpc.c
index f64e90a..97cca9e 100644
--- a/src/server/rpc.c
+++ b/src/server/rpc.c
@@ -133,7 +133,11 @@ void rpc_sendStatsJson(int sock, dnbd3_host_t* host, const void* data, const int
// Reaching here means partial request or parse error
if ( pret == -2 ) { // Partial, keep reading
prevLen = hoff;
+#ifdef AFL_MODE
+ ssize_t ret = recv( 0, headerBuf + hoff, sizeof(headerBuf) - hoff, 0 );
+#else
ssize_t ret = recv( sock, headerBuf + hoff, sizeof(headerBuf) - hoff, 0 );
+#endif
if ( ret == 0 ) return;
if ( ret == -1 ) {
if ( errno == EINTR ) continue;
@@ -260,6 +264,9 @@ static bool sendReply(int sock, const char *status, const char *ctype, const cha
if ( keepAlive == HTTP_CLOSE ) {
// Wait for flush
shutdown( sock, SHUT_WR );
+#ifdef AFL_MODE
+ sock = 0;
+#endif
while ( read( sock, buffer, sizeof buffer ) > 0 );
return false;
}
@@ -303,7 +310,11 @@ static int getacl(dnbd3_host_t *host)
if ( aclRules[i].bitMask != 0 && aclRules[i].host[aclRules[i].bytes] != ( host->addr[aclRules[i].bytes] & aclRules[i].bitMask ) ) continue;
return aclRules[i].permissions;
}
+#ifdef AFL_MODE
+ return 0x7fffff;
+#else
return 0;
+#endif
}
#define SETBIT(x) else if ( strcmp( argv[i], #x ) == 0 ) mask |= ACL_ ## x
diff --git a/src/server/rpc.h b/src/server/rpc.h
index 1d50e77..f337067 100644
--- a/src/server/rpc.h
+++ b/src/server/rpc.h
@@ -3,6 +3,7 @@
struct dnbd3_host_t;
+void rpc_init();
void rpc_sendStatsJson(int sock, struct dnbd3_host_t* host, const void *data, const int dataLen);
#endif
diff --git a/src/server/server.c b/src/server/server.c
index 5932b0b..5776765 100644
--- a/src/server/server.c
+++ b/src/server/server.c
@@ -28,6 +28,7 @@
#include "altservers.h"
#include "integrity.h"
#include "threadpool.h"
+#include "rpc.h"
#include "../version.h"
#include "../shared/sockhelper.h"
@@ -227,6 +228,40 @@ int main(int argc, char *argv[])
exit( EXIT_FAILURE );
}
+ timing_setBase();
+ timing_get( &startupTime );
+
+#ifdef AFL_MODE
+ // ###### AFL
+ //
+ image_serverStartup();
+ net_init();
+ uplink_globalsInit();
+ rpc_init();
+ if ( !image_loadAll( NULL ) || _shutdown ) {
+ fprintf( stderr, "Error loading images\n" );
+ exit( 3 );
+ }
+ {
+ struct sockaddr_storage client;
+ memset( &client, 0, sizeof client );
+ client.ss_family = AF_INET;
+ dnbd3_client_t *dnbd3_client = dnbd3_prepareClient( &client, 1 );
+ if ( dnbd3_client == NULL ) {
+ fprintf( stderr, "New client failed\n" );
+ exit( 1 );
+ }
+#ifdef __AFL_HAVE_MANUAL_CONTROL
+ __AFL_INIT();
+#endif
+ net_handleNewConnection( dnbd3_client );
+ exit( 0 );
+ }
+ //
+ // ###### AFL END
+#endif
+
+
// One-shots first:
if ( paramCreate != NULL ) {
@@ -236,12 +271,12 @@ int main(int argc, char *argv[])
// No one-shot detected, normal server operation
if ( demonize ) daemon( 1, 0 );
- timing_setBase();
image_serverStartup();
altservers_init();
integrity_init();
net_init();
uplink_globalsInit();
+ rpc_init();
logadd( LOG_INFO, "DNBD3 server starting.... Machine type: " ENDIAN_MODE );
if ( altservers_load() < 0 ) {
@@ -268,8 +303,6 @@ int main(int argc, char *argv[])
return 0;
}
- timing_get( &startupTime );
-
// Give other threads some time to start up before accepting connections
sleep( 1 );