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