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