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