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