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