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