⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fatcontroller.cpp

📁 一个UNIX/LINUX下的基于内容的过滤服务器源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//Please refer to http://dansguardian.org/?page=copyright2//for the license for this code.//Written by Daniel Barron (daniel@jadeb//.com).//For support go to http://groups.yahoo.com/group/dansguardian//  This program is free software; you can redistribute it and/or modify//  it under the terms of the GNU General Public License as published by//  the Free Software Foundation; either version 2 of the License, or//  (at your option) any later version.////  This program is distributed in the hope that it will be useful,//  but WITHOUT ANY WARRANTY; without even the implied warranty of//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the//  GNU General Public License for more details.////  You should have received a copy of the GNU General Public License//  along with this program; if not, write to the Free Software//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA#include "autoconf/platform.h"#include <syslog.h>#include "FatController.hpp"#include <csignal>#ifdef __BSD	#include <sys/wait.h>#else	#include <wait.h>#endif#include <sys/stat.h>#include "ConnectionHandler.hpp"#include "DynamicURLList.hpp"#include "String.hpp"#include "Socket.hpp"#include "UDSocket.hpp"#include "SysV.hpp"#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <pwd.h>#include <cerrno>#include <unistd.h>#include <fcntl.h>#include <fstream>#include <sys/time.h>#include <sys/poll.h>#ifdef __GCCVER3    #include <istream>#else    #include <istream.h>#endifextern OptionContainer o;extern bool isDaemonised;int FatController::controlIt(int pidfilefd) {    o.lm.garbageCollect();    serversock.reset();    if (o.no_logger == 0) {        ipcsock.reset();    }    else {        ipcsock.close();    }    urllistsock.reset();    peersock.reset();    pid_t loggerpid = 0;  // to hold the logging process pid    pid_t urllistpid = 0;  // to hold the logging process pid (zero to stop                           // warning    int rc, serversockfd, fds;    serversockfd = serversock.getFD();    if (serversockfd < 0) {        if (!isDaemonised) {            std::cerr << "Error creating server socket" << std::endl;        }        syslog(LOG_ERR, "%s","Error creating server socket");        return 1;  // if the socket fd is not +ve then the socket                   // creation failed    }    if (o.no_logger == 0) {        if (ipcsock.getFD() < 0) {            if (!isDaemonised) {               std::cerr << "Error creating ipc socket" << std::endl;            }            syslog(LOG_ERR, "%s","Error creating ipc socket");            return 1;  // if the socket fd is not +ve then the socket                       // creation failed        }    }    bool needdrop = false;    if (o.filter_port < 1024) {        #ifdef DGDEBUG            std::cout << "seteuiding for low port binding" << std::endl;        #endif        needdrop = true;        int rc;        #ifdef __HPUX            rc = setreuid(-1, o.root_user);        #else            rc = seteuid(o.root_user);        #endif        if (rc == -1) {            syslog(LOG_ERR, "%s","Unable to seteuid() to bind filter port.");            #ifdef DGDEBUG                std::cerr << "Unable to seteuid() to bind filter port." << std::endl;            #endif            return 1;        }    }    if (o.filter_ip.length() > 6) {  // filter ip specified in conf                       // listen/bind to a port and ip        if (serversock.bind(o.filter_ip, o.filter_port)) {            if (!isDaemonised) {                std::cerr << "Error binding server socket (is something else running on the filter port and ip? [" << o.filter_port << " " << o.filter_ip << "])" << std::endl;            }            syslog(LOG_ERR, "%s","Error binding server socket (is something else running on the filter port and ip?");            return 1;        }    }    else {             // listen/bind to a port        if (serversock.bind(o.filter_port)) {            if (!isDaemonised) {                std::cerr << "Error binding server socket (is something else running on the filter port? [" << o.filter_port << "])" << std::endl;            }            syslog(LOG_ERR, "%s","Error binding server socket (is something else running on the filter port?");            return 1;        }    }    if (needdrop) {        int rc;        #ifdef __HPUX            rc = setreuid(-1, o.proxy_user);        #else            rc = seteuid(o.proxy_user);  // become low priv again        #endif        if (rc == -1) {	    syslog(LOG_ERR, "%s","Unable to re-seteuid()");	    #ifdef DGDEBUG                std::cerr << "Unable to re-seteuid()" << std::endl;            #endif	    return 1;  // seteuid failed for some reason so exit with error        }    }    // Needs deleting if its there//    unlink(o.ipc_filename.c_str()); // this would normally be in a -r situation.// disabled as requested by Christopher Weimann <csw@k12hq.com>// Fri, 11 Feb 2005 15:42:28 -0500    // Needs deleting if its there    unlink(o.urlipc_filename.c_str()); // this would normally be in a -r situation.    if (o.no_logger == 0) {        if (ipcsock.bind((char*) o.ipc_filename.c_str())) {  // bind to file            if (!isDaemonised) {                std::cerr << "Error binding ipc server file (try using the SysV to stop DansGuardian then try starting it again or doing an 'rm " << o.ipc_filename << "')." << std::endl;            }            syslog(LOG_ERR, "%s","Error binding ipc server file (try using the SysV to stop DansGuardian then try starting it again or doing an 'rm /tmp/.dguardianipc' or whatever you have it configured to).");            return 1;        }    }    if (o.url_cache_number > 0) {        if (urllistsock.bind((char*) o.urlipc_filename.c_str())) {  // bind to file            if (!isDaemonised) {                std::cerr << "Error binding urllistsock server file (try using the SysV to stop DansGuardian then try starting it again or doing an 'rm " << o.urlipc_filename << "')." << std::endl;            }            syslog(LOG_ERR, "%s","Error binding urllistsock server file (try using the SysV to stop DansGuardian then try starting it again or doing an 'rm /tmp/.dguardianurlipc' or whatever you have it configured to).");            return 1;        }    }    if (serversock.listen(256)) {  // set it to listen mode with a kernel                                  // queue of 256 backlog connections        if (!isDaemonised) {            std::cerr << "Error listening to server socket" << std::endl;        }        syslog(LOG_ERR, "%s","Error listening to server socket");        return 1;    }    if (o.no_logger == 0) {        if (ipcsock.listen(256)) {  // set it to listen mode with a kernel                                  // queue of 256 backlog connections            if (!isDaemonised) {                std::cerr << "Error listening to ipc server file" << std::endl;            }            syslog(LOG_ERR, "%s","Error listening to ipc server file");            return 1;        }    }    if (o.url_cache_number > 0) {        if (urllistsock.listen(256)) {  // set it to listen mode with a kernel                                  // queue of 256 backlog connections            if (!isDaemonised) {                std::cerr << "Error listening to url ipc server file" << std::endl;            }            syslog(LOG_ERR, "%s","Error listening to url ipc server file");            return 1;        }    }    if (peersock.getFD() < 0) {        if (!isDaemonised) {            std::cerr << "Error creating peer socket" << std::endl;        }        syslog(LOG_ERR, "%s","Error creating peer socket");        return 1;  // if the socket fd is not +ve then the socket                   // creation failed    }    peersock.close();  // We need to do this as we won't be using the                       // fd created by the contructor as it will be                       // set to the ones accepted().    if (!daemonise(pidfilefd)) {  // become a detached daemon        if (!isDaemonised) {            std::cerr << "Error daemonising" << std::endl;        }        syslog(LOG_ERR, "%s","Error daemonising");        return 1;    }    // We are now a daemon so all errors need to go in the syslog, rather    // than being reported on screen as we've detached from the console and    // trying to write to stdout will not be nice.    struct sigaction sa;    memset(&sa, 0, sizeof(sa));    sa.sa_handler = SIG_IGN;    if (sigaction(SIGPIPE, &sa, NULL)) {  // ignore SIGPIPE so we can handle                                          // premature disconections better        syslog(LOG_ERR, "%s","Error ignoring SIGPIPE");        return(1);    }    memset(&sa, 0, sizeof(sa));    sa.sa_handler = SIG_IGN;    if (sigaction(SIGHUP, &sa, NULL)) {  // ignore HUP        syslog(LOG_ERR, "%s","Error ignoring HUP");        return(1);    }    // Next thing we need to do is to split into two processes - one to    // handle incoming TCP connections from the clients and one to handle    // incoming UDS ipc from our forked children.  This helps reduce    // bottlenecks by not having only one select() loop.    if (o.no_logger == 0) {        loggerpid = fork(); // make a child processes copy of self to be logger        if (loggerpid == 0) {  // ma ma!  i am the child            serversock.close();  // we don't need our copy of this so close it            urllistsock.close();  // we don't need our copy of this so close it            logListener(o.log_location, o.logconerror);            #ifdef DGDEBUG                std::cout << "Log listener exiting" << std::endl;            #endif            _exit(0); // is reccomended for child and daemons to use this instead        }    }    if (o.url_cache_number > 0) {        urllistpid = fork(); // make a child processes copy of self to be logger        if (urllistpid == 0) {  // ma ma!  i am the child            serversock.close();  // we don't need our copy of this so close it            if (o.no_logger == 0) {                ipcsock.close();  // we don't need our copy of this so close it            }            urlListListener(o.logconerror);            #ifdef DGDEBUG                std::cout << "URL List listener exiting" << std::endl;            #endif            _exit(0); // is reccomended for child and daemons to use this instead        }    }    // I am the parent process here onwards.    #ifdef DGDEBUG        std::cout << "Parent process created children" << std::endl;    #endif    if (o.url_cache_number > 0) {        urllistsock.close();  // we don't need our copy of this so close it    }    if (o.no_logger == 0) {        ipcsock.close();  // we don't need our copy of this so close it    }    memset(&sa, 0, sizeof(sa));    if (o.soft_restart == 0) {        sa.sa_handler = &sig_term;  // register sig_term as our handler    }    else {        sa.sa_handler = &sig_termsafe;    }    if (sigaction(SIGTERM, &sa, NULL)) {  // when the parent process gets a                                          // sigterm we need to kill our                                          // children which this will do,                                          // then we need to exit        syslog(LOG_ERR, "%s","Error registering SIGTERM handler");        return(1);    }    memset(&sa, 0, sizeof(sa));    sa.sa_handler = &sig_hup;  // register sig_hup as our handler    if (sigaction(SIGHUP, &sa, NULL)) {  // when the parent process gets a                                          // sighup we need to kill our                                          // children which this will do,                                          // then we need to read config        syslog(LOG_ERR, "%s","Error registering SIGHUP handler");        return(1);    }    memset(&sa, 0, sizeof(sa));    sa.sa_handler = &sig_usr1;  // register sig_usr1 as our handler    if (sigaction(SIGUSR1, &sa, NULL)) {  // when the parent process gets a                                          // sigusr1 we need to hup our                                          // children to make them exit                                          // then we need to read fg config        syslog(LOG_ERR, "%s","Error registering SIGUSR handler");        return(1);    }    #ifdef DGDEBUG        std::cout << "Parent process sig handlers done" << std::endl;    #endif    struct timeval quicksleep;  // used later on for a short sleep    quicksleep.tv_sec = 0;    quicksleep.tv_usec = 10000; // = 10ms = 0.01sec    struct timeval qscopy;  // copy to use as select() can modify    numchildren = 0;  // to keep count of our children    busychildren = 0;  // to keep count of our children    freechildren = 0;  // to keep count of our children    childrenpids = new int[o.max_children];  // so when one exits we know                                                 // who    childrenstates = new int[o.max_children];  // so we know what                                                    // they're up to    fds = o.max_children + 1;    pids = new struct pollfd[fds];    int i;    time_t tnow;    time_t tmaxspare;    time(&tmaxspare);    #ifdef DGDEBUG        std::cout << "Parent process pid structs allocated" << std::endl;    #endif    for(i = 0; i < o.max_children; i++) {        childrenpids[i] = -1;        childrenstates[i] = -1;        pids[i + 1].fd = -1;        pids[i + 1].events = POLLIN;    }    pids[0].fd = serversockfd;    pids[0].events = POLLIN;    #ifdef DGDEBUG        std::cout << "Parent process pid structs zeroed" << std::endl;    #endif    failurecount = 0;  // as we don't exit on an error with select()                           // due to the fact that these errors do happen                           // every so often on a fully working, but busy                           // system, we just watch for too many errors                           // consecutivly.    waitingfor = 0;    rc = preFork(o.min_children);    sleep(1);  // need to allow some of the forks to complete    #ifdef DGDEBUG        std::cout << "Parent process preforked rc:" << rc << std::endl;        std::cout << "Parent process pid:" << getpid() << std::endl;    #endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -