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