Files
m241Neelima/components/ip_net2-6.9/ipappl/src/iptftps.c
T
2026-07-30 11:19:44 +05:30

925 lines
26 KiB
C

/*
******************************************************************************
* SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: iptftps.c,v $ $Revision: 1.25.10.6 $
* $Source: /home/interpeak/CVSRoot/ipappl/src/iptftps.c,v $
* $Author: jren $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Markus Carlstedt <markus@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
* TFTP server implementation.
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#include "ipcom_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_ipd.h>
#include "iptftp_h.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/* Specifies if TFTP write requests are permitted */
#define IPTFTP_SERVER_ALLOW_UPLOAD
/* Specifies if TFTP read requests are permitted */
#define IPTFTP_SERVER_ALLOW_DOWNLOAD
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_PUBLIC Ip_err iptftps_create(void);
IP_PUBLIC Ip_err iptftps_start(void);
IP_PUBLIC const char *iptftps_version(void);
IP_STATIC IPCOM_PROCESS(iptftps);
IP_STATIC Ip_err iptftp_server_spawn_handler(Iptftp *tftp);
IP_STATIC Ip_err iptftp_server_parse_request(Ip_fd sock, Ip_s32 family, Iptftp *tftp);
IP_STATIC void iptftp_server_send_file(Iptftp *tftp);
IP_STATIC void iptftp_server_receive_file(Iptftp *tftp);
IP_STATIC IPCOM_PROCESS(iptftp_server_handler);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 LOCAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* iptftp_server_handler
*===========================================================================
* Description: Spawned TFTP handler.
* Parameters: none.
* Returns: nothing.
*/
IP_STATIC
IPCOM_PROCESS(iptftp_server_handler)
{
Ip_bool ipc_opened = IP_FALSE;
Ipcom_ipc ipc;
Iptftp *ipc_tftp = IP_NULL;
ipcom_proc_init();
if (ipcom_ipc_open(&ipc, "iptftps", -1) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "iptftp_server_handler :: ipcom_ipc_open(\"ipwebsd\") failed");
goto exit;
}
ipc_opened = IP_TRUE;
ipc_tftp = ipcom_ipc_malloc(sizeof(*ipc_tftp));
if (ipc_tftp == IP_NULL)
{
IPCOM_LOG0(ERR, "iptftp_server_handler :: ipcom_ipc_malloc() failed");
goto exit;
}
/* Get info from tftp server. */
if (ipcom_ipc_send(&ipc, ipc_tftp) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "iptftp_server_handler :: ipcom_ipc_send() failed");
goto exit;
}
ipc_tftp = IP_NULL;
/* Wait for reply. */
if (ipcom_ipc_receive(IP_NULL, &ipc_tftp, -1) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "iptftp_server_handler :: ipcom_ipc_receive() failed");
goto exit;
}
if (ipc_tftp->opcode == IPTFTP_OPCODE_RRQ)
{
iptftp_server_send_file(ipc_tftp);
}
else if (ipc_tftp->opcode == IPTFTP_OPCODE_WRQ)
{
iptftp_server_receive_file(ipc_tftp);
}
exit:
if (ipc_opened)
(void)ipcom_ipc_close(&ipc);
if (ipc_tftp != IP_NULL)
ipcom_ipc_free(ipc_tftp);
ipcom_proc_exit();
}
/*
*===========================================================================
* iptftp_server_spawn_handler
*===========================================================================
* Description: Called by the tftp server to spawn a new handler for each
* connection
* Parameters: sock - The socket the connection arrived on.
* family - The Internet address family.
* srv_handle - handle for ipcom call messages
* Returns: IPCOM_SUCCESS or IPCOM_ERR_FAILED
*/
IP_STATIC Ip_err
iptftp_server_spawn_handler(Iptftp *tftp)
{
/* Spawn a tftp handler */
if (ipcom_proc_create("iptftp_server_handler", (Ipcom_proc_func)iptftp_server_handler, IPCOM_PROC_STACK_DEFAULT, IP_NULL))
{
IPCOM_LOG0(ERR, "iptftp_server_spawn_handler :: ipcom_proc_create() failed");
goto err;
}
else
{
/* Wait for a message from the handler */
Iptftp *ipc_tftp;
if (ipcom_ipc_receive(IP_NULL, &ipc_tftp, -1) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "iptftp_server_spawn_handler :: ipcom_ipc_receive() failed");
goto err;
}
/* Respond to handler */
ipcom_memcpy(ipc_tftp, tftp, sizeof(*tftp));
if (ipcom_ipc_send(IPCOM_IPC_SENDER, ipc_tftp) != IPCOM_SUCCESS)
{
ipcom_ipc_free(ipc_tftp);
IPCOM_LOG0(ERR, "iptftp_server_spawn_handler :: ipcom_ipc_send() failed");
goto err;
}
}
return IPCOM_SUCCESS;
err:
return IPCOM_ERR_FAILED;
}
/*
*===========================================================================
* iptftp_server_dirindex
*===========================================================================
*
* Description:
* Calculate level of directory path.
*
* Parameters:
* path Directory path.
*
* Returns:
* minimum subdirectory level.
*/
IP_STATIC int
iptftp_server_dirindex(char *path)
{
int level = 0;
int min = 0;
char *start;
char *stop;
char *cp;
cp = path;
while (*cp != '\0')
{
char c;
start = cp;
cp += ipcom_strcspn(cp, IPTFTP_DIR_SEP_STRING);
stop = cp;
cp += ipcom_strspn(cp, IPTFTP_DIR_SEP_STRING);
c = *stop;
*stop = '\0';
if (ipcom_strcmp(start, "..") == 0)
{
level--;
}
else if (*start != '\0' && ipcom_strcmp(start, ".") != 0)
{
level++;
}
*stop = c;
if (level < min)
{
min = level;
}
}
return min;
}
/*
*===========================================================================
* iptftp_server_parse_request
*===========================================================================
* Description: Parses a tftp request and calls the request handler
* Parameters: sock - socket descriptor the request arrived on.
* family - Internet address family for the request.
* tftp - TFTP structure.
* Returns: IPCOM_SUCCESS if ok and an IPCOM_ERR_XXX error code for
* failures.
*/
IP_STATIC Ip_err
iptftp_server_parse_request(Ip_fd sock, Ip_s32 family, Iptftp *tftp)
{
#ifdef IPCOM_USE_INET
struct Ip_sockaddr_in sa;
#endif
#ifdef IPCOM_USE_INET6
struct Ip_sockaddr_in6 sa6;
#endif
char buf[IPTFTP_MAX_PACKET];
Ip_s32 i, len;
char *err_msg = IP_NULL;
struct Ip_msghdr msghdr;
struct Ip_iovec iov;
Ip_err ret = IPCOM_SUCCESS;
/* Get the message from the socket */
tftp->controllen = sizeof(tftp->controlbuf);
msghdr.msg_controllen = tftp->controllen;
msghdr.msg_control = tftp->controlbuf;
msghdr.msg_flags = 0;
msghdr.msg_iov = &iov;
msghdr.msg_iovlen = 1;
iov.iov_base = buf;
iov.iov_len = sizeof(buf);
/* Get this connection's first packet */
switch (family)
{
#ifdef IPCOM_USE_INET
case IP_AF_INET:
msghdr.msg_name = &sa;
msghdr.msg_namelen = sizeof(sa);
len = (Ip_s32)ipcom_recvmsg(sock, &msghdr, 0);
if (len < 0)
{
ret = IPCOM_ERR_FAILED;
goto exit;
}
tftp->peer_port = ip_ntohs(sa.sin_port);
ipcom_memcpy(&tftp->peer_addr.addr, &sa.sin_addr, sizeof(tftp->peer_addr.addr));
tftp->family = IP_AF_INET;
break;
#endif /* IPCOM_USE_INET */
#ifdef IPCOM_USE_INET6
case IP_AF_INET6:
msghdr.msg_name = &sa6;
msghdr.msg_namelen = sizeof(sa6);
len = (Ip_s32)ipcom_recvmsg(sock, &msghdr, 0);
if (len < 0)
{
ret = IPCOM_ERR_FAILED;
goto exit;
}
tftp->peer_port = ip_ntohs(sa6.sin6_port);
ipcom_memcpy(&tftp->peer_addr.addr6, &sa6.sin6_addr, sizeof(tftp->peer_addr.addr6));
tftp->ifindex = sa6.sin6_scope_id;
tftp->family = IP_AF_INET6;
break;
#endif /* IPCOM_USE_INET6 */
default:
ret = IPCOM_ERR_FAILED;
goto exit;
}
/* Sanity checking */
if (len < 6)
{
/* Not enough characters */
err_msg = IPTFTP_ERRMSG_INCOMPLETEMSG;
goto exit;
}
if (buf[len-1] != '\0')
{
/* No null char at end */
err_msg = IPTFTP_ERRMSG_INCOMPLETEMSG;
goto exit;
}
for (i = 2; i < len; i++)
if (buf[i] == '\0')
break;
if (i < 3)
{
/* First char is null char */
err_msg = IPTFTP_ERRMSG_INCOMPLETEMSG;
goto exit;
}
if (i > (len-3))
{
/* Only one null char or two trailing null chars */
err_msg = IPTFTP_ERRMSG_INCOMPLETEMSG;
goto exit;
}
/* Check opcode */
tftp->opcode = (Ip_u16)(buf[0]*256 + buf[1]);
if (tftp->opcode != IPTFTP_OPCODE_RRQ && tftp->opcode != IPTFTP_OPCODE_WRQ)
{
err_msg = IPTFTP_ERRMSG_INVALIDOPCODE;
goto exit;
}
/* Check mode */
if (!ipcom_strcasecmp(&buf[i+1], "netascii"))
tftp->binary = IP_FALSE;
else if (!ipcom_strcasecmp(&buf[i+1], "octet"))
tftp->binary = IP_TRUE;
else
{
err_msg = IPTFTP_ERRMSG_INVALIDMODE;
goto exit;
}
if (tftp->dirlen + 1 + ipcom_strlen(&buf[2]) >= sizeof(tftp->file))
{
ret = IPCOM_ERR_REACHED_MAX;
goto exit;
}
/* Check for trespassing */
if (iptftp_server_dirindex(&buf[2]) < 0)
{
/* Peeked above root directory */
iptftp_send_err(sock, tftp, IPTFTP_ERRCODE_ACCESSVIOLATION,
IPTFTP_ERRMSG_FILEABOVEWORKINGDIR);
return IPCOM_ERR_PERMISSION_DENIED;
}
/* Append filename to server directory */
if (buf[2] == IPTFTP_DIR_SEP)
{
ipcom_strcpy(&tftp->file[tftp->dirlen], &buf[2]);
}
else
{
tftp->file[tftp->dirlen] = IPTFTP_DIR_SEP;
ipcom_strcpy(&tftp->file[tftp->dirlen+1], &buf[2]);
}
exit:
if (err_msg != IP_NULL)
iptftp_send_err(sock, tftp, IPTFTP_ERRCODE_ILLEGALTFTPOP, err_msg);
return ret;
}
/*
*===========================================================================
* iptftp_server_send_file
*===========================================================================
* Description: TFTP server internal send function.
* Parameters: tftp - TFTP structure.
* Returns: nothing.
*/
IP_STATIC void
iptftp_server_send_file(Iptftp *tftp)
{
Ip_fd sock;
IP_FILE *fp = IP_NULL;
char *err_msg = IP_NULL;
Ip_u16 err_code = 0;
/* Get a udp socket, and bind to port 0 */
sock = ipcom_socket(tftp->family, IP_SOCK_DGRAM, 0);
if (sock == IP_INVALID_SOCKET)
{
IPCOM_LOG0(ERR, "iptftp_server_send_file :: ipcom_socket() failed");
goto err;
}
if (iptftp_bind_zero(sock, tftp->family) != IPCOM_SUCCESS)
goto err;
#ifdef IPTFTP_SERVER_ALLOW_DOWNLOAD
/* Open the file */
if (tftp->binary)
fp = ipcom_fopen(tftp->file, "rb");
else
fp = ipcom_fopen(tftp->file, "r");
#endif
if (!fp)
{
IPCOM_LOG1(ERR, "iptftp_server_send_file :: Could not open file: \"%s\"", tftp->file);
err_code = IPTFTP_ERRCODE_FILENOTFOUND;
err_msg = IPTFTP_ERRMSG_COULDNOTOPENFILE;
goto err;
}
/* Start the send loop */
(void)iptftp_send_loop(sock, fp, &err_msg, &err_code, tftp);
err:
/* Send error */
if (err_msg)
iptftp_send_err(sock, tftp, err_code, err_msg);
/* Terminate connection */
if (fp != IP_NULL)
(void)ipcom_fclose(fp);
if (sock != IP_INVALID_SOCKET)
ipcom_socketclose(sock);
}
/*
*===========================================================================
* iptftp_server_receive_file
*===========================================================================
* Description: TFTP server internal receive function.
* Parameters: tftp - TFTP structure.
* Returns: nothing.
*/
IP_STATIC void
iptftp_server_receive_file(Iptftp *tftp)
{
Ip_fd sock;
IP_FILE *fp = IP_NULL;
Ip_u16 err_code = 0;
char *err_msg = IP_NULL;
char *buf = IP_NULL;
/* Get a udp socket, and bind to port 0 */
sock = ipcom_socket(tftp->family, IP_SOCK_DGRAM, 0);
if (sock == IP_INVALID_SOCKET)
{
IPCOM_LOG0(ERR, "iptftp_server_receive_file :: ipcom_socket() failed");
goto err;
}
if (iptftp_bind_zero(sock, tftp->family) != IPCOM_SUCCESS)
goto err;
#ifdef IPTFTP_SERVER_ALLOW_UPLOAD
/* Create the file */
buf = ipcom_sysvar_get ("iptftps.allow.upload", IP_NULL, IP_NULL);
if (buf)
{
if(ipcom_strcasecmp(buf,"enable")==0)
{
if (tftp->binary)
fp = ipcom_fopen(tftp->file, "wb");
else
fp = ipcom_fopen(tftp->file, "w");
}
ipcom_free(buf);
buf=IP_NULL;
}
#endif
if (!fp)
{
IPCOM_LOG1(ERR, "iptftp_server_receive_file :: Could not create file: \"%s\"", tftp->file);
err_code = IPTFTP_ERRCODE_ACCESSVIOLATION;
err_msg = IPTFTP_ERRMSG_COULDNOTCREATEFILE;
goto err;
}
/* Start the receive loop */
(void)iptftp_receive_loop(sock, fp, &err_msg, &err_code, tftp);
err:
/* Send error */
if (err_msg)
iptftp_send_err(sock, tftp, err_code, err_msg);
/* Terminate connection */
if (fp != IP_NULL)
(void)ipcom_fclose(fp);
if (sock != IP_INVALID_SOCKET)
ipcom_socketclose(sock);
}
/*
*===========================================================================
* iptftp_server_init
*===========================================================================
* Description: Initialize TFTP server.
* Parameters: tftp - TFTP structure.
* Returns: IPCOM_SUCCESS or an IPCOM_ERR_XXX error code for failures.
*/
IP_STATIC Ip_err
iptftp_server_init(Iptftp *tftp)
{
Ip_err ret = IPCOM_SUCCESS;
char *dir;
struct Ip_stat stat_buf;
/* Create the default directory */
dir = ipcom_sysvar_get("iptftp.dir", IP_NULL, IP_NULL);
if (dir == IP_NULL)
{
ipcom_strcpy(tftp->file, IPCOM_FILE_ROOT "tftpdir");
}
else if (ipcom_strlen(dir) >= sizeof(tftp->file))
{
IPCOM_LOG1(ERR, "TFTP server directory \"%s\" is too long!", dir);
ret = IPCOM_ERR_FAILED;
goto exit;
}
else
{
ipcom_strcpy(tftp->file, dir);
}
tftp->dirlen = (Ip_s32)ipcom_strlen(tftp->file);
/* Create the default TFTP directory if it does not exist. */
if (ipcom_stat(tftp->file, &stat_buf) != 0)
{
if (ipcom_mkdir(tftp->file, 0777) == 0)
{
IPCOM_LOG1(INFO, "created TFTP server directory \"%s\"",
tftp->file);
}
else
{
IPCOM_LOG2(ERR, "iptftp_server_init :: ipcom_mkdir(\"%s\") - %s",
tftp->file, ipcom_strerror(ipcom_errno));
ret = IPCOM_ERR_FAILED;
}
}
exit:
if (dir != IP_NULL)
ipcom_free(dir);
return ret;
}
/*
*===========================================================================
* iptftps
*===========================================================================
* Description: TFTP server damon. Listens for connections and spawns
* child processes for each connection.
* Parameters: none.
* Returns: nothing.
*/
IP_STATIC
IPCOM_PROCESS(iptftps)
{
#ifdef IPCOM_USE_INET
struct Ip_sockaddr_in sa;
Ip_fd sock = IP_INVALID_SOCKET;
#endif
#ifdef IPCOM_USE_INET6
struct Ip_sockaddr_in6 sa6;
Ip_fd sock6 = IP_INVALID_SOCKET;
#endif
Ip_fd max_sock, ipd_sock = IP_INVALID_SOCKET;
Ip_fd_set *read_set = IP_NULL;
Iptftp *tftp;
Ip_err err;
int on = 1;
ipcom_proc_init();
tftp = ipcom_malloc(sizeof(*tftp));
if (tftp == IP_NULL)
{
err = IPCOM_ERR_NO_MEMORY;
IPCOM_LOG0(ERR, "iptftps :: ipcom_malloc(tftp) failed");
goto fail;
}
ipcom_memset(tftp, 0, sizeof(*tftp));
/* Install IPC. */
err = ipcom_ipc_install();
if (err != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "iptftps :: ipcom_ipc_install() failed");
goto fail;
}
/* Initialize tftp server */
err = iptftp_server_init(tftp);
if (err != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "iptftps :: iptftp_server_init() failed");
goto fail;
}
/* Get read set. */
read_set = ipcom_malloc(sizeof(Ip_fd_set));
if (read_set == IP_NULL)
{
err = IPCOM_ERR_NO_MEMORY;
IPCOM_LOG0(ERR, "iptftps :: ipcom_malloc(read_set) failed");
goto fail;
}
err = IPCOM_ERR_SOCKCALLFAILED;
#ifdef IPCOM_USE_INET
/* Get a udp socket, bind to the tftp port */
sock = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, 0);
if (sock == IP_INVALID_SOCKET)
{
IPCOM_LOG0(ERR, "iptftps :: ipcom_socket() failed");
#ifndef IPCOM_USE_INET6
goto fail;
#endif
}
else
{
/* Enable ancillary data */
if (ipcom_setsockopt(sock, IP_IPPROTO_IP, IP_IP_PKTINFO, &on, sizeof(on)) < 0)
{
#ifndef IPLITE
IPCOM_LOG2(INFO, "iptftps :: ipcom_setsockopt(IP_IP_PKTINFO) failed, errno = %d (%s)",
ipcom_errno, ipcom_strerror(ipcom_errno));
#endif
}
ipcom_memset(&sa, 0, sizeof(sa));
IPCOM_SA_LEN_SET(&sa, sizeof(struct Ip_sockaddr_in));
sa.sin_family = IP_AF_INET;
sa.sin_port = ip_htons(IPTFTP_PORT);
sa.sin_addr.s_addr = IP_INADDR_ANY;
if (ipcom_bind(sock, (struct Ip_sockaddr *)&sa, sizeof(sa)) == IP_SOCKERR)
{
IPCOM_LOG1(ERR, "iptftps :: ipcom_bind() failed, errno = %d", ipcom_errno);
#ifdef IPCOM_USE_INET6
ipcom_socketclose(sock);
sock = IP_INVALID_SOCKET;
#else
goto fail;
#endif
}
}
#endif /* IPCOM_USE_INET */
#ifdef IPCOM_USE_INET6
/* Get a udp v6 socket, bind to the tftp port */
sock6 = ipcom_socket(IP_AF_INET6, IP_SOCK_DGRAM, 0);
if (sock6 == IP_INVALID_SOCKET)
{
IPCOM_LOG0(ERR, "iptftps :: ipcom_socket(INET6) failed");
#ifndef IPCOM_USE_INET
goto fail;
#endif
}
else
{
/* Enable ancillary data */
if (ipcom_setsockopt(sock6, IP_IPPROTO_IPV6, IP_IPV6_RECVPKTINFO, &on, sizeof(on)) < 0)
{
#ifndef IPLITE
IPCOM_LOG2(INFO, "iptftps :: ipcom_setsockopt(IP_IPV6_RECVPKTINFO) failed, errno = %d (%s)",
ipcom_errno, ipcom_strerror(ipcom_errno));
#endif
}
ipcom_memset(&sa6, 0, sizeof(sa6));
IPCOM_SA_LEN_SET(&sa6, sizeof(sa6));
sa6.sin6_family = IP_AF_INET6;
sa6.sin6_port = ip_htons(IPTFTP_PORT);
if (ipcom_bind(sock6, (struct Ip_sockaddr *)&sa6, sizeof(sa6)) == IP_SOCKERR)
{
IPCOM_LOG0(ERR, "iptftps :: ipcom_bind(INET6) failed");
#ifdef IPCOM_USE_INET
ipcom_socketclose(sock6);
sock6 = IP_INVALID_SOCKET;
#else
goto fail;
#endif
}
}
#endif /* IPCOM_USE_INET6 */
/* IPD init. */
if (ipcom_ipd_init("iptftps", IPCOM_SUCCESS, &ipd_sock) != IPCOM_SUCCESS)
{
IPCOM_LOG0 (ERR, "iptftps :: ipcom_ipd_init() failed");
goto fail;
}
max_sock = ipd_sock;
#ifdef IPCOM_USE_INET
max_sock = IP_MAX(max_sock, sock);
#endif
#ifdef IPCOM_USE_INET6
max_sock = IP_MAX(max_sock, sock6);
#endif
max_sock++;
/* Start the iptftps select loop */
IPCOM_LOG0(DEBUG, "iptftps :: listening for connections");
for (;;)
{
Ip_s32 num;
IP_FD_ZERO(read_set);
IP_FD_SET(ipd_sock, read_set);
#ifdef IPCOM_USE_INET
if (sock != IP_INVALID_SOCKET)
IP_FD_SET(sock, read_set);
#endif
#ifdef IPCOM_USE_INET6
if (sock6 != IP_INVALID_SOCKET)
IP_FD_SET(sock6, read_set);
#endif
/* Wait for a connection */
num = ipcom_socketselect(max_sock, read_set, IP_NULL, IP_NULL, IP_NULL);
if (num == IP_SOCKERR)
{
IPCOM_LOG1(ERR, "iptftps :: ipcom_socketselect() failed, errno = %d", ipcom_errno);
goto fail;
}
#ifdef IPCOM_USE_INET
/* Check for connection on ipv4 socket*/
if (num > 0 && sock != IP_INVALID_SOCKET && IP_FD_ISSET(sock, read_set))
{
num--;
if (iptftp_server_parse_request(sock, IP_AF_INET, tftp) == IPCOM_SUCCESS)
{
if (iptftp_server_spawn_handler(tftp) != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "iptftps :: iptftp_server_spawn_handler failed");
}
else
IPCOM_LOG0(ERR, "iptftps :: iptftp_server_parse_request(INET4) failed");
}
#endif /* IPCOM_USE_INET */
#ifdef IPCOM_USE_INET6
/* Check for connection on ipv6 socket*/
if (num > 0 && sock6 != IP_INVALID_SOCKET && IP_FD_ISSET(sock6, read_set))
{
num--;
if (iptftp_server_parse_request(sock6, IP_AF_INET6, tftp) == IPCOM_SUCCESS)
{
if (iptftp_server_spawn_handler(tftp) != IPCOM_SUCCESS)
IPCOM_LOG0(ERR, "iptftps :: iptftp_server_spawn_handler() failed");
}
else
IPCOM_LOG0(ERR, "iptftps :: iptftp_server_parse_request(INET6) failed");
}
#endif /* IPCOM_USE_INET6 */
/* Check for connection on ipd socket*/
if (num > 0 && IP_FD_ISSET(ipd_sock, read_set))
{
int event;
event = ipcom_ipd_input(ipd_sock);
switch(event)
{
case IPCOM_IPD_EVENT_RECONFIGURE:
IPCOM_LOG0(INFO, "received IPD reconfigure message");
/* Initialize tftp server */
if (iptftp_server_init(tftp) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "iptftps :: iptftp_server_init() failed");
goto fail;
}
break;
case IPCOM_IPD_EVENT_KILL:
IPCOM_LOG0(INFO, "received IPD kill message");
goto fail;
default:
break;
}
}
}
fail:
if (tftp != IP_NULL)
ipcom_free(tftp);
if (read_set != IP_NULL)
ipcom_free(read_set);
#ifdef IPCOM_USE_INET
if (sock != IP_INVALID_SOCKET)
ipcom_socketclose(sock);
#endif
#ifdef IPCOM_USE_INET6
if (sock6 != IP_INVALID_SOCKET)
ipcom_socketclose(sock6);
#endif
if (ipd_sock == IP_INVALID_SOCKET)
{
ip_assert(err != IPCOM_SUCCESS);
(void)ipcom_ipd_init("iptftps", err, &ipd_sock);
}
if (ipd_sock != IP_INVALID_SOCKET)
(void)ipcom_ipd_exit("iptftps", ipd_sock);
(void)ipcom_ipc_uninstall();
ipcom_proc_exit();
}
/*
****************************************************************************
* 10 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* iptftps_create
*===========================================================================
* Description: TFTP server create function.
* Parameters: none.
* Returns: IPCOM_SUCCESS or an IPCOM_ERR_XXX error code.
*/
IP_PUBLIC Ip_err
iptftps_create(void)
{
return IPCOM_SUCCESS;
}
/*
*===========================================================================
* iptftps_start
*===========================================================================
* Description: TFTP server start function.
* Parameters: none.
* Returns: IPCOM_SUCCESS or an IPCOM_ERR_XXX error code.
*/
IP_PUBLIC Ip_err
iptftps_start(void)
{
return ipcom_proc_create("iptftps", (Ipcom_proc_func)iptftps, IPCOM_PROC_STACK_DEFAULT, IP_NULL);
}
/*
*===========================================================================
* iptftps_version
*===========================================================================
* Description: Get TFTP server version string.
* Parameters: none.
* Returns: TFTP server version.
*/
IP_PUBLIC const char *
iptftps_version(void)
{
return "@(#) IPTFTPS $Name: VXWORKS_ITER40_2019102207 $ - INTERPEAK_COPYRIGHT_STRING";
}
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/