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