]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/conn.c
Fix handling of MaxConnections option
[ngircd-alex.git] / src / ngircd / conn.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  * Copyright (c)2001-2007 Alexander Barton (alex@barton.de)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * Please read the file COPYING, README and AUTHORS for more information.
10  *
11  * Connection management
12  */
13
14
15 #define CONN_MODULE
16
17 #include "portab.h"
18 #include "io.h"
19
20 #include "imp.h"
21 #include <assert.h>
22 #ifdef PROTOTYPES
23 #       include <stdarg.h>
24 #else
25 #       include <varargs.h>
26 #endif
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <unistd.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <sys/socket.h>
33 #include <sys/time.h>
34 #include <sys/types.h>
35 #include <time.h>
36 #include <netinet/in.h>
37
38 #ifdef HAVE_NETINET_IP_H
39 # include <netinet/ip.h>
40 #endif
41
42 #ifdef HAVE_STDINT_H
43 # include <stdint.h>                    /* e.g. for Mac OS X */
44 #endif
45
46 #ifdef TCPWRAP
47 # include <tcpd.h>                      /* for TCP Wrappers */
48 #endif
49
50 #include "array.h"
51 #include "defines.h"
52 #include "resolve.h"
53
54 #include "exp.h"
55 #include "conn.h"
56
57 #include "imp.h"
58 #include "ngircd.h"
59 #include "client.h"
60 #include "conf.h"
61 #include "conn-zip.h"
62 #include "conn-func.h"
63 #include "log.h"
64 #include "parse.h"
65 #include "tool.h"
66
67 #ifdef ZEROCONF
68 # include "rendezvous.h"
69 #endif
70
71 #include "exp.h"
72
73
74 #define SERVER_WAIT (NONE - 1)
75
76
77 static bool Handle_Write PARAMS(( CONN_ID Idx ));
78 static bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, size_t Len ));
79 static int New_Connection PARAMS(( int Sock ));
80 static CONN_ID Socket2Index PARAMS(( int Sock ));
81 static void Read_Request PARAMS(( CONN_ID Idx ));
82 static void Handle_Buffer PARAMS(( CONN_ID Idx ));
83 static void Check_Connections PARAMS(( void ));
84 static void Check_Servers PARAMS(( void ));
85 static void Init_Conn_Struct PARAMS(( CONN_ID Idx ));
86 static bool Init_Socket PARAMS(( int Sock ));
87 static void New_Server PARAMS(( int Server, ng_ipaddr_t *dest ));
88 static void Simple_Message PARAMS(( int Sock, const char *Msg ));
89 static int NewListener PARAMS(( const char *listen_addr, UINT16 Port ));
90
91 static array My_Listeners;
92 static array My_ConnArray;
93 static size_t NumConnections;
94
95 #ifdef TCPWRAP
96 int allow_severity = LOG_INFO;
97 int deny_severity = LOG_ERR;
98 #endif
99
100 static void server_login PARAMS((CONN_ID idx));
101
102 static void cb_Read_Resolver_Result PARAMS(( int sock, UNUSED short what));
103 static void cb_Connect_to_Server PARAMS(( int sock, UNUSED short what));
104 static void cb_clientserver PARAMS((int sock, short what));
105
106 static void
107 cb_listen(int sock, short irrelevant)
108 {
109         (void) irrelevant;
110         if (New_Connection( sock ) >= 0)
111                 NumConnections++;
112 }
113
114
115 static void
116 cb_connserver(int sock, UNUSED short what)
117 {
118         int res, err;
119         socklen_t sock_len;
120         CONN_ID idx = Socket2Index( sock );
121         if (idx <= NONE) {
122                 LogDebug("cb_connserver wants to write on unknown socket?!");
123                 io_close(sock);
124                 return;
125         }
126
127         assert( what & IO_WANTWRITE);
128
129         /* connect() finished, get result. */
130         sock_len = sizeof( err );
131         res = getsockopt( My_Connections[idx].sock, SOL_SOCKET, SO_ERROR, &err, &sock_len );
132         assert( sock_len == sizeof( err ));
133
134         /* Error while connecting? */
135         if ((res != 0) || (err != 0)) {
136                 if (res != 0)
137                         Log(LOG_CRIT, "getsockopt (connection %d): %s!",
138                             idx, strerror(errno));
139                 else
140                         Log(LOG_CRIT,
141                             "Can't connect socket to \"%s:%d\" (connection %d): %s!",
142                             My_Connections[idx].host,
143                             Conf_Server[Conf_GetServer(idx)].port,
144                             idx, strerror(err));
145
146                 res = Conf_GetServer(idx);
147                 assert(res >= 0);
148
149                 Conn_Close(idx, "Can't connect!", NULL, false);
150
151                 if (res < 0)
152                         return;
153                 if (ng_ipaddr_af(&Conf_Server[res].dst_addr[0])) {
154                         /* more addresses to try... */
155                         New_Server(res, &Conf_Server[res].dst_addr[0]);
156                         /* connection to dst_addr[0] in progress, remove this address... */
157                         Conf_Server[res].dst_addr[0] = Conf_Server[res].dst_addr[1];
158
159                         memset(&Conf_Server[res].dst_addr[1], 0, sizeof(&Conf_Server[res].dst_addr[1]));
160                 }
161                 return;
162         }
163
164         res = Conf_GetServer(idx);
165         assert(res >= 0);
166         if (res >= 0) /* connect succeeded, remove all additional addresses */
167                 memset(&Conf_Server[res].dst_addr, 0, sizeof(&Conf_Server[res].dst_addr));
168         Conn_OPTION_DEL( &My_Connections[idx], CONN_ISCONNECTING );
169         server_login(idx);
170 }
171
172
173 static void
174 server_login(CONN_ID idx)
175 {
176         Log( LOG_INFO, "Connection %d with \"%s:%d\" established. Now logging in ...", idx,
177                         My_Connections[idx].host, Conf_Server[Conf_GetServer( idx )].port );
178
179         io_event_setcb( My_Connections[idx].sock, cb_clientserver);
180         io_event_add( My_Connections[idx].sock, IO_WANTREAD|IO_WANTWRITE);
181
182         /* Send PASS and SERVER command to peer */
183         Conn_WriteStr( idx, "PASS %s %s", Conf_Server[Conf_GetServer( idx )].pwd_out, NGIRCd_ProtoID );
184         Conn_WriteStr( idx, "SERVER %s :%s", Conf_ServerName, Conf_ServerInfo );
185 }
186
187
188 static void
189 cb_clientserver(int sock, short what)
190 {
191         CONN_ID idx = Socket2Index( sock );
192         if (idx <= NONE) {
193 #ifdef DEBUG
194                 Log(LOG_WARNING, "WTF: cb_clientserver wants to write on unknown socket?!");
195 #endif
196                 io_close(sock);
197                 return;
198         }
199
200         if (what & IO_WANTREAD)
201                 Read_Request( idx );
202
203         if (what & IO_WANTWRITE)
204                 Handle_Write( idx );
205 }
206
207
208 GLOBAL void
209 Conn_Init( void )
210 {
211         /* Modul initialisieren: statische Strukturen "ausnullen". */
212
213         CONN_ID i;
214
215         /* Speicher fuer Verbindungs-Pool anfordern */
216         Pool_Size = CONNECTION_POOL;
217         if ((Conf_MaxConnections > 0) &&
218                 (Pool_Size > Conf_MaxConnections))
219                         Pool_Size = Conf_MaxConnections;
220
221         if (!array_alloc(&My_ConnArray, sizeof(CONNECTION), (size_t)Pool_Size)) {
222                 Log( LOG_EMERG, "Can't allocate memory! [Conn_Init]" );
223                 exit( 1 );
224         }
225
226         /* FIXME: My_Connetions/Pool_Size is needed by other parts of the
227          * code; remove them! */
228         My_Connections = (CONNECTION*) array_start(&My_ConnArray);
229
230         LogDebug("Allocated connection pool for %d items (%ld bytes).",
231                 array_length(&My_ConnArray, sizeof( CONNECTION )), array_bytes(&My_ConnArray));
232
233         assert( array_length(&My_ConnArray, sizeof( CONNECTION )) >= (size_t) Pool_Size);
234         
235         array_free( &My_Listeners );
236
237         /* Connection-Struktur initialisieren */
238         for( i = 0; i < Pool_Size; i++ ) Init_Conn_Struct( i );
239
240         /* Global write counter */
241         WCounter = 0;
242 } /* Conn_Init */
243
244
245 GLOBAL void
246 Conn_Exit( void )
247 {
248         /* Modul abmelden: alle noch offenen Connections
249          * schliessen und freigeben. */
250
251         CONN_ID idx;
252
253         LogDebug("Shutting down all connections ..." );
254
255         Conn_ExitListeners();
256
257         /* Sockets schliessen */
258         for( idx = 0; idx < Pool_Size; idx++ ) {
259                 if( My_Connections[idx].sock > NONE ) {
260                         Conn_Close( idx, NULL, NGIRCd_SignalRestart ?
261                                 "Server going down (restarting)":"Server going down", true );
262                 }
263         }
264
265         array_free(&My_ConnArray);
266         My_Connections = NULL;
267         Pool_Size = 0;
268         io_library_shutdown();
269 } /* Conn_Exit */
270
271
272 static unsigned int
273 ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short))
274 {
275         unsigned int created = 0;
276         size_t len;
277         int fd;
278         UINT16 *port;
279
280         len = array_length(a, sizeof (UINT16));
281         port = array_start(a);
282         while (len--) {
283                 fd = NewListener(listen_addr, *port);
284                 if (fd < 0) {
285                         port++;
286                         continue;
287                 }
288                 if (!io_event_create( fd, IO_WANTREAD, func )) {
289                         Log( LOG_ERR, "io_event_create(): Could not add listening fd %d (port %u): %s!",
290                                                 fd, (unsigned int) *port, strerror(errno));
291                         close(fd);
292                         port++;
293                         continue;
294                 }
295                 created++;
296                 port++;
297         }
298         return created;
299 }
300
301
302 GLOBAL unsigned int
303 Conn_InitListeners( void )
304 {
305         /* Initialize ports on which the server should accept connections */
306         unsigned int created = 0;
307         char *copy, *listen_addr;
308
309         if (!io_library_init(CONNECTION_POOL)) {
310                 Log(LOG_EMERG, "Cannot initialize IO routines: %s", strerror(errno));
311                 return -1;
312         }
313
314         assert(Conf_ListenAddress);
315
316         /* can't use Conf_ListenAddress directly, see below */
317         copy = strdup(Conf_ListenAddress);
318         if (!copy) {
319                 Log(LOG_CRIT, "Cannot copy %s: %s", Conf_ListenAddress, strerror(errno));
320                 return 0;
321         }
322         listen_addr = strtok(copy, ",");
323
324         while (listen_addr) {
325                 ngt_TrimStr(listen_addr);
326                 if (*listen_addr)
327                         created += ports_initlisteners(&Conf_ListenPorts, listen_addr, cb_listen);
328
329                 listen_addr = strtok(NULL, ",");
330         }
331
332         /*
333          * can't free() Conf_ListenAddress here. On /REHASH, if the config file
334          * cannot be re-loaded, we'd end up with a NULL Conf_ListenAddress.
335          * Instead, free() takes place in conf.c, before the config file
336          * is being parsed.
337          */
338         free(copy);
339         return created;
340 } /* Conn_InitListeners */
341
342
343 GLOBAL void
344 Conn_ExitListeners( void )
345 {
346         /* Close down all listening sockets */
347         int *fd;
348         size_t arraylen;
349 #ifdef ZEROCONF
350         Rendezvous_UnregisterListeners( );
351 #endif
352
353         arraylen = array_length(&My_Listeners, sizeof (int));
354         Log( LOG_INFO, "Shutting down all listening sockets (%d total)...", arraylen );
355         fd = array_start(&My_Listeners);
356         while(arraylen--) {
357                 assert(fd != NULL);
358                 assert(*fd >= 0);
359                 io_close(*fd);
360                 LogDebug("Listening socket %d closed.", *fd );
361                 fd++;
362         }
363         array_free(&My_Listeners);
364 } /* Conn_ExitListeners */
365
366
367 static bool
368 InitSinaddrListenAddr(ng_ipaddr_t *addr, const char *listen_addrstr, UINT16 Port)
369 {
370         bool ret;
371
372         ret = ng_ipaddr_init(addr, listen_addrstr, Port);
373         if (!ret) {
374                 assert(listen_addrstr);
375                 Log(LOG_CRIT, "Can't bind to [%s]:%u: can't convert ip address \"%s\"",
376                                                 listen_addrstr, Port, listen_addrstr);
377         }
378         return ret;
379 }
380
381
382 static void
383 set_v6_only(int af, int sock)
384 {
385 #if defined(IPV6_V6ONLY) && defined(WANT_IPV6)
386         int on = 1;
387
388         if (af != AF_INET6)
389                 return;
390
391         if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)))
392                 Log(LOG_ERR, "Could not set IPV6_V6ONLY: %s", strerror(errno));
393 #else
394         (void)af;
395         (void)sock;
396 #endif
397 }
398
399
400 /* return new listening port file descriptor or -1 on failure */
401 static int
402 NewListener(const char *listen_addr, UINT16 Port)
403 {
404         /* Create new listening socket on specified port */
405         ng_ipaddr_t addr;
406         int sock, af;
407 #ifdef ZEROCONF
408         char name[CLIENT_ID_LEN], *info;
409 #endif
410         if (!InitSinaddrListenAddr(&addr, listen_addr, Port))
411                 return -1;
412
413         af = ng_ipaddr_af(&addr);
414         sock = socket(af, SOCK_STREAM, 0);
415         if( sock < 0 ) {
416                 Log(LOG_CRIT, "Can't create socket (af %d) : %s!", af, strerror(errno));
417                 return -1;
418         }
419
420         set_v6_only(af, sock);
421
422         if (!Init_Socket(sock))
423                 return -1;
424
425         if (bind(sock, (struct sockaddr *)&addr, ng_ipaddr_salen(&addr)) != 0) {
426                 Log(LOG_CRIT, "Can't bind socket to address %s:%d - %s",
427                         ng_ipaddr_tostr(&addr), Port, strerror(errno));
428                 close(sock);
429                 return -1;
430         }
431
432         if( listen( sock, 10 ) != 0 ) {
433                 Log( LOG_CRIT, "Can't listen on socket: %s!", strerror( errno ));
434                 close( sock );
435                 return -1;
436         }
437
438         /* keep fd in list so we can close it when ngircd restarts/shuts down */
439         if (!array_catb( &My_Listeners,(char*) &sock, sizeof(int) )) {
440                 Log( LOG_CRIT, "Can't add socket to My_Listeners array: %s!", strerror( errno ));
441                 close( sock );
442                 return -1;
443         }
444
445         Log(LOG_INFO, "Now listening on [%s]:%d (socket %d).", ng_ipaddr_tostr(&addr), Port, sock);
446
447 #ifdef ZEROCONF
448         /* Get best server description text */
449         if( ! Conf_ServerInfo[0] ) info = Conf_ServerName;
450         else
451         {
452                 /* Use server info string */
453                 info = NULL;
454                 if( Conf_ServerInfo[0] == '[' )
455                 {
456                         /* Cut off leading hostname part in "[]" */
457                         info = strchr( Conf_ServerInfo, ']' );
458                         if( info )
459                         {
460                                 info++;
461                                 while( *info == ' ' ) info++;
462                         }
463                 }
464                 if( ! info ) info = Conf_ServerInfo;
465         }
466
467         /* Add port number to description if non-standard */
468         if (Port != 6667)
469                 snprintf(name, sizeof name, "%s (port %u)", info,
470                          (unsigned int)Port);
471         else
472                 strlcpy(name, info, sizeof name);
473
474         /* Register service */
475         Rendezvous_Register( name, MDNS_TYPE, Port );
476 #endif
477         return sock;
478 } /* NewListener */
479
480
481 /**
482  * "Main Loop": Loop until shutdown or restart is signalled.
483  * This function loops until a shutdown or restart of ngIRCd is signalled and
484  * calls io_dispatch() to check for readable and writable sockets every second.
485  * It checks for status changes on pending connections (e. g. when a hostname
486  * has been resolved), checks for "penalties" and timeouts, and handles the
487  * input buffers.
488  */
489 GLOBAL void
490 Conn_Handler(void)
491 {
492         int i;
493         unsigned int wdatalen;
494         struct timeval tv;
495         time_t t;
496
497         while (!NGIRCd_SignalQuit && !NGIRCd_SignalRestart) {
498                 t = time(NULL);
499
500 #ifdef ZEROCONF
501                 Rendezvous_Handler();
502 #endif
503
504                 /* Should the configuration be reloaded? */
505                 if (NGIRCd_SignalRehash)
506                         NGIRCd_Rehash();
507
508                 /* Check configured servers and established links */
509                 Check_Servers();
510                 Check_Connections();
511
512                 /* Look for non-empty read buffers ... */
513                 for (i = 0; i < Pool_Size; i++) {
514                         if ((My_Connections[i].sock > NONE)
515                             && (array_bytes(&My_Connections[i].rbuf) > 0)
516                             && (My_Connections[i].delaytime < t)) {
517                                 /* ... and try to handle the received data */
518                                 Handle_Buffer(i);
519                         }
520                 }
521
522                 /* Look for non-empty write buffers ... */
523                 for (i = 0; i < Pool_Size; i++) {
524                         if (My_Connections[i].sock <= NONE)
525                                 continue;
526
527                         wdatalen = (unsigned int)array_bytes(&My_Connections[i].wbuf);
528 #ifdef ZLIB
529                         if (wdatalen > 0 ||
530                             array_bytes(&My_Connections[i].zip.wbuf) > 0)
531 #else
532                         if (wdatalen > 0)
533 #endif
534                         {
535                                 /* Set the "WANTWRITE" flag on this socket */
536                                 io_event_add(My_Connections[i].sock,
537                                              IO_WANTWRITE);
538                         }
539                 }
540
541                 /* Check from which sockets we possibly could read ... */
542                 for (i = 0; i < Pool_Size; i++) {
543                         if (My_Connections[i].sock <= NONE)
544                                 continue;
545
546                         if (Resolve_INPROGRESS(&My_Connections[i].res_stat)) {
547                                 /* Wait for completion of resolver sub-process ... */
548                                 io_event_del(My_Connections[i].sock,
549                                              IO_WANTREAD);
550                                 continue;
551                         }
552
553                         if (Conn_OPTION_ISSET(&My_Connections[i], CONN_ISCONNECTING))
554                                 /* Wait for completion of connect() ... */
555                                 continue;
556
557                         if (My_Connections[i].delaytime > t) {
558                                 /* There is a "penalty time" set: ignore socket! */
559                                 io_event_del(My_Connections[i].sock,
560                                              IO_WANTREAD);
561                                 continue;
562                         }
563                         io_event_add(My_Connections[i].sock, IO_WANTREAD);
564                 }
565
566                 /* Set the timeout for reading from the network to 1 second,
567                  * which is the granularity with witch we handle "penalty
568                  * times" for example.
569                  * Note: tv_sec/usec are undefined(!) after io_dispatch()
570                  * returns, so we have to set it beforce each call to it! */
571                 tv.tv_usec = 0;
572                 tv.tv_sec = 1;
573
574                 /* Wait for activity ... */
575                 i = io_dispatch(&tv);
576                 if (i == -1 && errno != EINTR) {
577                         Log(LOG_EMERG, "Conn_Handler(): io_dispatch(): %s!",
578                             strerror(errno));
579                         Log(LOG_ALERT, "%s exiting due to fatal errors!",
580                             PACKAGE_NAME);
581                         exit(1);
582                 }
583         }
584
585         if (NGIRCd_SignalQuit)
586                 Log(LOG_NOTICE | LOG_snotice, "Server going down NOW!");
587         else if (NGIRCd_SignalRestart)
588                 Log(LOG_NOTICE | LOG_snotice, "Server restarting NOW!");
589 } /* Conn_Handler */
590
591
592 /**
593  * Write a text string into the socket of a connection.
594  * This function automatically appends CR+LF to the string and validates that
595  * the result is a valid IRC message (oversized messages are shortened, for
596  * example). Then it calls the Conn_Write() function to do the actual sending.
597  * @param Idx Index fo the connection.
598  * @param Format Format string, see printf().
599  * @return true on success, false otherwise.
600  */
601 #ifdef PROTOTYPES
602 GLOBAL bool
603 Conn_WriteStr( CONN_ID Idx, char *Format, ... )
604 #else
605 GLOBAL bool 
606 Conn_WriteStr( Idx, Format, va_alist )
607 CONN_ID Idx;
608 char *Format;
609 va_dcl
610 #endif
611 {
612         char buffer[COMMAND_LEN];
613         size_t len;
614         bool ok;
615         va_list ap;
616
617         assert( Idx > NONE );
618         assert( Format != NULL );
619
620 #ifdef PROTOTYPES
621         va_start( ap, Format );
622 #else
623         va_start( ap );
624 #endif
625         if (vsnprintf( buffer, COMMAND_LEN - 2, Format, ap ) >= COMMAND_LEN - 2 ) {
626                 /*
627                  * The string that should be written to the socket is longer
628                  * than the allowed size of COMMAND_LEN bytes (including both
629                  * the CR and LF characters). This can be caused by the
630                  * IRC_WriteXXX() functions when the prefix of this server had
631                  * to be added to an already "quite long" command line which
632                  * has been received from a regular IRC client, for example.
633                  * 
634                  * We are not allowed to send such "oversized" messages to
635                  * other servers and clients, see RFC 2812 2.3 and 2813 3.3
636                  * ("these messages SHALL NOT exceed 512 characters in length,
637                  * counting all characters including the trailing CR-LF").
638                  *
639                  * So we have a big problem here: we should send more bytes
640                  * to the network than we are allowed to and we don't know
641                  * the originator (any more). The "old" behaviour of blaming
642                  * the receiver ("next hop") is a bad idea (it could be just
643                  * an other server only routing the message!), so the only
644                  * option left is to shorten the string and to hope that the
645                  * result is still somewhat useful ...
646                  *                                                   -alex-
647                  */
648
649                 strcpy (buffer + sizeof(buffer) - strlen(CUT_TXTSUFFIX) - 2 - 1,
650                         CUT_TXTSUFFIX);
651         }
652
653 #ifdef SNIFFER
654         if (NGIRCd_Sniffer)
655                 Log(LOG_DEBUG, " -> connection %d: '%s'.", Idx, buffer);
656 #endif
657
658         len = strlcat( buffer, "\r\n", sizeof( buffer ));
659         ok = Conn_Write(Idx, buffer, len);
660         My_Connections[Idx].msg_out++;
661
662         va_end( ap );
663         return ok;
664 } /* Conn_WriteStr */
665
666
667 /**
668  * Append Data to the outbound write buffer of a connection.
669  * @param Idx Index of the connection.
670  * @param Data pointer to the data.
671  * @param Len length of Data.
672  * @return true on success, false otherwise.
673  */
674 static bool
675 Conn_Write( CONN_ID Idx, char *Data, size_t Len )
676 {
677         CLIENT *c;
678         size_t writebuf_limit = WRITEBUFFER_LEN;
679         assert( Idx > NONE );
680         assert( Data != NULL );
681         assert( Len > 0 );
682
683         c = Conn_GetClient(Idx);
684         assert( c != NULL);
685
686         /* Servers do get special write buffer limits, so they can generate
687          * all the messages that are required while peering. */
688         if (Client_Type(c) == CLIENT_SERVER)
689                 writebuf_limit = WRITEBUFFER_SLINK_LEN;
690
691         /* Is the socket still open? A previous call to Conn_Write()
692          * may have closed the connection due to a fatal error.
693          * In this case it is sufficient to return an error, as well. */
694         if( My_Connections[Idx].sock <= NONE ) {
695                 LogDebug("Skipped write on closed socket (connection %d).", Idx);
696                 return false;
697         }
698
699 #ifdef ZLIB
700         if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ZIP )) {
701                 /* Compressed link:
702                  * Zip_Buffer() does all the dirty work for us: it flushes
703                  * the (pre-)compression buffers if required and handles
704                  * all error conditions. */
705                 if (!Zip_Buffer(Idx, Data, Len))
706                         return false;
707         }
708         else
709 #endif
710         {
711                 /* Uncompressed link:
712                  * Check if outbound buffer has enough space for the data. */
713                 if (array_bytes(&My_Connections[Idx].wbuf) + Len >=
714                     writebuf_limit) {
715                         /* Buffer is full, flush it. Handle_Write deals with
716                          * low-level errors, if any. */
717                         if (!Handle_Write(Idx))
718                                 return false;
719                 }
720
721                 /* When the write buffer is still too big after flushing it,
722                  * the connection will be killed. */
723                 if (array_bytes(&My_Connections[Idx].wbuf) + Len >=
724                     writebuf_limit) {
725                         Log(LOG_NOTICE,
726                             "Write buffer overflow (connection %d, size %lu byte)!",
727                             Idx,
728                             (unsigned long)array_bytes(&My_Connections[Idx].wbuf));
729                         Conn_Close(Idx, "Write buffer overflow!", NULL, false);
730                         return false;
731                 }
732
733                 /* Copy data to write buffer */
734                 if (!array_catb(&My_Connections[Idx].wbuf, Data, Len))
735                         return false;
736
737                 My_Connections[Idx].bytes_out += Len;
738         }
739
740         /* Adjust global write counter */
741         WCounter += Len;
742
743         return true;
744 } /* Conn_Write */
745
746
747 GLOBAL void
748 Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient )
749 {
750         /* Close connection. Open pipes of asyncronous resolver
751          * sub-processes are closed down. */
752
753         CLIENT *c;
754         char *txt;
755         double in_k, out_k;
756         UINT16 port;
757 #ifdef ZLIB
758         double in_z_k, out_z_k;
759         int in_p, out_p;
760 #endif
761
762         assert( Idx > NONE );
763
764         /* Is this link already shutting down? */
765         if( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ISCLOSING )) {
766                 /* Conn_Close() has been called recursively for this link;
767                  * probabe reason: Handle_Write() failed  -- see below. */
768                 LogDebug("Recursive request to close connection: %d", Idx );
769                 return;
770         }
771
772         assert( My_Connections[Idx].sock > NONE );
773
774         /* Mark link as "closing" */
775         Conn_OPTION_ADD( &My_Connections[Idx], CONN_ISCLOSING );
776
777         if (LogMsg)
778                 txt = LogMsg;
779         else
780                 txt = FwdMsg;
781         if (! txt)
782                 txt = "Reason unknown";
783
784         port = ng_ipaddr_getport(&My_Connections[Idx].addr);
785         Log(LOG_INFO, "Shutting down connection %d (%s) with %s:%d ...", Idx,
786             LogMsg ? LogMsg : FwdMsg, My_Connections[Idx].host, port);
787
788         /* Search client, if any */
789         c = Conn_GetClient( Idx );
790
791         /* Should the client be informed? */
792         if (InformClient) {
793 #ifndef STRICT_RFC
794                 /* Send statistics to client if registered as user: */
795                 if ((c != NULL) && (Client_Type(c) == CLIENT_USER)) {
796                         Conn_WriteStr( Idx,
797                          ":%s NOTICE %s :%sConnection statistics: client %.1f kb, server %.1f kb.",
798                          Client_ID(Client_ThisServer()), Client_ID(c),
799                          NOTICE_TXTPREFIX,
800                          (double)My_Connections[Idx].bytes_in / 1024,
801                          (double)My_Connections[Idx].bytes_out / 1024);
802                 }
803 #endif
804                 /* Send ERROR to client (see RFC!) */
805                 if (FwdMsg)
806                         Conn_WriteStr(Idx, "ERROR :%s", FwdMsg);
807                 else
808                         Conn_WriteStr(Idx, "ERROR :Closing connection.");
809         }
810
811         /* Try to write out the write buffer. Note: Handle_Write() eventually
812          * removes the CLIENT structure associated with this connection if an
813          * error occurs! So we have to re-check if there is still an valid
814          * CLIENT structure after calling Handle_Write() ...*/
815         (void)Handle_Write( Idx );
816
817         /* Search client, if any (re-check!) */
818         c = Conn_GetClient( Idx );
819
820         /* Shut down socket */
821         if (! io_close(My_Connections[Idx].sock)) {
822                 /* Oops, we can't close the socket!? This is ... ugly! */
823                 Log(LOG_CRIT,
824                     "Error closing connection %d (socket %d) with %s:%d - %s! (ignored)",
825                     Idx, My_Connections[Idx].sock, My_Connections[Idx].host,
826                     port, strerror(errno));
827         }
828
829         /* Mark socket as invalid: */
830         My_Connections[Idx].sock = NONE;
831
832         /* If there is still a client, unregister it now */
833         if (c)
834                 Client_Destroy(c, LogMsg, FwdMsg, true);
835
836         /* Calculate statistics and log information */
837         in_k = (double)My_Connections[Idx].bytes_in / 1024;
838         out_k = (double)My_Connections[Idx].bytes_out / 1024;
839 #ifdef ZLIB
840         if (Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ZIP)) {
841                 in_z_k = (double)My_Connections[Idx].zip.bytes_in / 1024;
842                 out_z_k = (double)My_Connections[Idx].zip.bytes_out / 1024;
843                 /* Make sure that no division by zero can occur during
844                  * the calculation of in_p and out_p: in_z_k and out_z_k
845                  * are non-zero, that's guaranteed by the protocol until
846                  * compression can be enabled. */
847                 if (! in_z_k)
848                         in_z_k = in_k;
849                 if (! out_z_k)
850                         out_z_k = out_k;
851                 in_p = (int)(( in_k * 100 ) / in_z_k );
852                 out_p = (int)(( out_k * 100 ) / out_z_k );
853                 Log(LOG_INFO,
854                     "Connection %d with %s:%d closed (in: %.1fk/%.1fk/%d%%, out: %.1fk/%.1fk/%d%%).",
855                     Idx, My_Connections[Idx].host, port,
856                     in_k, in_z_k, in_p, out_k, out_z_k, out_p);
857         }
858         else
859 #endif
860         {
861                 Log(LOG_INFO,
862                     "Connection %d with %s:%d closed (in: %.1fk, out: %.1fk).",
863                     Idx, My_Connections[Idx].host, port,
864                     in_k, out_k);
865         }
866
867         /* cancel running resolver */
868         if (Resolve_INPROGRESS(&My_Connections[Idx].res_stat))
869                 Resolve_Shutdown(&My_Connections[Idx].res_stat);
870
871         /* Servers: Modify time of next connect attempt? */
872         Conf_UnsetServer( Idx );
873
874 #ifdef ZLIB
875         /* Clean up zlib, if link was compressed */
876         if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ZIP )) {
877                 inflateEnd( &My_Connections[Idx].zip.in );
878                 deflateEnd( &My_Connections[Idx].zip.out );
879                 array_free(&My_Connections[Idx].zip.rbuf);
880                 array_free(&My_Connections[Idx].zip.wbuf);
881         }
882 #endif
883
884         array_free(&My_Connections[Idx].rbuf);
885         array_free(&My_Connections[Idx].wbuf);
886
887         /* Clean up connection structure (=free it) */
888         Init_Conn_Struct( Idx );
889
890         assert(NumConnections > 0);
891         if (NumConnections)
892                 NumConnections--;
893         LogDebug("Shutdown of connection %d completed", Idx );
894 } /* Conn_Close */
895
896
897 GLOBAL void
898 Conn_SyncServerStruct( void )
899 {
900         /* Synchronize server structures (connection IDs):
901          * connections <-> configuration */
902
903         CLIENT *client;
904         CONN_ID i;
905         int c;
906
907         for( i = 0; i < Pool_Size; i++ ) {
908                 /* Established connection? */
909                 if (My_Connections[i].sock < 0)
910                         continue;
911
912                 /* Server connection? */
913                 client = Conn_GetClient( i );
914                 if(( ! client ) || ( Client_Type( client ) != CLIENT_SERVER )) continue;
915
916                 for( c = 0; c < MAX_SERVERS; c++ )
917                 {
918                         /* Configured server? */
919                         if( ! Conf_Server[c].host[0] ) continue;
920
921                         /* Duplicate? */
922                         if( strcmp( Conf_Server[c].name, Client_ID( client )) == 0 )
923                                 Conf_Server[c].conn_id = i;
924                 }
925         }
926 } /* SyncServerStruct */
927
928
929 /**
930  * Send out data of write buffer; connect new sockets.
931  */
932 static bool
933 Handle_Write( CONN_ID Idx )
934 {
935         ssize_t len;
936         size_t wdatalen;
937
938         assert( Idx > NONE );
939         if ( My_Connections[Idx].sock < 0 ) {
940                 LogDebug("Handle_Write() on closed socket, connection %d", Idx);
941                 return false;
942         }
943         assert( My_Connections[Idx].sock > NONE );
944
945         wdatalen = array_bytes(&My_Connections[Idx].wbuf );
946
947 #ifdef ZLIB
948         if (wdatalen == 0) {
949                 /* Write buffer is empty, so we try to flush the compression
950                  * buffer and get some data to work with from there :-) */
951                 if (!Zip_Flush(Idx))
952                         return false;
953
954                 /* Now the write buffer most probably has changed: */
955                 wdatalen = array_bytes(&My_Connections[Idx].wbuf);
956         }
957 #endif
958
959         if (wdatalen == 0) {
960                 /* Still no data, fine. */
961                 io_event_del(My_Connections[Idx].sock, IO_WANTWRITE );
962                 return true;
963         }
964
965         LogDebug
966             ("Handle_Write() called for connection %d, %ld bytes pending ...",
967              Idx, wdatalen);
968
969         len = write(My_Connections[Idx].sock,
970                     array_start(&My_Connections[Idx].wbuf), wdatalen );
971
972         if( len < 0 ) {
973                 if (errno == EAGAIN || errno == EINTR)
974                         return true;
975
976                 Log(LOG_ERR, "Write error on connection %d (socket %d): %s!",
977                     Idx, My_Connections[Idx].sock, strerror(errno));
978                 Conn_Close(Idx, "Write error!", NULL, false);
979                 return false;
980         }
981
982         /* move any data not yet written to beginning */
983         array_moveleft(&My_Connections[Idx].wbuf, 1, (size_t)len);
984
985         return true;
986 } /* Handle_Write */
987
988
989 static int
990 Count_Connections(ng_ipaddr_t *a)
991 {
992         int i, cnt;
993
994         cnt = 0;
995         for (i = 0; i < Pool_Size; i++) {
996                 if (My_Connections[i].sock <= NONE)
997                         continue;
998                 if (ng_ipaddr_ipequal(&My_Connections[i].addr, a))
999                         cnt++;
1000         }
1001         return cnt;
1002 } /* Count_Connections */
1003
1004
1005 static int
1006 New_Connection( int Sock )
1007 {
1008         /* Neue Client-Verbindung von Listen-Socket annehmen und
1009          * CLIENT-Struktur anlegen. */
1010
1011 #ifdef TCPWRAP
1012         struct request_info req;
1013 #endif
1014         ng_ipaddr_t new_addr;
1015         char ip_str[NG_INET_ADDRSTRLEN];
1016         int new_sock, new_sock_len;
1017         CLIENT *c;
1018         long cnt;
1019
1020         assert( Sock > NONE );
1021         /* Connection auf Listen-Socket annehmen */
1022         new_sock_len = (int)sizeof(new_addr);
1023
1024         new_sock = accept(Sock, (struct sockaddr *)&new_addr,
1025                           (socklen_t *)&new_sock_len);
1026         if (new_sock < 0) {
1027                 Log(LOG_CRIT, "Can't accept connection: %s!", strerror(errno));
1028                 return -1;
1029         }
1030
1031         if (!ng_ipaddr_tostr_r(&new_addr, ip_str)) {
1032                 Log(LOG_CRIT, "fd %d: Can't convert IP address!", new_sock);
1033                 Simple_Message(new_sock, "ERROR :Internal Server Error");
1034                 close(new_sock);
1035                 return -1;
1036         }
1037
1038 #ifdef TCPWRAP
1039         /* Validate socket using TCP Wrappers */
1040         request_init( &req, RQ_DAEMON, PACKAGE_NAME, RQ_FILE, new_sock, RQ_CLIENT_SIN, &new_addr, NULL );
1041         fromhost(&req);
1042         if (!hosts_access(&req)) {
1043                 Log (deny_severity, "Refused connection from %s (by TCP Wrappers)!", ip_str);
1044                 Simple_Message( new_sock, "ERROR :Connection refused" );
1045                 close( new_sock );
1046                 return -1;
1047         }
1048 #endif
1049
1050         /* Socket initialisieren */
1051         if (!Init_Socket( new_sock ))
1052                 return -1;
1053
1054         /* Check IP-based connection limit */
1055         cnt = Count_Connections(&new_addr);
1056         if ((Conf_MaxConnectionsIP > 0) && (cnt >= Conf_MaxConnectionsIP)) {
1057                 /* Access denied, too many connections from this IP address! */
1058                 Log( LOG_ERR, "Refused connection from %s: too may connections (%ld) from this IP address!", ip_str, cnt);
1059                 Simple_Message( new_sock, "ERROR :Connection refused, too many connections from your IP address!" );
1060                 close( new_sock );
1061                 return -1;
1062         }
1063
1064         if ((Conf_MaxConnections > 0) &&
1065                 (NumConnections >= (size_t) Conf_MaxConnections))
1066         {
1067                 Log( LOG_ALERT, "Can't accept connection: limit (%d) reached!", Conf_MaxConnections);
1068                 Simple_Message( new_sock, "ERROR :Connection limit reached" );
1069                 close( new_sock );
1070                 return -1;
1071         }
1072
1073         if( new_sock >= Pool_Size ) {
1074                 if (!array_alloc(&My_ConnArray, sizeof(CONNECTION),
1075                                  (size_t)new_sock)) {
1076                         Log( LOG_EMERG, "Can't allocate memory! [New_Connection]" );
1077                         Simple_Message( new_sock, "ERROR: Internal error" );
1078                         close( new_sock );
1079                         return -1;
1080                 }
1081                 LogDebug("Bumped connection pool to %ld items (internal: %ld items, %ld bytes)",
1082                         new_sock, array_length(&My_ConnArray, sizeof(CONNECTION)), array_bytes(&My_ConnArray));
1083
1084                 /* Adjust pointer to new block */
1085                 My_Connections = array_start(&My_ConnArray);
1086                 while (Pool_Size <= new_sock)
1087                         Init_Conn_Struct(Pool_Size++);
1088         }
1089
1090         /* register callback */
1091         if (!io_event_create( new_sock, IO_WANTREAD, cb_clientserver)) {
1092                 Log(LOG_ALERT, "Can't accept connection: io_event_create failed!");
1093                 Simple_Message(new_sock, "ERROR :Internal error");
1094                 close(new_sock);
1095                 return -1;
1096         }
1097
1098         c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWN, false );
1099         if( ! c ) {
1100                 Log(LOG_ALERT, "Can't accept connection: can't create client structure!");
1101                 Simple_Message(new_sock, "ERROR :Internal error");
1102                 io_close(new_sock);
1103                 return -1;
1104         }
1105
1106         Init_Conn_Struct( new_sock );
1107         My_Connections[new_sock].sock = new_sock;
1108         My_Connections[new_sock].addr = new_addr;
1109         My_Connections[new_sock].client = c;
1110
1111         Log( LOG_INFO, "Accepted connection %d from %s:%d on socket %d.", new_sock,
1112                         ip_str, ng_ipaddr_getport(&new_addr), Sock);
1113
1114         /* Hostnamen ermitteln */
1115         strlcpy(My_Connections[new_sock].host, ip_str, sizeof(My_Connections[new_sock].host));
1116
1117         Client_SetHostname(c, My_Connections[new_sock].host);
1118
1119         if (!Conf_NoDNS)
1120                 Resolve_Addr(&My_Connections[new_sock].res_stat, &new_addr,
1121                         My_Connections[new_sock].sock, cb_Read_Resolver_Result);
1122
1123         Conn_SetPenalty(new_sock, 4);
1124         return new_sock;
1125 } /* New_Connection */
1126
1127
1128 static CONN_ID
1129 Socket2Index( int Sock )
1130 {
1131         /* zum Socket passende Connection suchen */
1132
1133         assert( Sock >= 0 );
1134
1135         if( Sock >= Pool_Size || My_Connections[Sock].sock != Sock ) {
1136                 /* die Connection wurde vermutlich (wegen eines
1137                  * Fehlers) bereits wieder abgebaut ... */
1138                 LogDebug("Socket2Index: can't get connection for socket %d!", Sock);
1139                 return NONE;
1140         }
1141         return Sock;
1142 } /* Socket2Index */
1143
1144
1145 /**
1146  * Read data from the network to the read buffer. If an error occures,
1147  * the socket of this connection will be shut down.
1148  */
1149 static void
1150 Read_Request( CONN_ID Idx )
1151 {
1152         ssize_t len;
1153         char readbuf[READBUFFER_LEN];
1154         CLIENT *c;
1155         assert( Idx > NONE );
1156         assert( My_Connections[Idx].sock > NONE );
1157
1158 #ifdef ZLIB
1159         if ((array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN) ||
1160                 (array_bytes(&My_Connections[Idx].zip.rbuf) >= READBUFFER_LEN))
1161 #else
1162         if (array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN)
1163 #endif
1164         {
1165                 /* Read buffer is full */
1166                 Log(LOG_ERR,
1167                     "Receive buffer overflow (connection %d): %d bytes!",
1168                     Idx, array_bytes(&My_Connections[Idx].rbuf));
1169                 Conn_Close( Idx, "Receive buffer overflow!", NULL, false );
1170                 return;
1171         }
1172
1173         len = read(My_Connections[Idx].sock, readbuf, sizeof(readbuf));
1174         if (len == 0) {
1175                 Log(LOG_INFO, "%s:%u (%s) is closing the connection ...",
1176                                 My_Connections[Idx].host,
1177                                 (unsigned int) ng_ipaddr_getport(&My_Connections[Idx].addr),
1178                                 ng_ipaddr_tostr(&My_Connections[Idx].addr));
1179                 Conn_Close(Idx,
1180                            "Socket closed!", "Client closed connection",
1181                            false);
1182                 return;
1183         }
1184
1185         if (len < 0) {
1186                 if( errno == EAGAIN ) return;
1187                 Log(LOG_ERR, "Read error on connection %d (socket %d): %s!",
1188                     Idx, My_Connections[Idx].sock, strerror(errno));
1189                 Conn_Close(Idx, "Read error!", "Client closed connection",
1190                            false);
1191                 return;
1192         }
1193 #ifdef ZLIB
1194         if (Conn_OPTION_ISSET(&My_Connections[Idx], CONN_ZIP)) {
1195                 if (!array_catb(&My_Connections[Idx].zip.rbuf, readbuf,
1196                                 (size_t) len)) {
1197                         Log(LOG_ERR,
1198                             "Could not append recieved data to zip input buffer (connn %d): %d bytes!",
1199                             Idx, len);
1200                         Conn_Close(Idx, "Receive buffer overflow!", NULL,
1201                                    false);
1202                         return;
1203                 }
1204         } else
1205 #endif
1206         {
1207                 if (!array_catb( &My_Connections[Idx].rbuf, readbuf, len)) {
1208                         Log( LOG_ERR, "Could not append recieved data to input buffer (connn %d): %d bytes!", Idx, len );
1209                         Conn_Close( Idx, "Receive buffer overflow!", NULL, false );
1210                 }
1211         }
1212
1213         /* Update connection statistics */
1214         My_Connections[Idx].bytes_in += len;
1215
1216         /* Update timestamp of last data received if this connection is
1217          * registered as a user, server or service connection. Don't update
1218          * otherwise, so users have at least Conf_PongTimeout seconds time to
1219          * register with the IRC server -- see Check_Connections().
1220          * Set "lastping", too, so we can handle time shifts backwards ... */
1221         c = Conn_GetClient(Idx);
1222         if (c && (Client_Type(c) == CLIENT_USER
1223                   || Client_Type(c) == CLIENT_SERVER
1224                   || Client_Type(c) == CLIENT_SERVICE)) {
1225                 My_Connections[Idx].lastdata = time(NULL);
1226                 My_Connections[Idx].lastping = My_Connections[Idx].lastdata;
1227         }
1228
1229         /* Look at the data in the (read-) buffer of this connection */
1230         Handle_Buffer(Idx);
1231 } /* Read_Request */
1232
1233
1234 /**
1235  * Handle all data in the connection read-buffer.
1236  * All data is precessed until no complete command is left. When a fatal
1237  * error occurs, the connection is shut down.
1238  */
1239 static void
1240 Handle_Buffer(CONN_ID Idx)
1241 {
1242 #ifndef STRICT_RFC
1243         char *ptr1, *ptr2, *first_eol;
1244 #endif
1245         char *ptr;
1246         size_t len, delta;
1247         time_t starttime;
1248 #ifdef ZLIB
1249         bool old_z;
1250 #endif
1251
1252         starttime = time(NULL);
1253         for (;;) {
1254                 /* Check penalty */
1255                 if (My_Connections[Idx].delaytime > starttime)
1256                         return;
1257 #ifdef ZLIB
1258                 /* Unpack compressed data, if compression is in use */
1259                 if (Conn_OPTION_ISSET(&My_Connections[Idx], CONN_ZIP)) {
1260                         /* When unzipping fails, Unzip_Buffer() shuts
1261                          * down the connection itself */
1262                         if (!Unzip_Buffer(Idx))
1263                                 return;
1264                 }
1265 #endif
1266
1267                 if (0 == array_bytes(&My_Connections[Idx].rbuf))
1268                         return;
1269
1270                 /* Make sure that the buffer is NULL terminated */
1271                 if (!array_cat0_temporary(&My_Connections[Idx].rbuf)) {
1272                         Conn_Close(Idx, NULL,
1273                                    "Can't allocate memory [Handle_Buffer]",
1274                                    true);
1275                         return;
1276                 }
1277
1278                 /* RFC 2812, section "2.3 Messages", 5th paragraph:
1279                  * "IRC messages are always lines of characters terminated
1280                  * with a CR-LF (Carriage Return - Line Feed) pair [...]". */
1281                 delta = 2;
1282                 ptr = strstr(array_start(&My_Connections[Idx].rbuf), "\r\n");
1283
1284 #ifndef STRICT_RFC
1285                 /* Check for non-RFC-compliant request (only CR or LF)?
1286                  * Unfortunately, there are quite a few clients out there
1287                  * that do this -- e. g. mIRC, BitchX, and Trillian :-( */
1288                 ptr1 = strchr(array_start(&My_Connections[Idx].rbuf), '\r');
1289                 ptr2 = strchr(array_start(&My_Connections[Idx].rbuf), '\n');
1290                 if (ptr) {
1291                         /* Check if there is a single CR or LF _before_ the
1292                          * corerct CR+LF line terminator:  */
1293                         first_eol = ptr1 < ptr2 ? ptr1 : ptr2;
1294                         if (first_eol < ptr) {
1295                                 /* Single CR or LF before CR+LF found */
1296                                 ptr = first_eol;
1297                                 delta = 1;
1298                         }
1299                 } else if (ptr1 || ptr2) {
1300                         /* No CR+LF terminated command found, but single
1301                          * CR or LF found ... */
1302                         if (ptr1 && ptr2)
1303                                 ptr = ptr1 < ptr2 ? ptr1 : ptr2;
1304                         else
1305                                 ptr = ptr1 ? ptr1 : ptr2;
1306                         delta = 1;
1307                 }
1308 #endif
1309
1310                 if (!ptr)
1311                         return;
1312
1313                 /* Complete (=line terminated) request found, handle it! */
1314                 *ptr = '\0';
1315
1316                 len = ptr - (char *)array_start(&My_Connections[Idx].rbuf) + delta;
1317
1318                 if (len > (COMMAND_LEN - 1)) {
1319                         /* Request must not exceed 512 chars (incl. CR+LF!),
1320                          * see RFC 2812. Disconnect Client if this happens. */
1321                         Log(LOG_ERR,
1322                             "Request too long (connection %d): %d bytes (max. %d expected)!",
1323                             Idx, array_bytes(&My_Connections[Idx].rbuf),
1324                             COMMAND_LEN - 1);
1325                         Conn_Close(Idx, NULL, "Request too long", true);
1326                         return;
1327                 }
1328
1329                 if (len <= delta) {
1330                         /* Request is empty (only '\r\n', '\r' or '\n');
1331                          * delta is 2 ('\r\n') or 1 ('\r' or '\n'), see above */
1332                         array_moveleft(&My_Connections[Idx].rbuf, 1, len);
1333                         return;
1334                 }
1335
1336 #ifdef ZLIB
1337                 /* remember if stream is already compressed */
1338                 old_z = My_Connections[Idx].options & CONN_ZIP;
1339 #endif
1340
1341                 My_Connections[Idx].msg_in++;
1342                 if (!Parse_Request
1343                     (Idx, (char *)array_start(&My_Connections[Idx].rbuf)))
1344                         return;
1345
1346                 array_moveleft(&My_Connections[Idx].rbuf, 1, len);
1347                 LogDebug("Connection %d: %d bytes left in read buffer.",
1348                          Idx, array_bytes(&My_Connections[Idx].rbuf));
1349 #ifdef ZLIB
1350                 if ((!old_z) && (My_Connections[Idx].options & CONN_ZIP) &&
1351                     (array_bytes(&My_Connections[Idx].rbuf) > 0)) {
1352                         /* The last command activated socket compression.
1353                          * Data that was read after that needs to be copied
1354                          * to the unzip buffer for decompression: */
1355                         if (!array_copy
1356                             (&My_Connections[Idx].zip.rbuf,
1357                              &My_Connections[Idx].rbuf)) {
1358                                 Conn_Close(Idx, NULL,
1359                                            "Can't allocate memory [Handle_Buffer]",
1360                                            true);
1361                                 return;
1362                         }
1363
1364                         array_trunc(&My_Connections[Idx].rbuf);
1365                         LogDebug
1366                             ("Moved already received data (%u bytes) to uncompression buffer.",
1367                              array_bytes(&My_Connections[Idx].zip.rbuf));
1368                 }
1369 #endif
1370         }
1371 } /* Handle_Buffer */
1372
1373
1374 static void
1375 Check_Connections(void)
1376 {
1377         /* check if connections are alive. if not, play PING-PONG first.
1378          * if this doesn't help either, disconnect client. */
1379         CLIENT *c;
1380         CONN_ID i;
1381
1382         for (i = 0; i < Pool_Size; i++) {
1383                 if (My_Connections[i].sock < 0)
1384                         continue;
1385
1386                 c = Conn_GetClient(i);
1387                 if (c && ((Client_Type(c) == CLIENT_USER)
1388                           || (Client_Type(c) == CLIENT_SERVER)
1389                           || (Client_Type(c) == CLIENT_SERVICE))) {
1390                         /* connected User, Server or Service */
1391                         if (My_Connections[i].lastping >
1392                             My_Connections[i].lastdata) {
1393                                 /* We already sent a ping */
1394                                 if (My_Connections[i].lastping <
1395                                     time(NULL) - Conf_PongTimeout) {
1396                                         /* Timeout */
1397                                         LogDebug
1398                                             ("Connection %d: Ping timeout: %d seconds.",
1399                                              i, Conf_PongTimeout);
1400                                         Conn_Close(i, NULL, "Ping timeout",
1401                                                    true);
1402                                 }
1403                         } else if (My_Connections[i].lastdata <
1404                                    time(NULL) - Conf_PingTimeout) {
1405                                 /* We need to send a PING ... */
1406                                 LogDebug("Connection %d: sending PING ...", i);
1407                                 My_Connections[i].lastping = time(NULL);
1408                                 Conn_WriteStr(i, "PING :%s",
1409                                               Client_ID(Client_ThisServer()));
1410                         }
1411                 } else {
1412                         /* The connection is not fully established yet, so
1413                          * we don't do the PING-PONG game here but instead
1414                          * disconnect the client after "a short time" if it's
1415                          * still not registered. */
1416
1417                         if (My_Connections[i].lastdata <
1418                             time(NULL) - Conf_PongTimeout) {
1419                                 LogDebug
1420                                     ("Unregistered connection %d timed out ...",
1421                                      i);
1422                                 Conn_Close(i, NULL, "Timeout", false);
1423                         }
1424                 }
1425         }
1426 } /* Check_Connections */
1427
1428
1429 static void
1430 Check_Servers( void )
1431 {
1432         /* Check if we can establish further server links */
1433
1434         int i, n;
1435         time_t time_now;
1436
1437         /* Check all configured servers */
1438         for( i = 0; i < MAX_SERVERS; i++ ) {
1439                 /* Valid outgoing server which isn't already connected or disabled? */
1440                 if(( ! Conf_Server[i].host[0] ) || ( ! Conf_Server[i].port > 0 ) ||
1441                         ( Conf_Server[i].conn_id > NONE ) || ( Conf_Server[i].flags & CONF_SFLAG_DISABLED ))
1442                                 continue;
1443
1444                 /* Is there already a connection in this group? */
1445                 if( Conf_Server[i].group > NONE ) {
1446                         for (n = 0; n < MAX_SERVERS; n++) {
1447                                 if (n == i) continue;
1448                                 if ((Conf_Server[n].conn_id != NONE) &&
1449                                         (Conf_Server[n].group == Conf_Server[i].group))
1450                                                 break;
1451                         }
1452                         if (n < MAX_SERVERS) continue;
1453                 }
1454
1455                 /* Check last connect attempt? */
1456                 time_now = time(NULL);
1457                 if( Conf_Server[i].lasttry > (time_now - Conf_ConnectRetry))
1458                         continue;
1459
1460                 /* Okay, try to connect now */
1461                 Conf_Server[i].lasttry = time_now;
1462                 Conf_Server[i].conn_id = SERVER_WAIT;
1463                 assert(Resolve_Getfd(&Conf_Server[i].res_stat) < 0);
1464                 Resolve_Name(&Conf_Server[i].res_stat, Conf_Server[i].host, cb_Connect_to_Server);
1465         }
1466 } /* Check_Servers */
1467
1468
1469 static void
1470 New_Server( int Server , ng_ipaddr_t *dest)
1471 {
1472         /* Establish new server link */
1473         char ip_str[NG_INET_ADDRSTRLEN];
1474         int af_dest, res, new_sock;
1475         CLIENT *c;
1476
1477         assert( Server > NONE );
1478
1479         if (!ng_ipaddr_tostr_r(dest, ip_str)) {
1480                 Log(LOG_WARNING, "New_Server: Could not convert IP to string");
1481                 return;
1482         }
1483
1484         Log( LOG_INFO, "Establishing connection to \"%s\", %s, port %d ... ",
1485                         Conf_Server[Server].host, ip_str, Conf_Server[Server].port );
1486
1487         af_dest = ng_ipaddr_af(dest);
1488         new_sock = socket(af_dest, SOCK_STREAM, 0);
1489         if (new_sock < 0) {
1490                 Log( LOG_CRIT, "Can't create socket (af %d) : %s!", af_dest, strerror( errno ));
1491                 return;
1492         }
1493
1494         if (!Init_Socket(new_sock))
1495                 return;
1496
1497         /* is a bind address configured? */
1498         res = ng_ipaddr_af(&Conf_Server[Server].bind_addr);
1499         /* if yes, bind now. If it fails, warn and let connect() pick a source address */
1500         if (res && bind(new_sock, (struct sockaddr *) &Conf_Server[Server].bind_addr,
1501                                 ng_ipaddr_salen(&Conf_Server[Server].bind_addr)))
1502         {
1503                 ng_ipaddr_tostr_r(&Conf_Server[Server].bind_addr, ip_str);
1504                 Log(LOG_WARNING, "Can't bind socket to %s: %s!", ip_str, strerror(errno));
1505         }
1506         ng_ipaddr_setport(dest, Conf_Server[Server].port);
1507         res = connect(new_sock, (struct sockaddr *) dest, ng_ipaddr_salen(dest));
1508         if(( res != 0 ) && ( errno != EINPROGRESS )) {
1509                 Log( LOG_CRIT, "Can't connect socket: %s!", strerror( errno ));
1510                 close( new_sock );
1511                 return;
1512         }
1513
1514         if (!array_alloc(&My_ConnArray, sizeof(CONNECTION), (size_t)new_sock)) {
1515                 Log(LOG_ALERT,
1516                     "Cannot allocate memory for server connection (socket %d)",
1517                     new_sock);
1518                 close( new_sock );
1519                 return;
1520         }
1521
1522         My_Connections = array_start(&My_ConnArray);
1523
1524         assert(My_Connections[new_sock].sock <= 0);
1525
1526         Init_Conn_Struct(new_sock);
1527
1528         ng_ipaddr_tostr_r(dest, ip_str);
1529         c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWNSERVER, false);
1530         if (!c) {
1531                 Log( LOG_ALERT, "Can't establish connection: can't create client structure!" );
1532                 close( new_sock );
1533                 return;
1534         }
1535
1536         Client_SetIntroducer( c, c );
1537         Client_SetToken( c, TOKEN_OUTBOUND );
1538
1539         /* Register connection */
1540         Conf_Server[Server].conn_id = new_sock;
1541         My_Connections[new_sock].sock = new_sock;
1542         My_Connections[new_sock].addr = *dest;
1543         My_Connections[new_sock].client = c;
1544         strlcpy( My_Connections[new_sock].host, Conf_Server[Server].host,
1545                                 sizeof(My_Connections[new_sock].host ));
1546
1547         /* Register new socket */
1548         if (!io_event_create( new_sock, IO_WANTWRITE, cb_connserver)) {
1549                 Log( LOG_ALERT, "io_event_create(): could not add fd %d", strerror(errno));
1550                 Conn_Close( new_sock, "io_event_create() failed", NULL, false );
1551                 Init_Conn_Struct( new_sock );
1552                 Conf_Server[Server].conn_id = NONE;
1553         }
1554
1555         LogDebug("Registered new connection %d on socket %d.",
1556                                 new_sock, My_Connections[new_sock].sock );
1557         Conn_OPTION_ADD( &My_Connections[new_sock], CONN_ISCONNECTING );
1558 } /* New_Server */
1559
1560
1561 /**
1562  * Initialize connection structure.
1563  */
1564 static void
1565 Init_Conn_Struct(CONN_ID Idx)
1566 {
1567         time_t now = time(NULL);
1568
1569         memset(&My_Connections[Idx], 0, sizeof(CONNECTION));
1570         My_Connections[Idx].sock = -1;
1571         My_Connections[Idx].signon = now;
1572         My_Connections[Idx].lastdata = now;
1573         My_Connections[Idx].lastprivmsg = now;
1574         Resolve_Init(&My_Connections[Idx].res_stat);
1575 } /* Init_Conn_Struct */
1576
1577
1578 static bool
1579 Init_Socket( int Sock )
1580 {
1581         /* Initialize socket (set options) */
1582
1583         int value;
1584
1585         if (!io_setnonblock(Sock)) {
1586                 Log( LOG_CRIT, "Can't enable non-blocking mode for socket: %s!", strerror( errno ));
1587                 close( Sock );
1588                 return false;
1589         }
1590
1591         /* Don't block this port after socket shutdown */
1592         value = 1;
1593         if( setsockopt( Sock, SOL_SOCKET, SO_REUSEADDR, &value, (socklen_t)sizeof( value )) != 0 )
1594         {
1595                 Log( LOG_ERR, "Can't set socket option SO_REUSEADDR: %s!", strerror( errno ));
1596                 /* ignore this error */
1597         }
1598
1599         /* Set type of service (TOS) */
1600 #if defined(IP_TOS) && defined(IPTOS_LOWDELAY)
1601         value = IPTOS_LOWDELAY;
1602         LogDebug("Setting option IP_TOS on socket %d to IPTOS_LOWDELAY (%d).", Sock, value );
1603         if( setsockopt( Sock, SOL_IP, IP_TOS, &value, (socklen_t)sizeof( value )) != 0 )
1604         {
1605                 Log( LOG_ERR, "Can't set socket option IP_TOS: %s!", strerror( errno ));
1606                 /* ignore this error */
1607         }
1608 #endif
1609
1610         return true;
1611 } /* Init_Socket */
1612
1613
1614
1615 static void
1616 cb_Connect_to_Server(int fd, UNUSED short events)
1617 {
1618         /* Read result of resolver sub-process from pipe and start connection */
1619         int i;
1620         size_t len;
1621         ng_ipaddr_t dest_addrs[4];      /* we can handle at most 3; but we read up to
1622                                            four so we can log the 'more than we can handle'
1623                                            condition */
1624
1625         LogDebug("Resolver: Got forward lookup callback on fd %d, events %d", fd, events);
1626
1627         for (i=0; i < MAX_SERVERS; i++) {
1628                   if (Resolve_Getfd(&Conf_Server[i].res_stat) == fd )
1629                           break;
1630         }
1631
1632         if( i >= MAX_SERVERS) {
1633                 /* Ops, no matching server found?! */
1634                 io_close( fd );
1635                 LogDebug("Resolver: Got Forward Lookup callback for unknown server!?");
1636                 return;
1637         }
1638
1639         /* Read result from pipe */
1640         len = Resolve_Read(&Conf_Server[i].res_stat, dest_addrs, sizeof(dest_addrs));
1641         if (len == 0)
1642                 return;
1643
1644         assert((len % sizeof(ng_ipaddr_t)) == 0);
1645
1646         LogDebug("Got result from resolver: %u structs (%u bytes).", len/sizeof(ng_ipaddr_t), len);
1647
1648         memset(&Conf_Server[i].dst_addr, 0, sizeof(&Conf_Server[i].dst_addr));
1649         if (len > sizeof(ng_ipaddr_t)) {
1650                 /* more than one address for this hostname, remember them
1651                  * in case first address is unreachable/not available */
1652                 len -= sizeof(ng_ipaddr_t);
1653                 if (len > sizeof(&Conf_Server[i].dst_addr)) {
1654                         len = sizeof(&Conf_Server[i].dst_addr);
1655                         Log(LOG_NOTICE, "Notice: Resolver returned more IP Addresses for host than we can handle,"
1656                                         " additional addresses dropped");
1657                 }
1658                 memcpy(&Conf_Server[i].dst_addr, &dest_addrs[1], len);
1659         }
1660         /* connect() */
1661         New_Server(i, dest_addrs);
1662 } /* cb_Read_Forward_Lookup */
1663
1664
1665 static void
1666 cb_Read_Resolver_Result( int r_fd, UNUSED short events )
1667 {
1668         /* Read result of resolver sub-process from pipe and update the
1669          * apropriate connection/client structure(s): hostname and/or
1670          * IDENT user name.*/
1671
1672         CLIENT *c;
1673         int i;
1674         size_t len;
1675         char *identptr;
1676 #ifdef IDENTAUTH
1677         char readbuf[HOST_LEN + 2 + CLIENT_USER_LEN];
1678 #else
1679         char readbuf[HOST_LEN + 1];
1680 #endif
1681
1682         LogDebug("Resolver: Got callback on fd %d, events %d", r_fd, events );
1683
1684         /* Search associated connection ... */
1685         for( i = 0; i < Pool_Size; i++ ) {
1686                 if(( My_Connections[i].sock != NONE )
1687                   && ( Resolve_Getfd(&My_Connections[i].res_stat) == r_fd ))
1688                         break;
1689         }
1690         if( i >= Pool_Size ) {
1691                 /* Ops, none found? Probably the connection has already
1692                  * been closed!? We'll ignore that ... */
1693                 io_close( r_fd );
1694                 LogDebug("Resolver: Got callback for unknown connection!?");
1695                 return;
1696         }
1697
1698         /* Read result from pipe */
1699         len = Resolve_Read(&My_Connections[i].res_stat, readbuf, sizeof readbuf -1);
1700         if (len == 0)
1701                 return;
1702
1703         readbuf[len] = '\0';
1704         identptr = strchr(readbuf, '\n');
1705         assert(identptr != NULL);
1706         if (!identptr) {
1707                 Log( LOG_CRIT, "Resolver: Got malformed result!");
1708                 return;
1709         }
1710
1711         *identptr = '\0';
1712         LogDebug("Got result from resolver: \"%s\" (%u bytes read).", readbuf, len);
1713         /* Okay, we got a complete result: this is a host name for outgoing
1714          * connections and a host name and IDENT user name (if enabled) for
1715          * incoming connections.*/
1716         assert ( My_Connections[i].sock >= 0 );
1717         /* Incoming connection. Search client ... */
1718         c = Conn_GetClient( i );
1719         assert( c != NULL );
1720
1721         /* Only update client information of unregistered clients */
1722         if( Client_Type( c ) == CLIENT_UNKNOWN ) {
1723                 strlcpy(My_Connections[i].host, readbuf, sizeof( My_Connections[i].host));
1724                 Client_SetHostname( c, readbuf);
1725 #ifdef IDENTAUTH
1726                 ++identptr;
1727                 if (*identptr) {
1728                         Log(LOG_INFO, "IDENT lookup for connection %d: \"%s\".", i, identptr);
1729                         Client_SetUser(c, identptr, true);
1730                 } else {
1731                         Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i);
1732                 }
1733 #endif
1734         }
1735 #ifdef DEBUG
1736                 else Log( LOG_DEBUG, "Resolver: discarding result for already registered connection %d.", i );
1737 #endif
1738         /* Reset penalty time */
1739         Conn_ResetPenalty( i );
1740 } /* cb_Read_Resolver_Result */
1741
1742
1743 static void
1744 Simple_Message( int Sock, const char *Msg )
1745 {
1746         char buf[COMMAND_LEN];
1747         size_t len;
1748         /* Write "simple" message to socket, without using compression
1749          * or even the connection write buffers. Used e.g. for error
1750          * messages by New_Connection(). */
1751         assert( Sock > NONE );
1752         assert( Msg != NULL );
1753
1754         strlcpy( buf, Msg, sizeof buf - 2);
1755         len = strlcat( buf, "\r\n", sizeof buf);
1756         (void)write(Sock, buf, len);
1757 } /* Simple_Error */
1758
1759
1760 GLOBAL CLIENT *
1761 Conn_GetClient( CONN_ID Idx ) 
1762 {
1763         /* return Client-Structure that belongs to the local Connection Idx.
1764          * If none is found, return NULL.
1765          */
1766         CONNECTION *c;
1767         assert( Idx >= 0 );
1768
1769         c = array_get(&My_ConnArray, sizeof (CONNECTION), (size_t)Idx);
1770
1771         assert(c != NULL);
1772
1773         return c ? c->client : NULL;
1774 }
1775
1776 /* -eof- */