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