~ubuntu-branches/ubuntu/trusty/dansguardian/trusty

« back to all changes in this revision

Viewing changes to src/FatController.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alexander Wirt, Thomas Viehmann
  • Date: 2008-10-13 09:29:35 UTC
  • mfrom: (1.1.7 upstream) (7.1.1 squeeze)
  • Revision ID: james.westby@ubuntu.com-20081013092935-g8uz3kgfjs37ikgv
Tags: 2.9.9.7-2
[ Thomas Viehmann ]
OptionContainer.cpp: If you need to iterate through all lines in the
config file to find a field, at least don't abuse the configfile deque
by accessing it as if it was an array with signed index.
Works way better on arm, too, i.e. closes: #493047.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 
21
21
// INCLUDES
22
22
 
23
 
#include "platform.h"
24
 
 
25
 
#include "FatController.hpp"
26
 
#include "ConnectionHandler.hpp"
27
 
#include "DynamicURLList.hpp"
28
 
#include "DynamicIPList.hpp"
29
 
#include "String.hpp"
30
 
#include "SocketArray.hpp"
31
 
#include "UDSocket.hpp"
32
 
#include "SysV.hpp"
 
23
#ifdef HAVE_CONFIG_H
 
24
        #include "dgconfig.h"
 
25
#endif
33
26
 
34
27
#include <syslog.h>
35
28
#include <csignal>
42
35
#include <fstream>
43
36
#include <sys/time.h>
44
37
#include <sys/poll.h>
45
 
 
46
 
#ifdef __SEGV_BACKTRACE
47
 
#include <execinfo.h>
48
 
#endif
49
 
 
50
 
#ifdef __GCCVER3
51
38
#include <istream>
52
39
#include <map>
53
 
#else
54
 
#include <istream.h>
55
 
#include <map.h>
 
40
#include <sys/types.h>
 
41
#include <sys/wait.h>
 
42
#include <sys/select.h>
 
43
 
 
44
#ifdef ENABLE_SEGV_BACKTRACE
 
45
#include <execinfo.h>
56
46
#endif
57
47
 
 
48
#include "FatController.hpp"
 
49
#include "ConnectionHandler.hpp"
 
50
#include "DynamicURLList.hpp"
 
51
#include "DynamicIPList.hpp"
 
52
#include "String.hpp"
 
53
#include "SocketArray.hpp"
 
54
#include "UDSocket.hpp"
 
55
#include "SysV.hpp"
 
56
 
58
57
 
59
58
// GLOBALS
60
59
 
86
85
Socket *peersock(NULL);  // the socket which will contain the connection
87
86
 
88
87
String peersockip;  // which will contain the connection ip
89
 
int peersockport;  // port connection originates
90
88
 
91
89
 
92
90
// DECLARATIONS
100
98
        void sig_hup(int signo);  // This is so we know if we should re-read our config.
101
99
        void sig_usr1(int signo);  // This is so we know if we should re-read our config but not kill current connections
102
100
        void sig_childterm(int signo);
103
 
#ifdef __SEGV_BACKTRACE
 
101
#ifdef ENABLE_SEGV_BACKTRACE
104
102
        void sig_segv(int signo/*, siginfo_t* info, void* p*/); // Generate a backtrace on segfault
105
103
#endif
106
104
}
126
124
// tell a non-busy child process to accept the incoming connection
127
125
void tellchild_accept(int num, int whichsock);
128
126
// child process accept()s connection from server socket
129
 
bool getsock_fromparent(UDSocket &fd/*, int &socknum*/);
 
127
bool getsock_fromparent(UDSocket &fd);
130
128
 
131
129
// add known info about a child to our info lists
132
130
void addchild(int pos, int fd, pid_t child_pid);
136
134
int getchildslot();
137
135
// cull up to this number of non-busy children
138
136
void cullchildren(int num);
139
 
// delete this child from our info lists (pass in child's recorded exit value - currently unused)
140
 
void deletechild(int child_pid, int stat);
 
137
// delete this child from our info lists
 
138
void deletechild(int child_pid);
141
139
// clean up any dead child processes (calls deletechild with exit values)
142
140
void mopup_afterkids();
143
141
 
189
187
#endif
190
188
                _exit(0);
191
189
        }
192
 
#ifdef __SEGV_BACKTRACE
193
 
        void sig_segv(int signo/*, siginfo_t* info, void* p*/)
 
190
#ifdef ENABLE_SEGV_BACKTRACE
 
191
        void sig_segv(int signo)
194
192
        {
195
193
#ifdef DGDEBUG
196
194
                std::cout << "SEGV received." << std::endl;
197
195
#endif
198
 
/*              char* str = "UNKNOWN";
199
 
                switch (info->si_code)
200
 
                {
201
 
#ifdef SEGV_MAPERR
202
 
                case SEGV_MAPERR: str = "SEGV_MAPERR"; break;
203
 
#endif
204
 
#ifdef SEGV_ACCERR
205
 
                case SEGV_ACCERR: str = "SEGV_ACCERR"; break;
206
 
#endif
207
 
                }
208
 
                syslog(LOG_ERR, "Segfault: %s", str);*/
209
196
                // Generate backtrace
210
197
                void *addresses[10];
211
198
                char **strings;
213
200
                strings = backtrace_symbols(addresses,c);
214
201
                printf("backtrace returned: %d\n", c);
215
202
                for (int i = 0; i < c; i++) {
216
 
                        syslog(LOG_ERR, "%d: %X ", i, (int)addresses[i]);
 
203
                        syslog(LOG_ERR, "%d: %zX ", i, (size_t)addresses[i]);
217
204
                        syslog(LOG_ERR, "%s", strings[i]);
218
205
                }
219
206
                // Kill off the current process
302
289
        try {
303
290
                fipcsock.writeString(request.toCharArray());  // throws on err
304
291
        }
305
 
        catch(exception & e) {
 
292
        catch(std::exception & e) {
306
293
#ifdef DGDEBUG
307
294
                std::cerr << "Exception flushing url cache" << std::endl;
308
295
                std::cerr << e.what() << std::endl;
486
473
                        return -1;
487
474
                }
488
475
        }
489
 
        catch(exception & e) {
 
476
        catch(std::exception & e) {
490
477
                return -1;
491
478
        }
492
479
        return 0;
515
502
                        toldparentready = true;
516
503
                }
517
504
 
518
 
                //int socknum;
519
 
 
520
 
                if (!getsock_fromparent(pipe/*, socknum*/)) {   // blocks waiting for a few mins
 
505
                if (!getsock_fromparent(pipe)) {        // blocks waiting for a few mins
521
506
                        continue;
522
507
                }
523
508
                toldparentready = false;
529
514
                        continue;
530
515
                }
531
516
 
532
 
                h.handleConnection(*peersock, peersockip, peersockport/*, socknum*/);  // deal with the connection
 
517
                h.handleConnection(*peersock, peersockip);  // deal with the connection
533
518
                delete peersock;
534
519
        }
535
520
        if (!(++cycle) && o.logchildprocs)
546
531
}
547
532
 
548
533
// the parent process recieves connections - children receive notifications of this over their socketpair, and accept() them for handling
549
 
bool getsock_fromparent(UDSocket &fd/*, int &socknum*/)
 
534
bool getsock_fromparent(UDSocket &fd)
550
535
{
551
536
        String message;
552
537
        char buf;
554
539
        try {
555
540
                rc = fd.readFromSocket(&buf, 1, 0, 360, true, true);  // blocks for a few mins
556
541
        }
557
 
        catch(exception & e) {
 
542
        catch(std::exception & e) {
558
543
                // whoop! we received a SIGHUP. we should reload our configuration - and no, we didn't get an FD.
559
544
 
560
545
                reloadconfig = true;
572
557
        }
573
558
 
574
559
        // woo! we have a connection. accept it.
575
 
        //socknum = (int)buf;
576
560
        peersock = serversockets[buf]->accept();
577
561
        peersockip = peersock->getPeerIP();
578
 
        peersockport = peersock->getPeerSourcePort();
579
562
 
580
563
        try {
581
564
                fd.writeToSockete("K", 1, 0, 10, true);  // need to make parent wait for OK
582
565
                // so effectively providing a lock
583
566
        }
584
 
        catch(exception & e) {
 
567
        catch(std::exception & e) {
585
568
                if (o.logconerror)
586
569
                        syslog(LOG_ERR, "Error telling parent we accepted: %s", e.what());
587
570
                peersock->close();
615
598
                if (pid < 1) {
616
599
                        break;
617
600
                }
618
 
                if (WIFEXITED(stat_val)) {      // exited normally
619
 
                        deletechild((int) pid, WEXITSTATUS(stat_val));
620
 
                } else {
621
 
                        deletechild((int) pid, -1);
622
 
                }
 
601
                deletechild((int) pid);
623
602
        }
624
603
}
625
604
 
652
631
void cullchildren(int num)
653
632
{
654
633
#ifdef DGDEBUG
655
 
        cout << "culling childs:" << num << endl;
 
634
        std::cout << "culling childs:" << num << std::endl;
656
635
#endif
657
636
        int i;
658
637
        int count = 0;
676
655
void kill_allchildren()
677
656
{
678
657
#ifdef DGDEBUG
679
 
        cout << "killing all childs:" << endl;
 
658
        std::cout << "killing all childs:" << std::endl;
680
659
#endif
681
660
        for (int i = o.max_children - 1; i >= 0; i--) {
682
661
                if (childrenstates[i] >= 0) {
694
673
void hup_allchildren()
695
674
{
696
675
#ifdef DGDEBUG
697
 
        cout << "huping all childs:" << endl;
 
676
        std::cout << "huping all childs:" << std::endl;
698
677
#endif
699
678
        for (int i = o.max_children - 1; i >= 0; i--) {
700
679
                if (childrenstates[i] >= 0) {
725
704
                        try {
726
705
                                rc = childsockets[f]->getLine(buf, 4, 100, true);
727
706
                        }
728
 
                        catch(exception & e) {
 
707
                        catch(std::exception & e) {
729
708
                                kill(childrenpids[f], SIGTERM);
730
 
                                deletechild(childrenpids[f], -1);
 
709
                                deletechild(childrenpids[f]);
731
710
                                tofind--;
732
711
                                continue;
733
712
                        }
742
721
                                }
743
722
                        } else {        // child -> parent communications failure so kill it
744
723
                                kill(childrenpids[f], SIGTERM);
745
 
                                deletechild(childrenpids[f], -1);
 
724
                                deletechild(childrenpids[f]);
746
725
                                tofind--;
747
726
                        }
748
727
                }
758
737
}
759
738
 
760
739
// remove child from our PID/FD and slot lists
761
 
void deletechild(int child_pid, int stat)
 
740
void deletechild(int child_pid)
762
741
{
763
742
        int i;
764
743
        for (i = 0; i < o.max_children; i++) {
765
744
                if (childrenpids[i] == child_pid) {
766
745
                        childrenpids[i] = -1;
 
746
                        // Delete a busy child
767
747
                        if (childrenstates[i] == 1) {
768
 
                                //if (stat == 2) {
769
 
                                        busychildren--;
770
 
                                /*} else {
771
 
                                        busychildren--;  // should only happen if kid goes screwy
772
 
                                        // child calls _exit with return value of handle_connections,
773
 
                                        // so if it's nonzero, it means there was an error in there somewhere
774
 
                                }*/
775
 
                        }
776
 
                        if (childrenstates[i] != -2) {  // -2 is when its been culled
777
 
                                numchildren--;  // so no need to duplicater
 
748
                                busychildren--;
 
749
                        }
 
750
                        // Delete a child which isn't "ready" yet
 
751
                        if (childrenstates[i] == 4) {
 
752
                                busychildren--;
 
753
                                waitingfor--;
 
754
                        }
 
755
                        // Common code for any non-"culled" child
 
756
                        if (childrenstates[i] != -2) {
 
757
                                numchildren--;
778
758
                                delete childsockets[i];
779
759
                                childsockets[i] = NULL;
780
760
                                pids[i].fd = -1;
808
788
        // include server socket number in message
809
789
        try {
810
790
                childsockets[num]->writeToSockete((char*)&whichsock, 1, 0, 5, true);
811
 
        } catch(exception & e) {
 
791
        } catch(std::exception & e) {
812
792
                kill(childrenpids[num], SIGTERM);
813
 
                deletechild(childrenpids[num], -1);
 
793
                deletechild(childrenpids[num]);
814
794
                return;
815
795
        }
816
796
 
818
798
        char buf;
819
799
        try {
820
800
                childsockets[num]->readFromSocket(&buf, 1, 0, 5, false, true);
821
 
        } catch(exception & e) {
 
801
        } catch(std::exception & e) {
822
802
                kill(childrenpids[num], SIGTERM);
823
 
                deletechild(childrenpids[num], -1);
 
803
                deletechild(childrenpids[num]);
824
804
                return;
825
805
        }
826
806
        // no need to check what it actually contains,
855
835
        UDSocket* ipcpeersock;  // the socket which will contain the ipc connection
856
836
        int rc, ipcsockfd;
857
837
 
858
 
#ifdef __EMAIL
 
838
#ifdef ENABLE_EMAIL
859
839
        // Email notification patch by J. Gauthier
860
 
        map<string,int> violation_map;
861
 
        map<string,int> timestamp_map;   
862
 
        map<string,string> vbody_map;
 
840
        std::map<std::string, int> violation_map;
 
841
        std::map<std::string, int> timestamp_map;   
 
842
        std::map<std::string, std::string> vbody_map;
863
843
 
864
844
        int curv_tmp, stamp_tmp, byuser;
865
845
#endif
873
853
        long tv_sec = 0, tv_usec = 0;
874
854
        int contentmodified = 0, urlmodified = 0, headermodified = 0;
875
855
 
876
 
        ofstream* logfile = NULL;
 
856
        std::ofstream* logfile = NULL;
877
857
        if (!logsyslog) {
878
 
                logfile = new ofstream(log_location.c_str(), ios::app);
 
858
                logfile = new std::ofstream(log_location.c_str(), std::ios::app);
879
859
                if (logfile->fail()) {
880
860
                        syslog(LOG_ERR, "Error opening/creating log file.");
881
861
#ifdef DGDEBUG
1023
1003
                                        }
1024
1004
                                        delete[]logline;
1025
1005
                                }
1026
 
                                catch(exception & e) {
 
1006
                                catch(std::exception & e) {
1027
1007
                                        delete ipcpeersock;
1028
1008
                                        if (logconerror)
1029
1009
                                                syslog(LOG_ERR, "Error reading ipc. (Ignorable)");
1237
1217
#endif
1238
1218
                        delete ipcpeersock;  // close the connection
1239
1219
 
1240
 
#ifdef __EMAIL
 
1220
#ifdef ENABLE_EMAIL
1241
1221
                        // do the notification work here, but fork for speed
1242
1222
                        if (o.fg[filtergroup]->use_smtp==true) {
1243
1223
 
1498
1478
                        try {
1499
1479
                                rc = ipcpeersock->getLine(logline, 32000, 3, true);  // throws on err
1500
1480
                        }
1501
 
                        catch(exception & e) {
 
1481
                        catch(std::exception & e) {
1502
1482
                                delete ipcpeersock;  // close the connection
1503
1483
                                if (logconerror) {
1504
1484
#ifdef DGDEBUG
1539
1519
                        try {
1540
1520
                                ipcpeersock->writeToSockete(&reply, 1, 0, 6);
1541
1521
                        }
1542
 
                        catch(exception & e) {
 
1522
                        catch(std::exception & e) {
1543
1523
                                delete ipcpeersock;  // close the connection
1544
1524
                                if (logconerror) {
1545
1525
                                        syslog(LOG_ERR, "%s", "Error writing url ipc. (Ignorable)");
1664
1644
                        }
1665
1645
                        try {
1666
1646
                                rc = ipcpeersock->getLine(inbuff, 16, 3);  // throws on err
1667
 
                        } catch (exception& e) {
 
1647
                        } catch (std::exception& e) {
1668
1648
                                delete ipcpeersock;
1669
1649
                                if (logconerror) {
1670
1650
#ifdef DGDEBUG
1686
1666
                                reply = 'N';
1687
1667
                        try {
1688
1668
                                ipcpeersock->writeToSockete(&reply, 1, 0, 6);
1689
 
                        } catch (exception& e) {
 
1669
                        } catch (std::exception& e) {
1690
1670
                                delete ipcpeersock;
1691
1671
                                if (logconerror) {
1692
1672
#ifdef DGDEBUG
2048
2028
                return (1);
2049
2029
        }
2050
2030
 
2051
 
#ifdef __SEGV_BACKTRACE
 
2031
#ifdef ENABLE_SEGV_BACKTRACE
2052
2032
        memset(&sa, 0, sizeof(sa));
2053
2033
        sa.sa_handler = &sig_segv;
2054
2034
        if (sigaction(SIGSEGV, &sa, NULL)) {
2122
2102
                syslog(LOG_ERR, "%s", "Error creating initial fork pool - exiting...");
2123
2103
        }
2124
2104
 
2125
 
        bool preforked = true;
2126
2105
        int tofind;
2127
2106
        reloadconfig = false;
2128
2107
 
2137
2116
                // OR, we need to exit to reread config
2138
2117
                if (gentlereload) {
2139
2118
#ifdef DGDEBUG
2140
 
                        cout << "gentle reload activated" << endl;
 
2119
                        std::cout << "gentle reload activated" << std::endl;
2141
2120
#endif
2142
2121
                        o.deleteFilterGroups();
2143
2122
                        if (!o.readFilterGroupConf()) {
2199
2178
                tofind = rc;
2200
2179
                if (rc > 0) {
2201
2180
                        for (i = o.max_children; i < fds; i++) {
2202
 
                                if ((pids[i].revents & POLLIN) > 0) {
 
2181
                                if (pids[i].revents) {
2203
2182
                                        tofind--;
2204
2183
                                }
2205
2184
                        }
2206
2185
                }
2207
2186
 
2208
2187
                if (tofind > 0) {
2209
 
                        if (check_kid_readystatus(tofind)) {
2210
 
                                preforked = false;  // we are no longer waiting last prefork
2211
 
                        }
 
2188
                        check_kid_readystatus(tofind);
2212
2189
                }
2213
2190
 
2214
2191
                freechildren = numchildren - busychildren;
2222
2199
 
2223
2200
                if (rc > 0) {
2224
2201
                        for (i = o.max_children; i < fds; i++) {
2225
 
                                if ((pids[i].revents & (POLLERR | POLLHUP | POLLNVAL)) > 0) {
2226
 
                                        ttg = true;
2227
 
                                        syslog(LOG_ERR, "Error with main listening socket.  Exiting.");
2228
 
                                        continue;
2229
 
                                }
2230
2202
                                if ((pids[i].revents & POLLIN) > 0) {
2231
2203
                                        // socket ready to accept() a connection
2232
2204
                                        failurecount = 0;  // something is clearly working so reset count
2233
2205
                                        if (freechildren < 1 && numchildren < o.max_children) {
2234
 
                                                if (!preforked) {
 
2206
                                                if (waitingfor == 0) {
2235
2207
                                                        int num = o.prefork_children;
2236
2208
                                                        if ((o.max_children - numchildren) < num)
2237
2209
                                                                num = o.max_children - numchildren;
2242
2214
                                                                syslog(LOG_ERR, "Error forking %d extra process(es).", num);
2243
2215
                                                                failurecount++;
2244
2216
                                                        }
2245
 
                                                        preforked = true;
2246
 
                                                }
 
2217
                                                } else
 
2218
                                                        usleep(1000);
2247
2219
                                                continue;
2248
2220
                                        }
2249
2221
                                        if (freechildren > 0) {
2255
2227
                                                usleep(1000);
2256
2228
                                        }
2257
2229
                                }
 
2230
                                else if (pids[i].revents) {
 
2231
                                        ttg = true;
 
2232
                                        syslog(LOG_ERR, "Error with main listening socket.  Exiting.");
 
2233
                                        break;
 
2234
                                }
2258
2235
                        }
 
2236
                        if (ttg)
 
2237
                                break;
2259
2238
                }
2260
2239
 
2261
 
                if (freechildren < o.minspare_children && !preforked && numchildren < o.max_children) {
 
2240
                if (freechildren < o.minspare_children && (waitingfor == 0) && numchildren < o.max_children) {
2262
2241
                        if (o.logchildprocs)
2263
2242
                                syslog(LOG_ERR, "Fewer than %d free children - Spawning %d process(es)", o.minspare_children, o.prefork_children);
2264
2243
                        rc = prefork(o.prefork_children);
2265
 
                        preforked = true;
2266
2244
                        if (rc < 0) {
2267
2245
                                syslog(LOG_ERR, "Error forking preforkchildren extra processes.");
2268
2246
                                failurecount++;
2274
2252
                }
2275
2253
                if (freechildren > o.maxspare_children) {
2276
2254
                        time(&tnow);
2277
 
                        if ((tnow - tmaxspare) > (2 * 60)) {    // 2 * 60
 
2255
                        if ((tnow - tmaxspare) > (2 * 60)) {
2278
2256
                                if (o.logchildprocs)
2279
2257
                                        syslog(LOG_ERR, "More than %d free children - Killing %d process(es)", o.maxspare_children, freechildren - o.maxspare_children);
2280
2258
                                cullchildren(freechildren - o.maxspare_children);
2281
2259
                        }
2282
2260
                }
2283
 
 
2284
 
                // yield CPU for a while. this loop does not explicitly sleep other
2285
 
                // than when polling FDs; when connections are coming in at a rate of
2286
 
                // knots, it effectively turns into a busy loop. this should help.
2287
 
                //usleep(1000);
2288
2261
        }
2289
2262
        cullchildren(numchildren);  // remove the fork pool of spare children
2290
2263
        for (int i = 0; i < o.max_children; i++) {