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 /src/handlers.c | |
parent | b9635ce3b4ca30b14128c131bb9fe9be08740d6d (diff) | |
download | nbtpd-660da53647cdcdc5ce07054f74e5c420a15702fe.tar.gz nbtpd-660da53647cdcdc5ce07054f74e5c420a15702fe.tar.bz2 nbtpd-660da53647cdcdc5ce07054f74e5c420a15702fe.zip |
first RRQ processed
Diffstat (limited to 'src/handlers.c')
-rw-r--r-- | src/handlers.c | 122 |
1 files changed, 112 insertions, 10 deletions
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; } |