|
@@ -7,17 +7,19 @@
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
* (at your option) any later version.
|
|
* Please read the file COPYING, README and AUTHORS for more information.
|
|
* Please read the file COPYING, README and AUTHORS for more information.
|
|
- *
|
|
|
|
- * Connection management
|
|
|
|
*/
|
|
*/
|
|
|
|
|
|
-
|
|
|
|
#define CONN_MODULE
|
|
#define CONN_MODULE
|
|
|
|
|
|
#include "portab.h"
|
|
#include "portab.h"
|
|
#include "conf-ssl.h"
|
|
#include "conf-ssl.h"
|
|
#include "io.h"
|
|
#include "io.h"
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * @file
|
|
|
|
+ * Connection management
|
|
|
|
+ */
|
|
|
|
+
|
|
#include "imp.h"
|
|
#include "imp.h"
|
|
#include <assert.h>
|
|
#include <assert.h>
|
|
#ifdef PROTOTYPES
|
|
#ifdef PROTOTYPES
|
|
@@ -71,10 +73,6 @@
|
|
#include "resolve.h"
|
|
#include "resolve.h"
|
|
#include "tool.h"
|
|
#include "tool.h"
|
|
|
|
|
|
-#ifdef ZEROCONF
|
|
|
|
-# include "rendezvous.h"
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
#include "exp.h"
|
|
#include "exp.h"
|
|
|
|
|
|
|
|
|
|
@@ -82,6 +80,7 @@
|
|
|
|
|
|
#define MAX_COMMANDS 3
|
|
#define MAX_COMMANDS 3
|
|
#define MAX_COMMANDS_SERVER 10
|
|
#define MAX_COMMANDS_SERVER 10
|
|
|
|
+#define MAX_COMMANDS_SERVICE MAX_COMMANDS_SERVER
|
|
|
|
|
|
|
|
|
|
static bool Handle_Write PARAMS(( CONN_ID Idx ));
|
|
static bool Handle_Write PARAMS(( CONN_ID Idx ));
|
|
@@ -124,8 +123,9 @@ static void cb_clientserver PARAMS((int sock, short what));
|
|
/**
|
|
/**
|
|
* IO callback for listening sockets: handle new connections. This callback
|
|
* IO callback for listening sockets: handle new connections. This callback
|
|
* gets called when a new non-SSL connection should be accepted.
|
|
* gets called when a new non-SSL connection should be accepted.
|
|
- * @param sock Socket descriptor
|
|
|
|
- * @param irrelevant (ignored IO specification)
|
|
|
|
|
|
+ *
|
|
|
|
+ * @param sock Socket descriptor.
|
|
|
|
+ * @param irrelevant (ignored IO specification)
|
|
*/
|
|
*/
|
|
static void
|
|
static void
|
|
cb_listen(int sock, short irrelevant)
|
|
cb_listen(int sock, short irrelevant)
|
|
@@ -139,8 +139,9 @@ cb_listen(int sock, short irrelevant)
|
|
/**
|
|
/**
|
|
* IO callback for listening SSL sockets: handle new connections. This callback
|
|
* IO callback for listening SSL sockets: handle new connections. This callback
|
|
* gets called when a new SSL-enabled connection should be accepted.
|
|
* gets called when a new SSL-enabled connection should be accepted.
|
|
- * @param sock Socket descriptor
|
|
|
|
- * @param irrelevant (ignored IO specification)
|
|
|
|
|
|
+ *
|
|
|
|
+ * @param sock Socket descriptor.
|
|
|
|
+ * @param irrelevant (ignored IO specification)
|
|
*/
|
|
*/
|
|
static void
|
|
static void
|
|
cb_listen_ssl(int sock, short irrelevant)
|
|
cb_listen_ssl(int sock, short irrelevant)
|
|
@@ -158,8 +159,9 @@ cb_listen_ssl(int sock, short irrelevant)
|
|
|
|
|
|
/**
|
|
/**
|
|
* IO callback for new outgoing non-SSL server connections.
|
|
* IO callback for new outgoing non-SSL server connections.
|
|
- * @param sock Socket descriptor
|
|
|
|
- * @param what IO specification (IO_WANTREAD/IO_WANTWRITE/...)
|
|
|
|
|
|
+ *
|
|
|
|
+ * @param sock Socket descriptor.
|
|
|
|
+ * @param what IO specification (IO_WANTREAD/IO_WANTWRITE/...).
|
|
*/
|
|
*/
|
|
static void
|
|
static void
|
|
cb_connserver(int sock, UNUSED short what)
|
|
cb_connserver(int sock, UNUSED short what)
|
|
@@ -236,13 +238,16 @@ cb_connserver(int sock, UNUSED short what)
|
|
|
|
|
|
/**
|
|
/**
|
|
* Login to a remote server.
|
|
* Login to a remote server.
|
|
- * @param idx Connection index
|
|
|
|
|
|
+ *
|
|
|
|
+ * @param idx Connection index.
|
|
*/
|
|
*/
|
|
static void
|
|
static void
|
|
server_login(CONN_ID idx)
|
|
server_login(CONN_ID idx)
|
|
{
|
|
{
|
|
- Log( LOG_INFO, "Connection %d with \"%s:%d\" established. Now logging in ...", idx,
|
|
|
|
- My_Connections[idx].host, Conf_Server[Conf_GetServer( idx )].port );
|
|
|
|
|
|
+ Log(LOG_INFO,
|
|
|
|
+ "Connection %d (socket %d) with \"%s:%d\" established. Now logging in ...",
|
|
|
|
+ idx, My_Connections[idx].sock, My_Connections[idx].host,
|
|
|
|
+ Conf_Server[Conf_GetServer(idx)].port);
|
|
|
|
|
|
io_event_setcb( My_Connections[idx].sock, cb_clientserver);
|
|
io_event_setcb( My_Connections[idx].sock, cb_clientserver);
|
|
io_event_add( My_Connections[idx].sock, IO_WANTREAD|IO_WANTWRITE);
|
|
io_event_add( My_Connections[idx].sock, IO_WANTREAD|IO_WANTWRITE);
|
|
@@ -256,8 +261,9 @@ server_login(CONN_ID idx)
|
|
#ifdef SSL_SUPPORT
|
|
#ifdef SSL_SUPPORT
|
|
/**
|
|
/**
|
|
* IO callback for new outgoing SSL-enabled server connections.
|
|
* IO callback for new outgoing SSL-enabled server connections.
|
|
- * @param sock Socket descriptor
|
|
|
|
- * @param what IO specification (IO_WANTREAD/IO_WANTWRITE/...)
|
|
|
|
|
|
+ *
|
|
|
|
+ * @param sock Socket descriptor.
|
|
|
|
+ * @param unused (ignored IO specification)
|
|
*/
|
|
*/
|
|
static void
|
|
static void
|
|
cb_connserver_login_ssl(int sock, short unused)
|
|
cb_connserver_login_ssl(int sock, short unused)
|
|
@@ -290,8 +296,9 @@ cb_connserver_login_ssl(int sock, short unused)
|
|
|
|
|
|
/**
|
|
/**
|
|
* IO callback for established non-SSL client and server connections.
|
|
* IO callback for established non-SSL client and server connections.
|
|
- * @param sock Socket descriptor
|
|
|
|
- * @param what IO specification (IO_WANTREAD/IO_WANTWRITE/...)
|
|
|
|
|
|
+ *
|
|
|
|
+ * @param sock Socket descriptor.
|
|
|
|
+ * @param what IO specification (IO_WANTREAD/IO_WANTWRITE/...).
|
|
*/
|
|
*/
|
|
static void
|
|
static void
|
|
cb_clientserver(int sock, short what)
|
|
cb_clientserver(int sock, short what)
|
|
@@ -323,8 +330,9 @@ cb_clientserver(int sock, short what)
|
|
#ifdef SSL_SUPPORT
|
|
#ifdef SSL_SUPPORT
|
|
/**
|
|
/**
|
|
* IO callback for established SSL-enabled client and server connections.
|
|
* IO callback for established SSL-enabled client and server connections.
|
|
- * @param sock Socket descriptor
|
|
|
|
- * @param what IO specification (IO_WANTREAD/IO_WANTWRITE/...)
|
|
|
|
|
|
+ *
|
|
|
|
+ * @param sock Socket descriptor.
|
|
|
|
+ * @param what IO specification (IO_WANTREAD/IO_WANTWRITE/...).
|
|
*/
|
|
*/
|
|
static void
|
|
static void
|
|
cb_clientserver_ssl(int sock, short what)
|
|
cb_clientserver_ssl(int sock, short what)
|
|
@@ -436,6 +444,14 @@ Conn_CloseAllSockets(void)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Initialize listening ports.
|
|
|
|
+ *
|
|
|
|
+ * @param a Array containing the ports the daemon should listen on.
|
|
|
|
+ * @param listen_addr Address the socket should listen on (can be "0.0.0.0").
|
|
|
|
+ * @param func IO callback function to register.
|
|
|
|
+ * @returns Number of listening sockets created.
|
|
|
|
+ */
|
|
static unsigned int
|
|
static unsigned int
|
|
ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short))
|
|
ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short))
|
|
{
|
|
{
|
|
@@ -468,7 +484,8 @@ ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short))
|
|
|
|
|
|
/**
|
|
/**
|
|
* Initialize all listening sockets.
|
|
* Initialize all listening sockets.
|
|
- * @return Number of created listening sockets
|
|
|
|
|
|
+ *
|
|
|
|
+ * @returns Number of created listening sockets
|
|
*/
|
|
*/
|
|
GLOBAL unsigned int
|
|
GLOBAL unsigned int
|
|
Conn_InitListeners( void )
|
|
Conn_InitListeners( void )
|
|
@@ -509,15 +526,15 @@ Conn_InitListeners( void )
|
|
} /* Conn_InitListeners */
|
|
} /* Conn_InitListeners */
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Shut down all listening sockets.
|
|
|
|
+ */
|
|
GLOBAL void
|
|
GLOBAL void
|
|
Conn_ExitListeners( void )
|
|
Conn_ExitListeners( void )
|
|
{
|
|
{
|
|
/* Close down all listening sockets */
|
|
/* Close down all listening sockets */
|
|
int *fd;
|
|
int *fd;
|
|
size_t arraylen;
|
|
size_t arraylen;
|
|
-#ifdef ZEROCONF
|
|
|
|
- Rendezvous_UnregisterListeners( );
|
|
|
|
-#endif
|
|
|
|
|
|
|
|
arraylen = array_length(&My_Listeners, sizeof (int));
|
|
arraylen = array_length(&My_Listeners, sizeof (int));
|
|
Log(LOG_INFO,
|
|
Log(LOG_INFO,
|
|
@@ -534,6 +551,14 @@ Conn_ExitListeners( void )
|
|
} /* Conn_ExitListeners */
|
|
} /* Conn_ExitListeners */
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Bind a socket to a specific (source) address.
|
|
|
|
+ *
|
|
|
|
+ * @param addr Address structure.
|
|
|
|
+ * @param listen_addrstr Source address as string.
|
|
|
|
+ * @param Port Port number.
|
|
|
|
+ * @returns true on success, false otherwise.
|
|
|
|
+ */
|
|
static bool
|
|
static bool
|
|
InitSinaddrListenAddr(ng_ipaddr_t *addr, const char *listen_addrstr, UINT16 Port)
|
|
InitSinaddrListenAddr(ng_ipaddr_t *addr, const char *listen_addrstr, UINT16 Port)
|
|
{
|
|
{
|
|
@@ -549,6 +574,14 @@ InitSinaddrListenAddr(ng_ipaddr_t *addr, const char *listen_addrstr, UINT16 Port
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Set a socket to "IPv6 only". If the given socket doesn't belong to the
|
|
|
|
+ * AF_INET6 family, or the operating system doesn't support this functionality,
|
|
|
|
+ * this function retruns silently.
|
|
|
|
+ *
|
|
|
|
+ * @param af Address family of the socket.
|
|
|
|
+ * @param sock Socket handle.
|
|
|
|
+ */
|
|
static void
|
|
static void
|
|
set_v6_only(int af, int sock)
|
|
set_v6_only(int af, int sock)
|
|
{
|
|
{
|
|
@@ -567,16 +600,20 @@ set_v6_only(int af, int sock)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
-/* return new listening port file descriptor or -1 on failure */
|
|
|
|
|
|
+/**
|
|
|
|
+ * Initialize new listening port.
|
|
|
|
+ *
|
|
|
|
+ * @param listen_addr Local address to bind the socet to (can be 0.0.0.0).
|
|
|
|
+ * @param Port Port number on which the new socket should be listening.
|
|
|
|
+ * @returns file descriptor of the socket or -1 on failure.
|
|
|
|
+ */
|
|
static int
|
|
static int
|
|
NewListener(const char *listen_addr, UINT16 Port)
|
|
NewListener(const char *listen_addr, UINT16 Port)
|
|
{
|
|
{
|
|
/* Create new listening socket on specified port */
|
|
/* Create new listening socket on specified port */
|
|
ng_ipaddr_t addr;
|
|
ng_ipaddr_t addr;
|
|
int sock, af;
|
|
int sock, af;
|
|
-#ifdef ZEROCONF
|
|
|
|
- char name[CLIENT_ID_LEN], *info;
|
|
|
|
-#endif
|
|
|
|
|
|
+
|
|
if (!InitSinaddrListenAddr(&addr, listen_addr, Port))
|
|
if (!InitSinaddrListenAddr(&addr, listen_addr, Port))
|
|
return -1;
|
|
return -1;
|
|
|
|
|
|
@@ -612,44 +649,17 @@ NewListener(const char *listen_addr, UINT16 Port)
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
- Log(LOG_INFO, "Now listening on [%s]:%d (socket %d).", ng_ipaddr_tostr(&addr), Port, sock);
|
|
|
|
-
|
|
|
|
-#ifdef ZEROCONF
|
|
|
|
- /* Get best server description text */
|
|
|
|
- if( ! Conf_ServerInfo[0] ) info = Conf_ServerName;
|
|
|
|
- else
|
|
|
|
- {
|
|
|
|
- /* Use server info string */
|
|
|
|
- info = NULL;
|
|
|
|
- if( Conf_ServerInfo[0] == '[' )
|
|
|
|
- {
|
|
|
|
- /* Cut off leading hostname part in "[]" */
|
|
|
|
- info = strchr( Conf_ServerInfo, ']' );
|
|
|
|
- if( info )
|
|
|
|
- {
|
|
|
|
- info++;
|
|
|
|
- while( *info == ' ' ) info++;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if( ! info ) info = Conf_ServerInfo;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /* Add port number to description if non-standard */
|
|
|
|
- if (Port != 6667)
|
|
|
|
- snprintf(name, sizeof name, "%s (port %u)", info,
|
|
|
|
- (unsigned int)Port);
|
|
|
|
- else
|
|
|
|
- strlcpy(name, info, sizeof name);
|
|
|
|
-
|
|
|
|
- /* Register service */
|
|
|
|
- Rendezvous_Register( name, MDNS_TYPE, Port );
|
|
|
|
-#endif
|
|
|
|
|
|
+ Log(LOG_INFO, "Now listening on [%s]:%d (socket %d).",
|
|
|
|
+ ng_ipaddr_tostr(&addr), Port, sock);
|
|
return sock;
|
|
return sock;
|
|
} /* NewListener */
|
|
} /* NewListener */
|
|
|
|
|
|
|
|
|
|
#ifdef SSL_SUPPORT
|
|
#ifdef SSL_SUPPORT
|
|
-/*
|
|
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Check if SSL library needs to read SSL-protocol related data.
|
|
|
|
+ *
|
|
* SSL/TLS connections require extra treatment:
|
|
* SSL/TLS connections require extra treatment:
|
|
* When either CONN_SSL_WANT_WRITE or CONN_SSL_WANT_READ is set, we
|
|
* When either CONN_SSL_WANT_WRITE or CONN_SSL_WANT_READ is set, we
|
|
* need to take care of that first, before checking read/write buffers.
|
|
* need to take care of that first, before checking read/write buffers.
|
|
@@ -660,6 +670,9 @@ NewListener(const char *listen_addr, UINT16 Port)
|
|
* If this function returns true, such a condition is met and we have
|
|
* If this function returns true, such a condition is met and we have
|
|
* to reverse the condition (check for read even if we've data to write,
|
|
* to reverse the condition (check for read even if we've data to write,
|
|
* do not check for read but writeability even if write-buffer is empty).
|
|
* do not check for read but writeability even if write-buffer is empty).
|
|
|
|
+ *
|
|
|
|
+ * @param c Connection to check.
|
|
|
|
+ * @returns true if SSL-library has to read protocol data.
|
|
*/
|
|
*/
|
|
static bool
|
|
static bool
|
|
SSL_WantRead(const CONNECTION *c)
|
|
SSL_WantRead(const CONNECTION *c)
|
|
@@ -670,6 +683,15 @@ SSL_WantRead(const CONNECTION *c)
|
|
}
|
|
}
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Check if SSL library needs to write SSL-protocol related data.
|
|
|
|
+ *
|
|
|
|
+ * Please see description of SSL_WantRead() for full description!
|
|
|
|
+ *
|
|
|
|
+ * @param c Connection to check.
|
|
|
|
+ * @returns true if SSL-library has to write protocol data.
|
|
|
|
+ */
|
|
static bool
|
|
static bool
|
|
SSL_WantWrite(const CONNECTION *c)
|
|
SSL_WantWrite(const CONNECTION *c)
|
|
{
|
|
{
|
|
@@ -679,18 +701,23 @@ SSL_WantWrite(const CONNECTION *c)
|
|
}
|
|
}
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
+
|
|
#else
|
|
#else
|
|
|
|
+
|
|
static inline bool
|
|
static inline bool
|
|
SSL_WantRead(UNUSED const CONNECTION *c)
|
|
SSL_WantRead(UNUSED const CONNECTION *c)
|
|
{ return false; }
|
|
{ return false; }
|
|
|
|
+
|
|
static inline bool
|
|
static inline bool
|
|
SSL_WantWrite(UNUSED const CONNECTION *c)
|
|
SSL_WantWrite(UNUSED const CONNECTION *c)
|
|
{ return false; }
|
|
{ return false; }
|
|
|
|
+
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
* "Main Loop": Loop until shutdown or restart is signalled.
|
|
* "Main Loop": Loop until shutdown or restart is signalled.
|
|
|
|
+ *
|
|
* This function loops until a shutdown or restart of ngIRCd is signalled and
|
|
* This function loops until a shutdown or restart of ngIRCd is signalled and
|
|
* calls io_dispatch() to check for readable and writable sockets every second.
|
|
* calls io_dispatch() to check for readable and writable sockets every second.
|
|
* It checks for status changes on pending connections (e. g. when a hostname
|
|
* It checks for status changes on pending connections (e. g. when a hostname
|
|
@@ -708,10 +735,6 @@ Conn_Handler(void)
|
|
while (!NGIRCd_SignalQuit && !NGIRCd_SignalRestart) {
|
|
while (!NGIRCd_SignalQuit && !NGIRCd_SignalRestart) {
|
|
t = time(NULL);
|
|
t = time(NULL);
|
|
|
|
|
|
-#ifdef ZEROCONF
|
|
|
|
- Rendezvous_Handler();
|
|
|
|
-#endif
|
|
|
|
-
|
|
|
|
/* Check configured servers and established links */
|
|
/* Check configured servers and established links */
|
|
Check_Servers();
|
|
Check_Servers();
|
|
Check_Connections();
|
|
Check_Connections();
|
|
@@ -814,12 +837,14 @@ Conn_Handler(void)
|
|
|
|
|
|
/**
|
|
/**
|
|
* Write a text string into the socket of a connection.
|
|
* Write a text string into the socket of a connection.
|
|
|
|
+ *
|
|
* This function automatically appends CR+LF to the string and validates that
|
|
* This function automatically appends CR+LF to the string and validates that
|
|
* the result is a valid IRC message (oversized messages are shortened, for
|
|
* the result is a valid IRC message (oversized messages are shortened, for
|
|
* example). Then it calls the Conn_Write() function to do the actual sending.
|
|
* example). Then it calls the Conn_Write() function to do the actual sending.
|
|
- * @param Idx Index fo the connection.
|
|
|
|
- * @param Format Format string, see printf().
|
|
|
|
- * @return true on success, false otherwise.
|
|
|
|
|
|
+ *
|
|
|
|
+ * @param Idx Index fo the connection.
|
|
|
|
+ * @param Format Format string, see printf().
|
|
|
|
+ * @returns true on success, false otherwise.
|
|
*/
|
|
*/
|
|
#ifdef PROTOTYPES
|
|
#ifdef PROTOTYPES
|
|
GLOBAL bool
|
|
GLOBAL bool
|
|
@@ -889,16 +914,17 @@ va_dcl
|
|
|
|
|
|
/**
|
|
/**
|
|
* Append Data to the outbound write buffer of a connection.
|
|
* Append Data to the outbound write buffer of a connection.
|
|
- * @param Idx Index of the connection.
|
|
|
|
- * @param Data pointer to the data.
|
|
|
|
- * @param Len length of Data.
|
|
|
|
- * @return true on success, false otherwise.
|
|
|
|
|
|
+ *
|
|
|
|
+ * @param Idx Index of the connection.
|
|
|
|
+ * @param Data pointer to the data.
|
|
|
|
+ * @param Len length of Data.
|
|
|
|
+ * @returns true on success, false otherwise.
|
|
*/
|
|
*/
|
|
static bool
|
|
static bool
|
|
Conn_Write( CONN_ID Idx, char *Data, size_t Len )
|
|
Conn_Write( CONN_ID Idx, char *Data, size_t Len )
|
|
{
|
|
{
|
|
CLIENT *c;
|
|
CLIENT *c;
|
|
- size_t writebuf_limit = WRITEBUFFER_LEN;
|
|
|
|
|
|
+ size_t writebuf_limit = WRITEBUFFER_MAX_LEN;
|
|
assert( Idx > NONE );
|
|
assert( Idx > NONE );
|
|
assert( Data != NULL );
|
|
assert( Data != NULL );
|
|
assert( Len > 0 );
|
|
assert( Len > 0 );
|
|
@@ -934,7 +960,7 @@ Conn_Write( CONN_ID Idx, char *Data, size_t Len )
|
|
/* Uncompressed link:
|
|
/* Uncompressed link:
|
|
* Check if outbound buffer has enough space for the data. */
|
|
* Check if outbound buffer has enough space for the data. */
|
|
if (array_bytes(&My_Connections[Idx].wbuf) + Len >=
|
|
if (array_bytes(&My_Connections[Idx].wbuf) + Len >=
|
|
- writebuf_limit) {
|
|
|
|
|
|
+ WRITEBUFFER_FLUSH_LEN) {
|
|
/* Buffer is full, flush it. Handle_Write deals with
|
|
/* Buffer is full, flush it. Handle_Write deals with
|
|
* low-level errors, if any. */
|
|
* low-level errors, if any. */
|
|
if (!Handle_Write(Idx))
|
|
if (!Handle_Write(Idx))
|
|
@@ -946,10 +972,10 @@ Conn_Write( CONN_ID Idx, char *Data, size_t Len )
|
|
if (array_bytes(&My_Connections[Idx].wbuf) + Len >=
|
|
if (array_bytes(&My_Connections[Idx].wbuf) + Len >=
|
|
writebuf_limit) {
|
|
writebuf_limit) {
|
|
Log(LOG_NOTICE,
|
|
Log(LOG_NOTICE,
|
|
- "Write buffer overflow (connection %d, size %lu byte)!",
|
|
|
|
- Idx,
|
|
|
|
|
|
+ "Write buffer space exhausted (connection %d, limit is %lu bytes, %lu bytes new, %lu bytes pending)",
|
|
|
|
+ Idx, writebuf_limit, Len,
|
|
(unsigned long)array_bytes(&My_Connections[Idx].wbuf));
|
|
(unsigned long)array_bytes(&My_Connections[Idx].wbuf));
|
|
- Conn_Close(Idx, "Write buffer overflow!", NULL, false);
|
|
|
|
|
|
+ Conn_Close(Idx, "Write buffer space exhausted", NULL, false);
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -967,6 +993,17 @@ Conn_Write( CONN_ID Idx, char *Data, size_t Len )
|
|
} /* Conn_Write */
|
|
} /* Conn_Write */
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Shut down a connection.
|
|
|
|
+ *
|
|
|
|
+ * @param Idx Connection index.
|
|
|
|
+ * @param LogMsg Message to write to the log or NULL. If no LogMsg
|
|
|
|
+ * is given, the FwdMsg is logged.
|
|
|
|
+ * @param FwdMsg Message to forward to remote servers.
|
|
|
|
+ * @param InformClient If true, inform the client on the connection which is
|
|
|
|
+ * to be shut down of the reason (FwdMsg) and send
|
|
|
|
+ * connection statistics before disconnecting it.
|
|
|
|
+ */
|
|
GLOBAL void
|
|
GLOBAL void
|
|
Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClient )
|
|
Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClient )
|
|
{
|
|
{
|
|
@@ -1020,7 +1057,7 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
|
|
if (FwdMsg)
|
|
if (FwdMsg)
|
|
Conn_WriteStr(Idx, "ERROR :%s", FwdMsg);
|
|
Conn_WriteStr(Idx, "ERROR :%s", FwdMsg);
|
|
else
|
|
else
|
|
- Conn_WriteStr(Idx, "ERROR :Closing connection.");
|
|
|
|
|
|
+ Conn_WriteStr(Idx, "ERROR :Closing connection");
|
|
}
|
|
}
|
|
|
|
|
|
/* Try to write out the write buffer. Note: Handle_Write() eventually
|
|
/* Try to write out the write buffer. Note: Handle_Write() eventually
|
|
@@ -1111,6 +1148,11 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie
|
|
} /* Conn_Close */
|
|
} /* Conn_Close */
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Get current number of connections.
|
|
|
|
+ *
|
|
|
|
+ * @returns Number of current connections.
|
|
|
|
+ */
|
|
GLOBAL long
|
|
GLOBAL long
|
|
Conn_Count(void)
|
|
Conn_Count(void)
|
|
{
|
|
{
|
|
@@ -1118,6 +1160,11 @@ Conn_Count(void)
|
|
} /* Conn_Count */
|
|
} /* Conn_Count */
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Get number of maximum simultaneous connections.
|
|
|
|
+ *
|
|
|
|
+ * @returns Number of maximum simultaneous connections.
|
|
|
|
+ */
|
|
GLOBAL long
|
|
GLOBAL long
|
|
Conn_CountMax(void)
|
|
Conn_CountMax(void)
|
|
{
|
|
{
|
|
@@ -1125,6 +1172,11 @@ Conn_CountMax(void)
|
|
} /* Conn_CountMax */
|
|
} /* Conn_CountMax */
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Get number of connections accepted since the daemon startet.
|
|
|
|
+ *
|
|
|
|
+ * @returns Number of connections accepted.
|
|
|
|
+ */
|
|
GLOBAL long
|
|
GLOBAL long
|
|
Conn_CountAccepted(void)
|
|
Conn_CountAccepted(void)
|
|
{
|
|
{
|
|
@@ -1166,6 +1218,9 @@ Conn_SyncServerStruct(void)
|
|
|
|
|
|
/**
|
|
/**
|
|
* Send out data of write buffer; connect new sockets.
|
|
* Send out data of write buffer; connect new sockets.
|
|
|
|
+ *
|
|
|
|
+ * @param Idx Connection index.
|
|
|
|
+ * @returns true on success, false otherwise.
|
|
*/
|
|
*/
|
|
static bool
|
|
static bool
|
|
Handle_Write( CONN_ID Idx )
|
|
Handle_Write( CONN_ID Idx )
|
|
@@ -1230,6 +1285,11 @@ Handle_Write( CONN_ID Idx )
|
|
} /* Handle_Write */
|
|
} /* Handle_Write */
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Count established connections to a specific IP address.
|
|
|
|
+ *
|
|
|
|
+ * @returns Number of established connections.
|
|
|
|
+ */
|
|
static int
|
|
static int
|
|
Count_Connections(ng_ipaddr_t *a)
|
|
Count_Connections(ng_ipaddr_t *a)
|
|
{
|
|
{
|
|
@@ -1248,8 +1308,9 @@ Count_Connections(ng_ipaddr_t *a)
|
|
|
|
|
|
/**
|
|
/**
|
|
* Initialize new client connection on a listening socket.
|
|
* Initialize new client connection on a listening socket.
|
|
- * @param Sock Listening socket descriptor
|
|
|
|
- * @return Accepted socket descriptor or -1 on error
|
|
|
|
|
|
+ *
|
|
|
|
+ * @param Sock Listening socket descriptor.
|
|
|
|
+ * @returns Accepted socket descriptor or -1 on error.
|
|
*/
|
|
*/
|
|
static int
|
|
static int
|
|
New_Connection(int Sock)
|
|
New_Connection(int Sock)
|
|
@@ -1316,7 +1377,7 @@ New_Connection(int Sock)
|
|
"Refused connection from %s: too may connections (%ld) from this IP address!",
|
|
"Refused connection from %s: too may connections (%ld) from this IP address!",
|
|
ip_str, cnt);
|
|
ip_str, cnt);
|
|
Simple_Message(new_sock,
|
|
Simple_Message(new_sock,
|
|
- "ERROR :Connection refused, too many connections from your IP address!");
|
|
|
|
|
|
+ "ERROR :Connection refused, too many connections from your IP address");
|
|
close(new_sock);
|
|
close(new_sock);
|
|
return -1;
|
|
return -1;
|
|
}
|
|
}
|
|
@@ -1380,18 +1441,32 @@ New_Connection(int Sock)
|
|
|
|
|
|
identsock = new_sock;
|
|
identsock = new_sock;
|
|
#ifdef IDENTAUTH
|
|
#ifdef IDENTAUTH
|
|
- if (Conf_NoIdent)
|
|
|
|
|
|
+ if (!Conf_Ident)
|
|
identsock = -1;
|
|
identsock = -1;
|
|
#endif
|
|
#endif
|
|
- if (!Conf_NoDNS)
|
|
|
|
|
|
+ if (Conf_DNS) {
|
|
|
|
+ if (Conf_NoticeAuth) {
|
|
|
|
+#ifdef IDENTAUTH
|
|
|
|
+ if (Conf_Ident)
|
|
|
|
+ (void)Conn_WriteStr(new_sock,
|
|
|
|
+ "NOTICE AUTH :*** Looking up your hostname and checking ident");
|
|
|
|
+ else
|
|
|
|
+#endif
|
|
|
|
+ (void)Conn_WriteStr(new_sock,
|
|
|
|
+ "NOTICE AUTH :*** Looking up your hostname");
|
|
|
|
+ }
|
|
Resolve_Addr(&My_Connections[new_sock].proc_stat, &new_addr,
|
|
Resolve_Addr(&My_Connections[new_sock].proc_stat, &new_addr,
|
|
identsock, cb_Read_Resolver_Result);
|
|
identsock, cb_Read_Resolver_Result);
|
|
|
|
+ }
|
|
|
|
|
|
Account_Connection();
|
|
Account_Connection();
|
|
return new_sock;
|
|
return new_sock;
|
|
} /* New_Connection */
|
|
} /* New_Connection */
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Update global connection counters.
|
|
|
|
+ */
|
|
static void
|
|
static void
|
|
Account_Connection(void)
|
|
Account_Connection(void)
|
|
{
|
|
{
|
|
@@ -1403,6 +1478,12 @@ Account_Connection(void)
|
|
} /* Account_Connection */
|
|
} /* Account_Connection */
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Translate socket handle into connection index.
|
|
|
|
+ *
|
|
|
|
+ * @param Sock Socket handle.
|
|
|
|
+ * @returns Connecion index or NONE, if no connection could be found.
|
|
|
|
+ */
|
|
static CONN_ID
|
|
static CONN_ID
|
|
Socket2Index( int Sock )
|
|
Socket2Index( int Sock )
|
|
{
|
|
{
|
|
@@ -1421,6 +1502,8 @@ Socket2Index( int Sock )
|
|
/**
|
|
/**
|
|
* Read data from the network to the read buffer. If an error occures,
|
|
* Read data from the network to the read buffer. If an error occures,
|
|
* the socket of this connection will be shut down.
|
|
* the socket of this connection will be shut down.
|
|
|
|
+ *
|
|
|
|
+ * @param Idx Connection index.
|
|
*/
|
|
*/
|
|
static void
|
|
static void
|
|
Read_Request( CONN_ID Idx )
|
|
Read_Request( CONN_ID Idx )
|
|
@@ -1442,9 +1525,9 @@ Read_Request( CONN_ID Idx )
|
|
{
|
|
{
|
|
/* Read buffer is full */
|
|
/* Read buffer is full */
|
|
Log(LOG_ERR,
|
|
Log(LOG_ERR,
|
|
- "Receive buffer overflow (connection %d): %d bytes!",
|
|
|
|
|
|
+ "Receive buffer space exhausted (connection %d): %d bytes",
|
|
Idx, array_bytes(&My_Connections[Idx].rbuf));
|
|
Idx, array_bytes(&My_Connections[Idx].rbuf));
|
|
- Conn_Close( Idx, "Receive buffer overflow!", NULL, false );
|
|
|
|
|
|
+ Conn_Close(Idx, "Receive buffer space exhausted", NULL, false);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1480,7 +1563,7 @@ Read_Request( CONN_ID Idx )
|
|
Log(LOG_ERR,
|
|
Log(LOG_ERR,
|
|
"Could not append recieved data to zip input buffer (connn %d): %d bytes!",
|
|
"Could not append recieved data to zip input buffer (connn %d): %d bytes!",
|
|
Idx, len);
|
|
Idx, len);
|
|
- Conn_Close(Idx, "Receive buffer overflow!", NULL,
|
|
|
|
|
|
+ Conn_Close(Idx, "Receive buffer space exhausted", NULL,
|
|
false);
|
|
false);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -1489,22 +1572,27 @@ Read_Request( CONN_ID Idx )
|
|
{
|
|
{
|
|
if (!array_catb( &My_Connections[Idx].rbuf, readbuf, len)) {
|
|
if (!array_catb( &My_Connections[Idx].rbuf, readbuf, len)) {
|
|
Log( LOG_ERR, "Could not append recieved data to input buffer (connn %d): %d bytes!", Idx, len );
|
|
Log( LOG_ERR, "Could not append recieved data to input buffer (connn %d): %d bytes!", Idx, len );
|
|
- Conn_Close( Idx, "Receive buffer overflow!", NULL, false );
|
|
|
|
|
|
+ Conn_Close(Idx, "Receive buffer space exhausted", NULL, false );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Update connection statistics */
|
|
/* Update connection statistics */
|
|
My_Connections[Idx].bytes_in += len;
|
|
My_Connections[Idx].bytes_in += len;
|
|
|
|
+ My_Connections[Idx].bps += Handle_Buffer(Idx);
|
|
|
|
+
|
|
|
|
+ /* Make sure that there is still a valid client registered */
|
|
|
|
+ c = Conn_GetClient(Idx);
|
|
|
|
+ if (!c)
|
|
|
|
+ return;
|
|
|
|
|
|
/* Update timestamp of last data received if this connection is
|
|
/* Update timestamp of last data received if this connection is
|
|
* registered as a user, server or service connection. Don't update
|
|
* registered as a user, server or service connection. Don't update
|
|
* otherwise, so users have at least Conf_PongTimeout seconds time to
|
|
* otherwise, so users have at least Conf_PongTimeout seconds time to
|
|
* register with the IRC server -- see Check_Connections().
|
|
* register with the IRC server -- see Check_Connections().
|
|
* Update "lastping", too, if time shifted backwards ... */
|
|
* Update "lastping", too, if time shifted backwards ... */
|
|
- c = Conn_GetClient(Idx);
|
|
|
|
- if (c && (Client_Type(c) == CLIENT_USER
|
|
|
|
- || Client_Type(c) == CLIENT_SERVER
|
|
|
|
- || Client_Type(c) == CLIENT_SERVICE)) {
|
|
|
|
|
|
+ if (Client_Type(c) == CLIENT_USER
|
|
|
|
+ || Client_Type(c) == CLIENT_SERVER
|
|
|
|
+ || Client_Type(c) == CLIENT_SERVICE) {
|
|
t = time(NULL);
|
|
t = time(NULL);
|
|
if (My_Connections[Idx].lastdata != t)
|
|
if (My_Connections[Idx].lastdata != t)
|
|
My_Connections[Idx].bps = 0;
|
|
My_Connections[Idx].bps = 0;
|
|
@@ -1515,8 +1603,9 @@ Read_Request( CONN_ID Idx )
|
|
}
|
|
}
|
|
|
|
|
|
/* Look at the data in the (read-) buffer of this connection */
|
|
/* Look at the data in the (read-) buffer of this connection */
|
|
- My_Connections[Idx].bps += Handle_Buffer(Idx);
|
|
|
|
if (Client_Type(c) != CLIENT_SERVER
|
|
if (Client_Type(c) != CLIENT_SERVER
|
|
|
|
+ && Client_Type(c) != CLIENT_UNKNOWNSERVER
|
|
|
|
+ && Client_Type(c) != CLIENT_SERVICE
|
|
&& My_Connections[Idx].bps >= maxbps) {
|
|
&& My_Connections[Idx].bps >= maxbps) {
|
|
LogDebug("Throttling connection %d: BPS exceeded! (%u >= %u)",
|
|
LogDebug("Throttling connection %d: BPS exceeded! (%u >= %u)",
|
|
Idx, My_Connections[Idx].bps, maxbps);
|
|
Idx, My_Connections[Idx].bps, maxbps);
|
|
@@ -1527,11 +1616,13 @@ Read_Request( CONN_ID Idx )
|
|
|
|
|
|
/**
|
|
/**
|
|
* Handle all data in the connection read-buffer.
|
|
* Handle all data in the connection read-buffer.
|
|
|
|
+ *
|
|
* Data is processed until no complete command is left in the read buffer,
|
|
* Data is processed until no complete command is left in the read buffer,
|
|
- * or MAX_COMMANDS[_SERVER] commands were processed.
|
|
|
|
|
|
+ * or MAX_COMMANDS[_SERVER|_SERVICE] commands were processed.
|
|
* When a fatal error occurs, the connection is shut down.
|
|
* When a fatal error occurs, the connection is shut down.
|
|
- * @param Idx Index of the connection.
|
|
|
|
- * @return number of bytes processed.
|
|
|
|
|
|
+ *
|
|
|
|
+ * @param Idx Index of the connection.
|
|
|
|
+ * @returns Number of bytes processed.
|
|
*/
|
|
*/
|
|
static unsigned int
|
|
static unsigned int
|
|
Handle_Buffer(CONN_ID Idx)
|
|
Handle_Buffer(CONN_ID Idx)
|
|
@@ -1549,14 +1640,25 @@ Handle_Buffer(CONN_ID Idx)
|
|
CLIENT *c;
|
|
CLIENT *c;
|
|
|
|
|
|
c = Conn_GetClient(Idx);
|
|
c = Conn_GetClient(Idx);
|
|
- assert( c != NULL);
|
|
|
|
|
|
+ starttime = time(NULL);
|
|
|
|
+
|
|
|
|
+ assert(c != NULL);
|
|
|
|
|
|
/* Servers do get special command limits, so they can process
|
|
/* Servers do get special command limits, so they can process
|
|
* all the messages that are required while peering. */
|
|
* all the messages that are required while peering. */
|
|
- if (Client_Type(c) == CLIENT_SERVER)
|
|
|
|
- maxcmd = MAX_COMMANDS_SERVER;
|
|
|
|
|
|
+ switch (Client_Type(c)) {
|
|
|
|
+ case CLIENT_SERVER:
|
|
|
|
+ /* Allow servers to send more commands in the first 10 secods
|
|
|
|
+ * to speed up server login and network synchronisation. */
|
|
|
|
+ if (starttime - Client_StartTime(c) < 10)
|
|
|
|
+ maxcmd = MAX_COMMANDS_SERVER * 5;
|
|
|
|
+ else
|
|
|
|
+ maxcmd = MAX_COMMANDS_SERVER;
|
|
|
|
+ break;
|
|
|
|
+ case CLIENT_SERVICE:
|
|
|
|
+ maxcmd = MAX_COMMANDS_SERVICE; break;
|
|
|
|
+ }
|
|
|
|
|
|
- starttime = time(NULL);
|
|
|
|
for (i=0; i < maxcmd; i++) {
|
|
for (i=0; i < maxcmd; i++) {
|
|
/* Check penalty */
|
|
/* Check penalty */
|
|
if (My_Connections[Idx].delaytime > starttime)
|
|
if (My_Connections[Idx].delaytime > starttime)
|
|
@@ -1786,6 +1888,12 @@ Check_Servers(void)
|
|
} /* Check_Servers */
|
|
} /* Check_Servers */
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Establish a new outgoing server connection.
|
|
|
|
+ *
|
|
|
|
+ * @param Server Configuration index of the server.
|
|
|
|
+ * @param dest Destination IP address to connect to.
|
|
|
|
+ */
|
|
static void
|
|
static void
|
|
New_Server( int Server , ng_ipaddr_t *dest)
|
|
New_Server( int Server , ng_ipaddr_t *dest)
|
|
{
|
|
{
|
|
@@ -1801,14 +1909,17 @@ New_Server( int Server , ng_ipaddr_t *dest)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
- Log(LOG_INFO, "Establishing connection for \"%s\" to \"%s\" (%s) port %d ... ",
|
|
|
|
- Conf_Server[Server].name, Conf_Server[Server].host, ip_str,
|
|
|
|
- Conf_Server[Server].port);
|
|
|
|
-
|
|
|
|
af_dest = ng_ipaddr_af(dest);
|
|
af_dest = ng_ipaddr_af(dest);
|
|
new_sock = socket(af_dest, SOCK_STREAM, 0);
|
|
new_sock = socket(af_dest, SOCK_STREAM, 0);
|
|
|
|
+
|
|
|
|
+ Log(LOG_INFO,
|
|
|
|
+ "Establishing connection for \"%s\" to \"%s:%d\" (%s), socket %d ...",
|
|
|
|
+ Conf_Server[Server].name, Conf_Server[Server].host,
|
|
|
|
+ Conf_Server[Server].port, ip_str, new_sock);
|
|
|
|
+
|
|
if (new_sock < 0) {
|
|
if (new_sock < 0) {
|
|
- Log( LOG_CRIT, "Can't create socket (af %d) : %s!", af_dest, strerror( errno ));
|
|
|
|
|
|
+ Log(LOG_CRIT, "Can't create socket (af %d): %s!",
|
|
|
|
+ af_dest, strerror(errno));
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1840,6 +1951,12 @@ New_Server( int Server , ng_ipaddr_t *dest)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if (!io_event_create( new_sock, IO_WANTWRITE, cb_connserver)) {
|
|
|
|
+ Log(LOG_ALERT, "io_event_create(): could not add fd %d", strerror(errno));
|
|
|
|
+ close(new_sock);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
My_Connections = array_start(&My_ConnArray);
|
|
My_Connections = array_start(&My_ConnArray);
|
|
|
|
|
|
assert(My_Connections[new_sock].sock <= 0);
|
|
assert(My_Connections[new_sock].sock <= 0);
|
|
@@ -1850,7 +1967,7 @@ New_Server( int Server , ng_ipaddr_t *dest)
|
|
c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWNSERVER, false);
|
|
c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWNSERVER, false);
|
|
if (!c) {
|
|
if (!c) {
|
|
Log( LOG_ALERT, "Can't establish connection: can't create client structure!" );
|
|
Log( LOG_ALERT, "Can't establish connection: can't create client structure!" );
|
|
- close( new_sock );
|
|
|
|
|
|
+ io_close(new_sock);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1867,13 +1984,6 @@ New_Server( int Server , ng_ipaddr_t *dest)
|
|
strlcpy( My_Connections[new_sock].host, Conf_Server[Server].host,
|
|
strlcpy( My_Connections[new_sock].host, Conf_Server[Server].host,
|
|
sizeof(My_Connections[new_sock].host ));
|
|
sizeof(My_Connections[new_sock].host ));
|
|
|
|
|
|
- /* Register new socket */
|
|
|
|
- if (!io_event_create( new_sock, IO_WANTWRITE, cb_connserver)) {
|
|
|
|
- Log( LOG_ALERT, "io_event_create(): could not add fd %d", strerror(errno));
|
|
|
|
- Conn_Close( new_sock, "io_event_create() failed", NULL, false );
|
|
|
|
- Init_Conn_Struct( new_sock );
|
|
|
|
- Conf_Server[Server].conn_id = NONE;
|
|
|
|
- }
|
|
|
|
#ifdef SSL_SUPPORT
|
|
#ifdef SSL_SUPPORT
|
|
if (Conf_Server[Server].SSLConnect && !ConnSSL_PrepareConnect( &My_Connections[new_sock],
|
|
if (Conf_Server[Server].SSLConnect && !ConnSSL_PrepareConnect( &My_Connections[new_sock],
|
|
&Conf_Server[Server] ))
|
|
&Conf_Server[Server] ))
|
|
@@ -1893,6 +2003,8 @@ New_Server( int Server , ng_ipaddr_t *dest)
|
|
|
|
|
|
/**
|
|
/**
|
|
* Initialize connection structure.
|
|
* Initialize connection structure.
|
|
|
|
+ *
|
|
|
|
+ * @param Idx Connection index.
|
|
*/
|
|
*/
|
|
static void
|
|
static void
|
|
Init_Conn_Struct(CONN_ID Idx)
|
|
Init_Conn_Struct(CONN_ID Idx)
|
|
@@ -1908,11 +2020,18 @@ Init_Conn_Struct(CONN_ID Idx)
|
|
} /* Init_Conn_Struct */
|
|
} /* Init_Conn_Struct */
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Initialize options of a new socket.
|
|
|
|
+ *
|
|
|
|
+ * For example, we try to set socket options SO_REUSEADDR and IPTOS_LOWDELAY.
|
|
|
|
+ * The socket is automatically closed if a fatal error is encountered.
|
|
|
|
+ *
|
|
|
|
+ * @param Sock Socket handle.
|
|
|
|
+ * @returns false if socket was closed due to fatal error.
|
|
|
|
+ */
|
|
static bool
|
|
static bool
|
|
Init_Socket( int Sock )
|
|
Init_Socket( int Sock )
|
|
{
|
|
{
|
|
- /* Initialize socket (set options) */
|
|
|
|
-
|
|
|
|
int value;
|
|
int value;
|
|
|
|
|
|
if (!io_setnonblock(Sock)) {
|
|
if (!io_setnonblock(Sock)) {
|
|
@@ -1945,6 +2064,13 @@ Init_Socket( int Sock )
|
|
} /* Init_Socket */
|
|
} /* Init_Socket */
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Read results of a resolver sub-process and try to initiate a new server
|
|
|
|
+ * connection.
|
|
|
|
+ *
|
|
|
|
+ * @param fd File descriptor of the pipe to the sub-process.
|
|
|
|
+ * @param events (ignored IO specification)
|
|
|
|
+ */
|
|
static void
|
|
static void
|
|
cb_Connect_to_Server(int fd, UNUSED short events)
|
|
cb_Connect_to_Server(int fd, UNUSED short events)
|
|
{
|
|
{
|
|
@@ -1999,13 +2125,16 @@ cb_Connect_to_Server(int fd, UNUSED short events)
|
|
} /* cb_Read_Forward_Lookup */
|
|
} /* cb_Read_Forward_Lookup */
|
|
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Read results of a resolver sub-process from the pipe and update the
|
|
|
|
+ * apropriate connection/client structure(s): hostname and/or IDENT user name.
|
|
|
|
+ *
|
|
|
|
+ * @param r_fd File descriptor of the pipe to the sub-process.
|
|
|
|
+ * @param events (ignored IO specification)
|
|
|
|
+ */
|
|
static void
|
|
static void
|
|
cb_Read_Resolver_Result( int r_fd, UNUSED short events )
|
|
cb_Read_Resolver_Result( int r_fd, UNUSED short events )
|
|
{
|
|
{
|
|
- /* Read result of resolver sub-process from pipe and update the
|
|
|
|
- * apropriate connection/client structure(s): hostname and/or
|
|
|
|
- * IDENT user name.*/
|
|
|
|
-
|
|
|
|
CLIENT *c;
|
|
CLIENT *c;
|
|
CONN_ID i;
|
|
CONN_ID i;
|
|
size_t len;
|
|
size_t len;
|
|
@@ -2057,13 +2186,22 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
|
|
strlcpy(My_Connections[i].host, readbuf,
|
|
strlcpy(My_Connections[i].host, readbuf,
|
|
sizeof(My_Connections[i].host));
|
|
sizeof(My_Connections[i].host));
|
|
Client_SetHostname(c, readbuf);
|
|
Client_SetHostname(c, readbuf);
|
|
|
|
+ if (Conf_NoticeAuth)
|
|
|
|
+ (void)Conn_WriteStr(i,
|
|
|
|
+ "NOTICE AUTH :*** Found your hostname");
|
|
#ifdef IDENTAUTH
|
|
#ifdef IDENTAUTH
|
|
++identptr;
|
|
++identptr;
|
|
if (*identptr) {
|
|
if (*identptr) {
|
|
Log(LOG_INFO, "IDENT lookup for connection %d: \"%s\".", i, identptr);
|
|
Log(LOG_INFO, "IDENT lookup for connection %d: \"%s\".", i, identptr);
|
|
Client_SetUser(c, identptr, true);
|
|
Client_SetUser(c, identptr, true);
|
|
|
|
+ if (Conf_NoticeAuth)
|
|
|
|
+ (void)Conn_WriteStr(i,
|
|
|
|
+ "NOTICE AUTH :*** Got ident response");
|
|
} else {
|
|
} else {
|
|
Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i);
|
|
Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i);
|
|
|
|
+ if (Conf_NoticeAuth && Conf_Ident)
|
|
|
|
+ (void)Conn_WriteStr(i,
|
|
|
|
+ "NOTICE AUTH :*** No ident response");
|
|
}
|
|
}
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
@@ -2075,9 +2213,14 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
|
|
|
|
|
|
/**
|
|
/**
|
|
* Write a "simple" (error) message to a socket.
|
|
* Write a "simple" (error) message to a socket.
|
|
|
|
+ *
|
|
* The message is sent without using the connection write buffers, without
|
|
* The message is sent without using the connection write buffers, without
|
|
* compression/encryption, and even without any error reporting. It is
|
|
* compression/encryption, and even without any error reporting. It is
|
|
- * designed for error messages of e.g. New_Connection(). */
|
|
|
|
|
|
+ * designed for error messages of e.g. New_Connection().
|
|
|
|
+ *
|
|
|
|
+ * @param Sock Socket handle.
|
|
|
|
+ * @param Msg Message string to send.
|
|
|
|
+ */
|
|
static void
|
|
static void
|
|
Simple_Message(int Sock, const char *Msg)
|
|
Simple_Message(int Sock, const char *Msg)
|
|
{
|
|
{
|
|
@@ -2106,8 +2249,9 @@ Simple_Message(int Sock, const char *Msg)
|
|
* Get CLIENT structure that belongs to a local connection identified by its
|
|
* Get CLIENT structure that belongs to a local connection identified by its
|
|
* index number. Each connection belongs to a client by definition, so it is
|
|
* index number. Each connection belongs to a client by definition, so it is
|
|
* not required that the caller checks for NULL return values.
|
|
* not required that the caller checks for NULL return values.
|
|
- * @param Idx Connection index number
|
|
|
|
- * @return Pointer to CLIENT structure
|
|
|
|
|
|
+ *
|
|
|
|
+ * @param Idx Connection index number.
|
|
|
|
+ * @returns Pointer to CLIENT structure.
|
|
*/
|
|
*/
|
|
GLOBAL CLIENT *
|
|
GLOBAL CLIENT *
|
|
Conn_GetClient( CONN_ID Idx )
|
|
Conn_GetClient( CONN_ID Idx )
|
|
@@ -2122,8 +2266,9 @@ Conn_GetClient( CONN_ID Idx )
|
|
|
|
|
|
/**
|
|
/**
|
|
* Get PROC_STAT sub-process structure of a connection.
|
|
* Get PROC_STAT sub-process structure of a connection.
|
|
- * @param Idx Connection index number
|
|
|
|
- * @return PROC_STAT structure
|
|
|
|
|
|
+ *
|
|
|
|
+ * @param Idx Connection index number.
|
|
|
|
+ * @returns PROC_STAT structure.
|
|
*/
|
|
*/
|
|
GLOBAL PROC_STAT *
|
|
GLOBAL PROC_STAT *
|
|
Conn_GetProcStat(CONN_ID Idx)
|
|
Conn_GetProcStat(CONN_ID Idx)
|
|
@@ -2139,8 +2284,9 @@ Conn_GetProcStat(CONN_ID Idx)
|
|
|
|
|
|
/**
|
|
/**
|
|
* Get CONN_ID from file descriptor associated to a subprocess structure.
|
|
* Get CONN_ID from file descriptor associated to a subprocess structure.
|
|
- * @param fd File descriptor
|
|
|
|
- * @return CONN_ID or NONE (-1)
|
|
|
|
|
|
+ *
|
|
|
|
+ * @param fd File descriptor.
|
|
|
|
+ * @returns CONN_ID or NONE (-1).
|
|
*/
|
|
*/
|
|
GLOBAL CONN_ID
|
|
GLOBAL CONN_ID
|
|
Conn_GetFromProc(int fd)
|
|
Conn_GetFromProc(int fd)
|
|
@@ -2157,14 +2303,34 @@ Conn_GetFromProc(int fd)
|
|
} /* Conn_GetFromProc */
|
|
} /* Conn_GetFromProc */
|
|
|
|
|
|
|
|
|
|
|
|
+#ifndef STRICT_RFC
|
|
|
|
+
|
|
|
|
+GLOBAL long
|
|
|
|
+Conn_GetAuthPing(CONN_ID Idx)
|
|
|
|
+{
|
|
|
|
+ assert (Idx != NONE);
|
|
|
|
+ return My_Connections[Idx].auth_ping;
|
|
|
|
+} /* Conn_GetAuthPing */
|
|
|
|
+
|
|
|
|
+GLOBAL void
|
|
|
|
+Conn_SetAuthPing(CONN_ID Idx, long ID)
|
|
|
|
+{
|
|
|
|
+ assert (Idx != NONE);
|
|
|
|
+ My_Connections[Idx].auth_ping = ID;
|
|
|
|
+} /* Conn_SetAuthPing */
|
|
|
|
+
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+
|
|
#ifdef SSL_SUPPORT
|
|
#ifdef SSL_SUPPORT
|
|
|
|
|
|
/**
|
|
/**
|
|
* Get information about used SSL chiper.
|
|
* Get information about used SSL chiper.
|
|
- * @param Idx Connection index number
|
|
|
|
- * @param buf Buffer for returned information text
|
|
|
|
- * @param len Size of return buffer "buf"
|
|
|
|
- * @return true on success, false otherwise
|
|
|
|
|
|
+ *
|
|
|
|
+ * @param Idx Connection index number.
|
|
|
|
+ * @param buf Buffer for returned information text.
|
|
|
|
+ * @param len Size of return buffer "buf".
|
|
|
|
+ * @returns true on success, false otherwise.
|
|
*/
|
|
*/
|
|
GLOBAL bool
|
|
GLOBAL bool
|
|
Conn_GetCipherInfo(CONN_ID Idx, char *buf, size_t len)
|
|
Conn_GetCipherInfo(CONN_ID Idx, char *buf, size_t len)
|
|
@@ -2178,8 +2344,9 @@ Conn_GetCipherInfo(CONN_ID Idx, char *buf, size_t len)
|
|
|
|
|
|
/**
|
|
/**
|
|
* Check if a connection is SSL-enabled or not.
|
|
* Check if a connection is SSL-enabled or not.
|
|
- * @param Idx Connection index number
|
|
|
|
- * @return true if connection is SSL-enabled, false otherwise.
|
|
|
|
|
|
+ *
|
|
|
|
+ * @param Idx Connection index number.
|
|
|
|
+ * @return true if connection is SSL-enabled, false otherwise.
|
|
*/
|
|
*/
|
|
GLOBAL bool
|
|
GLOBAL bool
|
|
Conn_UsesSSL(CONN_ID Idx)
|
|
Conn_UsesSSL(CONN_ID Idx)
|
|
@@ -2195,6 +2362,9 @@ Conn_UsesSSL(CONN_ID Idx)
|
|
|
|
|
|
#ifdef DEBUG
|
|
#ifdef DEBUG
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * Dump internal state of the "connection module".
|
|
|
|
+ */
|
|
GLOBAL void
|
|
GLOBAL void
|
|
Conn_DebugDump(void)
|
|
Conn_DebugDump(void)
|
|
{
|
|
{
|