]> git.sur5r.net Git - openldap/blob - contrib/tweb/server.c
Update man page date.
[openldap] / contrib / tweb / server.c
1 /*_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/ 
2 *                                                                          *
3 * server.c...                                                              *
4 *                                                                          *
5 * Function:..WorldWideWeb-X.500-Gateway - Server-Funktions                 *
6 *            Based on web500gw.c 1.3 written by Frank Richter, TU Chemmniz *
7 *            which is based on go500gw by Tim Howes, University of         *
8 *            Michigan  - All rights reserved                               *
9 *                                                                          *
10 * Authors:...Dr. Kurt Spanier & Bernhard Winkler,                          *
11 *            Zentrum fuer Datenverarbeitung, Bereich Entwicklung           *
12 *            neuer Dienste, Universitaet Tuebingen, GERMANY                *
13 *                                                                          *
14 *                                       ZZZZZ  DDD    V   V                *
15 *            Creation date:                Z   D  D   V   V                *
16 *            August 16 1995               Z    D   D   V V                 *
17 *            Last modification:          Z     D  D    V V                 *
18 *            May 6 1999                 ZZZZ   DDD      V                  *
19 *                                                                          *
20 _/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_*/
21
22 /*
23  * $Id: server.c,v 1.6 1999/09/10 15:01:19 zrnsk01 Exp $
24  *
25  */
26
27 #include "tgeneral.h"
28 #include "tglobal.h"
29 #include "init_exp.h"
30 #include "checkclient_exp.h"
31 #include "server.h"
32 #include "charray_exp.h"
33
34 #if defined( TUE_TEL ) || defined( AMBIXGW )
35 #include "tueTest_exp.h"
36 #endif
37
38
39 /**
40  **  start_server()
41  **
42  **    Start the Web-X.500-Server.
43  **/
44
45 PUBLIC void start_server(glob)
46 GLOB_STRUCT *glob;
47 {
48
49     int            s, ns, rc;
50     int            tblsize;
51     int            pid = getpid();
52     fd_set            readfds;
53     struct hostent        *hp;
54     struct sockaddr_in    from;
55     int            fromlen;
56     void            wait4child();
57     long int       idx;
58
59     glob->stat_slice = time(&glob->stat_slice);
60     stat_slice = &glob->stat_slice;
61     /* if logging is desired via syslog establish connection to syslogd
62        and write first log-message */
63     if ( dosyslog ) {
64
65         openlog( glob->myname, LOG_PID | LOG_NOWAIT, dosyslog );
66         syslog( LOG_INFO, "initializing" );
67
68     }
69
70     /* set up the socket to listen on */
71         /*  the actual port to listen is composed by the base-port
72             and the language-offset */
73         s = set_socket( glob->webport + atoi(glob->lang) );
74
75         /* arrange to reap children */
76         (void) signal( SIGCHLD, wait4child );
77
78     if ( dosyslog )
79         syslog (LOG_INFO, "socket: %d", s);
80
81     /*  Read LDAP-filter for search-operations */
82     if ( (filtd = ldap_init_getfilter( glob->filterfile )) == NULL ) {
83         fprintf(stderr,"Cannot open filter file (%s)\n", glob->filterfile );
84         exit( 1 );
85     }
86
87 /*  ###  Code for the static server ### */
88
89     tblsize = getdtablesize();
90     syslog (LOG_INFO, "listening for calls...");
91
92     /*  Initialisation of the Anti-Hack-code */
93     srand(pid);
94     if (glob->comrefuse) hackTimer();
95     bzero((char *) conArr, CARRSIZE * sizeof(int));
96     bzero((char *) shadowconArr, CARRSIZE * sizeof(long int));
97     bzero((char *) sumconArr, CARRSIZE * sizeof(long int));
98
99 #ifdef TUE_TEL
100     /* initialisation of dit_config 1st time  */
101     if(glob->dit_config) {
102         init_dit_config();
103     }
104 #endif
105
106     /* initialisation of ip_refuse 1st time  */
107     if(glob->ip_refuse) {
108         get_ip_refuse_clients(glob);
109     }
110
111     /*  the server runs in an infinite loop !!! */
112     for ( ;; ) {
113
114         /*  listen on the server-port for incoming connections */
115         FD_ZERO( &readfds );
116         FD_SET( s, &readfds );
117
118         if ((rc=select(tblsize,(fd_set *)&readfds,NULL,NULL,0))==-1) {
119             if ( debug ) perror( "select" );
120             continue;
121         } else if ( rc == 0 ) {
122             continue;
123         }
124
125         if ( ! FD_ISSET( s, &readfds ) )
126             continue;
127
128
129         /*  got connection for the server: get data */
130         fromlen = sizeof(from);
131
132                 /* increment the counter for total connections */
133                 glob->svc_cnt++;
134
135         /*  get new file-descriptors for the connection */
136         if ( (ns = accept( s, (struct sockaddr *)  &from, &fromlen )) == -1 ) {
137
138             /*  new fd could not be assigned -> log & bye */
139             if ( debug ) perror( "accept" );
140             if ( dosyslog ) {
141                 syslog (LOG_INFO,
142                     "problem with accept, errno=%d, %s <%08d>",
143                     errno, strerror(errno), glob->svc_cnt);
144             }
145             continue;
146         }
147
148         /* get time for performance log */
149         gettimeofday(&timestore[0], NULL);
150
151         /*  get client-address via DNS */
152         hp = gethostbyaddr( (char *) &(from.sin_addr.s_addr),
153             sizeof(from.sin_addr.s_addr), AF_INET );
154
155         /* check ip-address for ip_refuse and bye if matched */
156                 if ( check_ip_denial( &from, glob ) == NOTOK ) {
157
158                         if ( dosyslog )
159                                 syslog( LOG_INFO, "IP-REFUSE: access denied for %s <%08d>",
160                                                         inet_ntoa( from.sin_addr ), glob->svc_cnt);
161
162             close (ns);
163             continue;
164
165         }
166
167         /* get time for performance log */
168         gettimeofday(&timestore[1], NULL);
169
170         /* Anti-Hack-part */
171
172         /*  divide Host-IP-addresses in index-groups and count connection */
173         idx = IP_HACK(from.sin_addr.s_addr);
174         sumconArr[idx]++;
175
176         /*  count try if already locked and bye */
177         if(conArr[idx] < 0) {
178
179             shadowconArr[idx]++;
180             close (ns);
181             continue;
182
183         }
184
185         /*  if not yet locked and maximum amount of connections is exeeded ->
186             lock & message & bye
187         */
188         if (glob->comrefuse && (++conArr[idx] > glob->comrefuse->maxAccept)){
189
190             if (dosyslog)
191                 syslog(LOG_INFO,
192 "connection refused for %s (IDX=%d): %d attempts, %d cycles suspended <%08d>",
193                              hp ? hp->h_name : "unknown", idx, conArr[idx],
194                              glob->comrefuse->suspendCycle, glob->svc_cnt);
195
196             /*  lock for x timecycles */
197             conArr[idx] = glob->comrefuse->suspendCycle;
198
199             /*  bye, bye baby */
200             close (ns);
201             continue;
202
203         }
204
205         /* END of Anti-Hack-part */
206
207         /*  Log the connection */
208         if ( dosyslog ) {
209             char msg[BUFSIZ];
210
211             sprintf(msg, "TCP connection from %s (%s,%u)",
212                 (hp == NULL) ? "unknown" : hp->h_name,
213                 inet_ntoa( from.sin_addr ), from.sin_port );
214             glob->server_connection_msg = strdup(msg);
215         }
216
217         if ( debug ) {
218             fprintf( stderr, "connection from %s (%s)\n",    
219                 (hp == NULL) ? "unknown" : hp->h_name,
220                 inet_ntoa( from.sin_addr ) );
221         }
222
223         glob->unknown_host = !hp;
224     
225         /*  OK, now fork a sub-process performing the further communication
226             to the client; the father-process is listening for further
227             connections */
228         switch( pid = fork() ) {
229         case 0:        /* child */
230
231             /*  the connection to the client should last at most OUT_TIME
232                 thereafter terminate connection */
233             signal(SIGALRM, timeoutf);
234             alarm(OUT_TIME);
235
236             /*  the s-filedescriptor is not needed any more */
237             close( s );
238
239             /*  Serve client-request */
240             do_queries( ns, glob , inet_ntoa( from.sin_addr ), from.sin_port, hp);
241             break;
242
243         case -1:    /* failed */
244             if (dosyslog)
245                                 syslog (LOG_INFO, "%s <%08d>",
246                                         glob->server_connection_msg, glob->svc_cnt);
247             perror( "fork" );
248             break;
249
250         default:    /* parent */
251             /*  the father-process continues listening */
252             close( ns );
253             if ( debug )
254                 fprintf( stderr, "forked child %d\n", pid );
255             break;
256         }
257     }
258     /* NOT REACHED */
259 }
260 /* end of function: start_server */
261
262
263 /**
264  **  set_socket()
265  **
266  **    Initialise socket to listen on and assign dedicated FD
267  **/
268
269 PRIVATE int set_socket(port)
270 int port;
271 {
272     int            s, one;
273     struct sockaddr_in    addr;
274
275     if ( (s = socket( AF_INET, SOCK_STREAM, 0 )) == -1 ) {
276                 perror( "socket" );
277                 exit( 1 );
278         }
279
280         /* set option so clients can't keep us from coming back up */
281     one = 1;
282         if ( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char *) &one,
283         sizeof(one) ) < 0 ) {
284                 perror( "setsockopt" );
285                 exit( 1 );
286         }
287
288         /* bind to a name */
289         addr.sin_family = AF_INET;
290         addr.sin_addr.s_addr = INADDR_ANY;
291         addr.sin_port = htons( port );
292         if ( bind( s, (struct sockaddr *)  &addr, sizeof(addr) ) ) {
293                 perror( "bind" );
294                 exit( 1 );
295         }
296
297     /* listen for connections */
298         if ( listen( s, 512 ) == -1 ) {
299                 perror( "listen" );
300                 exit( 1 );
301         }
302
303         if ( debug )
304         printf( "web500gw listening on port %d\n", port );
305
306     return( s );
307 }
308 /* end of function: set_socket */
309
310 /* If a sub-daemon exists, remove from Process list */
311 PRIVATE void wait4child(arg)
312 int arg;
313 {
314         int     status;
315
316         if ( debug ) printf( "parent: catching child status\n" );
317         while ( wait3( &status, WNOHANG | WUNTRACED, 0 ) > 0 )
318                 ;       /* NULL */
319     (void) signal( SIGCHLD, wait4child );
320 }
321 /* end of function: wait4child */
322
323 /* set signal-handler for Anti-Hack */
324 PRIVATE void hackTimer()
325 {
326     static time_t  timer = (time_t) 0;
327            time_t  now   = time (&now);
328
329     /* re-read IP-REFUSE file if necessary */
330         re_readIPrefuse( globP );
331
332     /* re-read INDEX-URL file if necessary */
333         re_read_index_url_rules( globP );
334
335     if (!timer) {
336
337         timer = now + comRefuseP->statCycle;
338
339     }
340
341     signal(SIGALRM, reset_conMem);
342     alarm((rand() % comRefuseP->tdiff) + comRefuseP->tmin);
343
344     if (now + comRefuseP->tmin > timer) {
345
346         timer = put_hackStats (NULL, now) + comRefuseP->statCycle;
347         *stat_slice  = now;
348
349     }
350
351 }
352 /* end of function: hackTimer */
353
354
355 /* Signal-handler for Anti-Hack-code */
356 PRIVATE void reset_conMem()
357 {
358     int i;
359
360     hackTimer();
361
362     for(i=0; i< 8192; i++)
363         if(conArr[i] >= 0) conArr[i] = 0;
364         else {
365             if(++conArr[i] == 0){
366                 if (dosyslog)
367                     syslog(LOG_INFO, "connection accept resumed for IDX=%d; \
368 %u connection attempts during suspension <%08d>", i, shadowconArr[i],
369                                                         globP->svc_cnt);
370                 shadowconArr[i] = 0;
371         }
372     }
373
374 }
375 /* end of function: reset_conMem */
376
377
378 /*  regular output of the access-statistic */
379 PUBLIC time_t put_hackStats (fp, now)
380 FILE   *fp;
381 time_t  now;
382 {
383     int     i, bereiche;
384     int     is_html = (fp != NULL);
385     char   *eol = is_html ? "<BR>\n" : "\n";
386     unsigned long int gesamt = 0;
387
388     if (!now) now = time (&now);
389
390     if (!fp) fp = fopen (comRefuseP->statFile, "w");
391
392     if (fp) {
393
394         if (is_html) fprintf (fp, "<PRE><BR>\n");
395
396         fprintf (fp, "Access-Statistic TWEB%s", eol);
397         fprintf (fp, "======================%s", eol);
398         if (comRefuseP) fprintf (fp, "FILE : %s%s", comRefuseP->statFile, eol);
399         fprintf (fp, "START: %s%s", format_time (*stat_slice), eol);
400         fprintf (fp, "END  : %s%s%s%s", format_time (now), eol, eol, eol);
401
402         for (i = 0, bereiche = 0; i < CARRSIZE; i++) {
403
404             if(sumconArr[i]) {
405                 fprintf (fp, "IP-IDX %5d: %8lu%s", i, sumconArr[i], eol);
406                 gesamt += sumconArr[i];
407                 bereiche++;
408             }
409
410         }
411     if(bereiche > 1) {
412             fprintf (fp, "----------------------%s", eol);
413             fprintf (fp, "Total:       %8lu  ( from %d IP-Ranges )%s",
414                           gesamt, bereiche, eol);
415         }
416
417         if (is_html) {
418
419             fprintf (fp, "</PRE><BR>\n");
420
421         } else {
422
423             bzero((char *) sumconArr, CARRSIZE * sizeof(long int));
424             fprintf (fp, "\n");
425             fclose (fp);
426
427         }
428     }
429         
430     return (now);
431
432 } /* put_hackStats */