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