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