diff options
Diffstat (limited to 'src/main.c')
-rw-r--r-- | src/main.c | 105 |
1 files changed, 82 insertions, 23 deletions
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 |