diff options
author | Ren Kararou <[email protected]> | 2025-01-07 20:52:27 -0600 |
---|---|---|
committer | Ren Kararou <[email protected]> | 2025-01-07 20:52:27 -0600 |
commit | 660da53647cdcdc5ce07054f74e5c420a15702fe (patch) | |
tree | 796f00487c00a16a958467860354ad9f4bcc0276 | |
parent | b9635ce3b4ca30b14128c131bb9fe9be08740d6d (diff) | |
download | nbtpd-660da53647cdcdc5ce07054f74e5c420a15702fe.tar.gz nbtpd-660da53647cdcdc5ce07054f74e5c420a15702fe.tar.bz2 nbtpd-660da53647cdcdc5ce07054f74e5c420a15702fe.zip |
first RRQ processed
-rw-r--r-- | inc/handlers.h | 2 | ||||
-rw-r--r-- | inc/packet.h | 5 | ||||
-rw-r--r-- | src/handlers.c | 122 | ||||
-rw-r--r-- | src/main.c | 33 | ||||
-rw-r--r-- | src/packet.c | 39 |
5 files changed, 178 insertions, 23 deletions
diff --git a/inc/handlers.h b/inc/handlers.h index aecd964..acf994e 100644 --- a/inc/handlers.h +++ b/inc/handlers.h @@ -10,7 +10,7 @@ typedef enum opmode { NOT_FOUND, NETASCII, - OCTAL, + OCTET, MAIL // any additional modes } nbd_opmode; diff --git a/inc/packet.h b/inc/packet.h index abd6d3e..a404d49 100644 --- a/inc/packet.h +++ b/inc/packet.h @@ -2,6 +2,7 @@ #define NBD_TFTP_PACKET_H #include <stdint.h> +#include <unistd.h> typedef enum { RRQ = 1, @@ -32,6 +33,7 @@ typedef struct { uint16_t opcode; uint16_t block_num; char *data; + size_t datalen; } nbd_tftp_packet_data; typedef struct { @@ -46,6 +48,9 @@ typedef struct { } nbd_tftp_packet_error; char *nbd_tftp_error_to_message(nbd_tftp_ecode error); +char *nbd_tftp_ser_data(nbd_tftp_packet_data d); +char *nbd_tftp_ser_data_from_parts(uint16_t blocknum, char *data, size_t datalen); +nbd_tftp_packet_ack nbd_tftp_de_ack(char *buf, ssize_t buflen); #endif diff --git a/src/handlers.c b/src/handlers.c index fdd16f8..394ccb0 100644 --- a/src/handlers.c +++ b/src/handlers.c @@ -24,8 +24,8 @@ 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 *)&"octal", NBD_NBTPD_ARGS_MODE_MAX) == 0) { - opmode = OCTAL; + } 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 { @@ -35,9 +35,10 @@ nbd_opmode get_mode(char *mode) { } void *read_req_resp(void *args) { - char *fname = NULL, *wd = NULL, *buf = NULL; + char *fname = NULL, *wd = 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); if (!is_netascii_str((char *)&argptr->path)) { argptr->err = 1; goto pre_socket; @@ -71,21 +72,46 @@ void *read_req_resp(void *args) { goto pre_socket; } #endif - if (!strncmp(wd, fname, sizeof(wd) - 1)) { + syslog(LOG_DEBUG, "cwd: %s :: realpath: %s", wd, fname); + 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 pre_socket; } - if (!is_netascii_str((char *)&argptr->mode)) { + 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 != OCTAL)) { + 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) { syslog( LOG_CRIT, @@ -95,13 +121,17 @@ void *read_req_resp(void *args) { argptr->err = 0; goto pre_socket; } - memset(buf, '\0', 512); int s = socket(AF_INET, SOCK_DGRAM, 0); if (s <= 0) { syslog(LOG_ERR, "unable to define socket: %s", strerror(errno)); goto cleanup; } - if (connect(s, (struct sockaddr *)&argptr->client, sizeof(struct sockaddr)) < 0) { + 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)); + goto socket_clean; + } + if (connect(s, (struct sockaddr *)&(argptr->client), sizeof(struct sockaddr)) < 0) { syslog( LOG_ERR, "unable to connect to client %s: %s", @@ -110,12 +140,82 @@ void *read_req_resp(void *args) { ); goto socket_clean; } - + 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)) { + //TODO: error response function! + } + 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); + 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) { + //TODO: error response function! + } + } + } + free(packet); + if (num_read < 512) { + lon = 0; + } + } socket_clean: close(s); cleanup: fclose(fp); free(buf); + free(rxb); free(fname); free(wd); free(args); @@ -125,6 +225,7 @@ pre_socket: fclose(fp); } free(buf); + free(rxb); free(fname); free(wd); return nbd_nbtpd_resp_error(args); @@ -137,6 +238,7 @@ void *write_req_resp(void *args) { void *nbd_nbtpd_resp_error(void *args) { //TODO: open socket and scream error, then cleanup. + //TODO: error response function! free(args); return (void *)NULL; } diff --git a/src/main.c b/src/main.c index c36bc9a..fc5835b 100644 --- a/src/main.c +++ b/src/main.c @@ -64,35 +64,35 @@ void usage(char *name) { } int set_loglevel(char *level) { - if (strncmp("emerg", level, 6) != 0) { + if (strncmp("emerg", level, 6) == 0) { setlogmask(LOG_UPTO(LOG_EMERG)); return 0; } - if (strncmp("alert", level, 6) != 0) { + if (strncmp("alert", level, 6) == 0) { setlogmask(LOG_UPTO(LOG_ALERT)); return 0; } - if (strncmp("crit", level, 5) != 0) { + if (strncmp("crit", level, 5) == 0) { setlogmask(LOG_UPTO(LOG_CRIT)); return 0; } - if (strncmp("err", level, 4) != 0) { + if (strncmp("err", level, 4) == 0) { setlogmask(LOG_UPTO(LOG_ERR)); return 0; } - if (strncmp("warn", level, 5) != 0) { + if (strncmp("warn", level, 5) == 0) { setlogmask(LOG_UPTO(LOG_WARNING)); return 0; } - if (strncmp("notice", level, 7) != 0) { + if (strncmp("notice", level, 7) == 0) { setlogmask(LOG_UPTO(LOG_NOTICE)); return 0; } - if (strncmp("info", level, 5) != 0) { + if (strncmp("info", level, 5) == 0) { setlogmask(LOG_UPTO(LOG_INFO)); return 0; } - if (strncmp("debug", level, 6) != 0) { + if (strncmp("debug", level, 6) == 0) { setlogmask(LOG_UPTO(LOG_DEBUG)); return 0; } @@ -144,7 +144,7 @@ int main(int argc, char **argv) { break; case 'l': loglevset = 1; - if (!set_loglevel(optarg)) { + if (set_loglevel(optarg)) { fprintf(stderr, "invalid option for -l\n"); usage(argv[0]); return -1; @@ -181,7 +181,7 @@ int main(int argc, char **argv) { syslog(LOG_INFO, "daemonized"); } } - struct timeval timeout = { 1, 0 }; + 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; @@ -196,7 +196,7 @@ int main(int argc, char **argv) { retme = -1; goto cleanup; } - syslog(LOG_INFO, "socket bind success"); + syslog(LOG_DEBUG, "socket bind success"); if (daemonize) { //TODO: use getpwnam_r() and getgrnam_r() struct group *g = getgrnam((const char *)&group); @@ -246,6 +246,12 @@ int main(int argc, char **argv) { ); 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( @@ -255,7 +261,7 @@ int main(int argc, char **argv) { ); continue; } - nbd_tftp_opcode oc = ntohs(((uint16_t)buf[0] << 8) + buf[1]); + 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); @@ -293,6 +299,9 @@ int main(int argc, char **argv) { } //TODO: use std threads int e; + syslog(LOG_ERR, "spawning thread for %s", inet_ntoa(caddr.sin_addr)); +// void *lol = func((void *)args); +// free(lol); if ((e = pthread_create(_thread, 0, func, (void *)args)) != 0) { syslog( LOG_CRIT, diff --git a/src/packet.c b/src/packet.c index 5bc8be6..0c9d592 100644 --- a/src/packet.c +++ b/src/packet.c @@ -1,3 +1,7 @@ +#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) { @@ -22,3 +26,38 @@ char *nbd_tftp_error_to_message(nbd_tftp_ecode error) { 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_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; +} + |