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