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