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