]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/conn.c
conn.c: fix more sizeof(..dst_addr) misuse
[ngircd-alex.git] / src / ngircd / conn.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  * Copyright (c)2001-2009 Alexander Barton (alex@barton.de)
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  * Connection management
12  */
13
14
15 #define CONN_MODULE
16
17 #include "portab.h"
18 #include "conf-ssl.h"
19 #include "io.h"
20
21 #include "imp.h"
22 #include <assert.h>
23 #ifdef PROTOTYPES
24 #       include <stdarg.h>
25 #else
26 #       include <varargs.h>
27 #endif
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <sys/socket.h>
34 #include <sys/time.h>
35 #include <sys/types.h>
36 #include <time.h>
37 #include <netinet/in.h>
38
39 #ifdef HAVE_NETINET_IP_H
40 # include <netinet/ip.h>
41 #endif
42
43 #ifdef HAVE_STDINT_H
44 # include <stdint.h>                    /* e.g. for Mac OS X */
45 #endif
46
47 #ifdef TCPWRAP
48 # include <tcpd.h>                      /* for TCP Wrappers */
49 #endif
50
51 #include "array.h"
52 #include "defines.h"
53 #include "resolve.h"
54
55 #include "exp.h"
56 #include "conn.h"
57
58 #include "imp.h"
59 #include "ngircd.h"
60 #include "client.h"
61 #include "conf.h"
62 #include "conn-ssl.h"
63 #include "conn-zip.h"
64 #include "conn-func.h"
65 #include "log.h"
66 #include "parse.h"
67 #include "tool.h"
68
69 #ifdef ZEROCONF
70 # include "rendezvous.h"
71 #endif
72
73 #include "exp.h"
74
75
76 #define SERVER_WAIT (NONE - 1)
77
78 #define MAX_COMMANDS 3
79 #define MAX_COMMANDS_SERVER 10
80
81
82 static bool Handle_Write PARAMS(( CONN_ID Idx ));
83 static bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, size_t Len ));
84 static int New_Connection PARAMS(( int Sock ));
85 static CONN_ID Socket2Index PARAMS(( int Sock ));
86 static void Read_Request PARAMS(( CONN_ID Idx ));
87 static unsigned int Handle_Buffer PARAMS(( CONN_ID Idx ));
88 static void Check_Connections PARAMS(( void ));
89 static void Check_Servers PARAMS(( void ));
90 static void Init_Conn_Struct PARAMS(( CONN_ID Idx ));
91 static bool Init_Socket PARAMS(( int Sock ));
92 static void New_Server PARAMS(( int Server, ng_ipaddr_t *dest ));
93 static void Simple_Message PARAMS(( int Sock, const char *Msg ));
94 static int NewListener PARAMS(( const char *listen_addr, UINT16 Port ));
95
96 static array My_Listeners;
97 static array My_ConnArray;
98 static size_t NumConnections;
99
100 #ifdef TCPWRAP
101 int allow_severity = LOG_INFO;
102 int deny_severity = LOG_ERR;
103 #endif
104
105 static void server_login PARAMS((CONN_ID idx));
106
107 #ifdef SSL_SUPPORT
108 extern struct SSLOptions Conf_SSLOptions;
109 static void cb_connserver_login_ssl PARAMS((int sock, short what));
110 static void cb_clientserver_ssl PARAMS((int sock, short what));
111 #endif
112 static void cb_Read_Resolver_Result PARAMS(( int sock, UNUSED short what));
113 static void cb_Connect_to_Server PARAMS(( int sock, UNUSED short what));
114 static void cb_clientserver PARAMS((int sock, short what));
115
116 static void
117 cb_listen(int sock, short irrelevant)
118 {
119         (void) irrelevant;
120         if (New_Connection( sock ) >= 0)
121                 NumConnections++;
122         LogDebug("Total number of connections now %ld.", NumConnections);
123 }
124
125
126 #ifdef SSL_SUPPORT
127 static void
128 cb_listen_ssl(int sock, short irrelevant)
129 {
130         int fd;
131         (void) irrelevant;
132         fd = New_Connection(sock);
133         if (fd < 0)
134                 return;
135
136         NumConnections++;
137         LogDebug("Total number of connections now %ld.", NumConnections);
138         io_event_setcb(My_Connections[fd].sock, cb_clientserver_ssl);
139 }
140 #endif
141
142
143 static void
144 cb_connserver(int sock, UNUSED short what)
145 {
146         int res, err;
147         socklen_t sock_len;
148         CONN_ID idx = Socket2Index( sock );
149         if (idx <= NONE) {
150                 LogDebug("cb_connserver wants to write on unknown socket?!");
151                 io_close(sock);
152                 return;
153         }
154
155         assert( what & IO_WANTWRITE);
156
157         /* connect() finished, get result. */
158         sock_len = (socklen_t)sizeof(err);
159         res = getsockopt( My_Connections[idx].sock, SOL_SOCKET, SO_ERROR, &err, &sock_len );
160         assert( sock_len == sizeof( err ));
161
162         /* Error while connecting? */
163         if ((res != 0) || (err != 0)) {
164                 if (res != 0)
165                         Log(LOG_CRIT, "getsockopt (connection %d): %s!",
166                             idx, strerror(errno));
167                 else
168                         Log(LOG_CRIT,
169                             "Can't connect socket to \"%s:%d\" (connection %d): %s!",
170                             My_Connections[idx].host,
171                             Conf_Server[Conf_GetServer(idx)].port,
172                             idx, strerror(err));
173
174                 res = Conf_GetServer(idx);
175                 assert(res >= 0);
176
177                 Conn_Close(idx, "Can't connect!", NULL, false);
178
179                 if (res < 0)
180                         return;
181                 if (ng_ipaddr_af(&Conf_Server[res].dst_addr[0])) {
182                         /* more addresses to try... */
183                         New_Server(res, &Conf_Server[res].dst_addr[0]);
184                         /* connection to dst_addr[0] in progress, remove this address... */
185                         Conf_Server[res].dst_addr[0] = Conf_Server[res].dst_addr[1];
186
187                         memset(&Conf_Server[res].dst_addr[1], 0, sizeof(Conf_Server[res].dst_addr[1]));
188                 }
189                 return;
190         }
191
192         res = Conf_GetServer(idx);
193         assert(res >= 0);
194         if (res >= 0) /* connect succeeded, remove all additional addresses */
195                 memset(&Conf_Server[res].dst_addr, 0, sizeof(Conf_Server[res].dst_addr));
196         Conn_OPTION_DEL( &My_Connections[idx], CONN_ISCONNECTING );
197 #ifdef SSL_SUPPORT
198         if ( Conn_OPTION_ISSET( &My_Connections[idx], CONN_SSL_CONNECT )) {
199                 io_event_setcb( sock, cb_connserver_login_ssl );
200                 io_event_add( sock, IO_WANTWRITE|IO_WANTREAD );
201                 return;
202         }
203 #endif
204         server_login(idx);
205 }
206
207
208 static void
209 server_login(CONN_ID idx)
210 {
211         Log( LOG_INFO, "Connection %d with \"%s:%d\" established. Now logging in ...", idx,
212                         My_Connections[idx].host, Conf_Server[Conf_GetServer( idx )].port );
213
214         io_event_setcb( My_Connections[idx].sock, cb_clientserver);
215         io_event_add( My_Connections[idx].sock, IO_WANTREAD|IO_WANTWRITE);
216
217         /* Send PASS and SERVER command to peer */
218         Conn_WriteStr( idx, "PASS %s %s", Conf_Server[Conf_GetServer( idx )].pwd_out, NGIRCd_ProtoID );
219         Conn_WriteStr( idx, "SERVER %s :%s", Conf_ServerName, Conf_ServerInfo );
220 }
221
222
223 #ifdef SSL_SUPPORT
224 static void
225 cb_connserver_login_ssl(int sock, short unused)
226 {
227         CONN_ID idx = Socket2Index(sock);
228
229         assert(idx >= 0);
230         if (idx < 0) {
231                 io_close(sock);
232                 return;
233         }
234         (void) unused;
235         switch (ConnSSL_Connect( &My_Connections[idx])) {
236         case 1: break;
237         case 0: LogDebug("ConnSSL_Connect: not ready");
238                 return;
239         case -1:
240                 Log(LOG_ERR, "SSL connection on socket %d failed!", sock);
241                 Conn_Close(idx, "Can't connect!", NULL, false);
242                 return;
243         }
244
245         Log( LOG_INFO, "SSL connection %d with \"%s:%d\" established.", idx,
246                         My_Connections[idx].host, Conf_Server[Conf_GetServer( idx )].port );
247
248         server_login(idx);
249 }
250 #endif
251
252
253 static void
254 cb_clientserver(int sock, short what)
255 {
256         CONN_ID idx = Socket2Index(sock);
257
258         assert(idx >= 0);
259
260         if (idx < 0) {
261                 io_close(sock);
262                 return;
263         }
264 #ifdef SSL_SUPPORT
265         if (what & IO_WANTREAD || (Conn_OPTION_ISSET(&My_Connections[idx], CONN_SSL_WANT_WRITE)))
266                 Read_Request( idx ); /* if TLS layer needs to write additional data, call Read_Request instead so SSL/TLS can continue */
267 #else
268         if (what & IO_WANTREAD)
269                 Read_Request( idx );
270 #endif
271         if (what & IO_WANTWRITE)
272                 Handle_Write( idx );
273 }
274
275
276 #ifdef SSL_SUPPORT
277 static void
278 cb_clientserver_ssl(int sock, short what)
279 {
280         CONN_ID idx = Socket2Index(sock);
281
282         assert(idx >= 0);
283
284         if (idx < 0) {
285                 io_close(sock);
286                 return;
287         }
288
289         switch (ConnSSL_Accept(&My_Connections[idx])) {
290                 case 1: break;  /* OK */
291                 case 0: return; /* EAGAIN: this callback will be invoked again by the io layer */
292                 default:
293                         Conn_Close( idx, "Socket closed!", "SSL accept error", false );
294                         return;
295         }
296         if (what & IO_WANTREAD)
297                 Read_Request(idx);
298
299         if (what & IO_WANTWRITE)
300                 Handle_Write(idx);
301
302         io_event_setcb(sock, cb_clientserver);  /* SSL handshake completed */
303 }
304 #endif
305
306
307 GLOBAL void
308 Conn_Init( void )
309 {
310         CONN_ID i;
311
312         /* Speicher fuer Verbindungs-Pool anfordern */
313         Pool_Size = CONNECTION_POOL;
314         if ((Conf_MaxConnections > 0) &&
315                 (Pool_Size > Conf_MaxConnections))
316                         Pool_Size = Conf_MaxConnections;
317
318         if (!array_alloc(&My_ConnArray, sizeof(CONNECTION), (size_t)Pool_Size)) {
319                 Log( LOG_EMERG, "Can't allocate memory! [Conn_Init]" );
320                 exit( 1 );
321         }
322
323         /* FIXME: My_Connetions/Pool_Size is needed by other parts of the
324          * code; remove them! */
325         My_Connections = (CONNECTION*) array_start(&My_ConnArray);
326
327         LogDebug("Allocated connection pool for %d items (%ld bytes).",
328                 array_length(&My_ConnArray, sizeof( CONNECTION )), array_bytes(&My_ConnArray));
329
330         assert( array_length(&My_ConnArray, sizeof( CONNECTION )) >= (size_t) Pool_Size);
331         
332         array_free( &My_Listeners );
333
334         /* Connection-Struktur initialisieren */
335         for( i = 0; i < Pool_Size; i++ ) Init_Conn_Struct( i );
336
337         /* Global write counter */
338         WCounter = 0;
339 } /* Conn_Init */
340
341
342 GLOBAL void
343 Conn_Exit( void )
344 {
345         CONN_ID idx;
346
347         Conn_ExitListeners();
348
349         LogDebug("Shutting down all connections ..." );
350         for( idx = 0; idx < Pool_Size; idx++ ) {
351                 if( My_Connections[idx].sock > NONE ) {
352                         Conn_Close( idx, NULL, NGIRCd_SignalRestart ?
353                                 "Server going down (restarting)":"Server going down", true );
354                 }
355         }
356
357         array_free(&My_ConnArray);
358         My_Connections = NULL;
359         Pool_Size = 0;
360         io_library_shutdown();
361 } /* Conn_Exit */
362
363
364 static unsigned int
365 ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short))
366 {
367         unsigned int created = 0;
368         size_t len;
369         int fd;
370         UINT16 *port;
371
372         len = array_length(a, sizeof (UINT16));
373         port = array_start(a);
374         while (len--) {
375                 fd = NewListener(listen_addr, *port);
376                 if (fd < 0) {
377                         port++;
378                         continue;
379                 }
380                 if (!io_event_create( fd, IO_WANTREAD, func )) {
381                         Log( LOG_ERR, "io_event_create(): Could not add listening fd %d (port %u): %s!",
382                                                 fd, (unsigned int) *port, strerror(errno));
383                         close(fd);
384                         port++;
385                         continue;
386                 }
387                 created++;
388                 port++;
389         }
390         return created;
391 }
392
393
394 GLOBAL unsigned int
395 Conn_InitListeners( void )
396 {
397         /* Initialize ports on which the server should accept connections */
398         unsigned int created = 0;
399         char *copy, *listen_addr;
400
401         if (!io_library_init(CONNECTION_POOL)) {
402                 Log(LOG_EMERG, "Cannot initialize IO routines: %s", strerror(errno));
403                 return -1;
404         }
405
406         assert(Conf_ListenAddress);
407
408         /* can't use Conf_ListenAddress directly, see below */
409         copy = strdup(Conf_ListenAddress);
410         if (!copy) {
411                 Log(LOG_CRIT, "Cannot copy %s: %s", Conf_ListenAddress, strerror(errno));
412                 return 0;
413         }
414         listen_addr = strtok(copy, ",");
415
416         while (listen_addr) {
417                 ngt_TrimStr(listen_addr);
418                 if (*listen_addr) {
419                         created += ports_initlisteners(&Conf_ListenPorts, listen_addr, cb_listen);
420 #ifdef SSL_SUPPORT
421                         created += ports_initlisteners(&Conf_SSLOptions.ListenPorts, listen_addr, cb_listen_ssl);
422 #endif
423                 }
424
425                 listen_addr = strtok(NULL, ",");
426         }
427
428         /*
429          * can't free() Conf_ListenAddress here. On /REHASH, if the config file
430          * cannot be re-loaded, we'd end up with a NULL Conf_ListenAddress.
431          * Instead, free() takes place in conf.c, before the config file
432          * is being parsed.
433          */
434         free(copy);
435         return created;
436 } /* Conn_InitListeners */
437
438
439 GLOBAL void
440 Conn_ExitListeners( void )
441 {
442         /* Close down all listening sockets */
443         int *fd;
444         size_t arraylen;
445 #ifdef ZEROCONF
446         Rendezvous_UnregisterListeners( );
447 #endif
448
449         arraylen = array_length(&My_Listeners, sizeof (int));
450         Log(LOG_INFO,
451             "Shutting down all listening sockets (%d total) ...", arraylen);
452         fd = array_start(&My_Listeners);
453         while(arraylen--) {
454                 assert(fd != NULL);
455                 assert(*fd >= 0);
456                 io_close(*fd);
457                 LogDebug("Listening socket %d closed.", *fd );
458                 fd++;
459         }
460         array_free(&My_Listeners);
461 } /* Conn_ExitListeners */
462
463
464 static bool
465 InitSinaddrListenAddr(ng_ipaddr_t *addr, const char *listen_addrstr, UINT16 Port)
466 {
467         bool ret;
468
469         ret = ng_ipaddr_init(addr, listen_addrstr, Port);
470         if (!ret) {
471                 assert(listen_addrstr);
472                 Log(LOG_CRIT, "Can't bind to [%s]:%u: can't convert ip address \"%s\"",
473                                                 listen_addrstr, Port, listen_addrstr);
474         }
475         return ret;
476 }
477
478
479 static void
480 set_v6_only(int af, int sock)
481 {
482 #if defined(IPV6_V6ONLY) && defined(WANT_IPV6)
483         int on = 1;
484
485         if (af != AF_INET6)
486                 return;
487
488         if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, (socklen_t)sizeof(on)))
489                 Log(LOG_ERR, "Could not set IPV6_V6ONLY: %s", strerror(errno));
490 #else
491         (void)af;
492         (void)sock;
493 #endif
494 }
495
496
497 /* return new listening port file descriptor or -1 on failure */
498 static int
499 NewListener(const char *listen_addr, UINT16 Port)
500 {
501         /* Create new listening socket on specified port */
502         ng_ipaddr_t addr;
503         int sock, af;
504 #ifdef ZEROCONF
505         char name[CLIENT_ID_LEN], *info;
506 #endif
507         if (!InitSinaddrListenAddr(&addr, listen_addr, Port))
508                 return -1;
509
510         af = ng_ipaddr_af(&addr);
511         sock = socket(af, SOCK_STREAM, 0);
512         if( sock < 0 ) {
513                 Log(LOG_CRIT, "Can't create socket (af %d) : %s!", af, strerror(errno));
514                 return -1;
515         }
516
517         set_v6_only(af, sock);
518
519         if (!Init_Socket(sock))
520                 return -1;
521
522         if (bind(sock, (struct sockaddr *)&addr, ng_ipaddr_salen(&addr)) != 0) {
523                 Log(LOG_CRIT, "Can't bind socket to address %s:%d - %s",
524                         ng_ipaddr_tostr(&addr), Port, strerror(errno));
525                 close(sock);
526                 return -1;
527         }
528
529         if( listen( sock, 10 ) != 0 ) {
530                 Log( LOG_CRIT, "Can't listen on socket: %s!", strerror( errno ));
531                 close( sock );
532                 return -1;
533         }
534
535         /* keep fd in list so we can close it when ngircd restarts/shuts down */
536         if (!array_catb( &My_Listeners,(char*) &sock, sizeof(int) )) {
537                 Log( LOG_CRIT, "Can't add socket to My_Listeners array: %s!", strerror( errno ));
538                 close( sock );
539                 return -1;
540         }
541
542         Log(LOG_INFO, "Now listening on [%s]:%d (socket %d).", ng_ipaddr_tostr(&addr), Port, sock);
543
544 #ifdef ZEROCONF
545         /* Get best server description text */
546         if( ! Conf_ServerInfo[0] ) info = Conf_ServerName;
547         else
548         {
549                 /* Use server info string */
550                 info = NULL;
551                 if( Conf_ServerInfo[0] == '[' )
552                 {
553                         /* Cut off leading hostname part in "[]" */
554                         info = strchr( Conf_ServerInfo, ']' );
555                         if( info )
556                         {
557                                 info++;
558                                 while( *info == ' ' ) info++;
559                         }
560                 }
561                 if( ! info ) info = Conf_ServerInfo;
562         }
563
564         /* Add port number to description if non-standard */
565         if (Port != 6667)
566                 snprintf(name, sizeof name, "%s (port %u)", info,
567                          (unsigned int)Port);
568         else
569                 strlcpy(name, info, sizeof name);
570
571         /* Register service */
572         Rendezvous_Register( name, MDNS_TYPE, Port );
573 #endif
574         return sock;
575 } /* NewListener */
576
577 #ifdef SSL_SUPPORT
578 /*
579  * SSL/TLS connections require extra treatment:
580  * When either CONN_SSL_WANT_WRITE or CONN_SSL_WANT_READ is set, we
581  * need to take care of that first, before checking read/write buffers.
582  * For instance, while we might have data in our write buffer, the
583  * TLS/SSL protocol might need to read internal data first for TLS/SSL
584  * writes to succeed.
585  *
586  * If this function returns true, such a condition is met and we have
587  * to reverse the condition (check for read even if we've data to write,
588  * do not check for read but writeability even if write-buffer is empty).
589  */
590 static bool
591 SSL_WantRead(const CONNECTION *c)
592 {
593         if (Conn_OPTION_ISSET(c, CONN_SSL_WANT_READ)) {
594                 io_event_add(c->sock, IO_WANTREAD);
595                 return true;
596         }
597         return false;
598 }
599 static bool
600 SSL_WantWrite(const CONNECTION *c)
601 {
602         if (Conn_OPTION_ISSET(c, CONN_SSL_WANT_WRITE)) {
603                 io_event_add(c->sock, IO_WANTWRITE);
604                 return true;
605         }
606         return false;
607 }
608 #else
609 static inline bool
610 SSL_WantRead(UNUSED const CONNECTION *c) { return false; }
611 static inline bool
612 SSL_WantWrite(UNUSED const CONNECTION *c) { return false; }
613 #endif
614
615
616 /**
617  * "Main Loop": Loop until shutdown or restart is signalled.
618  * This function loops until a shutdown or restart of ngIRCd is signalled and
619  * calls io_dispatch() to check for readable and writable sockets every second.
620  * It checks for status changes on pending connections (e. g. when a hostname
621  * has been resolved), checks for "penalties" and timeouts, and handles the
622  * input buffers.
623  */
624 GLOBAL void
625 Conn_Handler(void)
626 {
627         int i;
628         unsigned int wdatalen, bytes_processed;
629         struct timeval tv;
630         time_t t;
631
632         while (!NGIRCd_SignalQuit && !NGIRCd_SignalRestart) {
633                 t = time(NULL);
634
635 #ifdef ZEROCONF
636                 Rendezvous_Handler();
637 #endif
638
639                 /* Should the configuration be reloaded? */
640                 if (NGIRCd_SignalRehash)
641                         NGIRCd_Rehash();
642
643                 /* Check configured servers and established links */
644                 Check_Servers();
645                 Check_Connections();
646
647                 /* Look for non-empty read buffers ... */
648                 for (i = 0; i < Pool_Size; i++) {
649                         if ((My_Connections[i].sock > NONE)
650                             && (array_bytes(&My_Connections[i].rbuf) > 0)
651                             && (My_Connections[i].delaytime <= t)) {
652                                 /* ... and try to handle the received data */
653                                 bytes_processed = Handle_Buffer(i);
654                                 /* if we processed data, and there might be
655                                  * more commands in the input buffer, do not
656                                  * try to read any more data now */
657                                 if (bytes_processed &&
658                                     array_bytes(&My_Connections[i].rbuf) > 2) {
659                                         LogDebug
660                                             ("Throttling connection %d: command limit reached!",
661                                              i);
662                                         Conn_SetPenalty(i, 1);
663                                 }
664                         }
665                 }
666
667                 /* Look for non-empty write buffers ... */
668                 for (i = 0; i < Pool_Size; i++) {
669                         if (My_Connections[i].sock <= NONE)
670                                 continue;
671
672                         wdatalen = (unsigned int)array_bytes(&My_Connections[i].wbuf);
673 #ifdef ZLIB
674                         if (wdatalen > 0 ||
675                             array_bytes(&My_Connections[i].zip.wbuf) > 0)
676 #else
677                         if (wdatalen > 0)
678 #endif
679                         {
680                                 if (SSL_WantRead(&My_Connections[i]))
681                                         continue;
682                                 io_event_add(My_Connections[i].sock,
683                                              IO_WANTWRITE);
684                         }
685                 }
686
687                 /* Check from which sockets we possibly could read ... */
688                 for (i = 0; i < Pool_Size; i++) {
689                         if (My_Connections[i].sock <= NONE)
690                                 continue;
691 #ifdef SSL_SUPPORT
692                         if (SSL_WantWrite(&My_Connections[i]))
693                                 continue; /* TLS/SSL layer needs to write data; deal with this first */
694 #endif
695                         if (Resolve_INPROGRESS(&My_Connections[i].res_stat)) {
696                                 /* Wait for completion of resolver sub-process ... */
697                                 io_event_del(My_Connections[i].sock,
698                                              IO_WANTREAD);
699                                 continue;
700                         }
701
702                         if (Conn_OPTION_ISSET(&My_Connections[i], CONN_ISCONNECTING))
703                                 /* Wait for completion of connect() ... */
704                                 continue;
705
706                         if (My_Connections[i].delaytime > t) {
707                                 /* There is a "penalty time" set: ignore socket! */
708                                 io_event_del(My_Connections[i].sock,
709                                              IO_WANTREAD);
710                                 continue;
711                         }
712                         io_event_add(My_Connections[i].sock, IO_WANTREAD);
713                 }
714
715                 /* Set the timeout for reading from the network to 1 second,
716                  * which is the granularity with witch we handle "penalty
717                  * times" for example.
718                  * Note: tv_sec/usec are undefined(!) after io_dispatch()
719                  * returns, so we have to set it beforce each call to it! */
720                 tv.tv_usec = 0;
721                 tv.tv_sec = 1;
722
723                 /* Wait for activity ... */
724                 i = io_dispatch(&tv);
725                 if (i == -1 && errno != EINTR) {
726                         Log(LOG_EMERG, "Conn_Handler(): io_dispatch(): %s!",
727                             strerror(errno));
728                         Log(LOG_ALERT, "%s exiting due to fatal errors!",
729                             PACKAGE_NAME);
730                         exit(1);
731                 }
732         }
733
734         if (NGIRCd_SignalQuit)
735                 Log(LOG_NOTICE | LOG_snotice, "Server going down NOW!");
736         else if (NGIRCd_SignalRestart)
737                 Log(LOG_NOTICE | LOG_snotice, "Server restarting NOW!");
738 } /* Conn_Handler */
739
740
741 /**
742  * Write a text string into the socket of a connection.
743  * This function automatically appends CR+LF to the string and validates that
744  * the result is a valid IRC message (oversized messages are shortened, for
745  * example). Then it calls the Conn_Write() function to do the actual sending.
746  * @param Idx Index fo the connection.
747  * @param Format Format string, see printf().
748  * @return true on success, false otherwise.
749  */
750 #ifdef PROTOTYPES
751 GLOBAL bool
752 Conn_WriteStr( CONN_ID Idx, char *Format, ... )
753 #else
754 GLOBAL bool 
755 Conn_WriteStr( Idx, Format, va_alist )
756 CONN_ID Idx;
757 char *Format;
758 va_dcl
759 #endif
760 {
761         char buffer[COMMAND_LEN];
762         size_t len;
763         bool ok;
764         va_list ap;
765
766         assert( Idx > NONE );
767         assert( Format != NULL );
768
769 #ifdef PROTOTYPES
770         va_start( ap, Format );
771 #else
772         va_start( ap );
773 #endif
774         if (vsnprintf( buffer, COMMAND_LEN - 2, Format, ap ) >= COMMAND_LEN - 2 ) {
775                 /*
776                  * The string that should be written to the socket is longer
777                  * than the allowed size of COMMAND_LEN bytes (including both
778                  * the CR and LF characters). This can be caused by the
779                  * IRC_WriteXXX() functions when the prefix of this server had
780                  * to be added to an already "quite long" command line which
781                  * has been received from a regular IRC client, for example.
782                  * 
783                  * We are not allowed to send such "oversized" messages to
784                  * other servers and clients, see RFC 2812 2.3 and 2813 3.3
785                  * ("these messages SHALL NOT exceed 512 characters in length,
786                  * counting all characters including the trailing CR-LF").
787                  *
788                  * So we have a big problem here: we should send more bytes
789                  * to the network than we are allowed to and we don't know
790                  * the originator (any more). The "old" behaviour of blaming
791                  * the receiver ("next hop") is a bad idea (it could be just
792                  * an other server only routing the message!), so the only
793                  * option left is to shorten the string and to hope that the
794                  * result is still somewhat useful ...
795                  *                                                   -alex-
796                  */
797
798                 strcpy (buffer + sizeof(buffer) - strlen(CUT_TXTSUFFIX) - 2 - 1,
799                         CUT_TXTSUFFIX);
800         }
801
802 #ifdef SNIFFER
803         if (NGIRCd_Sniffer)
804                 Log(LOG_DEBUG, " -> connection %d: '%s'.", Idx, buffer);
805 #endif
806
807         len = strlcat( buffer, "\r\n", sizeof( buffer ));
808         ok = Conn_Write(Idx, buffer, len);
809         My_Connections[Idx].msg_out++;
810
811         va_end( ap );
812         return ok;
813 } /* Conn_WriteStr */
814
815
816 /**
817  * Append Data to the outbound write buffer of a connection.
818  * @param Idx Index of the connection.
819  * @param Data pointer to the data.
820  * @param Len length of Data.
821  * @return true on success, false otherwise.
822  */
823 static bool
824 Conn_Write( CONN_ID Idx, char *Data, size_t Len )
825 {
826         CLIENT *c;
827         size_t writebuf_limit = WRITEBUFFER_LEN;
828         assert( Idx > NONE );
829         assert( Data != NULL );
830         assert( Len > 0 );
831
832         c = Conn_GetClient(Idx);
833         assert( c != NULL);
834
835         /* Servers do get special write buffer limits, so they can generate
836          * all the messages that are required while peering. */
837         if (Client_Type(c) == CLIENT_SERVER)
838                 writebuf_limit = WRITEBUFFER_SLINK_LEN;
839
840         /* Is the socket still open? A previous call to Conn_Write()
841          * may have closed the connection due to a fatal error.
842          * In this case it is sufficient to return an error, as well. */
843         if( My_Connections[Idx].sock <= NONE ) {
844                 LogDebug("Skipped write on closed socket (connection %d).", Idx);
845                 return false;
846         }
847
848 #ifdef ZLIB
849         if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ZIP )) {
850                 /* Compressed link:
851                  * Zip_Buffer() does all the dirty work for us: it flushes
852                  * the (pre-)compression buffers if required and handles
853                  * all error conditions. */
854                 if (!Zip_Buffer(Idx, Data, Len))
855                         return false;
856         }
857         else
858 #endif
859         {
860                 /* Uncompressed link:
861                  * Check if outbound buffer has enough space for the data. */
862                 if (array_bytes(&My_Connections[Idx].wbuf) + Len >=
863                     writebuf_limit) {
864                         /* Buffer is full, flush it. Handle_Write deals with
865                          * low-level errors, if any. */
866                         if (!Handle_Write(Idx))
867                                 return false;
868                 }
869
870                 /* When the write buffer is still too big after flushing it,
871                  * the connection will be killed. */
872                 if (array_bytes(&My_Connections[Idx].wbuf) + Len >=
873                     writebuf_limit) {
874                         Log(LOG_NOTICE,
875                             "Write buffer overflow (connection %d, size %lu byte)!",
876                             Idx,
877                             (unsigned long)array_bytes(&My_Connections[Idx].wbuf));
878                         Conn_Close(Idx, "Write buffer overflow!", NULL, false);
879                         return false;
880                 }
881
882                 /* Copy data to write buffer */
883                 if (!array_catb(&My_Connections[Idx].wbuf, Data, Len))
884                         return false;
885
886                 My_Connections[Idx].bytes_out += Len;
887         }
888
889         /* Adjust global write counter */
890         WCounter += Len;
891
892         return true;
893 } /* Conn_Write */
894
895
896 GLOBAL void
897 Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClient )
898 {
899         /* Close connection. Open pipes of asyncronous resolver
900          * sub-processes are closed down. */
901
902         CLIENT *c;
903         double in_k, out_k;
904         UINT16 port;
905 #ifdef ZLIB
906         double in_z_k, out_z_k;
907         int in_p, out_p;
908 #endif
909
910         assert( Idx > NONE );
911
912         /* Is this link already shutting down? */
913         if( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ISCLOSING )) {
914                 /* Conn_Close() has been called recursively for this link;
915                  * probabe reason: Handle_Write() failed  -- see below. */
916                 LogDebug("Recursive request to close connection: %d", Idx );
917                 return;
918         }
919
920         assert( My_Connections[Idx].sock > NONE );
921
922         /* Mark link as "closing" */
923         Conn_OPTION_ADD( &My_Connections[Idx], CONN_ISCLOSING );
924
925         port = ng_ipaddr_getport(&My_Connections[Idx].addr);
926         Log(LOG_INFO, "Shutting down connection %d (%s) with %s:%d ...", Idx,
927             LogMsg ? LogMsg : FwdMsg, My_Connections[Idx].host, port);
928
929         /* Search client, if any */
930         c = Conn_GetClient( Idx );
931
932         /* Should the client be informed? */
933         if (InformClient) {
934 #ifndef STRICT_RFC
935                 /* Send statistics to client if registered as user: */
936                 if ((c != NULL) && (Client_Type(c) == CLIENT_USER)) {
937                         Conn_WriteStr( Idx,
938                          ":%s NOTICE %s :%sConnection statistics: client %.1f kb, server %.1f kb.",
939                          Client_ID(Client_ThisServer()), Client_ID(c),
940                          NOTICE_TXTPREFIX,
941                          (double)My_Connections[Idx].bytes_in / 1024,
942                          (double)My_Connections[Idx].bytes_out / 1024);
943                 }
944 #endif
945                 /* Send ERROR to client (see RFC 2812, section 3.1.7) */
946                 if (FwdMsg)
947                         Conn_WriteStr(Idx, "ERROR :%s", FwdMsg);
948                 else
949                         Conn_WriteStr(Idx, "ERROR :Closing connection.");
950         }
951
952         /* Try to write out the write buffer. Note: Handle_Write() eventually
953          * removes the CLIENT structure associated with this connection if an
954          * error occurs! So we have to re-check if there is still an valid
955          * CLIENT structure after calling Handle_Write() ...*/
956         (void)Handle_Write( Idx );
957
958         /* Search client, if any (re-check!) */
959         c = Conn_GetClient( Idx );
960 #ifdef SSL_SUPPORT
961         if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_SSL )) {
962                 Log(LOG_INFO, "SSL connection %d shutting down ...", Idx);
963                 ConnSSL_Free(&My_Connections[Idx]);
964         }
965 #endif
966         /* Shut down socket */
967         if (! io_close(My_Connections[Idx].sock)) {
968                 /* Oops, we can't close the socket!? This is ... ugly! */
969                 Log(LOG_CRIT,
970                     "Error closing connection %d (socket %d) with %s:%d - %s! (ignored)",
971                     Idx, My_Connections[Idx].sock, My_Connections[Idx].host,
972                     port, strerror(errno));
973         }
974
975         /* Mark socket as invalid: */
976         My_Connections[Idx].sock = NONE;
977
978         /* If there is still a client, unregister it now */
979         if (c)
980                 Client_Destroy(c, LogMsg, FwdMsg, true);
981
982         /* Calculate statistics and log information */
983         in_k = (double)My_Connections[Idx].bytes_in / 1024;
984         out_k = (double)My_Connections[Idx].bytes_out / 1024;
985 #ifdef ZLIB
986         if (Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ZIP)) {
987                 in_z_k = (double)My_Connections[Idx].zip.bytes_in / 1024;
988                 out_z_k = (double)My_Connections[Idx].zip.bytes_out / 1024;
989                 /* Make sure that no division by zero can occur during
990                  * the calculation of in_p and out_p: in_z_k and out_z_k
991                  * are non-zero, that's guaranteed by the protocol until
992                  * compression can be enabled. */
993                 if (! in_z_k)
994                         in_z_k = in_k;
995                 if (! out_z_k)
996                         out_z_k = out_k;
997                 in_p = (int)(( in_k * 100 ) / in_z_k );
998                 out_p = (int)(( out_k * 100 ) / out_z_k );
999                 Log(LOG_INFO,
1000                     "Connection %d with %s:%d closed (in: %.1fk/%.1fk/%d%%, out: %.1fk/%.1fk/%d%%).",
1001                     Idx, My_Connections[Idx].host, port,
1002                     in_k, in_z_k, in_p, out_k, out_z_k, out_p);
1003         }
1004         else
1005 #endif
1006         {
1007                 Log(LOG_INFO,
1008                     "Connection %d with %s:%d closed (in: %.1fk, out: %.1fk).",
1009                     Idx, My_Connections[Idx].host, port,
1010                     in_k, out_k);
1011         }
1012
1013         /* cancel running resolver */
1014         if (Resolve_INPROGRESS(&My_Connections[Idx].res_stat))
1015                 Resolve_Shutdown(&My_Connections[Idx].res_stat);
1016
1017         /* Servers: Modify time of next connect attempt? */
1018         Conf_UnsetServer( Idx );
1019
1020 #ifdef ZLIB
1021         /* Clean up zlib, if link was compressed */
1022         if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ZIP )) {
1023                 inflateEnd( &My_Connections[Idx].zip.in );
1024                 deflateEnd( &My_Connections[Idx].zip.out );
1025                 array_free(&My_Connections[Idx].zip.rbuf);
1026                 array_free(&My_Connections[Idx].zip.wbuf);
1027         }
1028 #endif
1029
1030         array_free(&My_Connections[Idx].rbuf);
1031         array_free(&My_Connections[Idx].wbuf);
1032
1033         /* Clean up connection structure (=free it) */
1034         Init_Conn_Struct( Idx );
1035
1036         assert(NumConnections > 0);
1037         if (NumConnections)
1038                 NumConnections--;
1039         LogDebug("Shutdown of connection %d completed, %ld connection%s left.",
1040                  Idx, NumConnections, NumConnections != 1 ? "s" : "");
1041 } /* Conn_Close */
1042
1043
1044 GLOBAL void
1045 Conn_SyncServerStruct( void )
1046 {
1047         /* Synchronize server structures (connection IDs):
1048          * connections <-> configuration */
1049
1050         CLIENT *client;
1051         CONN_ID i;
1052         int c;
1053
1054         for( i = 0; i < Pool_Size; i++ ) {
1055                 /* Established connection? */
1056                 if (My_Connections[i].sock < 0)
1057                         continue;
1058
1059                 /* Server connection? */
1060                 client = Conn_GetClient( i );
1061                 if(( ! client ) || ( Client_Type( client ) != CLIENT_SERVER )) continue;
1062
1063                 for( c = 0; c < MAX_SERVERS; c++ )
1064                 {
1065                         /* Configured server? */
1066                         if( ! Conf_Server[c].host[0] ) continue;
1067
1068                         /* Duplicate? */
1069                         if( strcmp( Conf_Server[c].name, Client_ID( client )) == 0 )
1070                                 Conf_Server[c].conn_id = i;
1071                 }
1072         }
1073 } /* SyncServerStruct */
1074
1075
1076 /**
1077  * Send out data of write buffer; connect new sockets.
1078  */
1079 static bool
1080 Handle_Write( CONN_ID Idx )
1081 {
1082         ssize_t len;
1083         size_t wdatalen;
1084
1085         assert( Idx > NONE );
1086         if ( My_Connections[Idx].sock < 0 ) {
1087                 LogDebug("Handle_Write() on closed socket, connection %d", Idx);
1088                 return false;
1089         }
1090         assert( My_Connections[Idx].sock > NONE );
1091
1092         wdatalen = array_bytes(&My_Connections[Idx].wbuf );
1093
1094 #ifdef ZLIB
1095         if (wdatalen == 0) {
1096                 /* Write buffer is empty, so we try to flush the compression
1097                  * buffer and get some data to work with from there :-) */
1098                 if (!Zip_Flush(Idx))
1099                         return false;
1100
1101                 /* Now the write buffer most probably has changed: */
1102                 wdatalen = array_bytes(&My_Connections[Idx].wbuf);
1103         }
1104 #endif
1105
1106         if (wdatalen == 0) {
1107                 /* Still no data, fine. */
1108                 io_event_del(My_Connections[Idx].sock, IO_WANTWRITE );
1109                 return true;
1110         }
1111
1112         LogDebug
1113             ("Handle_Write() called for connection %d, %ld bytes pending ...",
1114              Idx, wdatalen);
1115
1116 #ifdef SSL_SUPPORT
1117         if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_SSL )) {
1118                 len = ConnSSL_Write(&My_Connections[Idx], array_start(&My_Connections[Idx].wbuf), wdatalen);
1119         } else
1120 #endif
1121         {
1122                 len = write(My_Connections[Idx].sock,
1123                             array_start(&My_Connections[Idx].wbuf), wdatalen );
1124         }
1125         if( len < 0 ) {
1126                 if (errno == EAGAIN || errno == EINTR)
1127                         return true;
1128
1129                 Log(LOG_ERR, "Write error on connection %d (socket %d): %s!",
1130                     Idx, My_Connections[Idx].sock, strerror(errno));
1131                 Conn_Close(Idx, "Write error!", NULL, false);
1132                 return false;
1133         }
1134
1135         /* move any data not yet written to beginning */
1136         array_moveleft(&My_Connections[Idx].wbuf, 1, (size_t)len);
1137
1138         return true;
1139 } /* Handle_Write */
1140
1141
1142 static int
1143 Count_Connections(ng_ipaddr_t *a)
1144 {
1145         int i, cnt;
1146
1147         cnt = 0;
1148         for (i = 0; i < Pool_Size; i++) {
1149                 if (My_Connections[i].sock <= NONE)
1150                         continue;
1151                 if (ng_ipaddr_ipequal(&My_Connections[i].addr, a))
1152                         cnt++;
1153         }
1154         return cnt;
1155 } /* Count_Connections */
1156
1157
1158 static int
1159 New_Connection( int Sock )
1160 {
1161         /* Neue Client-Verbindung von Listen-Socket annehmen und
1162          * CLIENT-Struktur anlegen. */
1163
1164 #ifdef TCPWRAP
1165         struct request_info req;
1166 #endif
1167         ng_ipaddr_t new_addr;
1168         char ip_str[NG_INET_ADDRSTRLEN];
1169         int new_sock, new_sock_len, identsock;
1170         CLIENT *c;
1171         long cnt;
1172
1173         assert( Sock > NONE );
1174         /* Connection auf Listen-Socket annehmen */
1175         new_sock_len = (int)sizeof(new_addr);
1176
1177         new_sock = accept(Sock, (struct sockaddr *)&new_addr,
1178                           (socklen_t *)&new_sock_len);
1179         if (new_sock < 0) {
1180                 Log(LOG_CRIT, "Can't accept connection: %s!", strerror(errno));
1181                 return -1;
1182         }
1183
1184         if (!ng_ipaddr_tostr_r(&new_addr, ip_str)) {
1185                 Log(LOG_CRIT, "fd %d: Can't convert IP address!", new_sock);
1186                 Simple_Message(new_sock, "ERROR :Internal Server Error");
1187                 close(new_sock);
1188                 return -1;
1189         }
1190
1191 #ifdef TCPWRAP
1192         /* Validate socket using TCP Wrappers */
1193         request_init( &req, RQ_DAEMON, PACKAGE_NAME, RQ_FILE, new_sock, RQ_CLIENT_SIN, &new_addr, NULL );
1194         fromhost(&req);
1195         if (!hosts_access(&req)) {
1196                 Log (deny_severity, "Refused connection from %s (by TCP Wrappers)!", ip_str);
1197                 Simple_Message( new_sock, "ERROR :Connection refused" );
1198                 close( new_sock );
1199                 return -1;
1200         }
1201 #endif
1202
1203         /* Socket initialisieren */
1204         if (!Init_Socket( new_sock ))
1205                 return -1;
1206
1207         /* Check IP-based connection limit */
1208         cnt = Count_Connections(&new_addr);
1209         if ((Conf_MaxConnectionsIP > 0) && (cnt >= Conf_MaxConnectionsIP)) {
1210                 /* Access denied, too many connections from this IP address! */
1211                 Log( LOG_ERR, "Refused connection from %s: too may connections (%ld) from this IP address!", ip_str, cnt);
1212                 Simple_Message( new_sock, "ERROR :Connection refused, too many connections from your IP address!" );
1213                 close( new_sock );
1214                 return -1;
1215         }
1216
1217         if ((Conf_MaxConnections > 0) &&
1218                 (NumConnections >= (size_t) Conf_MaxConnections))
1219         {
1220                 Log( LOG_ALERT, "Can't accept connection: limit (%d) reached!", Conf_MaxConnections);
1221                 Simple_Message( new_sock, "ERROR :Connection limit reached" );
1222                 close( new_sock );
1223                 return -1;
1224         }
1225
1226         if( new_sock >= Pool_Size ) {
1227                 if (!array_alloc(&My_ConnArray, sizeof(CONNECTION),
1228                                  (size_t)new_sock)) {
1229                         Log( LOG_EMERG, "Can't allocate memory! [New_Connection]" );
1230                         Simple_Message( new_sock, "ERROR: Internal error" );
1231                         close( new_sock );
1232                         return -1;
1233                 }
1234                 LogDebug("Bumped connection pool to %ld items (internal: %ld items, %ld bytes)",
1235                         new_sock, array_length(&My_ConnArray, sizeof(CONNECTION)), array_bytes(&My_ConnArray));
1236
1237                 /* Adjust pointer to new block */
1238                 My_Connections = array_start(&My_ConnArray);
1239                 while (Pool_Size <= new_sock)
1240                         Init_Conn_Struct(Pool_Size++);
1241         }
1242
1243         /* register callback */
1244         if (!io_event_create( new_sock, IO_WANTREAD, cb_clientserver)) {
1245                 Log(LOG_ALERT, "Can't accept connection: io_event_create failed!");
1246                 Simple_Message(new_sock, "ERROR :Internal error");
1247                 close(new_sock);
1248                 return -1;
1249         }
1250
1251         c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWN, false );
1252         if( ! c ) {
1253                 Log(LOG_ALERT, "Can't accept connection: can't create client structure!");
1254                 Simple_Message(new_sock, "ERROR :Internal error");
1255                 io_close(new_sock);
1256                 return -1;
1257         }
1258
1259         Init_Conn_Struct( new_sock );
1260         My_Connections[new_sock].sock = new_sock;
1261         My_Connections[new_sock].addr = new_addr;
1262         My_Connections[new_sock].client = c;
1263
1264         /* Set initial hostname to IP address. This becomes overwritten when
1265          * the DNS lookup is enabled and succeeds, but is used otherwise. */
1266         if (ng_ipaddr_af(&new_addr) != AF_INET)
1267                 snprintf(My_Connections[new_sock].host,
1268                          sizeof(My_Connections[new_sock].host), "[%s]", ip_str);
1269         else
1270                 strlcpy(My_Connections[new_sock].host, ip_str,
1271                         sizeof(My_Connections[new_sock].host));
1272
1273         Client_SetHostname(c, My_Connections[new_sock].host);
1274
1275         Log(LOG_INFO, "Accepted connection %d from %s:%d on socket %d.",
1276             new_sock, My_Connections[new_sock].host,
1277             ng_ipaddr_getport(&new_addr), Sock);
1278
1279         identsock = new_sock;
1280 #ifdef IDENTAUTH
1281         if (Conf_NoIdent)
1282                 identsock = -1;
1283 #endif
1284         if (!Conf_NoDNS)
1285                 Resolve_Addr(&My_Connections[new_sock].res_stat, &new_addr,
1286                              identsock, cb_Read_Resolver_Result);
1287         Conn_SetPenalty(new_sock, 4);
1288         return new_sock;
1289 } /* New_Connection */
1290
1291
1292 static CONN_ID
1293 Socket2Index( int Sock )
1294 {
1295         assert( Sock >= 0 );
1296
1297         if( Sock >= Pool_Size || My_Connections[Sock].sock != Sock ) {
1298                 /* the Connection was already closed again, likely due to
1299                  * an error. */
1300                 LogDebug("Socket2Index: can't get connection for socket %d!", Sock);
1301                 return NONE;
1302         }
1303         return Sock;
1304 } /* Socket2Index */
1305
1306
1307 /**
1308  * Read data from the network to the read buffer. If an error occures,
1309  * the socket of this connection will be shut down.
1310  */
1311 static void
1312 Read_Request( CONN_ID Idx )
1313 {
1314         ssize_t len;
1315         static const unsigned int maxbps = COMMAND_LEN / 2;
1316         char readbuf[READBUFFER_LEN];
1317         time_t t;
1318         CLIENT *c;
1319         assert( Idx > NONE );
1320         assert( My_Connections[Idx].sock > NONE );
1321
1322 #ifdef ZLIB
1323         if ((array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN) ||
1324                 (array_bytes(&My_Connections[Idx].zip.rbuf) >= READBUFFER_LEN))
1325 #else
1326         if (array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN)
1327 #endif
1328         {
1329                 /* Read buffer is full */
1330                 Log(LOG_ERR,
1331                     "Receive buffer overflow (connection %d): %d bytes!",
1332                     Idx, array_bytes(&My_Connections[Idx].rbuf));
1333                 Conn_Close( Idx, "Receive buffer overflow!", NULL, false );
1334                 return;
1335         }
1336
1337 #ifdef SSL_SUPPORT
1338         if (Conn_OPTION_ISSET(&My_Connections[Idx], CONN_SSL))
1339                 len = ConnSSL_Read( &My_Connections[Idx], readbuf, sizeof(readbuf));
1340         else
1341 #endif
1342         len = read(My_Connections[Idx].sock, readbuf, sizeof(readbuf));
1343         if (len == 0) {
1344                 Log(LOG_INFO, "%s:%u (%s) is closing the connection ...",
1345                                 My_Connections[Idx].host,
1346                                 (unsigned int) ng_ipaddr_getport(&My_Connections[Idx].addr),
1347                                 ng_ipaddr_tostr(&My_Connections[Idx].addr));
1348                 Conn_Close(Idx,
1349                            "Socket closed!", "Client closed connection",
1350                            false);
1351                 return;
1352         }
1353
1354         if (len < 0) {
1355                 if( errno == EAGAIN ) return;
1356                 Log(LOG_ERR, "Read error on connection %d (socket %d): %s!",
1357                     Idx, My_Connections[Idx].sock, strerror(errno));
1358                 Conn_Close(Idx, "Read error!", "Client closed connection",
1359                            false);
1360                 return;
1361         }
1362 #ifdef ZLIB
1363         if (Conn_OPTION_ISSET(&My_Connections[Idx], CONN_ZIP)) {
1364                 if (!array_catb(&My_Connections[Idx].zip.rbuf, readbuf,
1365                                 (size_t) len)) {
1366                         Log(LOG_ERR,
1367                             "Could not append recieved data to zip input buffer (connn %d): %d bytes!",
1368                             Idx, len);
1369                         Conn_Close(Idx, "Receive buffer overflow!", NULL,
1370                                    false);
1371                         return;
1372                 }
1373         } else
1374 #endif
1375         {
1376                 if (!array_catb( &My_Connections[Idx].rbuf, readbuf, len)) {
1377                         Log( LOG_ERR, "Could not append recieved data to input buffer (connn %d): %d bytes!", Idx, len );
1378                         Conn_Close( Idx, "Receive buffer overflow!", NULL, false );
1379                 }
1380         }
1381
1382         /* Update connection statistics */
1383         My_Connections[Idx].bytes_in += len;
1384
1385         /* Update timestamp of last data received if this connection is
1386          * registered as a user, server or service connection. Don't update
1387          * otherwise, so users have at least Conf_PongTimeout seconds time to
1388          * register with the IRC server -- see Check_Connections().
1389          * Set "lastping", too, so we can handle time shifts backwards ... */
1390         c = Conn_GetClient(Idx);
1391         if (c && (Client_Type(c) == CLIENT_USER
1392                   || Client_Type(c) == CLIENT_SERVER
1393                   || Client_Type(c) == CLIENT_SERVICE)) {
1394                 t = time(NULL);
1395                 if (My_Connections[Idx].lastdata != t)
1396                         My_Connections[Idx].bps = 0;
1397
1398                 My_Connections[Idx].lastdata = t;
1399                 My_Connections[Idx].lastping = My_Connections[Idx].lastdata;
1400         }
1401
1402         /* Look at the data in the (read-) buffer of this connection */
1403         My_Connections[Idx].bps += Handle_Buffer(Idx);
1404         if (Client_Type(c) != CLIENT_SERVER
1405             && My_Connections[Idx].bps >= maxbps) {
1406                 LogDebug("Throttling connection %d: BPS exceeded! (%u >= %u)",
1407                          Idx, My_Connections[Idx].bps, maxbps);
1408                 Conn_SetPenalty(Idx, 1);
1409         }
1410 } /* Read_Request */
1411
1412
1413 /**
1414  * Handle all data in the connection read-buffer.
1415  * Data is processed until no complete command is left in the read buffer,
1416  * or MAX_COMMANDS[_SERVER] commands were processed.
1417  * When a fatal error occurs, the connection is shut down.
1418  * @param Idx Index of the connection.
1419  * @return number of bytes processed.
1420  */
1421 static unsigned int
1422 Handle_Buffer(CONN_ID Idx)
1423 {
1424 #ifndef STRICT_RFC
1425         char *ptr1, *ptr2, *first_eol;
1426 #endif
1427         char *ptr;
1428         size_t len, delta;
1429         time_t starttime;
1430 #ifdef ZLIB
1431         bool old_z;
1432 #endif
1433         unsigned int i, maxcmd = MAX_COMMANDS, len_processed = 0;
1434         CLIENT *c;
1435
1436         c = Conn_GetClient(Idx);
1437         assert( c != NULL);
1438
1439         /* Servers do get special command limits, so they can process
1440          * all the messages that are required while peering. */
1441         if (Client_Type(c) == CLIENT_SERVER)
1442                 maxcmd = MAX_COMMANDS_SERVER;
1443
1444         starttime = time(NULL);
1445         for (i=0; i < maxcmd; i++) {
1446                 /* Check penalty */
1447                 if (My_Connections[Idx].delaytime > starttime)
1448                         return 0;
1449 #ifdef ZLIB
1450                 /* Unpack compressed data, if compression is in use */
1451                 if (Conn_OPTION_ISSET(&My_Connections[Idx], CONN_ZIP)) {
1452                         /* When unzipping fails, Unzip_Buffer() shuts
1453                          * down the connection itself */
1454                         if (!Unzip_Buffer(Idx))
1455                                 return 0;
1456                 }
1457 #endif
1458
1459                 if (0 == array_bytes(&My_Connections[Idx].rbuf))
1460                         break;
1461
1462                 /* Make sure that the buffer is NULL terminated */
1463                 if (!array_cat0_temporary(&My_Connections[Idx].rbuf)) {
1464                         Conn_Close(Idx, NULL,
1465                                    "Can't allocate memory [Handle_Buffer]",
1466                                    true);
1467                         return 0;
1468                 }
1469
1470                 /* RFC 2812, section "2.3 Messages", 5th paragraph:
1471                  * "IRC messages are always lines of characters terminated
1472                  * with a CR-LF (Carriage Return - Line Feed) pair [...]". */
1473                 delta = 2;
1474                 ptr = strstr(array_start(&My_Connections[Idx].rbuf), "\r\n");
1475
1476 #ifndef STRICT_RFC
1477                 /* Check for non-RFC-compliant request (only CR or LF)?
1478                  * Unfortunately, there are quite a few clients out there
1479                  * that do this -- e. g. mIRC, BitchX, and Trillian :-( */
1480                 ptr1 = strchr(array_start(&My_Connections[Idx].rbuf), '\r');
1481                 ptr2 = strchr(array_start(&My_Connections[Idx].rbuf), '\n');
1482                 if (ptr) {
1483                         /* Check if there is a single CR or LF _before_ the
1484                          * corerct CR+LF line terminator:  */
1485                         first_eol = ptr1 < ptr2 ? ptr1 : ptr2;
1486                         if (first_eol < ptr) {
1487                                 /* Single CR or LF before CR+LF found */
1488                                 ptr = first_eol;
1489                                 delta = 1;
1490                         }
1491                 } else if (ptr1 || ptr2) {
1492                         /* No CR+LF terminated command found, but single
1493                          * CR or LF found ... */
1494                         if (ptr1 && ptr2)
1495                                 ptr = ptr1 < ptr2 ? ptr1 : ptr2;
1496                         else
1497                                 ptr = ptr1 ? ptr1 : ptr2;
1498                         delta = 1;
1499                 }
1500 #endif
1501
1502                 if (!ptr)
1503                         break;
1504
1505                 /* Complete (=line terminated) request found, handle it! */
1506                 *ptr = '\0';
1507
1508                 len = ptr - (char *)array_start(&My_Connections[Idx].rbuf) + delta;
1509
1510                 if (len > (COMMAND_LEN - 1)) {
1511                         /* Request must not exceed 512 chars (incl. CR+LF!),
1512                          * see RFC 2812. Disconnect Client if this happens. */
1513                         Log(LOG_ERR,
1514                             "Request too long (connection %d): %d bytes (max. %d expected)!",
1515                             Idx, array_bytes(&My_Connections[Idx].rbuf),
1516                             COMMAND_LEN - 1);
1517                         Conn_Close(Idx, NULL, "Request too long", true);
1518                         return 0;
1519                 }
1520
1521                 len_processed += (unsigned int)len;
1522                 if (len <= delta) {
1523                         /* Request is empty (only '\r\n', '\r' or '\n');
1524                          * delta is 2 ('\r\n') or 1 ('\r' or '\n'), see above */
1525                         array_moveleft(&My_Connections[Idx].rbuf, 1, len);
1526                         continue;
1527                 }
1528 #ifdef ZLIB
1529                 /* remember if stream is already compressed */
1530                 old_z = My_Connections[Idx].options & CONN_ZIP;
1531 #endif
1532
1533                 My_Connections[Idx].msg_in++;
1534                 if (!Parse_Request
1535                     (Idx, (char *)array_start(&My_Connections[Idx].rbuf)))
1536                         return 0; /* error -> connection has been closed */
1537
1538                 array_moveleft(&My_Connections[Idx].rbuf, 1, len);
1539                 LogDebug("Connection %d: %d bytes left in read buffer.",
1540                          Idx, array_bytes(&My_Connections[Idx].rbuf));
1541 #ifdef ZLIB
1542                 if ((!old_z) && (My_Connections[Idx].options & CONN_ZIP) &&
1543                     (array_bytes(&My_Connections[Idx].rbuf) > 0)) {
1544                         /* The last command activated socket compression.
1545                          * Data that was read after that needs to be copied
1546                          * to the unzip buffer for decompression: */
1547                         if (!array_copy
1548                             (&My_Connections[Idx].zip.rbuf,
1549                              &My_Connections[Idx].rbuf)) {
1550                                 Conn_Close(Idx, NULL,
1551                                            "Can't allocate memory [Handle_Buffer]",
1552                                            true);
1553                                 return 0;
1554                         }
1555
1556                         array_trunc(&My_Connections[Idx].rbuf);
1557                         LogDebug
1558                             ("Moved already received data (%u bytes) to uncompression buffer.",
1559                              array_bytes(&My_Connections[Idx].zip.rbuf));
1560                 }
1561 #endif
1562         }
1563         return len_processed;
1564 } /* Handle_Buffer */
1565
1566
1567 static void
1568 Check_Connections(void)
1569 {
1570         /* check if connections are alive. if not, play PING-PONG first.
1571          * if this doesn't help either, disconnect client. */
1572         CLIENT *c;
1573         CONN_ID i;
1574         char msg[64];
1575
1576         for (i = 0; i < Pool_Size; i++) {
1577                 if (My_Connections[i].sock < 0)
1578                         continue;
1579
1580                 c = Conn_GetClient(i);
1581                 if (c && ((Client_Type(c) == CLIENT_USER)
1582                           || (Client_Type(c) == CLIENT_SERVER)
1583                           || (Client_Type(c) == CLIENT_SERVICE))) {
1584                         /* connected User, Server or Service */
1585                         if (My_Connections[i].lastping >
1586                             My_Connections[i].lastdata) {
1587                                 /* We already sent a ping */
1588                                 if (My_Connections[i].lastping <
1589                                     time(NULL) - Conf_PongTimeout) {
1590                                         /* Timeout */
1591                                         LogDebug
1592                                             ("Connection %d: Ping timeout: %d seconds.",
1593                                              i, Conf_PongTimeout);
1594                                         snprintf(msg, sizeof(msg), "Ping timeout: %d seconds", Conf_PongTimeout);
1595                                         Conn_Close(i, NULL, msg, true);
1596                                 }
1597                         } else if (My_Connections[i].lastdata <
1598                                    time(NULL) - Conf_PingTimeout) {
1599                                 /* We need to send a PING ... */
1600                                 LogDebug("Connection %d: sending PING ...", i);
1601                                 My_Connections[i].lastping = time(NULL);
1602                                 Conn_WriteStr(i, "PING :%s",
1603                                               Client_ID(Client_ThisServer()));
1604                         }
1605                 } else {
1606                         /* The connection is not fully established yet, so
1607                          * we don't do the PING-PONG game here but instead
1608                          * disconnect the client after "a short time" if it's
1609                          * still not registered. */
1610
1611                         if (My_Connections[i].lastdata <
1612                             time(NULL) - Conf_PongTimeout) {
1613                                 LogDebug
1614                                     ("Unregistered connection %d timed out ...",
1615                                      i);
1616                                 Conn_Close(i, NULL, "Timeout", false);
1617                         }
1618                 }
1619         }
1620 } /* Check_Connections */
1621
1622
1623 static void
1624 Check_Servers( void )
1625 {
1626         /* Check if we can establish further server links */
1627
1628         int i, n;
1629         time_t time_now;
1630
1631         /* Check all configured servers */
1632         for( i = 0; i < MAX_SERVERS; i++ ) {
1633                 /* Valid outgoing server which isn't already connected or disabled? */
1634                 if(( ! Conf_Server[i].host[0] ) || ( ! Conf_Server[i].port > 0 ) ||
1635                         ( Conf_Server[i].conn_id > NONE ) || ( Conf_Server[i].flags & CONF_SFLAG_DISABLED ))
1636                                 continue;
1637
1638                 /* Is there already a connection in this group? */
1639                 if( Conf_Server[i].group > NONE ) {
1640                         for (n = 0; n < MAX_SERVERS; n++) {
1641                                 if (n == i) continue;
1642                                 if ((Conf_Server[n].conn_id != NONE) &&
1643                                         (Conf_Server[n].group == Conf_Server[i].group))
1644                                                 break;
1645                         }
1646                         if (n < MAX_SERVERS) continue;
1647                 }
1648
1649                 /* Check last connect attempt? */
1650                 time_now = time(NULL);
1651                 if( Conf_Server[i].lasttry > (time_now - Conf_ConnectRetry))
1652                         continue;
1653
1654                 /* Okay, try to connect now */
1655                 Conf_Server[i].lasttry = time_now;
1656                 Conf_Server[i].conn_id = SERVER_WAIT;
1657                 assert(Resolve_Getfd(&Conf_Server[i].res_stat) < 0);
1658                 Resolve_Name(&Conf_Server[i].res_stat, Conf_Server[i].host, cb_Connect_to_Server);
1659         }
1660 } /* Check_Servers */
1661
1662
1663 static void
1664 New_Server( int Server , ng_ipaddr_t *dest)
1665 {
1666         /* Establish new server link */
1667         char ip_str[NG_INET_ADDRSTRLEN];
1668         int af_dest, res, new_sock;
1669         CLIENT *c;
1670
1671         assert( Server > NONE );
1672
1673         if (!ng_ipaddr_tostr_r(dest, ip_str)) {
1674                 Log(LOG_WARNING, "New_Server: Could not convert IP to string");
1675                 return;
1676         }
1677
1678         Log( LOG_INFO, "Establishing connection to \"%s\", %s, port %d ... ",
1679                         Conf_Server[Server].host, ip_str, Conf_Server[Server].port );
1680
1681         af_dest = ng_ipaddr_af(dest);
1682         new_sock = socket(af_dest, SOCK_STREAM, 0);
1683         if (new_sock < 0) {
1684                 Log( LOG_CRIT, "Can't create socket (af %d) : %s!", af_dest, strerror( errno ));
1685                 return;
1686         }
1687
1688         if (!Init_Socket(new_sock))
1689                 return;
1690
1691         /* is a bind address configured? */
1692         res = ng_ipaddr_af(&Conf_Server[Server].bind_addr);
1693         /* if yes, bind now. If it fails, warn and let connect() pick a source address */
1694         if (res && bind(new_sock, (struct sockaddr *) &Conf_Server[Server].bind_addr,
1695                                 ng_ipaddr_salen(&Conf_Server[Server].bind_addr)))
1696         {
1697                 ng_ipaddr_tostr_r(&Conf_Server[Server].bind_addr, ip_str);
1698                 Log(LOG_WARNING, "Can't bind socket to %s: %s!", ip_str, strerror(errno));
1699         }
1700         ng_ipaddr_setport(dest, Conf_Server[Server].port);
1701         res = connect(new_sock, (struct sockaddr *) dest, ng_ipaddr_salen(dest));
1702         if(( res != 0 ) && ( errno != EINPROGRESS )) {
1703                 Log( LOG_CRIT, "Can't connect socket: %s!", strerror( errno ));
1704                 close( new_sock );
1705                 return;
1706         }
1707
1708         if (!array_alloc(&My_ConnArray, sizeof(CONNECTION), (size_t)new_sock)) {
1709                 Log(LOG_ALERT,
1710                     "Cannot allocate memory for server connection (socket %d)",
1711                     new_sock);
1712                 close( new_sock );
1713                 return;
1714         }
1715
1716         My_Connections = array_start(&My_ConnArray);
1717
1718         assert(My_Connections[new_sock].sock <= 0);
1719
1720         Init_Conn_Struct(new_sock);
1721
1722         ng_ipaddr_tostr_r(dest, ip_str);
1723         c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWNSERVER, false);
1724         if (!c) {
1725                 Log( LOG_ALERT, "Can't establish connection: can't create client structure!" );
1726                 close( new_sock );
1727                 return;
1728         }
1729
1730         /* Conn_Close() decrements this counter again */
1731         NumConnections++;
1732         Client_SetIntroducer( c, c );
1733         Client_SetToken( c, TOKEN_OUTBOUND );
1734
1735         /* Register connection */
1736         Conf_Server[Server].conn_id = new_sock;
1737         My_Connections[new_sock].sock = new_sock;
1738         My_Connections[new_sock].addr = *dest;
1739         My_Connections[new_sock].client = c;
1740         strlcpy( My_Connections[new_sock].host, Conf_Server[Server].host,
1741                                 sizeof(My_Connections[new_sock].host ));
1742
1743         /* Register new socket */
1744         if (!io_event_create( new_sock, IO_WANTWRITE, cb_connserver)) {
1745                 Log( LOG_ALERT, "io_event_create(): could not add fd %d", strerror(errno));
1746                 Conn_Close( new_sock, "io_event_create() failed", NULL, false );
1747                 Init_Conn_Struct( new_sock );
1748                 Conf_Server[Server].conn_id = NONE;
1749         }
1750 #ifdef SSL_SUPPORT
1751         if (Conf_Server[Server].SSLConnect && !ConnSSL_PrepareConnect( &My_Connections[new_sock],
1752                                                                 &Conf_Server[Server] ))
1753         {
1754                 Log(LOG_ALERT, "Could not initialize SSL for outgoing connection");
1755                 Conn_Close( new_sock, "Could not initialize SSL for outgoing connection", NULL, false );
1756                 Init_Conn_Struct( new_sock );
1757                 Conf_Server[Server].conn_id = NONE;
1758                 return;
1759         }
1760 #endif
1761         LogDebug("Registered new connection %d on socket %d (%ld in total).",
1762                  new_sock, My_Connections[new_sock].sock, NumConnections);
1763         Conn_OPTION_ADD( &My_Connections[new_sock], CONN_ISCONNECTING );
1764 } /* New_Server */
1765
1766
1767 /**
1768  * Initialize connection structure.
1769  */
1770 static void
1771 Init_Conn_Struct(CONN_ID Idx)
1772 {
1773         time_t now = time(NULL);
1774
1775         memset(&My_Connections[Idx], 0, sizeof(CONNECTION));
1776         My_Connections[Idx].sock = -1;
1777         My_Connections[Idx].signon = now;
1778         My_Connections[Idx].lastdata = now;
1779         My_Connections[Idx].lastprivmsg = now;
1780         Resolve_Init(&My_Connections[Idx].res_stat);
1781 } /* Init_Conn_Struct */
1782
1783
1784 static bool
1785 Init_Socket( int Sock )
1786 {
1787         /* Initialize socket (set options) */
1788
1789         int value;
1790
1791         if (!io_setnonblock(Sock)) {
1792                 Log( LOG_CRIT, "Can't enable non-blocking mode for socket: %s!", strerror( errno ));
1793                 close( Sock );
1794                 return false;
1795         }
1796
1797         /* Don't block this port after socket shutdown */
1798         value = 1;
1799         if( setsockopt( Sock, SOL_SOCKET, SO_REUSEADDR, &value, (socklen_t)sizeof( value )) != 0 )
1800         {
1801                 Log( LOG_ERR, "Can't set socket option SO_REUSEADDR: %s!", strerror( errno ));
1802                 /* ignore this error */
1803         }
1804
1805         /* Set type of service (TOS) */
1806 #if defined(IP_TOS) && defined(IPTOS_LOWDELAY)
1807         value = IPTOS_LOWDELAY;
1808         LogDebug("Setting option IP_TOS on socket %d to IPTOS_LOWDELAY (%d).", Sock, value );
1809         if( setsockopt( Sock, SOL_IP, IP_TOS, &value, (socklen_t)sizeof( value )) != 0 )
1810         {
1811                 Log( LOG_ERR, "Can't set socket option IP_TOS: %s!", strerror( errno ));
1812                 /* ignore this error */
1813         }
1814 #endif
1815
1816         return true;
1817 } /* Init_Socket */
1818
1819
1820
1821 static void
1822 cb_Connect_to_Server(int fd, UNUSED short events)
1823 {
1824         /* Read result of resolver sub-process from pipe and start connection */
1825         int i;
1826         size_t len;
1827         ng_ipaddr_t dest_addrs[4];      /* we can handle at most 3; but we read up to
1828                                            four so we can log the 'more than we can handle'
1829                                            condition. First result is tried immediately, rest
1830                                            is saved for later if needed. */
1831
1832         LogDebug("Resolver: Got forward lookup callback on fd %d, events %d", fd, events);
1833
1834         for (i=0; i < MAX_SERVERS; i++) {
1835                   if (Resolve_Getfd(&Conf_Server[i].res_stat) == fd )
1836                           break;
1837         }
1838
1839         if( i >= MAX_SERVERS) {
1840                 /* Ops, no matching server found?! */
1841                 io_close( fd );
1842                 LogDebug("Resolver: Got Forward Lookup callback for unknown server!?");
1843                 return;
1844         }
1845
1846         /* Read result from pipe */
1847         len = Resolve_Read(&Conf_Server[i].res_stat, dest_addrs, sizeof(dest_addrs));
1848         if (len == 0)
1849                 return;
1850
1851         assert((len % sizeof(ng_ipaddr_t)) == 0);
1852
1853         LogDebug("Got result from resolver: %u structs (%u bytes).", len/sizeof(ng_ipaddr_t), len);
1854
1855         memset(&Conf_Server[i].dst_addr, 0, sizeof(Conf_Server[i].dst_addr));
1856         if (len > sizeof(ng_ipaddr_t)) {
1857                 /* more than one address for this hostname, remember them
1858                  * in case first address is unreachable/not available */
1859                 len -= sizeof(ng_ipaddr_t);
1860                 if (len > sizeof(Conf_Server[i].dst_addr)) {
1861                         len = sizeof(Conf_Server[i].dst_addr);
1862                         Log(LOG_NOTICE,
1863                                 "Notice: Resolver returned more IP Addresses for host than we can handle, additional addresses dropped.");
1864                 }
1865                 memcpy(&Conf_Server[i].dst_addr, &dest_addrs[1], len);
1866         }
1867         /* connect() */
1868         New_Server(i, dest_addrs);
1869 } /* cb_Read_Forward_Lookup */
1870
1871
1872 static void
1873 cb_Read_Resolver_Result( int r_fd, UNUSED short events )
1874 {
1875         /* Read result of resolver sub-process from pipe and update the
1876          * apropriate connection/client structure(s): hostname and/or
1877          * IDENT user name.*/
1878
1879         CLIENT *c;
1880         int i;
1881         size_t len;
1882         char *identptr;
1883 #ifdef IDENTAUTH
1884         char readbuf[HOST_LEN + 2 + CLIENT_USER_LEN];
1885 #else
1886         char readbuf[HOST_LEN + 1];
1887 #endif
1888
1889         LogDebug("Resolver: Got callback on fd %d, events %d", r_fd, events );
1890
1891         /* Search associated connection ... */
1892         for( i = 0; i < Pool_Size; i++ ) {
1893                 if(( My_Connections[i].sock != NONE )
1894                   && ( Resolve_Getfd(&My_Connections[i].res_stat) == r_fd ))
1895                         break;
1896         }
1897         if( i >= Pool_Size ) {
1898                 /* Ops, none found? Probably the connection has already
1899                  * been closed!? We'll ignore that ... */
1900                 io_close( r_fd );
1901                 LogDebug("Resolver: Got callback for unknown connection!?");
1902                 return;
1903         }
1904
1905         /* Read result from pipe */
1906         len = Resolve_Read(&My_Connections[i].res_stat, readbuf, sizeof readbuf -1);
1907         if (len == 0)
1908                 return;
1909
1910         readbuf[len] = '\0';
1911         identptr = strchr(readbuf, '\n');
1912         assert(identptr != NULL);
1913         if (!identptr) {
1914                 Log( LOG_CRIT, "Resolver: Got malformed result!");
1915                 return;
1916         }
1917
1918         *identptr = '\0';
1919         LogDebug("Got result from resolver: \"%s\" (%u bytes read).", readbuf, len);
1920         /* Okay, we got a complete result: this is a host name for outgoing
1921          * connections and a host name and IDENT user name (if enabled) for
1922          * incoming connections.*/
1923         assert ( My_Connections[i].sock >= 0 );
1924         /* Incoming connection. Search client ... */
1925         c = Conn_GetClient( i );
1926         assert( c != NULL );
1927
1928         /* Only update client information of unregistered clients */
1929         if( Client_Type( c ) == CLIENT_UNKNOWN ) {
1930                 strlcpy(My_Connections[i].host, readbuf, sizeof( My_Connections[i].host));
1931                 Client_SetHostname( c, readbuf);
1932 #ifdef IDENTAUTH
1933                 ++identptr;
1934                 if (*identptr) {
1935                         Log(LOG_INFO, "IDENT lookup for connection %d: \"%s\".", i, identptr);
1936                         Client_SetUser(c, identptr, true);
1937                 } else {
1938                         Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i);
1939                 }
1940 #endif
1941         }
1942 #ifdef DEBUG
1943                 else Log( LOG_DEBUG, "Resolver: discarding result for already registered connection %d.", i );
1944 #endif
1945         /* Reset penalty time */
1946         Conn_ResetPenalty( i );
1947 } /* cb_Read_Resolver_Result */
1948
1949
1950 static void
1951 Simple_Message( int Sock, const char *Msg )
1952 {
1953         char buf[COMMAND_LEN];
1954         size_t len;
1955         /* Write "simple" message to socket, without using compression
1956          * or even the connection write buffers. Used e.g. for error
1957          * messages by New_Connection(). */
1958         assert( Sock > NONE );
1959         assert( Msg != NULL );
1960
1961         strlcpy( buf, Msg, sizeof buf - 2);
1962         len = strlcat( buf, "\r\n", sizeof buf);
1963         (void)write(Sock, buf, len);
1964 } /* Simple_Error */
1965
1966
1967 GLOBAL CLIENT *
1968 Conn_GetClient( CONN_ID Idx ) 
1969 {
1970         /* return Client-Structure that belongs to the local Connection Idx.
1971          * If none is found, return NULL.
1972          */
1973         CONNECTION *c;
1974         assert( Idx >= 0 );
1975
1976         c = array_get(&My_ConnArray, sizeof (CONNECTION), (size_t)Idx);
1977
1978         assert(c != NULL);
1979
1980         return c ? c->client : NULL;
1981 }
1982
1983 #ifdef SSL_SUPPORT
1984 /* we cannot access My_Connections in irc-info.c */
1985 GLOBAL bool
1986 Conn_GetCipherInfo(CONN_ID Idx, char *buf, size_t len)
1987 {
1988         if (Idx < 0)
1989                 return false;
1990         assert(Idx < (int) array_length(&My_ConnArray, sizeof(CONNECTION)));
1991         return ConnSSL_GetCipherInfo(&My_Connections[Idx], buf, len);
1992 }
1993
1994
1995 GLOBAL bool
1996 Conn_UsesSSL(CONN_ID Idx)
1997 {
1998         if (Idx < 0)
1999                 return false;
2000         assert(Idx < (int) array_length(&My_ConnArray, sizeof(CONNECTION)));
2001         return Conn_OPTION_ISSET(&My_Connections[Idx], CONN_SSL);
2002 }
2003 #endif
2004
2005
2006 /* -eof- */