about summary refs log tree commit diff stats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/handlers.c535
-rw-r--r--src/main.c313
-rw-r--r--src/netascii.c53
-rw-r--r--src/packet.c125
4 files changed, 0 insertions, 1026 deletions
diff --git a/src/handlers.c b/src/handlers.c
deleted file mode 100644
index d42382e..0000000
--- a/src/handlers.c
+++ /dev/null
@@ -1,535 +0,0 @@
-#ifdef __linux__
-#define _POSIX_C_SOURCE 200809L
-#define _DEFAULT_SOURCE
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include <syslog.h>
-#include <limits.h>
-#include <errno.h>
-#include <unistd.h>
-#ifdef __FreeBSD__
-#include <sys/param.h>
-#endif
-
-#include "handlers.h"
-#include "packet.h"
-#include "netascii.h"
-
-inline nbd_opmode get_mode(char *mode) {
-	nbd_opmode opmode;
-	if (strncmp(mode, (char *)&"netascii", NBD_NBTPD_ARGS_MODE_MAX) == 0) {
-		opmode = NETASCII;
-	} else if (strncmp(mode, (char *)&"octet", NBD_NBTPD_ARGS_MODE_MAX) == 0) {
-		opmode = OCTET;
-	} else if (strncmp(mode, (char *)&"mail", NBD_NBTPD_ARGS_MODE_MAX) == 0) {
-		opmode = MAIL;
-	} else {
-		opmode = NOT_FOUND;
-	}
-	return opmode;
-}
-
-int makesock(nbd_nbtpd_args *argptr) {
-	int s = socket(AF_INET, SOCK_DGRAM, 0);
-	if (s <= 0) {
-		syslog(LOG_ERR, "unable to define socket: %s", strerror(errno));
-		return -1;
-	}
-	struct timeval timeout = { 30, 0 };
-	if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
-		syslog(LOG_ERR, "unable to set socket timeout: %s", strerror(errno));
-		close(s);
-		return -1;
-	}
-	if (connect(s, (struct sockaddr *)&(argptr->client), sizeof(struct sockaddr)) < 0) {
-		syslog(
-			LOG_ERR,
-			"unable to connect to client %s: %s",
-			inet_ntoa(argptr->client.sin_addr),
-			strerror(errno)
-		);
-		close(s);
-		return -1;
-	}
-	return s;
-}
-
-char *checkpath(nbd_nbtpd_args *argptr, uint8_t read) {
-	char *fname = NULL, *wd = NULL, *path = NULL, *ptr = NULL;
-	char **parts = NULL;
-	if (!is_netascii_str((char *)&argptr->path)) {
-		argptr->err = 1;
-		goto cleanup;
-	}
-	if (read) {
-		fname = realpath((char *)&argptr->path, NULL);
-	} else {
-		//TODO: figure out how to canonicalize non-existent path
-		char *tok = NULL;
-		parts = malloc(sizeof(parts) * NBD_NBTPD_ARGS_PATH_MAX);
-		if (parts == NULL) {
-			goto cleanup;
-		}
-		memset(parts, '\0', sizeof(parts) * NBD_NBTPD_ARGS_PATH_MAX);
-		ptr = (char *)&argptr->path;
-		for (int i = 0; ((tok = strsep(&ptr, "/")) != NULL); i++ ) {
-			parts[i] = tok;
-		}
-		path = malloc(NBD_NBTPD_ARGS_PATH_MAX);
-		if (path == NULL) {
-			goto cleanup;
-		}
-		memset(path, '\0', NBD_NBTPD_ARGS_PATH_MAX);
-		int z = 0;
-		for (int i = 0; parts[i] != NULL; i++) {
-			if (strncmp(parts[i], "..", 2) == 0) {
-				continue;
-			}
-			if (strncmp(parts[i], ".", NBD_NBTPD_ARGS_PATH_MAX) == 0) {
-				continue;
-			}
-			for (int x = 0; parts[i][x] != '\0'; x++) {
-				if (z < NBD_NBTPD_ARGS_PATH_MAX) {
-					path[z++] = parts[i][x];
-				} else {
-					goto cleanup;
-				}
-			}
-			if (z < NBD_NBTPD_ARGS_PATH_MAX) {
-				path[z++] = '/';
-			} else {
-				goto cleanup;
-			}
-		}
-		// erase trailing slash
-		path[z - 1] = '\0';
-		fname = strdup(path);
-	}
-	if (fname == NULL) {
-		syslog(LOG_ERR, "unable to get real path: %s", strerror(errno));
-		argptr->err = 1;
-		goto cleanup;
-	}
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * POSIX does not define what happens when getcwd() is given NULL.     *
- * This means that illumos libc and GNU libc both return a newly       *
- * malloc()'d string, while FreeBSD libc does not.  Also, FreeBSD uses *
- * constant MAXPATHLEN defined in <sys/param.h> rather than PATH_MAX.  *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-#ifdef __FreeBSD__
-	wd = malloc(MAXPATHLEN);
-	if (wd == NULL) {
-		syslog(LOG_ERR, "unable to allocate PATH_MAX memory: %s", strerror(errno));
-		argptr->err = 0;
-		goto cleanup;
-	}
-	if (getcwd(wd, MAXPATHLEN) == NULL) {
-		argptr->err = 0;
-		goto cleanup;
-	}
-#else
-	if ((wd = getcwd(NULL, PATH_MAX)) == NULL) {
-		argptr->err = 0;
-		goto cleanup;
-	}
-#endif
-	syslog(LOG_DEBUG, "cwd: %s :: realpath: %s", wd, fname);
-	if (read) {
-		if (strncmp(wd, fname, strlen(wd))) {
-			syslog(
-				LOG_ERR,
-				"%s:%d requested invalid file %s",
-				inet_ntoa(argptr->client.sin_addr),
-				ntohs(argptr->client.sin_port),
-				fname
-			);
-			argptr->err = 2;
-			goto cleanup;
-		}
-	} else {
-		strcat(wd, "/");
-		strcat(wd, fname);
-		char *intermediate = wd;
-		wd = fname;
-		fname = intermediate;
-	}
-cleanup:
-	free(wd);
-	free(path);
-	free(parts);
-	return fname;
-}
-
-ssize_t senderror(int s, nbd_nbtpd_args *argptr) {
-	size_t buflen = 4 + strlen(nbd_tftp_error_to_message((nbd_tftp_ecode)argptr->err));
-	char *buf = nbd_tftp_ser_error_from_code((nbd_tftp_ecode)argptr->err);
-	ssize_t sb = send(s, buf, buflen, 0);
-	free(buf);
-	return sb;
-}
-
-void *read_req_resp(void *args) {
-	char *fname = NULL, *buf = NULL, *rxb = NULL;
-	FILE *fp = NULL;
-	nbd_nbtpd_args *argptr = (nbd_nbtpd_args *)args;
-	syslog(
-		LOG_DEBUG,
-		"%s:%d is requesting file %s",
-		inet_ntoa(argptr->client.sin_addr),
-		ntohs(argptr->client.sin_port),
-		argptr->path
-	);
-	fname = checkpath(argptr, 1);
-	if (fname == NULL) {
-		goto pre_socket;
-	}
-	if (!is_netascii_str((char *)&(argptr->mode))) {
-		syslog(
-			LOG_ERR,
-			"%s:%d mode is invalid %s",
-			inet_ntoa(argptr->client.sin_addr),
-			ntohs(argptr->client.sin_port),
-			argptr->mode
-		);
-		argptr->err = 4;
-		goto pre_socket;
-	}
-	nbd_opmode opmode = get_mode((char *)&(argptr->mode));
-	if ((opmode != NETASCII) && (opmode != OCTET)) {
-		argptr->err = 4;
-		goto pre_socket;
-	}
-	fp = fopen(fname, "r");
-	if (fp == NULL) {
-		syslog(
-			LOG_ERR,
-			"failed to open file for reading: %s",
-			strerror(errno)
-		);
-		argptr->err = 2;
-		goto pre_socket;
-	}
-	buf = malloc(512);
-	rxb = malloc(256);
-	if ((buf == NULL) || (rxb == NULL)) {
-		syslog(
-			LOG_CRIT,
-			"failed to allocate memory: %s",
-			strerror(errno)
-		);
-		argptr->err = 0;
-		goto pre_socket;
-	}
-	int s = makesock(argptr);
-	if (s <= 0) {
-		goto cleanup;
-	}
-	uint8_t rxon = 0, lon = 1;
-	uint16_t bnum = 0;
-	while (lon) {
-		memset(buf, '\0', 512);
-		uint8_t verif = 0;
-		uint8_t vcount = 0;
-		size_t num_read = fread(buf, 1, 512, fp);
-		if (((num_read < 512) && (!feof(fp))) || (vcount > 5)) {
-			argptr->err = 0;
-			senderror(s, argptr);
-			goto cleanup;
-		}
-		if ((opmode == NETASCII) && (!is_netascii_buf(buf, num_read))) {
-			syslog(
-				LOG_ERR,
-				"%s:%d: requested file is not netascii compliant.",
-				inet_ntoa(argptr->client.sin_addr),
-				ntohs(argptr->client.sin_port)
-			);
-			argptr->err = 5;
-			senderror(s, argptr);
-			goto cleanup;
-		}
-		char *packet = nbd_tftp_ser_data_from_parts(++bnum, buf, num_read);
-		while (!verif) {
-			syslog(LOG_DEBUG, "sending block number %d to %s:%d",
-				bnum,
-				inet_ntoa(argptr->client.sin_addr),
-				htons(argptr->client.sin_port)
-			);
-			if (send(s, packet, num_read + 4, 0) < 0) {
-				syslog(
-					LOG_ERR,
-					"unable to send data to %s: %s",
-					inet_ntoa(argptr->client.sin_addr),
-					strerror(errno)
-				);
-				continue;
-			}
-			rxon = 1;
-			uint8_t rxcount = 0;
-			while (rxon) {
-				syslog(LOG_DEBUG, "waiting for ack %d from %s:%d",
-					bnum,
-					inet_ntoa(argptr->client.sin_addr),
-					htons(argptr->client.sin_port)
-				);
-				memset(rxb, '\0', 256);
-				ssize_t rcv = recv(s, rxb, 256, 0);
-				syslog(LOG_DEBUG, "recv'd %ld bytes from %s:%d",
-					rcv,
-					inet_ntoa(argptr->client.sin_addr),
-					htons(argptr->client.sin_port)
-				);
-				if (rcv == 4) {
-					nbd_tftp_packet_ack ack = nbd_tftp_de_ack(rxb, rcv);
-					if (ack.opcode == 5) {
-						goto socket_clean;
-					}
-					syslog(LOG_DEBUG, "%s:%d ack'd with block number: %d (expect %d)",
-						inet_ntoa(argptr->client.sin_addr),
-						htons(argptr->client.sin_port),
-						ack.block_num,
-						bnum
-					);
-					if (ack.block_num == bnum) {
-						rxon = 0;
-						verif = 1;
-						break;
-					}
-					if (ack.block_num == (bnum - 1)) {
-						rxon = 0;
-						vcount++;
-						break;
-					}
-				}
-				if (++rxcount > 30) {
-					argptr->err = 0;
-					senderror(s, argptr);
-					goto cleanup;
-				}
-				if (rcv > 4) {
-					if ((((uint16_t)buf[0] << 8) + buf[1]) == 5) {
-						goto socket_clean;
-					}
-				}
-			}
-		}
-		free(packet);
-		if (num_read < 512) {
-			lon = 0;
-		}
-	}
-socket_clean:
-	close(s);
-cleanup:
-	fclose(fp);
-	free(buf);
-	free(rxb);
-	free(fname);
-	free(args);
-	return (void *)NULL;
-pre_socket:
-	if (fp != NULL) {
-		fclose(fp);
-	}
-	free(buf);
-	free(rxb);
-	free(fname);
-	return nbd_nbtpd_resp_error(args);
-}
-
-void *write_req_resp(void *args) {
-	char *fname = NULL, *rxb = NULL;
-	FILE *fp = NULL;
-	nbd_nbtpd_args *argptr = (nbd_nbtpd_args *)args;
-	syslog(
-		LOG_DEBUG,
-		"%s:%d is trying to write file %s",
-		inet_ntoa(argptr->client.sin_addr),
-		ntohs(argptr->client.sin_port),
-		argptr->path
-	);
-	fname = checkpath(argptr, 0);
-	if (fname == NULL) {
-		syslog(LOG_ERR, "fname is NULL");
-		goto pre_socket;
-	}
-	if (!is_netascii_str((char *)&(argptr->mode))) {
-		syslog(
-			LOG_ERR,
-			"%s:%d mode is invalid %s",
-			inet_ntoa(argptr->client.sin_addr),
-			ntohs(argptr->client.sin_port),
-			argptr->mode
-		);
-		argptr->err = 4;
-		goto pre_socket;
-	}
-	nbd_opmode opmode = get_mode((char *)&(argptr->mode));
-	if ((opmode != NETASCII) && (opmode != OCTET)) {
-		syslog(LOG_ERR, "%s:%d mode is not supported.", inet_ntoa(argptr->client.sin_addr), ntohs(argptr->client.sin_port));
-		argptr->err = 4;
-		goto pre_socket;
-	}
-	fp = fopen(fname, "w");
-	if (fp == NULL) {
-		syslog(
-			LOG_ERR,
-			"failed to open file for writing: %s",
-			strerror(errno)
-		);
-		argptr->err = 2;
-		goto pre_socket;
-	}
-	rxb = malloc(768); // 768 is 1.5x expected block size
-	if (rxb == NULL) {
-		syslog(
-			LOG_CRIT,
-			"failed to allocate memory: %s",
-			strerror(errno)
-		);
-		argptr->err = 0;
-		goto pre_socket;
-	}
-	int s = makesock(argptr);
-	if (s <= 0) {
-		goto cleanup;
-	}
-	uint8_t rxon = 0, lon = 1;
-	uint16_t bnum = 0;
-	ssize_t rcv = 516;
-	while (lon) {
-		uint8_t verif = 0;
-		uint8_t vcount = 0;
-		char *packet = nbd_tftp_ser_ack_from_block_num(bnum++);
-		while (!verif) {
-			syslog(LOG_DEBUG, "sending ack number %d to %s:%d",
-				bnum,
-				inet_ntoa(argptr->client.sin_addr),
-				htons(argptr->client.sin_port)
-			);
-			if (send(s, packet, 4, 0) < 0) {
-				syslog(
-					LOG_ERR,
-					"unable to send ack to %s:%d: %s",
-					inet_ntoa(argptr->client.sin_addr),
-					htons(argptr->client.sin_port),
-					strerror(errno)
-				);
-				continue;
-			}
-			if ((rcv < 516) || (vcount > 5)) {
-				lon = 0;
-				break;
-			}
-			rxon = 1;
-			uint8_t rxcount = 0;
-			while (rxon) {
-				syslog(LOG_DEBUG, "waiting for data from %s:%d",
-					inet_ntoa(argptr->client.sin_addr),
-					htons(argptr->client.sin_port)
-				);
-				memset(rxb, '\0', 768);
-				rcv = recv(s, rxb, 768, 0);
-				syslog(LOG_DEBUG, "recv'd %ld bytes from %s:%d",
-					rcv,
-					inet_ntoa(argptr->client.sin_addr),
-					htons(argptr->client.sin_port)
-				);
-				if (rcv >= 4) {
-					nbd_tftp_packet_data data = nbd_tftp_de_data(rxb, rcv);
-					if (data.opcode == 5) {
-						free(data.data);
-						goto cleanup;
-					}
-					syslog(
-						LOG_DEBUG,
-						"%s:%d sent block number: %d (expect %d)",
-						inet_ntoa(argptr->client.sin_addr),
-						htons(argptr->client.sin_port),
-						data.block_num,
-						bnum
-					);
-					if (data.block_num == bnum) {
-						rxon = 0;
-						verif = 1;
-						if (data.datalen > 0) {
-							if ((opmode == NETASCII) && (!is_netascii_buf(data.data, data.datalen))) {
-								syslog(
-									LOG_ERR,
-									"%s:%d: requested file is not netascii compliant.",
-									inet_ntoa(argptr->client.sin_addr),
-									ntohs(argptr->client.sin_port)
-								);
-								argptr->err = 5;
-								senderror(s, argptr);
-								free(data.data);
-								goto cleanup;
-							}
-							if (fwrite(data.data, 1, data.datalen, fp) < data.datalen) {
-								syslog(LOG_ERR, "filewrite failed for %s: %s", fname, strerror(errno));
-								argptr->err = 0;
-								senderror(s, argptr);
-								free(data.data);
-								goto clean_socket;
-							}
-						}
-						free(data.data);
-						break;
-					}
-					if (data.block_num == (bnum - 1)) {
-						rxon = 0;
-						vcount++;
-						free(data.data);
-						break;
-					}
-					free(data.data);
-				}
-				if (++rxcount > 30) {
-					syslog(LOG_ERR, "retry count exceeded");
-					argptr->err = 0;
-					senderror(s, argptr);
-					goto clean_socket;
-				}
-			}
-		}
-		free(packet);
-	}
-clean_socket:
-	close(s);
-cleanup:
-	fclose(fp);
-	free(rxb);
-	free(fname);
-	free(args);
-	return (void *)NULL;
-pre_socket:
-	if (fp != NULL) {
-		fclose(fp);
-	}
-	free(rxb);
-	free(fname);
-	return nbd_nbtpd_resp_error(args);
-}
-
-void *nbd_nbtpd_resp_error(void *args) {
-	nbd_nbtpd_args *argptr = (nbd_nbtpd_args *)args;
-	int s = makesock(argptr);
-	if (s <= 0) {
-		syslog(
-			LOG_ERR,
-			"cannot send error to %s:%d",
-			inet_ntoa(argptr->client.sin_addr),
-			ntohs(argptr->client.sin_port)
-		);
-		goto cleanup;
-	}
-	senderror(s, argptr);
-cleanup:
-	free(args);
-	return (void *)NULL;
-}
-
diff --git a/src/main.c b/src/main.c
deleted file mode 100644
index 7114cc7..0000000
--- a/src/main.c
+++ /dev/null
@@ -1,313 +0,0 @@
-#ifdef __linux__
-#define _POSIX_C_SOURCE 2
-#define _DEFAULT_SOURCE
-#endif
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <syslog.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <pwd.h>
-#include <grp.h>
-#include <errno.h>
-#include <signal.h>
-//TODO: use threads.h instead
-#include <pthread.h>
-
-// illumos-only headers
-#ifdef __illumos__
-#include <priv.h>
-#endif
-
-#include "packet.h"
-#include "netascii.h"
-#include "handlers.h"
-
-int nbtpd_stop = 0;
-
-void stop_handler(int i) {
-	syslog(LOG_ERR, "caught shutdown signal, cleaning up and awaiting threads");
-	if (i != 0) {
-		nbtpd_stop = i;
-	} else {
-		nbtpd_stop = 1;
-	}
-	return;
-}
-
-void usage(char *name) {
-	//TODO: print to stderr; cleanup to be compliant
-	fprintf(stderr,
-		"usage: %s -h [-d [-u USER] [-g GROUP]] [-a INET_ADDRESS] [-p PORT] [-l LEVEL]\n",
-		name
-	);
-	fprintf(stderr, "\td: daemonize.\n");
-	fprintf(stderr,
-		"\tu: username to run as (default: nobody).  Must be specified after -d.\n"
-	);
-	fprintf(stderr,
-		"\tg: group to run as (default: nobody).  Must be specified after -d.\n"
-	);
-	fprintf(stderr, "\ta: address to bind to (default: 127.0.0.1)\n");
-	fprintf(stderr, "\tp: port to bind to (default: 69)\n");
-	fprintf(stderr, "\tl: log level; one of:\n");
-	fprintf(stderr, "\t\temerg\n\t\talert\n\t\tcrit\n\t\terr\n\t\twarn\n");
-	fprintf(stderr, "\t\tnotice\n\t\tinfo (default)\n\t\tdebug\n");
-}
-
-int set_loglevel(char *level) {
-	if (strncmp("emerg", level, 6) == 0) {
-		setlogmask(LOG_UPTO(LOG_EMERG));
-		return 0;
-	}
-	if (strncmp("alert", level, 6) == 0) {
-		setlogmask(LOG_UPTO(LOG_ALERT));
-		return 0;
-	}
-	if (strncmp("crit", level, 5) == 0) {
-		setlogmask(LOG_UPTO(LOG_CRIT));
-		return 0;
-	}
-	if (strncmp("err", level, 4) == 0) {
-		setlogmask(LOG_UPTO(LOG_ERR));
-		return 0;
-	}
-	if (strncmp("warn", level, 5) == 0) {
-		setlogmask(LOG_UPTO(LOG_WARNING));
-		return 0;
-	}
-	if (strncmp("notice", level, 7) == 0) {
-		setlogmask(LOG_UPTO(LOG_NOTICE));
-		return 0;
-	}
-	if (strncmp("info", level, 5) == 0) {
-		setlogmask(LOG_UPTO(LOG_INFO));
-		return 0;
-	}
-	if (strncmp("debug", level, 6) == 0) {
-		setlogmask(LOG_UPTO(LOG_DEBUG));
-		return 0;
-	}
-	return -1;
-}
-
-int main(int argc, char **argv) {
-	int retme = 0;
-	int daemonize = 0, loglevset = 0;
-	char addr[17], user[32], group[32];
-	memset(addr, '\0', sizeof(addr));
-	memset(user, '\0', sizeof(user));
-	memset(group, '\0', sizeof(group));
-	strcpy(addr, "127.0.0.1");
-	strcpy(user, "nobody");
-	strcpy(group, "nobody");
-	int port = 69;
-	int ch = 0;
-	while ((ch = getopt(argc, argv, "da:p:u:g:l:h")) != -1) {
-		switch (ch) {
-			case 'a':
-				strncpy(addr, optarg, sizeof(addr) - 1);
-				break;
-			case 'p':
-				port = atoi(optarg);
-				if ((port <= 0) || (port >= 65536)) {
-					fprintf(stderr, "invalid port specified.\n");
-					return -1;
-				}
-				break;
-			case 'd':
-				daemonize = 1;
-				break;
-			case 'g':
-				if (daemonize) {
-					strncpy(group, optarg, sizeof(group) - 1);
-				} else {
-					fprintf(stderr, "-g requires -d\n");
-					return -1;
-				}
-				break;
-			case 'u':
-				if (daemonize) {
-					strncpy(user, optarg, sizeof(user) - 1);
-				} else {
-					fprintf(stderr, "-u requires -d\n");
-					return -1;
-				}
-				break;
-			case 'l':
-				loglevset = 1;
-				if (set_loglevel(optarg)) {
-					fprintf(stderr, "invalid option for -l\n");
-					usage(argv[0]);
-					return -1;
-				}
-				break;
-			 case 'h': case '?':
-				usage(argv[0]);
-				return -1;
-		}
-	}
-	if (!loglevset) {
-		setlogmask(LOG_UPTO(LOG_INFO));
-	}
-#ifdef __illumos__
-	openlog(argv[0], LOG_PID | LOG_NDELAY, LOG_FTP);
-#else
-	openlog(argv[0], LOG_PID | LOG_PERROR | LOG_NDELAY, LOG_FTP);
-#endif
-	syslog(LOG_INFO, "starting up...");
-	signal(SIGTERM, &stop_handler);
-	signal(SIGINT, &stop_handler);
-	char *buf = NULL;
-	int s = socket(AF_INET, SOCK_DGRAM, 0);
-	if (s <= 0) {
-		syslog(LOG_ERR, "unable to bind socket!");
-		return -1;
-	}
-	if (daemonize) {
-		if (daemon(1, 0)) {
-			syslog(LOG_ERR, "failed to daemonize: %s", strerror(errno));
-			retme = -1;
-			goto cleanup;
-		} else {
-			syslog(LOG_INFO, "daemonized");
-		}
-	}
-	struct timeval timeout = { 30, 0 };
-	if (setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
-		syslog(LOG_ERR, "unable to set socket timeout: %s", strerror(errno));
-		retme = -1;
-		goto cleanup;
-	}
-	struct sockaddr_in saddr;
-	saddr.sin_family = AF_INET;
-	saddr.sin_port = htons(port);
-	saddr.sin_addr.s_addr = inet_addr(addr);
-	if (bind(s, (struct sockaddr*)&saddr, sizeof(saddr)) < 0) {
-		syslog(LOG_ERR, "socket bind failed: %s", strerror(errno));
-		retme = -1;
-		goto cleanup;
-	}
-	syslog(LOG_DEBUG, "socket bind success");
-	if (daemonize) {
-		//TODO: use getpwnam_r() and getgrnam_r()
-		struct group *g = getgrnam((const char *)&group);
-		if (setgid((*g).gr_gid) == -1) {
-			syslog(
-				LOG_ERR,
-				"failed to drop group privileges: %s",
-				strerror(errno)
-			);
-			retme = -1;
-			goto cleanup;
-		}
-		struct passwd *u = getpwnam((const char *)&user);
-		if (setuid((*u).pw_uid) == -1) {
-			syslog(
-				LOG_ERR,
-				"failed to drop user privileges: %s",
-				strerror(errno)
-			);
-			retme = -1;
-			goto cleanup;
-		}
-	}
-#ifdef __illumos__
-	//TODO: illumos priv.h privdrop
-#endif
-	buf = malloc(1024);
-	if (buf == NULL) {
-		syslog(LOG_CRIT, "unable to allocate memory: %s", strerror(errno));
-		retme = -1;
-		goto cleanup;
-	}
-	while (!nbtpd_stop) {
-		struct sockaddr_in caddr;
-		unsigned int clen = sizeof(caddr);
-		memset(buf, '\0', 1024);
-		ssize_t recvd_bytes = 0;
-		if ((recvd_bytes = recvfrom(s, buf, 1024, 0,
-				(struct sockaddr *)&caddr, &clen)) < 0) {
-			continue;
-		}
-		if (recvd_bytes < 4) {
-			syslog(
-				LOG_ERR,
-				"ignoring invalid packet from %s.",
-				inet_ntoa(caddr.sin_addr)
-			);
-			continue;
-		}
-		syslog(
-			LOG_INFO,
-			"got connection from %s:%d",
-			inet_ntoa(caddr.sin_addr),
-			ntohs(caddr.sin_port)
-		);
-		nbd_nbtpd_args *args = malloc(sizeof(nbd_nbtpd_args));
-		if (args == NULL) {
-			syslog(
-				LOG_CRIT,
-				"unable to allocate memory: %s",
-				strerror(errno)
-			);
-			continue;
-		}
-		nbd_tftp_opcode oc = ((uint16_t)buf[0] << 8) + buf[1];
-		args->client = caddr;
-		args->err = 0;
-		memset(args->path, '\0', NBD_NBTPD_ARGS_PATH_MAX);
-		memset(args->mode, '\0', NBD_NBTPD_ARGS_MODE_MAX);
-		int i;
-		for(i = 2; buf[i] != 0 && i < recvd_bytes && (i - 2) < (NBD_NBTPD_ARGS_PATH_MAX - 1); i++) {
-			args->path[i - 2] = buf[i];
-		}
-		int s = i + 1;
-		if (s >= recvd_bytes) {
-			oc = 0;
-		} else {
-			for(i = s; buf[i] != 0 && i < recvd_bytes && (i - s) < (NBD_NBTPD_ARGS_MODE_MAX - 1); i++) {
-				args->mode[i - s] = buf[i];
-			}
-		}
-		//TODO: use std threads
-		pthread_t _thread;
-		void *(*func)(void *);
-		switch (oc) {
-			case RRQ:
-				func = &read_req_resp;
-				break;
-			case WRQ:
-				func = &write_req_resp;
-				break;
-			default:
-				(*args).err = 4;
-				func = &nbd_nbtpd_resp_error;
-		}
-		//TODO: use std threads
-		int e;
-		syslog(LOG_ERR, "spawning thread for %s", inet_ntoa(caddr.sin_addr));
-		if ((e = pthread_create(&_thread, 0, func, (void *)args)) != 0) {
-			syslog(
-				LOG_CRIT,
-				"unable to spawn thread: %s",
-				strerror(e)
-			);
-			free(args);
-		}
-	}
-cleanup:
-	free(buf);
-	close(s);
-	pthread_exit(NULL);
-	return retme;
-}
-
diff --git a/src/netascii.c b/src/netascii.c
deleted file mode 100644
index d061e57..0000000
--- a/src/netascii.c
+++ /dev/null
@@ -1,53 +0,0 @@
-#include <stdint.h>
-#include <stdlib.h>
-
-#include "netascii.h"
-
-uint8_t is_netascii_char(char c) {
-	static const uint64_t LUT[4] = 
-		{0xffffffff00003f81,
-		 0x7fffffffffffffff,
-		 0x00,0x00};
-	int i = c / 64;
-	int e = i % 64;
-	return (LUT[i] >> e) & 1;
-}
-
-/// WARNING!  This function is NOT safe.  Use only for strings you have already
-/// verified are NULL terminated!
-uint8_t is_netascii_str(char *str) {
-	for (uint64_t i = 0; str[i] != 0; i++) {
-		if (!is_netascii_char(str[i])) {
-			return 0;
-		} else {
-			if (str[i] == '\r') {
-				if (str[++i] != '\n') {
-					return 0;
-				}
-			}
-		}
-	}
-	return 1;
-}
-
-uint8_t is_netascii_buf(char *buf, size_t len) {
-	for (uint64_t i = 0; i < len; i++) {
-		if (!is_netascii_char(buf[i])) {
-			return 0;
-		} else {
-			if (buf[i] == '\r') {
-				if ((i + 1) < len) {
-					switch (buf[++i]) {
-						case 0: case '\n':
-							break;
-						default:
-							return 0;
-					}
-				} else {
-					return 0;
-				}
-			}
-		}
-	}
-	return 1;
-}
diff --git a/src/packet.c b/src/packet.c
deleted file mode 100644
index d439ec9..0000000
--- a/src/packet.c
+++ /dev/null
@@ -1,125 +0,0 @@
-#include <stdlib.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-#include <string.h>
-#include "packet.h"
-
-char *nbd_tftp_error_to_message(nbd_tftp_ecode error) {
-	switch (error) {
-		case 0:
-			return "ERROR";
-		case 1:
-			return "File not Found";
-		case 2:
-			return "Access violation";
-		case 3:
-			return "Disk full or allocation exceeded";
-		case 4:
-			return "Illegal TFTP operation";
-		case 5:
-			return "Unknown Transfer ID";
-		case 6:
-			return "File already exists";
-		case 7:
-			return "No such user";
-	}
-	return "UNKNOWN ERROR";
-}
-
-char *nbd_tftp_ser_data(nbd_tftp_packet_data d) {
-	char *buf = malloc(sizeof(d.opcode) + sizeof(d.block_num) + d.datalen);
-	if (buf != NULL) {
-		uint16_t netopcode = htons(d.opcode);
-		uint16_t netbnum = htons(d.block_num);
-		memcpy(buf, &netopcode, sizeof(netopcode));
-		memcpy((buf + sizeof(netopcode)), &netbnum, sizeof(netbnum));
-		memcpy((buf + sizeof(netopcode) + sizeof(netbnum)), d.data, d.datalen);
-	}
-	return buf;
-}
-
-char *nbd_tftp_ser_data_from_parts(uint16_t blocknum, char *data, size_t datalen) {
-	char *buf = malloc(sizeof(uint16_t) + sizeof(blocknum) + datalen);
-	if (buf != NULL) {
-		uint16_t netopcode = htons(3);
-		uint16_t netbnum = htons(blocknum);
-		memcpy(buf, &netopcode, sizeof(netopcode));
-		memcpy((buf + sizeof(netopcode)), &netbnum, sizeof(netbnum));
-		memcpy((buf + sizeof(netopcode) + sizeof(netbnum)), data, datalen);
-	}
-	return buf;
-}
-
-nbd_tftp_packet_data nbd_tftp_de_data(char *data, size_t len) {
-	nbd_tftp_packet_data ret = { 0, 0, (char *)NULL, (size_t)0 };
-	if ((len >= 4) && (data != NULL)) {
-		ret.opcode = ((uint16_t)data[0] << 8) + data[1];
-		ret.block_num = ((uint16_t)data[2] << 8) + data[3];
-		ret.datalen = len - 4;
-		if (ret.datalen > 0) {
-			if ((ret.data = malloc(ret.datalen)) != NULL) {
-				memcpy(ret.data, (data + 4), ret.datalen);
-			}
-		}
-	}
-	return ret;
-}
-
-char *nbd_tftp_ser_error(nbd_tftp_packet_error e) {
-	char *buf = malloc(sizeof(e.opcode) + sizeof((uint16_t)e.err) + strlen(e.emsg));
-	if (buf != NULL) {
-		uint16_t netopcode = htons(e.opcode);
-		uint16_t netecode = htons((uint16_t)e.err);
-		memcpy(buf, &netopcode, sizeof(netopcode));
-		memcpy((buf + sizeof(netopcode)), &netecode, sizeof(netecode));
-		memcpy((buf + sizeof(netopcode) + sizeof(netecode)), e.emsg, strlen(e.emsg));
-	}
-	return buf;
-}
-
-char *nbd_tftp_ser_error_from_code(nbd_tftp_ecode error) {
-	char *emsg = nbd_tftp_error_to_message(error);
-	char *buf = malloc(sizeof(uint16_t) + sizeof(uint16_t) + strlen(emsg));
-	if (buf != NULL) {
-		uint16_t netopcode = htons(5);
-		uint16_t netecode = htons((uint16_t)error);
-		memcpy(buf, &netopcode, sizeof(netopcode));
-		memcpy((buf + sizeof(netopcode)), &netecode, sizeof(netecode));
-		memcpy((buf + sizeof(netopcode) + sizeof(netecode)), emsg, strlen(emsg));
-	}
-	return buf;
-}
-
-char *nbd_tftp_ser_ack(nbd_tftp_packet_ack ack) {
-	char *buf = malloc(sizeof(ack.opcode) + sizeof(ack.block_num));
-	if (buf != NULL) {
-		uint16_t netopcode = htons(ack.opcode);
-		uint16_t netbnum = htons(ack.block_num);
-		memcpy(buf, &netopcode, sizeof(netopcode));
-		memcpy((buf + sizeof(netopcode)), &netbnum, sizeof(netbnum));
-	}
-	return buf;
-}
-
-char *nbd_tftp_ser_ack_from_block_num(uint16_t block_num) {
-	char *buf = malloc(sizeof(uint16_t) + sizeof(block_num));
-	if (buf != NULL) {
-		uint16_t netopcode = htons(4);
-		uint16_t netbnum = htons(block_num);
-		memcpy(buf, &netopcode, sizeof(netopcode));
-		memcpy((buf + sizeof(netopcode)), &netbnum, sizeof(netbnum));
-	}
-	return buf;
-}
-
-nbd_tftp_packet_ack nbd_tftp_de_ack(char *buf, ssize_t buflen) {
-	nbd_tftp_packet_ack ack = { 0, 0 };
-	if ((buf != NULL) && (buflen == 4)) {
-		uint16_t opcode = ((uint16_t)buf[0] << 8) + buf[1];
-		uint16_t block_num = ((uint16_t)buf[2] << 8) + buf[3];
-		ack.opcode = opcode;
-		ack.block_num = block_num;
-	}
-	return ack;
-}
-