standalone.c
上传用户:ig0539
上传日期:2022-05-21
资源大小:181k
文件大小:7k
源码类别:

Ftp客户端

开发平台:

C/C++

  1. /*
  2.  * Part of Very Secure FTPd
  3.  * Licence: GPL v2
  4.  * Author: Chris Evans
  5.  * standalone.c
  6.  *
  7.  * Code to listen on the network and launch children servants.
  8.  */
  9. #include "standalone.h"
  10. #include "parseconf.h"
  11. #include "tunables.h"
  12. #include "sysutil.h"
  13. #include "sysdeputil.h"
  14. #include "utility.h"
  15. #include "defs.h"
  16. #include "hash.h"
  17. #include "str.h"
  18. #include "ipaddrparse.h"
  19. static unsigned int s_children;
  20. static struct hash* s_p_ip_count_hash;
  21. static struct hash* s_p_pid_ip_hash;
  22. static unsigned int s_ipaddr_size;
  23. static void handle_sigchld(void*  duff);
  24. static void handle_sighup(void*  duff);
  25. static void prepare_child(int sockfd);
  26. static unsigned int handle_ip_count(void* p_raw_addr);
  27. static void drop_ip_count(void* p_raw_addr);
  28. static unsigned int hash_ip(unsigned int buckets, void* p_key);
  29. static unsigned int hash_pid(unsigned int buckets, void* p_key);
  30. struct vsf_client_launch
  31. vsf_standalone_main(void)
  32. {
  33.   struct vsf_sysutil_sockaddr* p_accept_addr = 0;
  34.   int listen_sock = -1;
  35.   int retval;
  36.   s_ipaddr_size = vsf_sysutil_get_ipaddr_size();
  37.   if (tunable_listen && tunable_listen_ipv6)
  38.   {
  39.     die("run two copies of vsftpd for IPv4 and IPv6");
  40.   }
  41.   if (tunable_background)
  42.   {
  43.     int forkret = vsf_sysutil_fork();
  44.     if (forkret > 0)
  45.     {
  46.       /* Parent, just exit */
  47.       vsf_sysutil_exit(0);
  48.     }
  49.     /* Son, close standard FDs to avoid SSH hang-on-exit */
  50.     vsf_sysutil_reopen_standard_fds();
  51.     vsf_sysutil_make_session_leader();
  52.   }
  53.   if (tunable_listen)
  54.   {
  55.     listen_sock = vsf_sysutil_get_ipv4_sock();
  56.   }
  57.   else
  58.   {
  59.     listen_sock = vsf_sysutil_get_ipv6_sock();
  60.   }
  61.   vsf_sysutil_activate_reuseaddr(listen_sock);
  62.   s_p_ip_count_hash = hash_alloc(256, s_ipaddr_size,
  63.                                  sizeof(unsigned int), hash_ip);
  64.   s_p_pid_ip_hash = hash_alloc(256, sizeof(int),
  65.                                s_ipaddr_size, hash_pid);
  66.   if (tunable_setproctitle_enable)
  67.   {
  68.     vsf_sysutil_setproctitle("LISTENER");
  69.   }
  70.   vsf_sysutil_install_sighandler(kVSFSysUtilSigCHLD, handle_sigchld, 0, 1);
  71.   vsf_sysutil_install_sighandler(kVSFSysUtilSigHUP, handle_sighup, 0, 1);
  72.   if (tunable_listen)
  73.   {
  74.     struct vsf_sysutil_sockaddr* p_sockaddr = 0;
  75.     vsf_sysutil_sockaddr_alloc_ipv4(&p_sockaddr);
  76.     vsf_sysutil_sockaddr_set_port(p_sockaddr, tunable_listen_port);
  77.     if (!tunable_listen_address)
  78.     {
  79.       vsf_sysutil_sockaddr_set_any(p_sockaddr);
  80.     }
  81.     else
  82.     {
  83.       if (!vsf_sysutil_inet_aton(tunable_listen_address, p_sockaddr))
  84.       {
  85.         die2("bad listen_address: ", tunable_listen_address);
  86.       }
  87.     }
  88.     retval = vsf_sysutil_bind(listen_sock, p_sockaddr);
  89.     vsf_sysutil_free(p_sockaddr);
  90.     if (vsf_sysutil_retval_is_error(retval))
  91.     {
  92.       die("could not bind listening IPv4 socket");
  93.     }
  94.   }
  95.   else
  96.   {
  97.     struct vsf_sysutil_sockaddr* p_sockaddr = 0;
  98.     vsf_sysutil_sockaddr_alloc_ipv6(&p_sockaddr);
  99.     vsf_sysutil_sockaddr_set_port(p_sockaddr, tunable_listen_port);
  100.     if (!tunable_listen_address6)
  101.     {
  102.       vsf_sysutil_sockaddr_set_any(p_sockaddr);
  103.     }
  104.     else
  105.     {
  106.       struct mystr addr_str = INIT_MYSTR;
  107.       const unsigned char* p_raw_addr;
  108.       str_alloc_text(&addr_str, tunable_listen_address6);
  109.       p_raw_addr = vsf_sysutil_parse_ipv6(&addr_str);
  110.       str_free(&addr_str);
  111.       if (!p_raw_addr)
  112.       {
  113.         die2("bad listen_address6: ", tunable_listen_address6);
  114.       }
  115.       vsf_sysutil_sockaddr_set_ipv6addr(p_sockaddr, p_raw_addr);
  116.     }
  117.     retval = vsf_sysutil_bind(listen_sock, p_sockaddr);
  118.     vsf_sysutil_free(p_sockaddr);
  119.     if (vsf_sysutil_retval_is_error(retval))
  120.     {
  121.       die("could not bind listening IPv6 socket");
  122.     }
  123.   }
  124.   retval = vsf_sysutil_listen(listen_sock, VSFTP_LISTEN_BACKLOG);
  125.   if (vsf_sysutil_retval_is_error(retval))
  126.   {
  127.     die("could not listen");
  128.   }
  129.   vsf_sysutil_sockaddr_alloc(&p_accept_addr);
  130.   while (1)
  131.   {
  132.     struct vsf_client_launch child_info;
  133.     void* p_raw_addr;
  134.     int new_child;
  135.     int new_client_sock;
  136.     new_client_sock = vsf_sysutil_accept_timeout(
  137.         listen_sock, p_accept_addr, 0);
  138.     if (vsf_sysutil_retval_is_error(new_client_sock))
  139.     {
  140.       continue;
  141.     }
  142.     ++s_children;
  143.     child_info.num_children = s_children;
  144.     child_info.num_this_ip = 0;
  145.     p_raw_addr = vsf_sysutil_sockaddr_get_raw_addr(p_accept_addr);
  146.     child_info.num_this_ip = handle_ip_count(p_raw_addr);
  147.     if (tunable_isolate)
  148.     {
  149.       new_child = vsf_sysutil_fork_isolate_failok();
  150.     }
  151.     else
  152.     {
  153.       new_child = vsf_sysutil_fork_failok();
  154.     }
  155.     if (new_child != 0)
  156.     {
  157.       /* Parent context */
  158.       vsf_sysutil_close(new_client_sock);
  159.       if (new_child > 0)
  160.       {
  161.         hash_add_entry(s_p_pid_ip_hash, (void*)&new_child, p_raw_addr);
  162.       }
  163.       else
  164.       {
  165.         /* fork() failed, clear up! */
  166.         --s_children;
  167.         drop_ip_count(p_raw_addr);
  168.       }
  169.       /* Fall through to while() loop and accept() again */
  170.     }
  171.     else
  172.     {
  173.       /* Child context */
  174.       vsf_set_die_if_parent_dies();
  175.       vsf_sysutil_close(listen_sock);
  176.       prepare_child(new_client_sock);
  177.       /* By returning here we "launch" the child process with the same
  178.        * contract as xinetd would provide.
  179.        */
  180.       return child_info;
  181.     }
  182.   }
  183. }
  184. static void
  185. prepare_child(int new_client_sock)
  186. {
  187.   /* We must satisfy the contract: command socket on fd 0, 1, 2 */
  188.   vsf_sysutil_dupfd2(new_client_sock, 0);
  189.   vsf_sysutil_dupfd2(new_client_sock, 1);
  190.   vsf_sysutil_dupfd2(new_client_sock, 2);
  191.   if (new_client_sock > 2)
  192.   {
  193.     vsf_sysutil_close(new_client_sock);
  194.   }
  195. }
  196. static void
  197. drop_ip_count(void* p_raw_addr)
  198. {
  199.   unsigned int count;
  200.   unsigned int* p_count =
  201.     (unsigned int*)hash_lookup_entry(s_p_ip_count_hash, p_raw_addr);
  202.   if (!p_count)
  203.   {
  204.     bug("IP address missing from hash");
  205.   }
  206.   count = *p_count;
  207.   if (!count)
  208.   {
  209.     bug("zero count for IP address");
  210.   }
  211.   count--;
  212.   *p_count = count;
  213.   if (!count)
  214.   {
  215.     hash_free_entry(s_p_ip_count_hash, p_raw_addr);
  216.   }
  217. }
  218. static void
  219. handle_sigchld(void* duff)
  220. {
  221.   unsigned int reap_one = 1;
  222.   (void) duff;
  223.   while (reap_one)
  224.   {
  225.     reap_one = (unsigned int)vsf_sysutil_wait_reap_one();
  226.     if (reap_one)
  227.     {
  228.       struct vsf_sysutil_ipaddr* p_ip;
  229.       /* Account total number of instances */
  230.       --s_children;
  231.       /* Account per-IP limit */
  232.       p_ip = (struct vsf_sysutil_ipaddr*)
  233.         hash_lookup_entry(s_p_pid_ip_hash, (void*)&reap_one);
  234.       drop_ip_count(p_ip);      
  235.       hash_free_entry(s_p_pid_ip_hash, (void*)&reap_one);
  236.     }
  237.   }
  238. }
  239. static void
  240. handle_sighup(void* duff)
  241. {
  242.   (void) duff;
  243.   /* We don't crash the out the listener if an invalid config was added */
  244.   tunables_load_defaults();
  245.   vsf_parseconf_load_file(0, 0);
  246. }
  247. static unsigned int
  248. hash_ip(unsigned int buckets, void* p_key)
  249. {
  250.   const unsigned char* p_raw_ip = (const unsigned char*)p_key;
  251.   unsigned int val = 0;
  252.   int shift = 24;
  253.   unsigned int i;
  254.   for (i = 0; i < s_ipaddr_size; ++i)
  255.   {
  256.     val ^= p_raw_ip[i] << shift;
  257.     shift -= 8;
  258.     if (shift < 0)
  259.     {
  260.       shift = 24;
  261.     }
  262.   }
  263.   return val % buckets;
  264. }
  265. static unsigned int
  266. hash_pid(unsigned int buckets, void* p_key)
  267. {
  268.   unsigned int* p_pid = (unsigned int*)p_key;
  269.   return (*p_pid) % buckets;
  270. }
  271. static unsigned int
  272. handle_ip_count(void* p_ipaddr)
  273. {
  274.   unsigned int* p_count =
  275.     (unsigned int*)hash_lookup_entry(s_p_ip_count_hash, p_ipaddr);
  276.   unsigned int count;
  277.   if (!p_count)
  278.   {
  279.     count = 1;
  280.     hash_add_entry(s_p_ip_count_hash, p_ipaddr, (void*)&count);
  281.   }
  282.   else
  283.   {
  284.     count = *p_count;
  285.     count++;
  286.     *p_count = count;
  287.   }
  288.   return count;
  289. }