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