diff --git a/netutils/ftpd/ftpd.c b/netutils/ftpd/ftpd.c index 53c233c6b2c..602442ef8eb 100644 --- a/netutils/ftpd/ftpd.c +++ b/netutils/ftpd/ftpd.c @@ -1,7 +1,7 @@ /**************************************************************************** * apps/n etutils/ftpd.c * - * Copyright (C) 2012, 2015 Gregory Nutt. All rights reserved. + * Copyright (C) 2012, 2015, 2020 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Includes original code as well as logic adapted from hwport_ftpd, written @@ -75,6 +75,7 @@ /**************************************************************************** * Private Function Prototypes ****************************************************************************/ + /* Account functions */ static FAR struct ftpd_account_s *ftpd_account_new(FAR const char *user, @@ -113,7 +114,8 @@ static ssize_t ftpd_response(int sd, int timeout, FAR const char *fmt, ...); static int ftpd_dataopen(FAR struct ftpd_session_s *session); static int ftpd_dataclose(FAR struct ftpd_session_s *session); -static FAR struct ftpd_server_s *ftpd_openserver(int port, sa_family_t family); +static FAR struct ftpd_server_s *ftpd_openserver(int port, + sa_family_t family); /* Path helpers */ @@ -251,7 +253,8 @@ static const char g_respfmt2[] = "%03u%c%s%s\r\n"; /* Integer, character, two s static const char *g_monthtab[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", + "Oct", "Nov", "Dec" }; static const char *g_ftpdhelp[] = @@ -265,16 +268,13 @@ static const char *g_ftpdhelp[] = "APPE REST ABOR USER PASS ACCT* REIN* LIST", "NLST STAT* SITE* MLSD* MLST*", "Direct comments to " CONFIG_FTPD_VENDORID, - NULL + NULL }; /**************************************************************************** * Private Functions ****************************************************************************/ -/**************************************************************************** - * Account Functions - ****************************************************************************/ /**************************************************************************** * Name: ftpd_account_new ****************************************************************************/ @@ -506,12 +506,14 @@ ftpd_account_search_user(FAR struct ftpd_session_s *session, newaccount = ftpd_account_new(NULL, accountflags); if (newaccount) { - if (ftpd_account_setpassword(newaccount, account->password) < 0) + if (ftpd_account_setpassword(newaccount, + account->password) < 0) { ftpd_account_free(newaccount); newaccount = NULL; } - else if (ftpd_account_sethome(newaccount, account->home) < 0) + else if (ftpd_account_sethome(newaccount, + account->home) < 0) { ftpd_account_free(newaccount); newaccount = NULL; @@ -534,17 +536,20 @@ ftpd_account_search_user(FAR struct ftpd_session_s *session, newaccount = ftpd_account_new(account->user, accountflags); if (newaccount) { - if (ftpd_account_setpassword(newaccount, account->password) != 0) + if (ftpd_account_setpassword(newaccount, + account->password) != 0) { ftpd_account_free(newaccount); newaccount = NULL; } - else if (ftpd_account_sethome(newaccount, account->home) != 0) + else if (ftpd_account_sethome(newaccount, + account->home) != 0) { ftpd_account_free(newaccount); newaccount = NULL; } } + break; } } @@ -623,20 +628,17 @@ ftpd_account_login(FAR struct ftpd_session_s *session, session->work = strdup(!home ? "/" : home); } else - { - /* normal user */ + { + /* normal user */ - session->home = strdup(!home ? "/" : home); - session->work = strdup("/"); - } + session->home = strdup(!home ? "/" : home); + session->work = strdup("/"); + } ftpd_account_free(account); return account; } -/**************************************************************************** - * Parsing Functions - ****************************************************************************/ /**************************************************************************** * Name: ftpd_strtok ****************************************************************************/ @@ -682,10 +684,10 @@ static FAR char *ftpd_strtok(bool skipspace, FAR const char *delimiters, sptr++; } - /* Save the place where we will resuming searching */ + /* Save the place where we will resuming searching */ - *str = sptr; - return ret; + *str = sptr; + return ret; } /**************************************************************************** @@ -745,30 +747,28 @@ static FAR char *ftpd_strtok_alloc(bool skipspace, FAR const char *delimiters, } } - /* Allocate memory large enough to hold the entire sub-string (including - * the NUL terminator. - */ + /* Allocate memory large enough to hold the entire sub-string (including + * the NUL terminator. + */ - tokenlen = (size_t)(right - left); - ret = (FAR char *)malloc(tokenlen + 1); - if (ret) - { - if (tokenlen > 0) - { - memcpy(ret, left, tokenlen); - } - ret[tokenlen] = '\0'; - } + tokenlen = (size_t)(right - left); + ret = (FAR char *)malloc(tokenlen + 1); + if (ret) + { + if (tokenlen > 0) + { + memcpy(ret, left, tokenlen); + } - /* Save the place where we will resuming searching */ + ret[tokenlen] = '\0'; + } - *str = sptr; - return ret; + /* Save the place where we will resuming searching */ + + *str = sptr; + return ret; } -/**************************************************************************** - * Socket Helpers - ****************************************************************************/ /**************************************************************************** * Name: ftpd_rxpoll ****************************************************************************/ @@ -796,7 +796,6 @@ static int ftpd_rxpoll(int sd, int timeout) if (ret == 0) { - //ninfo("poll() timed out\n"); return -ETIMEDOUT; } else if (ret < 0) @@ -878,6 +877,7 @@ static int ftpd_accept(int sd, FAR void *addr, FAR socklen_t *addrlen, nerr("ERROR: ftpd_rxpoll() failed: %d\n", ret); } #endif + return ret; } } @@ -937,7 +937,8 @@ static ssize_t ftpd_recv(int sd, FAR void *data, size_t size, int timeout) * Name: ftpd_send ****************************************************************************/ -static ssize_t ftpd_send(int sd, FAR const void *data, size_t size, int timeout) +static ssize_t ftpd_send(int sd, FAR const void *data, size_t size, + int timeout) { ssize_t ret; @@ -1027,7 +1028,8 @@ static int ftpd_dataopen(FAR struct ftpd_session_s *session) } session->data.addrlen = (socklen_t)sizeof(session->data.addr); - ret = connect(session->data.sd, (FAR const struct sockaddr *)(&session->data.addr), + ret = connect(session->data.sd, + (FAR const struct sockaddr *)(&session->data.addr), session->data.addrlen); if (ret < 0) { @@ -1044,9 +1046,10 @@ static int ftpd_dataopen(FAR struct ftpd_session_s *session) struct linger ling; memset(&ling, 0, sizeof(ling)); - ling.l_onoff = 1; + ling.l_onoff = 1; ling.l_linger = 4; - setsockopt(session->data.sd, SOL_SOCKET, SO_LINGER, &ling, sizeof(ling)); + setsockopt(session->data.sd, SOL_SOCKET, SO_LINGER, &ling, + sizeof(ling)); } #endif @@ -1174,7 +1177,7 @@ static FAR struct ftpd_server_s *ftpd_openserver(int port, sa_family_t family) #ifdef CONFIG_NET_HAVE_REUSEADDR { int reuse = 1; - setsockopt(server->sd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); + setsockopt(server->sd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)); } #endif @@ -1199,9 +1202,6 @@ static FAR struct ftpd_server_s *ftpd_openserver(int port, sa_family_t family) return (FTPD_SESSION)server; } -/**************************************************************************** - * Path Helpers - ****************************************************************************/ /**************************************************************************** * Name: ftpd_pathignore ****************************************************************************/ @@ -1238,8 +1238,10 @@ static int ftpd_pathignore(FAR struct ftpd_pathnode_s *currpath) { node->ignore = true; } + break; } + node = node->blink; } @@ -1272,6 +1274,7 @@ static void ftpd_nodefree(FAR struct ftpd_pathnode_s *node) { free(prev->name); } + free(prev); } } @@ -1305,7 +1308,8 @@ static FAR struct ftpd_pathnode_s *ftpd_path2node(FAR const char *path) path++; } - newnode = (FAR struct ftpd_pathnode_s *)malloc(sizeof(struct ftpd_pathnode_s)); + newnode = (FAR struct ftpd_pathnode_s *) + malloc(sizeof(struct ftpd_pathnode_s)); if (!newnode) { free(name); @@ -1597,9 +1601,6 @@ static int ftpd_getpath(FAR struct ftpd_session_s *session, return OK; } -/**************************************************************************** - * Command Helpers - ****************************************************************************/ /**************************************************************************** * Name: ftpd_changedir ****************************************************************************/ @@ -1612,31 +1613,39 @@ static int ftpd_changedir(FAR struct ftpd_session_s *session, struct stat st; int ret; - ret = ftpd_getpath(session, rempath, (char **)(&abspath), (char **)(&workpath)); + ret = ftpd_getpath(session, rempath, (FAR char **)(&abspath), + (FAR char **)(&workpath)); if (ret < 0) { - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', - "Can not change directory !"); + free(workpath); + free(abspath); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', + "Can not change directory !"); + return ret; } ret = stat(abspath, &st); if (ret < 0) { + ret = -errno; + free(workpath); free(abspath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt2, 550, ' ', rempath, - ": No such file or directory"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt2, 550, ' ', rempath, + ": No such file or directory"); + return ret; } if (S_ISDIR(st.st_mode) == 0) { free(workpath); free(abspath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt2, 550, ' ', rempath, - ": No such file or directory"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt2, 550, ' ', rempath, + ": No such file or directory"); + return -ENOTDIR; } free(abspath); @@ -1644,6 +1653,7 @@ static int ftpd_changedir(FAR struct ftpd_session_s *session, { free(session->work); } + session->work = workpath; return ftpd_response(session->cmd.sd, session->txtimeout, @@ -1674,20 +1684,22 @@ static off_t ftpd_offsatoi(FAR const char *filename, off_t offset) if (offset == (off_t)(-1)) { - for (;;) + for (; ; ) { ch = getc(outstream); if (ch == EOF) { break; } + ret++; if (ch == '\n') { ret++; } } - /* ret is ascii mode size */ + + /* ret is ascii mode size */ } else { @@ -1742,6 +1754,7 @@ static int ftpd_stream(FAR struct ftpd_session_s *session, int cmdtype) g_respfmt1, 550, ' ', "Stream error !"); goto errout; } + path = abspath; ret = ftpd_dataopen(session); @@ -1863,7 +1876,7 @@ static int ftpd_stream(FAR struct ftpd_session_s *session, int cmdtype) goto errout_with_session; } - pos += (off_t)seekoffs; + pos += (off_t)seekoffs; } /* Send success message */ @@ -1876,7 +1889,7 @@ static int ftpd_stream(FAR struct ftpd_session_s *session, int cmdtype) goto errout_with_session; } - for (;;) + for (; ; ) { /* Read from the source (file or TCP connection) */ @@ -1903,8 +1916,8 @@ static int ftpd_stream(FAR struct ftpd_session_s *session, int cmdtype) } else { - /* Read from the TCP connection, ftpd_recve returns the negated error - * condition. + /* Read from the TCP connection, ftpd_recve returns the negated + * error condition. */ rdbytes = ftpd_recv(session->data.sd, session->data.buffer, @@ -1959,6 +1972,7 @@ static int ftpd_stream(FAR struct ftpd_session_s *session, int cmdtype) { buffer[buflen++] = '\r'; } + buffer[buflen++] = session->data.buffer[offset++]; } } @@ -1972,7 +1986,8 @@ static int ftpd_stream(FAR struct ftpd_session_s *session, int cmdtype) { /* Write to the TCP connection */ - wrbytes = ftpd_send(session->data.sd, buffer, buflen, session->txtimeout); + wrbytes = ftpd_send(session->data.sd, buffer, buflen, + session->txtimeout); if (wrbytes < 0) { errval = -wrbytes; @@ -2016,7 +2031,8 @@ static int ftpd_stream(FAR struct ftpd_session_s *session, int cmdtype) if (wrbytes != ((ssize_t)buflen)) { - nerr("ERROR: Write failed: wrbytes=%d errval=%d\n", wrbytes, errval); + nerr("ERROR: Write failed: wrbytes=%d errval=%d\n", + wrbytes, errval); ftpd_response(session->cmd.sd, session->txtimeout, g_respfmt1, 550, ' ', "Data send error !"); ret = -errval; @@ -2241,24 +2257,29 @@ static int ftpd_listbuffer(FAR struct ftpd_session_s *session, FAR char *path, #ifdef __NUTTX__ /* Fake nlink, user id, and group id */ - offset += snprintf(&buffer[offset], buflen - offset, "%4u %8u %8u", 1, 1001, 512); + offset += snprintf(&buffer[offset], buflen - offset, "%4u %8u %8u", + 1, 1001, 512); #else /* nlink */ - offset += snprintf(&buffer[offset], buflen - offset, "%4u", st->st_nlink); + offset += snprintf(&buffer[offset], buflen - offset, "%4u", + st->st_nlink); /* user id */ - offset += snprintf(&buffer[offset], buflen - offset, " %8u", st->st_uid); + offset += snprintf(&buffer[offset], buflen - offset, + " %8u", st->st_uid); /* group id */ - offset += snprintf(&buffer[offset], buflen - offset, " %8u", st->st_gid); + offset += snprintf(&buffer[offset], buflen - offset, " %8u", + st->st_gid); #endif /* size */ - offset += snprintf(&buffer[offset], buflen - offset, " %8u", st->st_size); + offset += snprintf(&buffer[offset], buflen - offset, + " %8u", st->st_size); /* time */ @@ -2298,7 +2319,8 @@ static int ftpd_listbuffer(FAR struct ftpd_session_s *session, FAR char *path, temp[namelen] = '\0'; } - offset += snprintf(&buffer[offset], buflen - offset, " -> %s", temp); + offset += snprintf(&buffer[offset], buflen - offset, + " -> %s", temp); free(temp); } } @@ -2358,7 +2380,7 @@ static int fptd_listscan(FAR struct ftpd_session_s *session, FAR char *path, return -errval; } - for (;;) + for (; ; ) { entry = readdir(dir); if (!entry) @@ -2425,9 +2447,6 @@ static int ftpd_list(FAR struct ftpd_session_s *session, unsigned int opton) return ret; } -/**************************************************************************** - * Command Handlers - ****************************************************************************/ /**************************************************************************** * Name: ftpd_command_user ****************************************************************************/ @@ -2463,6 +2482,7 @@ static int ftpd_command_user(FAR struct ftpd_session_s *session) return ftpd_response(session->cmd.sd, session->txtimeout, g_respfmt1, 451, ' ', "Memory exhausted !"); } + session->flags |= FTPD_SESSIONFLAG_USER; /* If there is no account information, then no login is required. */ @@ -2482,6 +2502,7 @@ static int ftpd_command_user(FAR struct ftpd_session_s *session) { session->curr = NULL; } + return ret; } @@ -2498,6 +2519,7 @@ static int ftpd_command_user(FAR struct ftpd_session_s *session) { session->curr = NULL; } + return ret; } @@ -2531,6 +2553,7 @@ static int ftpd_command_pass(FAR struct ftpd_session_s *session) { session->curr = NULL; } + return ret; } @@ -2598,13 +2621,15 @@ static int ftpd_command_type(FAR struct ftpd_session_s *session) { session->type = FTPD_SESSIONTYPE_L8; return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 200, ' ', "Type set to L 8"); + g_respfmt1, 200, ' ', + "Type set to L 8"); } else { session->type = FTPD_SESSIONTYPE_NONE; return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 504, ' ', "Byte size must be 8 !"); + g_respfmt1, 504, ' ', + "Byte size must be 8 !"); } } } @@ -2748,7 +2773,8 @@ static int ftpd_command_port(FAR struct ftpd_session_s *session) session->data.addr.in4.sin_family = AF_INET; - utemp = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | (value[3]); + utemp = (value[0] << 24) | (value[1] << 16) | + (value[2] << 8) | (value[3]); session->data.addr.in4.sin_addr.s_addr = htonl(utemp); } @@ -2761,7 +2787,8 @@ static int ftpd_command_port(FAR struct ftpd_session_s *session) session->data.addr.in4.sin_family = AF_INET; - utemp = (value[0] << 24) | (value[1] << 16) | (value[2] << 8) | (value[3]); + utemp = (value[0] << 24) | (value[1] << 16) | + (value[2] << 8) | (value[3]); session->data.addr.in4.sin_addr.s_addr = htonl(utemp); } @@ -2805,6 +2832,7 @@ static int ftpd_command_eprt(FAR struct ftpd_session_s *session) "EPRT command not implemented !"); return -EINVAL; } + right--; while (session->param[left] != '\0') @@ -2814,6 +2842,7 @@ static int ftpd_command_eprt(FAR struct ftpd_session_s *session) left++; break; } + left++; } @@ -2837,15 +2866,15 @@ static int ftpd_command_eprt(FAR struct ftpd_session_s *session) for (index = 0; index < count && *str != '\0'; index++) { field[index] = ftpd_strtok_alloc(true, ",|)", &str); - if (!field[index]) - { - break; - } + if (!field[index]) + { + break; + } - if (*str != '\0') - { - str++; - } + if (*str != '\0') + { + str++; + } } if (index < count) @@ -2861,7 +2890,7 @@ static int ftpd_command_eprt(FAR struct ftpd_session_s *session) ftpd_response(session->cmd.sd, session->txtimeout, g_respfmt1, 502, ' ', "EPRT command not implemented !"); - return -EINVAL; + return -EINVAL; } ftpd_dataclose(session); @@ -2895,7 +2924,7 @@ static int ftpd_command_eprt(FAR struct ftpd_session_s *session) family = AF_UNSPEC; } - for (index = 0;index < count;index++) + for (index = 0; index < count; index++) { if (field[index]) { @@ -2968,9 +2997,10 @@ static int ftpd_command_rmd(FAR struct ftpd_session_s *session) ret = ftpd_getpath(session, session->param, &abspath, &workpath); if (ret < 0) { - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', - "Can not remove directory !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', + "Can not remove directory !"); + return ret; } if (strcmp(session->home, abspath) == 0) @@ -2978,9 +3008,10 @@ static int ftpd_command_rmd(FAR struct ftpd_session_s *session) free(abspath); free(workpath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', - "Can not remove home directory !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', + "Can not remove home directory !"); + return -EINVAL; } if (strcmp(session->work, workpath) == 0) @@ -2988,20 +3019,23 @@ static int ftpd_command_rmd(FAR struct ftpd_session_s *session) free(abspath); free(workpath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', - "Can not remove current directory !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', + "Can not remove current directory !"); + return -EINVAL; } ret = rmdir(abspath); if (ret < 0) { + ret = -errno; free(abspath); free(workpath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', - "Can not remove directory !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', + "Can not remove directory !"); + return ret; } free(abspath); @@ -3024,17 +3058,21 @@ static int ftpd_command_mkd(FAR struct ftpd_session_s *session) ret = ftpd_getpath(session, session->param, &abspath, NULL); if (ret < 0) { - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', - "Can not make directory !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', + "Can not make directory !"); + return ret; } - ret = mkdir(abspath, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + ret = mkdir(abspath, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | + S_IXGRP | S_IROTH | S_IXOTH); if (ret < 0) { + ret = -errno; free(abspath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', "Can not make directory !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', "Can not make directory !"); + return ret; } free(abspath); @@ -3055,8 +3093,9 @@ static int ftpd_command_dele(FAR struct ftpd_session_s *session) ret = ftpd_getpath(session, session->param, &abspath, &workpath); if (ret < 0) { - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', "Can not delete file !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', "Can not delete file !"); + return ret; } if (strcmp(session->home, abspath) == 0) @@ -3064,9 +3103,10 @@ static int ftpd_command_dele(FAR struct ftpd_session_s *session) free(abspath); free(workpath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', - "Can not delete home directory !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', + "Can not delete home directory !"); + return -EINVAL; } if (strcmp(session->work, workpath) == 0) @@ -3074,19 +3114,22 @@ static int ftpd_command_dele(FAR struct ftpd_session_s *session) free(abspath); free(workpath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', - "Can not delete current directory !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', + "Can not delete current directory !"); + return -EINVAL; } ret = unlink(abspath); if (ret < 0) { + ret = -errno; free(abspath); free(workpath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', "Can not delete file !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', "Can not delete file !"); + return ret; } free(abspath); @@ -3116,10 +3159,12 @@ static int ftpd_command_pasv(FAR struct ftpd_session_s *session) { ftpd_dataclose(session); return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 425, ' ', "PASV socket create fail !"); + g_respfmt1, 425, ' ', + "PASV socket create fail !"); } - ret = getsockname(session->cmd.sd, (FAR struct sockaddr *)&session->data.addr, + ret = getsockname(session->cmd.sd, + (FAR struct sockaddr *)&session->data.addr, &session->data.addrlen); if (ret < 0) { @@ -3129,28 +3174,29 @@ static int ftpd_command_pasv(FAR struct ftpd_session_s *session) } #ifdef CONFIG_NET_IPv6 - if (session->data.addr.ss.ss_family == AF_INET6) - { - /* Convert ipv6 to ipv4 */ + if (session->data.addr.ss.ss_family == AF_INET6) + { + /* Convert ipv6 to ipv4 */ - if ((IN6_IS_ADDR_V4MAPPED(&session->data.addr.in6.sin6_addr) != 0) || - (IN6_IS_ADDR_V4COMPAT(&session->data.addr.in6.sin6_addr) != 0)) - { - /* convert ipv6 to ipv4 */ + if ((IN6_IS_ADDR_V4MAPPED(&session->data.addr.in6.sin6_addr) != 0) || + (IN6_IS_ADDR_V4COMPAT(&session->data.addr.in6.sin6_addr) != 0)) + { + /* convert ipv6 to ipv4 */ - in_addr in4addr; + in_addr in4addr; - in4addr.s_addr = session->data.addr.in6.sin6_addr.s6_addr32[3]; + in4addr.s_addr = session->data.addr.in6.sin6_addr.s6_addr32[3]; - memset(&session->data.addr, 0, sizeof(session->data.addr)); - session->data.addr.in4.sin_family = AF_INET; - session->data.addr.in4.sin_addr.s_addr = in4addr.s_addr; + memset(&session->data.addr, 0, sizeof(session->data.addr)); + session->data.addr.in4.sin_family = AF_INET; + session->data.addr.in4.sin_addr.s_addr = in4addr.s_addr; } } #endif session->data.addr.in4.sin_port = 0; - ret = bind(session->data.sd, (FAR const struct sockaddr *)&session->data.addr, + ret = bind(session->data.sd, + (FAR const struct sockaddr *)&session->data.addr, session->data.addrlen); if (ret < 0) { @@ -3159,7 +3205,8 @@ static int ftpd_command_pasv(FAR struct ftpd_session_s *session) g_respfmt1, 425, ' ', "PASV bind fail !"); } - ret = getsockname(session->data.sd, (FAR struct sockaddr *)&session->data.addr, + ret = getsockname(session->data.sd, + (FAR struct sockaddr *)&session->data.addr, &session->data.addrlen); if (ret < 0) { @@ -3236,7 +3283,8 @@ static int ftpd_command_epsv(FAR struct ftpd_session_s *session) { #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY) int ipv6only = 0; - setsockopt(session->data.sd, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6only, sizeof(ipv6only)); + setsockopt(session->data.sd, IPPROTO_IPV6, IPV6_V6ONLY, + &ipv6only, sizeof(ipv6only)); #endif } #else @@ -3251,8 +3299,9 @@ static int ftpd_command_epsv(FAR struct ftpd_session_s *session) return ret; } - ret = getsockname(session->cmd.sd, (FAR struct sockaddr *)&session->data.addr, - &session->data.addrlen); + ret = getsockname(session->cmd.sd, + (FAR struct sockaddr *)&session->data.addr, + &session->data.addrlen); if (ret < 0) { ret = ftpd_response(session->cmd.sd, session->txtimeout, @@ -3282,7 +3331,8 @@ static int ftpd_command_epsv(FAR struct ftpd_session_s *session) return ret; } - ret = bind(session->data.sd, (FAR const struct sockaddr *)&session->data.addr, + ret = bind(session->data.sd, + (FAR const struct sockaddr *)&session->data.addr, session->data.addrlen); if (ret < 0) { @@ -3292,7 +3342,8 @@ static int ftpd_command_epsv(FAR struct ftpd_session_s *session) return ret; } - ret = getsockname(session->data.sd, (FAR struct sockaddr *)&session->data.addr, + ret = getsockname(session->data.sd, + (FAR struct sockaddr *)&session->data.addr, &session->data.addrlen); if (ret < 0) { @@ -3315,7 +3366,8 @@ static int ftpd_command_epsv(FAR struct ftpd_session_s *session) if (session->data.addr.ss.ss_family == AF_INET6) { ret = ftpd_response(session->cmd.sd, session->txtimeout, - "%03u%cEntering Extended Passive Mode (|||%u|).\r\n", + "%03u%cEntering Extended Passive Mode " + "(|||%u|).\r\n", 229, ' ', ntohs(session->data.addr.in6.sin6_port)); if (ret < 0) @@ -3329,7 +3381,8 @@ static int ftpd_command_epsv(FAR struct ftpd_session_s *session) if (session->data.addr.ss.ss_family == AF_INET) { ret = ftpd_response(session->cmd.sd, session->txtimeout, - "%03u%cEntering Extended Passive Mode (|%u||%u|).\r\n", + "%03u%cEntering Extended Passive Mode " + "(|%u||%u|).\r\n", 229, ' ', 1, ntohs(session->data.addr.in4.sin_port)); if (ret < 0) @@ -3424,7 +3477,8 @@ static int ftpd_command_nlst(FAR struct ftpd_session_s *session) static int ftpd_command_acct(FAR struct ftpd_session_s *session) { return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 502, ' ', "ACCT command not implemented !"); + g_respfmt1, 502, ' ', + "ACCT command not implemented !"); } /**************************************************************************** @@ -3445,9 +3499,11 @@ static int ftpd_command_size(FAR struct ftpd_session_s *session) ret = ftpd_getpath(session, session->param, &abspath, NULL); if (ret < 0) { - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', "Unknown size !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', "Unknown size !"); + return ret; } + path = abspath; ret = 0; @@ -3473,7 +3529,8 @@ static int ftpd_command_size(FAR struct ftpd_session_s *session) else { ret = ftpd_response(session->cmd.sd, session->txtimeout, - "%03u%c%llu\r\n", 213, ' ', (unsigned long long)st.st_size); + "%03u%c%llu\r\n", 213, ' ', + (unsigned long long)st.st_size); } } break; @@ -3483,40 +3540,33 @@ static int ftpd_command_size(FAR struct ftpd_session_s *session) status = stat(path, &st); if (status < 0) { - ret = ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt2, 550, ' ', session->param, - ": not a regular file."); - if (ret < 0) - { - return ret; - } + ret = -errno; + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt2, 550, ' ', session->param, + ": not a regular file."); + goto errout_with_abspath; } else if (!S_ISREG(st.st_mode)) { ret = ftpd_response(session->cmd.sd, session->txtimeout, g_respfmt2, 550, ' ', session->param, ": not a regular file."); - if (ret < 0) - { - return ret; - } + ret = -EPERM; + goto errout_with_abspath; } - outstream = fopen(path, "r"); if (!outstream) { - ret = ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt2, 550, ' ', session->param, - ": Can not open file !"); - if (ret < 0) - { - return ret; - } - } + ret = -errno; + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt2, 550, ' ', session->param, + ": Can not open file !"); + goto errout_with_abspath; + } offset = 0; - for (;;) + for (; ; ) { ch = getc(outstream); if (ch == EOF) @@ -3527,23 +3577,27 @@ static int ftpd_command_size(FAR struct ftpd_session_s *session) { offset++; } + offset++; } fclose(outstream); ret = ftpd_response(session->cmd.sd, session->txtimeout, - "%03u%c%llu\r\n", 213, ' ', (unsigned long long)offset); + "%03u%c%llu\r\n", 213, ' ', + (unsigned long long)offset); } break; default: { ret = ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 504, ' ', "SIZE not implemented for type"); + g_respfmt1, 504, ' ', + "SIZE not implemented for type"); } break; } +errout_with_abspath: free(abspath); return ret; } @@ -3555,7 +3609,8 @@ static int ftpd_command_size(FAR struct ftpd_session_s *session) static int ftpd_command_stru(FAR struct ftpd_session_s *session) { return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 502, ' ', "STRU command not implemented !"); + g_respfmt1, 502, ' ', + "STRU command not implemented !"); } /**************************************************************************** @@ -3565,7 +3620,6 @@ static int ftpd_command_stru(FAR struct ftpd_session_s *session) static int ftpd_command_rnfr(FAR struct ftpd_session_s *session) { FAR char *abspath; - FAR char *path; struct stat st; int ret; @@ -3578,12 +3632,12 @@ static int ftpd_command_rnfr(FAR struct ftpd_session_s *session) ret = ftpd_getpath(session, session->param, &abspath, NULL); if (ret < 0) { - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', "RNFR error !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', "RNFR error !"); + return ret; } - path = abspath; - ret = stat(path, &st); + ret = stat(abspath, &st); if (ret < 0) { free(abspath); @@ -3612,22 +3666,26 @@ static int ftpd_command_rnto(FAR struct ftpd_session_s *session) { return ftpd_response(session->cmd.sd, session->txtimeout, g_respfmt1, 550, ' ', "RNTO error !"); + return ret; } ret = ftpd_getpath(session, session->param, &abspath, NULL); if (ret < 0) { - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', "RNTO error !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', "RNTO error !"); + return ret; } ret = rename(session->renamefrom, abspath); if (ret < 0) { + ret = -errno; free(abspath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt2, 550, ' ', session->param, - ": Rename error."); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt2, 550, ' ', session->param, + ": Rename error."); + return ret; } free(abspath); @@ -3641,7 +3699,7 @@ static int ftpd_command_rnto(FAR struct ftpd_session_s *session) static int ftpd_command_retr(FAR struct ftpd_session_s *session) { - return ftpd_stream(session, 0); + return ftpd_stream(session, 0); } /**************************************************************************** @@ -3650,7 +3708,7 @@ static int ftpd_command_retr(FAR struct ftpd_session_s *session) static int ftpd_command_stor(FAR struct ftpd_session_s *session) { - return ftpd_stream(session, 1); + return ftpd_stream(session, 1); } /**************************************************************************** @@ -3659,7 +3717,7 @@ static int ftpd_command_stor(FAR struct ftpd_session_s *session) static int ftpd_command_appe(FAR struct ftpd_session_s *session) { - return ftpd_stream(session, 2); + return ftpd_stream(session, 2); } /**************************************************************************** @@ -3669,14 +3727,14 @@ static int ftpd_command_appe(FAR struct ftpd_session_s *session) static int ftpd_command_rest(FAR struct ftpd_session_s *session) { #ifdef CONFIG_HAVE_LONG_LONG - session->restartpos = (off_t)atoll(session->param); + session->restartpos = (off_t)atoll(session->param); #else - session->restartpos = (off_t)atoi(session->param); + session->restartpos = (off_t)atoi(session->param); #endif - session->flags |= FTPD_SESSIONFLAG_RESTARTPOS; + session->flags |= FTPD_SESSIONFLAG_RESTARTPOS; - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 320, ' ', "Restart position ready"); + return ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 320, ' ', "Restart position ready"); } /**************************************************************************** @@ -3692,28 +3750,33 @@ static int ftpd_command_mdtm(FAR struct ftpd_session_s *session) int ret; ret = ftpd_getpath(session, session->param, &abspath, NULL); - if (ret <0) + if (ret < 0) { - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 550, ' ', "Unknown size !"); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt1, 550, ' ', "Unknown size !"); + return ret; } + path = abspath; ret = stat(path, &st); if (ret < 0) { + ret = -errno; free(abspath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt2, 550, ' ', session->param, - ": not a plain file."); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt2, 550, ' ', session->param, + ": not a plain file."); + return ret; } - if (!S_ISREG(st.st_mode)) - { - free(abspath); - return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt2, 550, ' ', session->param, - ": not a plain file."); + if (!S_ISREG(st.st_mode)) + { + free(abspath); + ftpd_response(session->cmd.sd, session->txtimeout, + g_respfmt2, 550, ' ', session->param, + ": not a plain file."); + return -EISDIR; } free(abspath); @@ -3751,6 +3814,7 @@ static int ftpd_command_opts(FAR struct ftpd_session_s *session) *str = '\0'; str++; } + value = str; if (strcasecmp(option, "UTF8") == 0 || strcasecmp(option, "UTF-8") == 0) @@ -3760,10 +3824,11 @@ static int ftpd_command_opts(FAR struct ftpd_session_s *session) if (value[0] == '\0' || strcasecmp(value, "ON") == 0 || strcasecmp(value, "ENABLE") == 0 || strcasecmp(value, "TRUE") == 0) { - remote = true; + remote = true; } - else { - remote = false; + else + { + remote = false; } lang = getenv("LANG"); @@ -3807,7 +3872,8 @@ static int ftpd_command_opts(FAR struct ftpd_session_s *session) static int ftpd_command_site(FAR struct ftpd_session_s *session) { return ftpd_response(session->cmd.sd, session->txtimeout, - g_respfmt1, 502, ' ', "SITE command not implemented !"); + g_respfmt1, 502, ' ', + "SITE command not implemented !"); } /**************************************************************************** @@ -3903,6 +3969,7 @@ static int ftpd_command(FAR struct ftpd_session_s *session) /**************************************************************************** * Worker Thread ****************************************************************************/ + /**************************************************************************** * Name: ftpd_startworker ****************************************************************************/ @@ -4071,7 +4138,7 @@ static FAR void *ftpd_worker(FAR void *arg) /* Then loop processing FTP commands */ - for (;;) + for (; ; ) { /* Receive the next command */ @@ -4103,12 +4170,13 @@ static FAR void *ftpd_worker(FAR void *arg) while (recvbytes > 0) { ch = session->cmd.buffer[offset]; - if (ch != 0xff && ch != 0xf4 && ch != 0xf2) - { - break; - } + if (ch != 0xff && ch != 0xf4 && ch != 0xf2) + { + break; + } - ftpd_send(session->cmd.sd, &session->cmd.buffer[offset], 1, session->txtimeout); + ftpd_send(session->cmd.sd, &session->cmd.buffer[offset], 1, + session->txtimeout); offset++; recvbytes--; @@ -4132,6 +4200,7 @@ static FAR void *ftpd_worker(FAR void *arg) session->cmd.buffer[offset] = '\0'; break; } + offset++; } @@ -4302,7 +4371,8 @@ int ftpd_session(FTPD_SESSION handle, int timeout) /* Allocate a session */ - session = (FAR struct ftpd_session_s *)zalloc(sizeof(struct ftpd_session_s)); + session = (FAR struct ftpd_session_s *) + zalloc(sizeof(struct ftpd_session_s)); if (!session) { nerr("ERROR: Failed to allocate session\n"); @@ -4370,6 +4440,7 @@ int ftpd_session(FTPD_SESSION handle, int timeout) nerr("ERROR: ftpd_accept() failed: %d\n", session->cmd.sd); } #endif + ret = session->cmd.sd; goto errout_with_session; }