diff options
Diffstat (limited to 'src/handlers.c')
-rw-r--r-- | src/handlers.c | 140 |
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) { |