/*
* ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2013 Alexander Barton (alex@barton.de) and Contributors.
+ * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#define SD_LISTEN_FDS_START 3
-
static bool Handle_Write PARAMS(( CONN_ID Idx ));
static bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, size_t Len ));
static int New_Connection PARAMS(( int Sock, bool IsSSL ));
static int NewListener PARAMS(( const char *listen_addr, UINT16 Port ));
static void Account_Connection PARAMS((void));
-
static array My_Listeners;
static array My_ConnArray;
static size_t NumConnections, NumConnectionsMax, NumConnectionsAccepted;
if (!e || !*e)
return -1;
count = atoi(e);
+#ifdef HAVE_UNSETENV
unsetenv("LISTEN_FDS");
+#endif
return count;
}
return false;
}
-#else
-
-static inline bool
-SSL_WantRead(UNUSED const CONNECTION *c)
-{ return false; }
-
-static inline bool
-SSL_WantWrite(UNUSED const CONNECTION *c)
-{ return false; }
-
#endif
if (wdatalen > 0)
#endif
{
+#ifdef SSL_SUPPORT
if (SSL_WantRead(&My_Connections[i]))
continue;
+#endif
io_event_add(My_Connections[i].sock,
IO_WANTWRITE);
}
size_t len;
bool ok;
va_list ap;
+ int r;
assert( Idx > NONE );
assert( Format != NULL );
#else
va_start( ap );
#endif
- if (vsnprintf( buffer, COMMAND_LEN - 2, Format, ap ) >= COMMAND_LEN - 2 ) {
+ r = vsnprintf(buffer, COMMAND_LEN - 2, Format, ap);
+ if (r >= COMMAND_LEN - 2 || r == -1) {
/*
* The string that should be written to the socket is longer
* than the allowed size of COMMAND_LEN bytes (including both
* an other server only routing the message!), so the only
* option left is to shorten the string and to hope that the
* result is still somewhat useful ...
+ *
+ * Note:
+ * C99 states that vsnprintf() "returns the number of characters
+ * that would have been printed if the n were unlimited"; but
+ * according to the Linux manual page "glibc until 2.0.6 would
+ * return -1 when the output was truncated" -- so we have to
+ * handle both cases ...
* -alex-
*/
/* Is this link already shutting down? */
if( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ISCLOSING )) {
/* Conn_Close() has been called recursively for this link;
- * probabe reason: Handle_Write() failed -- see below. */
- LogDebug("Recursive request to close connection: %d", Idx );
+ * probable reason: Handle_Write() failed -- see below. */
+ LogDebug("Recursive request to close connection %d!", Idx );
return;
}
if (errno == EAGAIN || errno == EINTR)
return true;
- Log(LOG_ERR, "Write error on connection %d (socket %d): %s!",
- Idx, My_Connections[Idx].sock, strerror(errno));
+ if (!Conn_OPTION_ISSET(&My_Connections[Idx], CONN_ISCLOSING))
+ Log(LOG_ERR,
+ "Write error on connection %d (socket %d): %s!",
+ Idx, My_Connections[Idx].sock, strerror(errno));
+ else
+ LogDebug("Recursive write error on connection %d (socket %d): %s!",
+ Idx, My_Connections[Idx].sock, strerror(errno));
Conn_Close(Idx, "Write error", NULL, false);
return false;
}
#endif
(void)Conn_WriteStr(Idx,
"NOTICE AUTH :*** Looking up your hostname");
- (void)Handle_Write(Idx);
+ /* Send buffered data to the client, but break on errors
+ * because Handle_Write() would have closed the connection
+ * again in this case! */
+ if (!Handle_Write(Idx))
+ return;
}
Resolve_Addr(&My_Connections[Idx].proc_stat, &My_Connections[Idx].addr,
ptr2 = strchr(array_start(&My_Connections[Idx].rbuf), '\n');
if (ptr) {
/* Check if there is a single CR or LF _before_ the
- * corerct CR+LF line terminator: */
+ * correct CR+LF line terminator: */
first_eol = ptr1 < ptr2 ? ptr1 : ptr2;
if (first_eol < ptr) {
/* Single CR or LF before CR+LF found */
if (!ng_ipaddr_tostr_r(dest, ip_str)) {
Log(LOG_WARNING, "New_Server: Could not convert IP to string");
+ Conf_Server[Server].conn_id = NONE;
return;
}
if (new_sock < 0) {
Log(LOG_CRIT, "Can't create socket (af %d): %s!",
af_dest, strerror(errno));
+ Conf_Server[Server].conn_id = NONE;
return;
}
- if (!Init_Socket(new_sock))
+ if (!Init_Socket(new_sock)) {
+ Conf_Server[Server].conn_id = NONE;
return;
+ }
/* is a bind address configured? */
res = ng_ipaddr_af(&Conf_Server[Server].bind_addr);
if(( res != 0 ) && ( errno != EINPROGRESS )) {
Log( LOG_CRIT, "Can't connect socket: %s!", strerror( errno ));
close( new_sock );
+ Conf_Server[Server].conn_id = NONE;
return;
}
"Cannot allocate memory for server connection (socket %d)",
new_sock);
close( new_sock );
+ Conf_Server[Server].conn_id = NONE;
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);
+ Conf_Server[Server].conn_id = NONE;
return;
}
if (!c) {
Log( LOG_ALERT, "Can't establish connection: can't create client structure!" );
io_close(new_sock);
+ Conf_Server[Server].conn_id = NONE;
return;
}
*ptr ? "" : ": ",
*ptr ? "" : identptr);
}
- } else {
+ } else if(Conf_Ident) {
Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i);
- if (Conf_NoticeAuth && Conf_Ident)
+ if (Conf_NoticeAuth)
(void)Conn_WriteStr(i,
"NOTICE AUTH :*** No ident response");
}
#endif
- if (Conf_NoticeAuth)
- (void)Handle_Write(i);
+ if (Conf_NoticeAuth) {
+ /* Send buffered data to the client, but break on
+ * errors because Handle_Write() would have closed
+ * the connection again in this case! */
+ if (!Handle_Write(i))
+ return;
+ }
Class_HandleServerBans(c);
}
#ifdef DEBUG
- else Log( LOG_DEBUG, "Resolver: discarding result for already registered connection %d.", i );
+ else
+ LogDebug("Resolver: discarding result for already registered connection %d.", i);
#endif
} /* cb_Read_Resolver_Result */