diff options
author | Ren Kararou <[email protected]> | 2024-12-31 02:18:40 -0600 |
---|---|---|
committer | Ren Kararou <[email protected]> | 2024-12-31 02:18:40 -0600 |
commit | f6b4ac41eec72a25c703c63f43bd1104049a405c (patch) | |
tree | 6fc60798944ac010c22ede4e2e9e33d6b97d39e0 | |
parent | 810de0a90148d5dc7fe5919949220a00d14f6447 (diff) | |
download | nbtpd-f6b4ac41eec72a25c703c63f43bd1104049a405c.tar.gz nbtpd-f6b4ac41eec72a25c703c63f43bd1104049a405c.tar.bz2 nbtpd-f6b4ac41eec72a25c703c63f43bd1104049a405c.zip |
complete setup code; complete initial packet handling
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | inc/handlers.h | 10 | ||||
-rw-r--r-- | inc/netascii.h | 4 | ||||
-rw-r--r-- | inc/packet.h | 26 | ||||
-rw-r--r-- | makefile | 2 | ||||
-rw-r--r-- | src/handlers.c | 25 | ||||
-rw-r--r-- | src/main.c | 105 | ||||
-rw-r--r-- | src/netascii.c | 4 | ||||
-rw-r--r-- | src/packet.c | 2 |
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"; |