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