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