1
0
This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
TP-Link_Archer-XR500v/EN7526G_3.18Kernel_SDK/apps/public/ftpd/server_mode.c
2024-07-22 01:58:46 -03:00

171 lines
3.4 KiB
C
Executable File

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <string.h>
#include <syslog.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
#ifdef HAVE_TCPD_H
#include <tcpd.h>
#endif
static void reapchild __P ((int));
#define DEFPORT 21
#ifdef WITH_WRAP
int allow_severity = LOG_INFO;
int deny_severity = LOG_NOTICE;
static int
check_host (struct sockaddr *sa)
{
struct sockaddr_in *sin;
struct hostent *hp;
char *addr;
if (sa->sa_family != AF_INET)
return 1;
sin = (struct sockaddr_in *)sa;
hp = gethostbyaddr ((char *)&sin->sin_addr,
sizeof (struct in_addr), AF_INET);
addr = inet_ntoa (sin->sin_addr);
if (hp)
{
if (!hosts_ctl ("ftpd", hp->h_name, addr, STRING_UNKNOWN))
{
syslog (LOG_NOTICE, "tcpwrappers rejected: %s [%s]",
hp->h_name, addr);
return 0;
}
}
else
{
if (!hosts_ctl ("ftpd", STRING_UNKNOWN, addr, STRING_UNKNOWN))
{
syslog (LOG_NOTICE, "tcpwrappers rejected: [%s]", addr);
return 0;
}
}
return (1);
}
#endif
static void
reapchild (int signo)
{
int save_errno = errno;
(void)signo;
while (waitpid (-1, NULL, WNOHANG) > 0)
;
errno = save_errno;
}
int
server_mode (const char *pidfile, struct sockaddr_in *phis_addr)
{
int ctl_sock, fd;
struct servent *sv;
int port;
static struct sockaddr_in server_addr; /* Our address. */
/* Become a daemon. */
#ifdef HAVE_DAEMON
if (daemon(1,1) < 0)
#endif
{
syslog (LOG_ERR, "failed to become a daemon");
return -1;
}
(void) signal (SIGCHLD, reapchild);
/* Get port for ftp/tcp. */
sv = getservbyname ("ftp", "tcp");
port = (sv == NULL) ? DEFPORT : sv->s_port;
/* Open socket, bind and start listen. */
ctl_sock = socket (AF_INET, SOCK_STREAM, 0);
if (ctl_sock < 0)
{
syslog (LOG_ERR, "control socket: %m");
return -1;
}
/* Enable local address reuse. */
{
int on = 1;
if (setsockopt (ctl_sock, SOL_SOCKET, SO_REUSEADDR,
(char *)&on, sizeof(on)) < 0)
syslog (LOG_ERR, "control setsockopt: %m");
}
memset (&server_addr, 0, sizeof server_addr);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons (port);
if (bind (ctl_sock, (struct sockaddr *)&server_addr, sizeof server_addr))
{
syslog (LOG_ERR, "control bind: %m");
return -1;
}
if (listen (ctl_sock, 32) < 0)
{
syslog (LOG_ERR, "control listen: %m");
return -1;
}
/* Stash pid in pidfile. */
{
FILE *pid_fp = fopen (pidfile, "w");
if (pid_fp == NULL)
syslog (LOG_ERR, "can't open %s: %m", PATH_FTPDPID);
else
{
fprintf (pid_fp, "%d\n", getpid());
fchmod (fileno(pid_fp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
fclose (pid_fp);
}
}
/* Loop forever accepting connection requests and forking off
children to handle them. */
while (1)
{
int addrlen = sizeof (*phis_addr);
fd = accept (ctl_sock, (struct sockaddr *)phis_addr, &addrlen);
#ifdef HAVE_WORKING_FORK
if (fork () == 0) /* child */
#else
if (vfork () == 0) /* child */
#endif
{
(void) dup2 (fd, 0);
(void) dup2 (fd, 1);
close (ctl_sock);
break;
}
close (fd);
}
#ifdef WITH_WRAP
/* In the child. */
if (!check_host ((struct sockaddr *)phis_addr))
return -1;
#endif
return fd;
}