about summary refs log tree commit diff stats
path: root/src/handlers.c
diff options
context:
space:
mode:
authorRen Kararou <[email protected]>2025-01-05 02:29:15 -0600
committerRen Kararou <[email protected]>2025-01-05 02:29:15 -0600
commit5605a5ddf3c77232b04c002a82b91e227c0f27da (patch)
tree30d5cf75759aa4bd2e8e75d5a7c852931e114066 /src/handlers.c
parent70a46fab050c3fdf38b9c72453f6e678cc8341be (diff)
downloadnbtpd-5605a5ddf3c77232b04c002a82b91e227c0f27da.tar.gz
nbtpd-5605a5ddf3c77232b04c002a82b91e227c0f27da.tar.bz2
nbtpd-5605a5ddf3c77232b04c002a82b91e227c0f27da.zip
builds on illumos, freebsd, and linux
Diffstat (limited to 'src/handlers.c')
-rw-r--r--src/handlers.c140
1 files changed, 82 insertions, 58 deletions
diff --git a/src/handlers.c b/src/handlers.c
index 7c2b768..10599a3 100644
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -1,8 +1,19 @@
+#ifdef __linux__
+#define _POSIX_C_SOURCE 200809L
+#define _DEFAULT_SOURCE
+#endif
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/socket.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"
@@ -18,11 +29,11 @@ typedef enum opmode {
 
 nbd_opmode get_mode(char *mode) {
 	nbd_opmode opmode;
-	if (strncmp((const char *)mode, (const char *)&"netascii", 32) == 0) {
+	if (strncmp((const char *)mode, (const char *)&"netascii", NBD_NBTPD_ARGS_MODE_MAX) == 0) {
 		opmode = NETASCII;
-	} else if (strncmp((const char *)mode, (const char *)&"octal", 32) == 0) {
+	} else if (strncmp((const char *)mode, (const char *)&"octal", NBD_NBTPD_ARGS_MODE_MAX) == 0) {
 		opmode = OCTAL;
-	} else if (strncmp((const char *)mode, (const char *)&"mail", 32) == 0) {
+	} else if (strncmp((const char *)mode, (const char *)&"mail", NBD_NBTPD_ARGS_MODE_MAX) == 0) {
 		opmode = MAIL;
 	} else {
 		opmode = NOT_FOUND;
@@ -30,83 +41,96 @@ nbd_opmode get_mode(char *mode) {
 	return opmode;
 }
 
-char *add_dotslash(char *fname) {
-	char *ret = malloc(768);
-	if (ret == NULL) {
-		return ret;
+void *read_req_resp(void *args) {
+	char *fname = NULL, *wd = NULL, *buf = NULL;
+	FILE *fp = NULL;
+	nbd_nbtpd_args *argptr = (nbd_nbtpd_args *)args;
+	if (!is_netascii_str((char *)&argptr->path)) {
+		argptr->err = 1;
+		goto nbd_nbtpd_thread_read_cleanup_ps;
 	}
-	memset(ret, '\0', 768);
-	ret[0] = '.';
-	ret[1] = '/';
-	for (int i = 0; (fname[i] != 0) && (i < 768); i++) {
-		ret[i + 2] = fname[i];
+	fname = realpath((char *)&argptr->path, NULL);
+	if (fname == NULL) {
+		syslog(LOG_ERR, "unable to get real path: %s", strerror(errno));
+		argptr->err = 1;
+		goto nbd_nbtpd_thread_read_cleanup_ps;
 	}
-	return ret;
-}
-
-void *read_req_resp(void *args) {
-	char fname[768];
-	memset(fname, '\0', sizeof(fname));
-	int dots = 0;
-	for (int i = 0; ((*(nbd_nbtpd_args *)args).path[i] != 0) && (i < 768); i++) {
-		if (is_netascii_char((*(nbd_nbtpd_args *)args).path[i])) {
-			if (i > 0) {
-				if ((*(nbd_nbtpd_args *)args).path[i] == '.' &&
-						(*(nbd_nbtpd_args *)args).path[i - 1] == '.') {
-					dots++;
-					continue;
-				}
-			} 
-			fname[i - dots] = (*(nbd_nbtpd_args *)args).path[i];
-		} else {
-			(*(nbd_nbtpd_args *)args).err = 1;
-			return nbd_nbtpd_resp_error(args);
-		}
+	/*
+	 * 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 nbd_nbtpd_thread_read_cleanup_ps;
+	}
+	if (getcwd(wd, MAXPATHLEN) == NULL) {
+		argptr->err = 0;
+		goto nbd_nbtpd_thread_read_cleanup_ps;
+	}
+#else
+	if ((wd = getcwd(NULL, PATH_MAX)) == NULL) {
+		argptr->err = 0;
+		goto nbd_nbtpd_thread_read_cleanup_ps;
 	}
-	char mode[32];
-	memset(mode, '\0', sizeof(mode));
-	for (int i = 0; ((*(nbd_nbtpd_args *)args).mode[i] != 0) && (i < 32); i++) {
-		if (is_netascii_char((*(nbd_nbtpd_args *)args).mode[i])) {
-			mode[i] = (*(nbd_nbtpd_args *)args).mode[i];
-		} else {
-			(*(nbd_nbtpd_args *)args).err = 4;
-			return nbd_nbtpd_resp_error(args);
-		}
+#endif
+	if (!strncmp(wd, fname, sizeof(wd) - 1)) {
+		argptr->err = 2;
+		goto nbd_nbtpd_thread_read_cleanup_ps;
 	}
-	FILE *fp;
-	nbd_opmode opmode = get_mode((char *)&mode);
+	if (!is_netascii_str((char *)&argptr->mode)) {
+		argptr->err = 4;
+		goto nbd_nbtpd_thread_read_cleanup_ps;
+	}
+	nbd_opmode opmode = get_mode((char *)&argptr->mode);
 	switch (opmode) {
 		case NETASCII:
 			break;
 		case OCTAL:
 			break;
 		default:
-			(*(nbd_nbtpd_args *)args).err = 4;
-			return nbd_nbtpd_resp_error(args);
+			argptr->err = 4;
+			goto nbd_nbtpd_thread_read_cleanup_ps;
 	}
-	fp = fopen(add_dotslash((char *)&fname), "r");
+	fp = fopen(fname, "r");
 
-	char *buf = malloc(512);
+	buf = malloc(512);
 	if (buf == NULL) {
-		syslog(LOG_CRIT, "we failed to allocated 512 bytes of memory");
-		(*(nbd_nbtpd_args *)args).err = 0;
-		return nbd_nbtpd_resp_error(args);
+		syslog(
+			LOG_CRIT,
+			"failed to allocate memory: %s",
+			strerror(errno)
+		);
+		argptr->err = 0;
+		goto nbd_nbtpd_thread_read_cleanup_ps;
 	}
 	memset(buf, '\0', 512);
 	int s = socket(AF_INET, SOCK_DGRAM, 0);
 	if (s <= 0) {
-		syslog(LOG_ERR, "unable to define socket!");
-		fclose(fp);
-		free(buf);
-		free(args);
-		return (void *)NULL;
+		syslog(LOG_ERR, "unable to define socket: %s", strerror(errno));
+		goto nbd_nbtpd_thread_read_cleanup;
 	}
-	
-	//TODO: make new socket and go into main loop
+
+	close(s);
+nbd_nbtpd_thread_read_cleanup:
 	fclose(fp);
 	free(buf);
+	free(fname);
+	free(wd);
 	free(args);
 	return (void *)NULL;
+nbd_nbtpd_thread_read_cleanup_ps:
+	if (fp != NULL) {
+		fclose(fp);
+	}
+	free(buf);
+	free(fname);
+	free(wd);
+	return nbd_nbtpd_resp_error(args);
 }
 
 void *write_req_resp(void *args) {