diff options
author | Ren Kararou <[email protected]> | 2025-01-26 03:41:25 -0600 |
---|---|---|
committer | Ren Kararou <[email protected]> | 2025-01-26 03:41:25 -0600 |
commit | 1bcf3de7f521d83185cce580db2dea6d50a617b6 (patch) | |
tree | c06850c6c0df9bdc9ca395ecc9ebe67b7c9dfb86 /src | |
parent | 9ec8d6d9dc03791f6ab1e3ad108c8d705d355696 (diff) | |
download | nbtpd-bazel.tar.gz nbtpd-bazel.tar.bz2 nbtpd-bazel.zip |
try bazel bazel
Diffstat (limited to 'src')
-rw-r--r-- | src/handlers.c | 535 | ||||
-rw-r--r-- | src/main.c | 313 | ||||
-rw-r--r-- | src/netascii.c | 53 | ||||
-rw-r--r-- | src/packet.c | 125 |
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; -} - |