about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorRen Kararou <[email protected]>2024-12-31 02:18:40 -0600
committerRen Kararou <[email protected]>2024-12-31 02:18:40 -0600
commitf6b4ac41eec72a25c703c63f43bd1104049a405c (patch)
tree6fc60798944ac010c22ede4e2e9e33d6b97d39e0
parent810de0a90148d5dc7fe5919949220a00d14f6447 (diff)
downloadnbtpd-f6b4ac41eec72a25c703c63f43bd1104049a405c.tar.gz
nbtpd-f6b4ac41eec72a25c703c63f43bd1104049a405c.tar.bz2
nbtpd-f6b4ac41eec72a25c703c63f43bd1104049a405c.zip
complete setup code; complete initial packet handling
-rw-r--r--.gitignore1
-rw-r--r--inc/handlers.h10
-rw-r--r--inc/netascii.h4
-rw-r--r--inc/packet.h26
-rw-r--r--makefile2
-rw-r--r--src/handlers.c25
-rw-r--r--src/main.c105
-rw-r--r--src/netascii.c4
-rw-r--r--src/packet.c2
9 files changed, 122 insertions, 57 deletions
diff --git a/.gitignore b/.gitignore
index c98082d..47a2b2e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,5 +9,6 @@
 bin/
 *.o
 *.so
+*.pch
 nbtpd
 a.out
diff --git a/inc/handlers.h b/inc/handlers.h
index 9f1988f..5aa0733 100644
--- a/inc/handlers.h
+++ b/inc/handlers.h
@@ -7,11 +7,15 @@
 typedef struct {
 	char path[768];
 	char mode[32];
+	int err;
 	struct sockaddr_in client;
 } nbd_nbtpd_args;
 
-void read_req_resp(nbd_nbtpd_args args);
-void write_req_resp(nbd_nbtpd_args args);
-void nbd_nbtpd_resp_error(nbd_nbtpd_args args);
+/// WARNING: use this only if you know what you are doing
+void *read_req_resp(void *args);
+/// WARNING: use this only if you know what you are doing
+void *write_req_resp(void *args);
+/// WARNING: use this only if you know what you are doing
+void *nbd_nbtpd_resp_error(void *args);
 
 #endif
diff --git a/inc/netascii.h b/inc/netascii.h
index 096b1c3..ada2051 100644
--- a/inc/netascii.h
+++ b/inc/netascii.h
@@ -3,7 +3,7 @@
 #include <stdint.h>
 
 uint8_t is_netascii_char(char c);
-uint8_t is_netascii_str(char* str);
-uint8_t is_netascii_buf(char* buf, uint64_t len);
+uint8_t is_netascii_str(char *str);
+uint8_t is_netascii_buf(char *buf, uint64_t len);
 
 #endif
diff --git a/inc/packet.h b/inc/packet.h
index a236f74..abd6d3e 100644
--- a/inc/packet.h
+++ b/inc/packet.h
@@ -1,5 +1,5 @@
-#ifndef NBT_TFTP_PACKET_H
-#define NBT_TFTP_PACKET_H
+#ifndef NBD_TFTP_PACKET_H
+#define NBD_TFTP_PACKET_H
 
 #include <stdint.h>
 
@@ -9,7 +9,7 @@ typedef enum {
 	DAT	= 3,
 	ACK	= 4,
 	ERR	= 5,
-} nbt_tftp_opcode;
+} nbd_tftp_opcode;
 
 typedef enum {
 	ERROR		= 0,
@@ -20,32 +20,32 @@ typedef enum {
 	ETRANS		= 5,
 	EEXISTS		= 6,
 	EUSER		= 7,
-} nbt_tftp_ecode;
+} nbd_tftp_ecode;
 
 typedef struct {
 	uint16_t opcode;
-	char* filename;
-	char* mode;
-} nbt_tftp_packet_rq;
+	char *filename;
+	char *mode;
+} nbd_tftp_packet_rq;
 
 typedef struct {
 	uint16_t opcode;
 	uint16_t block_num;
-	char* data;
-} nbt_tftp_packet_data;
+	char *data;
+} nbd_tftp_packet_data;
 
 typedef struct {
 	uint16_t opcode;
 	uint16_t block_num;
-} nbt_tftp_packet_ack;
+} nbd_tftp_packet_ack;
 
 typedef struct {
 	uint16_t opcode;
 	uint16_t err;
-	char* emsg;
-} nbt_tftp_packet_error;
+	char *emsg;
+} nbd_tftp_packet_error;
 
-char* nbt_tftp_error_to_message(nbt_tftp_ecode error);
+char *nbd_tftp_error_to_message(nbd_tftp_ecode error);
 
 #endif
 
diff --git a/makefile b/makefile
index da7070b..223e766 100644
--- a/makefile
+++ b/makefile
@@ -1,6 +1,6 @@
 CC:=clang
 CFLAGS:=-march=native -O3 -funroll-loops -Wall -Wextra -Werror
-LDFLAGS:=-flto=thin
+LDFLAGS:=-flto=thin -lpthread
 
 INCLUDES=-Iinc/
 
diff --git a/src/handlers.c b/src/handlers.c
index 4162926..788934d 100644
--- a/src/handlers.c
+++ b/src/handlers.c
@@ -1,26 +1,27 @@
+#include <stdlib.h>
 #include <sys/socket.h>
 #include "handlers.h"
 
-void read_req_resp(nbd_nbtpd_args args) {
-	if (args.path[0] == 0) {
+void *read_req_resp(void *args) {
+	if ((*(nbd_nbtpd_args *)args).path[0] == 0) {
 		nbd_nbtpd_resp_error(args);
-		return;
+		return (void *)NULL;
 	}
-	return;
+	return (void *)NULL;
 }
 
-void write_req_resp(nbd_nbtpd_args args) {
-	if (args.path[0] == 0) {
+void *write_req_resp(void *args) {
+	if ((*(nbd_nbtpd_args *)args).path[0] == 0) {
 		nbd_nbtpd_resp_error(args);
-		return;
+		return (void *)NULL;
 	}
-	return;
+	return (void *)NULL;
 }
 
-void nbd_nbtpd_resp_error(nbd_nbtpd_args args) {
-	if (args.path[0] == 0) {
-		return;
+void *nbd_nbtpd_resp_error(void *args) {
+	if ((*(nbd_nbtpd_args *)args).path[0] == 0) {
+		return (void *)NULL;
 	}
-	return;
+	return (void *)NULL;
 }
 
diff --git a/src/main.c b/src/main.c
index 3701c79..0264050 100644
--- a/src/main.c
+++ b/src/main.c
@@ -17,11 +17,17 @@
 
 #include "packet.h"
 #include "netascii.h"
+#include "handlers.h"
 
-static int stop = 0;
+int nbtpd_stop = 0;
 
-void stop_handler() {
-	stop = 1;
+void stop_handler(int i) {
+	syslog(LOG_ERR, "caught shutdown signal, cleaning up.");
+	if (i != 0) {
+		nbtpd_stop = i;
+	} else {
+		nbtpd_stop = 1;
+	}
 	return;
 }
 
@@ -89,6 +95,8 @@ int main(int argc, char **argv) {
 	setlogmask(LOG_UPTO(LOG_INFO));
 	openlog(argv[0], LOG_PID | LOG_PERROR | LOG_NDELAY, LOG_FTP);
 	syslog(LOG_INFO, "starting up...");
+	signal(SIGTERM, &stop_handler);
+	signal(SIGINT, &stop_handler);
 
 	if (daemonize) {
 		if (daemon(1, 0)) {
@@ -127,16 +135,18 @@ int main(int argc, char **argv) {
 	}
 	syslog(LOG_INFO, "socket bind success");
 
-	//TODO: use getpwnam_r() and getgrnam_r()
-	struct passwd *u = getpwnam((const char *)&user);
-	if (setuid((*u).pw_uid) == -1) {
-		syslog(LOG_ERR, "failed to drop user privileges");
-		return -1;
-	}
-	struct group *g = getgrnam((const char *)&group);
-	if (setgid((*g).gr_gid) == -1) {
-		syslog(LOG_ERR, "failed to drop group privileges");
-		return -1;
+	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");
+			return -1;
+		}
+		struct passwd *u = getpwnam((const char *)&user);
+		if (setuid((*u).pw_uid) == -1) {
+			syslog(LOG_ERR, "failed to drop user privileges");
+			return -1;
+		}
 	}
 
 	// create persistent buffer
@@ -147,21 +157,70 @@ int main(int argc, char **argv) {
 		close(s);
 		return -1;
 	}
-	while (!stop) {
+	while (!nbtpd_stop) {
 		struct sockaddr_in caddr;
 		unsigned int clen = sizeof(caddr);
 		memset(buf, '\0', 1024);
-		if (recvfrom(s, buf, 1024, 0, (struct sockaddr*)&caddr, &clen) < 0) {
-			syslog(LOG_ERR,
-					"got a client connection, but unable to receive data!");
-			free(buf);
+		ssize_t recvd_bytes = 0;
+		if ((recvd_bytes = recvfrom(s, buf, 1024, 0, 
+				(struct sockaddr *)&caddr, &clen)) < 0) {
+			syslog(
+				LOG_ERR,
+				"got a client connection, but unable to receive data!"
+			);
 			continue;
 		}
-		//TODO: process packet
-
-		// we will never actually join on this thread, and don't care to keep it around.
-		//pthread_t *_thread; // since this hasn't been implemented yet, clang is complaining
-
+		if (recvd_bytes < 4) {
+			syslog(LOG_ERR, "ignoring invalid packet.");
+			continue;
+		}
+		nbd_nbtpd_args *args = malloc(sizeof(nbd_nbtpd_args));
+		if (args == NULL) {
+			syslog(LOG_CRIT, "unable to allocate memory");
+			continue;
+		}
+		nbd_tftp_opcode oc = ntohs(((uint16_t)buf[0] << 8) + buf[1]);
+		(*args).client = caddr;
+		(*args).err = 0;
+		memset((*args).path, '\0', 768);
+		memset((*args).mode, '\0', 32);
+		int i;
+		for(i = 2; buf[i] != 0 && i < recvd_bytes && (i - 2) < 768; 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) < 32; i++) {
+				(*args).mode[i - s] = buf[i];
+			}
+		}
+		pthread_t *_thread = malloc(sizeof(pthread_t));
+		if (_thread == NULL) {
+			syslog(LOG_CRIT, "unable to allocate memory");
+			free(args);
+			continue;
+		}
+		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;
+		}
+		if (pthread_create(_thread, 0, func, (void *)args) != 0) {
+			syslog(
+				LOG_CRIT,
+				"unable to handle request: cannot create thread!"
+			);
+			free(args);
+		}
 	}
 
 	// free our persistent buffer
diff --git a/src/netascii.c b/src/netascii.c
index 2180093..fb4d7b8 100644
--- a/src/netascii.c
+++ b/src/netascii.c
@@ -14,7 +14,7 @@ uint8_t is_netascii_char(char c) {
 
 /// WARNING!  This function is NOT safe.  Use only for strings you have already
 /// verified are NULL terminated!
-uint8_t is_netascii_str(char* str) {
+uint8_t is_netascii_str(char *str) {
 	for (uint64_t i = 0; str[i] != 0; i++) {
 		if (!is_netascii_char(str[i])) {
 			return 0;
@@ -29,7 +29,7 @@ uint8_t is_netascii_str(char* str) {
 	return 1;
 }
 
-uint8_t is_netascii_buf(char* buf, uint64_t len) {
+uint8_t is_netascii_buf(char *buf, uint64_t len) {
 	for (uint64_t i = 0; i < len; i++) {
 		if (!is_netascii_char(buf[i])) {
 			return 0;
diff --git a/src/packet.c b/src/packet.c
index 8f7a7e6..5bc8be6 100644
--- a/src/packet.c
+++ b/src/packet.c
@@ -1,6 +1,6 @@
 #include "packet.h"
 
-char* nbt_tftp_error_to_message(nbt_tftp_ecode error) {
+char *nbd_tftp_error_to_message(nbd_tftp_ecode error) {
 	switch (error) {
 		case 0:
 			return "ERROR";