/*
* ----------------------------------------------------------------
* Night Light IRC Proxy - Listen I/O Functions
* ----------------------------------------------------------------
* Copyright (C) 1997-2007 Jonas Kvinge <jonas@night-light.net>
* All rights reserved.
*
* 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Last modified by:
* Jonas Kvinge (15.11.2006)
*
*/
#define LISTEN_IO_C
#define NEED_SYS_TYPES_H 1 /* Extra types */
#define NEED_SYS_PARAM_H 1 /* Some systems need this */
#define NEED_LIMITS_H 0 /* Kernel limits */
#define NEED_STDARG_H 1 /* va_list, etc */
#define NEED_ERRNO_H 1 /* errno */
#define NEED_CTYPE_H 1 /* isdigit(), etc */
#define NEED_NETINET_IN_H 1 /* in_addr, sockaddr_in, etc */
#define NEED_ARPA_INET_H 1 /* inet_ntoa(), inet_aton(), etc */
#define NEED_STDIO_H 1 /* Standard C UNIX functions */
#define NEED_STDLIB_H 1 /* malloc(), exit(), atoi(), etc */
#define NEED_TIME_H 1 /* time(), etc */
#define NEED_SYSCTL_H 0 /* sysctl(), etc */
#define NEED_SYS_STAT_H 0 /* chmod(), mkdir(), etc */
#define NEED_SYS_UIO_H 0 /* iovec, etc */
#define NEED_FCNTL_H 1 /* open(), creat(), fcntl(), etc */
#define NEED_SYS_IOCTL_H 1 /* ioctl(), etc */
#define NEED_SYS_FILIO_H 1 /* Solaris need this for ioctl(), etc */
#define NEED_UNISTD_H 1 /* Unix standard functions */
#define NEED_STRING_H 1 /* C string functions */
#define NEED_SIGNAL_H 0 /* Signal functions */
#define NEED_SYS_SOCKET_H 1 /* Socket functions */
#define NEED_NETDB_H 1 /* Network database functions */
#define NEED_ARPA_NAMESER_H 0 /* Nameserver definitions */
#define NEED_GETUSERPW_HEADERS 0 /* Functions to retrive system passwords */
#define NEED_ARES 1 /* Functions needed for ares */
#define NEED_SSL 1 /* Needed for SSL support */
#include "includes.h"
#include "conf.h"
#include "listen.h"
#include "listen_io.h"
#include "client.h"
#include "client_connection.h"
/* VARIABLES - JONAS (06.10.2000) */
extern struct Conf_Struct ConfS;
extern struct Listen_Struct *Listen_Head;
extern struct Listen_Struct *Listen_Tail;
extern struct Client_Struct *Client_Head;
#if ARES
extern ares_channel Ares_Channel;
#endif
#if SSL_SUPPORT
extern SSL_CTX *IRCPROXY_SSL_SERVER_CTX;
extern SSL_CTX *IRCPROXY_SSL_CLIENT_CTX;
#endif
/* LISTEN_START - JONAS (22.07.2001) */
void listen_start(struct Listen_Struct *ListenS) {
signed long int Result = 0;
struct sockaddr_in SockAddr = { 0 };
#if IPV6_SUPPORT
struct sockaddr_in6 SockAddr6 = { 0 };
#endif
unsigned long int Flags = 0;
assert(ListenS != NULL);
ListenS->Time = NOW;
++ListenS->Tries;
DEBUGPRINT(BITMASK_DEBUG_LISTEN, "*** DEBUG *** listen_start(%s)", ListenS->Host);
if (!Listen_IsResolved(ListenS)) {
#if !ARES
struct hostent *HostEnt = NULL;
#endif
if (ListenS->Host[0] == '*') {
#if IPV6_SUPPORT
if (Listen_IsIPv6(ListenS)) {
memset(&ListenS->INAddr6, 0, sizeof(ListenS->INAddr6));
ListenS->INAddr6 = in6addr_any;
}
else {
#endif /* IPV6_SUPPORT */
memset(&ListenS->INAddr, 0, sizeof(ListenS->INAddr));
ListenS->INAddr.s_addr = INADDR_ANY;
#if IPV6_SUPPORT
}
#endif /* IPV6_SUPPORT */
ListenS->HostIPS = strrealloc(ListenS->HostIPS, "ALL");
Listen_SetResolved(ListenS);
}
else {
#if IPV6_SUPPORT
if (Listen_IsIPv6(ListenS)) {
memset(&ListenS->INAddr6, 0, sizeof(ListenS->INAddr6));
Result = inet_pton(AF_INET6, ListenS->Host, &ListenS->INAddr6);
}
else {
memset(&ListenS->INAddr, 0, sizeof(ListenS->INAddr));
Result = inet_pton(AF_INET, ListenS->Host, &ListenS->INAddr);
}
#else /* IPV6_SUPPORT */
memset(&ListenS->INAddr, 0, sizeof(ListenS->INAddr));
Result = inet_aton(ListenS->Host, &ListenS->INAddr);
#endif /* IPV6_SUPPORT */
if (Result <= 0) {
Listen_SetResolving(ListenS);
#if ARES
#if IPV6_SUPPORT
if (Listen_IsIPv6(ListenS)) {
ares_gethostbyname(Ares_Channel, ListenS->Host, AF_INET6, (ares_host_callback) listen_hosttoip, ListenS);
}
else {
#endif /* IPV6_SUPPORT */
ares_gethostbyname(Ares_Channel, ListenS->Host, AF_INET, (ares_host_callback) listen_hosttoip, ListenS);
#if IPV6_SUPPORT
}
#endif /* IPV6_SUPPORT */
return;
#else /* ARES */
#if IPV6_SUPPORT
if (Listen_IsIPv6(ListenS)) { HostEnt = gethostbyname2(ListenS->Host, AF_INET6); }
else { HostEnt = gethostbyname2(ListenS->Host, AF_INET); }
#else /* IPV6_SUPPORT */
HostEnt = gethostbyname(ListenS->Host);
#endif /* IPV6_SUPPORT */
listen_hosttoip(ListenS, errno, HostEnt);
if (!Listen_IsResolved(ListenS)) { return; }
#endif /* ARES */
}
else {
Listen_SetResolved(ListenS);
ListenS->HostIPS = strrealloc(ListenS->HostIPS, ListenS->Host);
if (aerrno != AESUCCESS) { listen_init(ListenS); return; }
}
}
}
/* CREATE SOCKET */
#if IPV6_SUPPORT
if (Listen_IsIPv6(ListenS)) {
Result = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
}
else {
#endif
Result = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
#if IPV6_SUPPORT
}
#endif
if (Result <= ERROR) {
sysprint(BITMASK_MAIN, "Listener %s(%s):%ld%s: Unable to create socket: [%d] %s", ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
listen_stop(ListenS);
return;
}
ListenS->FD = Result;
Listen_SetSocket(ListenS);
/* SET SOCKET IN NON-BLOCKING MODE */
#if defined(NBLOCK_SYSV)
Flags = 1;
Result = ioctl(ListenS->FD, FIONBIO, &Flags);
if (Result <= ERROR) {
sysprint(BITMASK_MAIN, "Listener %s(%s):%ld%s: Unable to set socket in non-blocking mode using ioctl(): [%d] %s", ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
listen_stop(ListenS);
return;
}
#else
Result = fcntl(ListenS->FD, F_GETFL, &Flags);
if (Result <= ERROR) {
sysprint(BITMASK_MAIN, "Listener %s(%s):%ld%s: Unable to get socket flags using fcntl(): [%d] %s", ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
listen_stop(ListenS);
return;
}
#if defined(NBLOCK_BSD)
Flags |= O_NDELAY;
#elif defined(NBLOCK_POSIX)
Flags |= O_NONBLOCK;
#else
#warning "This system does not support non-blocking sockets?"
Flags |= O_NONBLOCK;
#endif
Result = fcntl(ListenS->FD, F_SETFL, Flags);
if (Result <= ERROR) {
sysprint(BITMASK_MAIN, "Listener %s(%s):%ld%s: Unable to set socket in non-blocking mode using fcntl(): [%d] %s", ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
listen_stop(ListenS);
return;
}
#endif
if (LISTEN_SOCKKEEPALIVE == TRUE) {
unsigned long int OPT = 1;
Result = setsockopt(ListenS->FD, SOL_SOCKET, SO_KEEPALIVE, &OPT, sizeof(OPT));
if (Result <= ERROR) {
sysprint(BITMASK_MAIN, "Listener %s(%s):%ld%s: Unable to set Keep Alive option for socket: [%d] %s", ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
listen_stop(ListenS);
return;
}
}
if (LISTEN_SOCKREUSEADDR == TRUE) {
unsigned long int OPT = 1;
Result = setsockopt(ListenS->FD, SOL_SOCKET, SO_REUSEADDR, &OPT, sizeof(OPT));
if (Result <= ERROR) {
sysprint(BITMASK_MAIN, "Listener %s(%s):%ld%s: Unable to set Reuse Address option for socket: [%d] %s", ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
listen_stop(ListenS);
return;
}
}
/* BIND */
#if !WIN32
if (ListenS->PortH < 1024) { sysseteuid(0); }
#endif
#if IPV6_SUPPORT
if (Listen_IsIPv6(ListenS)) {
memset(&SockAddr6, 0, sizeof(SockAddr6));
SockAddr6.sin6_family = AF_INET6;
SockAddr6.sin6_addr = ListenS->INAddr6;
SockAddr6.sin6_port = ListenS->PortN;
Result = bind(ListenS->FD, (struct sockaddr *) &SockAddr6, sizeof(SockAddr6));
}
else {
#endif /* IPV6_SUPPORT */
memset(&SockAddr, 0, sizeof(SockAddr));
SockAddr.sin_family = AF_INET;
SockAddr.sin_addr = ListenS->INAddr;
SockAddr.sin_port = ListenS->PortN;
Result = bind(ListenS->FD, (struct sockaddr *) &SockAddr, sizeof(SockAddr));
#if IPV6_SUPPORT
}
#endif /* IPV6_SUPPORT */
#if !WIN32
if (ListenS->PortH < 1024) { sysseteuidnormal(); }
#endif
if (Result <= ERROR) {
sysprint(BITMASK_MAIN, "Listener %s(%s):%ld%s: Unable to bind socket to address: [%d] %s", ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
listen_stop(ListenS);
return;
}
/* LISTEN */
Result = listen(ListenS->FD, SOMAXCONN);
if (Result <= ERROR) {
sysprint(BITMASK_MAIN, "Listener %s(%s):%ld%s: Unable to listen on address: [%d] %s", ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
listen_stop(ListenS);
return;
}
else {
sysprint(BITMASK_MAIN, "Listening on %s(%s):%ld%s for incoming connections.", ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""));
Listen_SetListening(ListenS);
return;
}
}
/* LISTEN_HOSTTOIP FUNCTION - JONAS (01.03.2000) */
#if HAVE_CARES_CALLBACK_TIMEOUTS
void listen_hosttoip(void *ArgPT, int ErrNo, int Timeouts, struct hostent *HostEnt) {
#else
void listen_hosttoip(void *ArgPT, int ErrNo, struct hostent *HostEnt) {
#endif
struct Listen_Struct *ListenS = ArgPT;
const char *HostIPPT = NULL;
#if IPV6_SUPPORT
char Host[INET6_ADDRSTRLEN+1] = "";
#endif
assert(ListenS != NULL);
if ((HostEnt == NULL) || (HostEnt->h_length < 1)) {
sysprint(BITMASK_MAIN, "Listener %s:%ld%s: Unable to resolve host %s to IP-address: [%d] %s", ListenS->Host, ListenS->PortH, ListenS->Host, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), ErrNo, res_strerror(ErrNo));
listen_init(ListenS);
return;
}
#if IPV6_SUPPORT
if (Listen_IsIPv6(ListenS)) {
memset(&ListenS->INAddr6, 0, sizeof(ListenS->INAddr6));
memcpy(&ListenS->INAddr6, HostEnt->h_addr, HostEnt->h_length);
HostIPPT = inet_ntop(AF_INET6, &ListenS->INAddr6, Host, INET6_ADDRSTRLEN);
if (HostIPPT == NULL) {
sysprint(BITMASK_MAIN, "Listener %s:%ld%s: inet_ntop() failed: [%d] %s", ListenS->Host, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
listen_init(ListenS);
return;
}
}
else {
memset(&ListenS->INAddr, 0, sizeof(ListenS->INAddr));
memcpy(&ListenS->INAddr, HostEnt->h_addr, HostEnt->h_length);
HostIPPT = inet_ntop(AF_INET, &ListenS->INAddr, Host, INET_ADDRSTRLEN);
if (HostIPPT == NULL) {
sysprint(BITMASK_MAIN, "Listener %s:%ld%s: inet_ntop() failed: [%d] %s", ListenS->Host, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
listen_init(ListenS);
return;
}
}
#else /* IPV6_SUPPORT */
memset(&ListenS->INAddr, 0, sizeof(ListenS->INAddr));
memcpy(&ListenS->INAddr, HostEnt->h_addr, HostEnt->h_length);
HostIPPT = inet_ntoa(ListenS->INAddr);
if (HostIPPT == NULL) {
sysprint(BITMASK_MAIN, "Listener %s:%ld%s: inet_ntoa() failed: [%d] %s", ListenS->Host, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
listen_init(ListenS);
return;
}
#endif
ListenS->HostIPS = strrealloc(ListenS->HostIPS, HostIPPT);
if (ListenS->HostIPS == NULL) {
listen_init(ListenS);
return;
}
Listen_ClearResolving(ListenS);
Listen_SetResolved(ListenS);
#if ARES
listen_start(ListenS);
#endif
}
/* LISTEN_STOP - JONAS (05.10.2000) */
void listen_stop(struct Listen_Struct *ListenS) {
assert(ListenS != NULL);
if (Listen_IsResolving(ListenS)) {
#if HAVE_ARES_CANCELQUERY
ares_cancelquery(Ares_Channel, ListenS);
#endif
return;
}
if (Listen_IsListening(ListenS)) { sysprint(BITMASK_MAIN, "Listener %s(%s):%ld%s has stopped.", ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : "")); }
if (Listen_IsSocket(ListenS)) {
close(ListenS->FD);
ListenS->FD = FD_NONE;
}
listen_init(ListenS);
}
/* LISTEN_FDS - JONAS (22.07.2001) */
void listen_fds(fd_set *ReadFDS, fd_set *WriteFDS, unsigned long int *FDS) {
struct Listen_Struct *ListenS = NULL;
for (ListenS = Listen_Head ; ListenS != NULL ;) {
if (Listen_IsRemove(ListenS)) {
struct Listen_Struct *ListenS_DEL = NULL;
if (Listen_IsResolving(ListenS)) { continue; }
listen_stop(ListenS);
ListenS_DEL = ListenS;
ListenS = ListenS->Next;
listen_rem(ListenS_DEL);
continue;
}
if (Listen_IsListening(ListenS)) { FD_SET(ListenS->FD, ReadFDS); }
else {
if (!Listen_IsResolving(ListenS)) {
time_t Duration = (NOW - ListenS->Time);
if (Duration >= LISTEN_INTERVAL) {
#if SSL_SUPPORT
if (ConfS.SSLSupport == TRUE) { listen_start(ListenS); }
else if (!Listen_IsSSL(ListenS)) { listen_start(ListenS); }
#else
if (!Listen_IsSSL(ListenS)) { listen_start(ListenS); }
#endif
}
}
}
ListenS = ListenS->Next;
}
}
/* LISTEN_IO - JONAS (06.10.2000) */
void listen_io(fd_set *ReadFDS, fd_set *WriteFDS, unsigned long int *FDS) {
struct Listen_Struct *ListenS = NULL;
for (ListenS = Listen_Head ; ListenS != NULL ; ListenS = ListenS->Next) {
unsigned short int Count = 0;
assert(*FDS >= 0);
if (*FDS <= 0) { return; }
if (!Listen_IsListening(ListenS)) { continue; }
if (!FD_ISSET(ListenS->FD, ReadFDS)) { continue; }
*FDS = *FDS - 1;
assert(*FDS >= 0);
for (Count = 0 ;; ++Count) {
signed long int Result = 0;
unsigned long int Flags = 0;
struct sockaddr_in SockAddr = { 0 };
accept_addrlen_type SockAddrLen = sizeof(SockAddr);
#if IPV6_SUPPORT
struct sockaddr_in6 SockAddr6 = { 0 };
accept_addrlen_type SockAddrLen6 = sizeof(SockAddr6);
#endif
unsigned long int FD = 0;
struct in_addr INAddr;
#if IPV6_SUPPORT
struct in6_addr INAddr6;
#endif
unsigned long int PortH = 0;
unsigned long int PortN = 0;
const char *HostIPPT = NULL;
struct Client_Struct *ClientS = NULL;
char Host[INET6_ADDRSTRLEN+1] = "";
#if SSL_SUPPORT
SSL *ClientSSL = NULL;
#endif
#if IPV6_SUPPORT
if (Listen_IsIPv6(ListenS)) {
Result = accept(ListenS->FD, (struct sockaddr *) &SockAddr6, &SockAddrLen6);
}
else {
#endif /* IPV6_SUPPORT */
Result = accept(ListenS->FD, (struct sockaddr *) &SockAddr, &SockAddrLen);
#if IPV6_SUPPORT
}
#endif /* IPV6_SUPPORT */
if (Result <= ERROR) {
if (Count == 0) { sysprint(BITMASK_MAIN, "Unable to accept incoming connection on address \"%s(%s):%ld\": [%d] %s", ListenS->Host, ListenS->HostIPS, ListenS->PortH, errno, strerror(errno)); }
return;
}
FD = Result;
#if SSL_SUPPORT
if ((Listen_IsSSL(ListenS)) && (IRCPROXY_SSL_SERVER_CTX == NULL)) { /* This is fatal and should never happen under normal circumstances */
sysprint(BITMASK_MAIN, "Closing socket to incoming connection on address \"%s(%s):%ld\": Missing SSL_CTX object.", ListenS->Host, ListenS->HostIPS, ListenS->PortH);
close(FD);
continue;
}
#endif
#if IPV6_SUPPORT
if (Listen_IsIPv6(ListenS)) {
memset(&INAddr6, 0, sizeof(INAddr6));
INAddr6 = SockAddr6.sin6_addr;
PortN = SockAddr6.sin6_port;
}
else {
#endif /* IPV6_SUPPORT */
memset(&INAddr, 0, sizeof(INAddr));
INAddr = SockAddr.sin_addr;
PortN = SockAddr.sin_port;
#if IPV6_SUPPORT
}
#endif /* IPV6_SUPPORT */
PortH = ntohs(PortN);
#if IPV6_SUPPORT
if (Listen_IsIPv6(ListenS)) {
HostIPPT = inet_ntop(AF_INET6, &INAddr6, Host, INET6_ADDRSTRLEN);
if (HostIPPT == NULL) {
close(FD);
sysprint(BITMASK_MAIN, "Failed inet_ntop() for incoming client connection on \"%s(%s):%ld%s\": [%d] %s", ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
continue;
}
}
else {
HostIPPT = inet_ntop(AF_INET, &INAddr, Host, INET6_ADDRSTRLEN);
if (HostIPPT == NULL) {
close(FD);
sysprint(BITMASK_MAIN, "Failed inet_ntop() for incoming client connection on \"%s(%s):%ld%s\": [%d] %s", ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
continue;
}
}
#else
HostIPPT = inet_ntoa(INAddr);
if (HostIPPT == NULL) {
close(FD);
sysprint(BITMASK_MAIN, "Failed inet_ntoa() for incoming client connection on \"%s(%s):%ld%s\": [%d] %s", ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
continue;
}
#endif
sysprint(BITMASK_MAIN, "Incoming client connection from \"%s:%ld\" on \"%s(%s):%ld%s\".", HostIPPT, PortH, ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""));
/* SET SOCKET IN NON-BLOCKING MODE */
#if defined(NBLOCK_SYSV)
Flags = 1;
Result = ioctl(FD, FIONBIO, &Flags);
if (Result <= ERROR) {
sysprint(BITMASK_MAIN, "Unable to set socket in non-blocking mode using ioctl() for incoming client \"%s:%ld\" on \"%s(%s):%ld%s\".: [%d] %s", HostIPPT, PortH, ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
close(FD);
continue;
}
#else
Result = fcntl(FD, F_GETFL, &Flags);
if (Result <= ERROR) {
sysprint(BITMASK_MAIN, "Unable to get socket flags using fcntl() for incoming client \"%s:%ld\" on \"%s(%s):%ld%s\".: [%d] %s", HostIPPT, PortH, ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
close(FD);
continue;
}
#if defined(NBLOCK_BSD)
Flags |= O_NDELAY;
#elif defined(NBLOCK_POSIX)
Flags |= O_NONBLOCK;
#else
#warning "This system does not support non-blocking sockets?"
Flags |= O_NONBLOCK;
#endif
Result = fcntl(FD, F_SETFL, Flags);
if (Result <= ERROR) {
sysprint(BITMASK_MAIN, "Unable to set socket in non-blocking mode using fcntl() for incoming client \"%s:%ld\" on \"%s(%s):%ld%s\".: [%d] %s", HostIPPT, PortH, ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
close(FD);
continue;
}
#endif
#if SSL_SUPPORT
if (Listen_IsSSL(ListenS)) {
assert(IRCPROXY_SSL_SERVER_CTX != NULL);
ClientSSL = SSL_new(IRCPROXY_SSL_SERVER_CTX);
if (ClientSSL == NULL) {
close(FD);
sysprint(BITMASK_MAIN, "Failed to create a new SSL structure for incoming client connection from \"%s:%ld\" on \"%s(%s):%ld%s\".: [%d] %s.", HostIPPT, PortH, ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), errno, strerror(errno));
continue;
}
Result = SSL_set_fd(ClientSSL, FD);
if (Result <= 0) {
signed long int sslerrno = SSL_get_error(ClientSSL, Result);
close(FD);
SSL_free(ClientSSL);
sysprint(BITMASK_MAIN, "Failed to connect the SSL object with file descriptor for incoming client connection from \"%s:%ld\" on \"%s(%s):%ld%s\".: [%ld] %s.", HostIPPT, PortH, ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""), sslerrno, ERR_error_string(sslerrno, NULL));
continue;
}
SSL_set_accept_state(ClientSSL);
}
#endif /* SSL_SUPPORT */
ClientS = client_add(ListenS, HostIPPT);
if (ClientS == NULL) {
close(FD);
#if SSL_SUPPORT
SSL_free(ClientSSL);
#endif
sysprint(BITMASK_MAIN, "Failed to allocate client structure for incoming client connection from \"%s:%ld\" on \"%s(%s):%ld%s\".", HostIPPT, PortH, ListenS->Host, ListenS->HostIPS, ListenS->PortH, (Listen_IsSSL(ListenS) ? "(SSL)" : ""));
continue;
}
ClientS->FD = FD;
ClientS->HostIPS = strrealloc(ClientS->HostIPS, HostIPPT);
ClientS->PortH = PortH;
ClientS->PortN = PortN;
#if IPV6_SUPPORT
if (Listen_IsIPv6(ListenS)) {
memset(&ClientS->INAddr6, 0, sizeof(ClientS->INAddr6));
ClientS->INAddr6 = INAddr6;
Client_SetIPv6(ClientS);
}
else {
#endif
memset(&ClientS->INAddr, 0, sizeof(ClientS->INAddr));
ClientS->INAddr = INAddr;
#if IPV6_SUPPORT
}
#endif
#if SSL_SUPPORT
if (Listen_IsSSL(ListenS)) {
Client_SetSSL(ClientS);
ClientS->SSL_H = ClientSSL;
}
#endif
client_resolve(ClientS);
}
}
}
/* LISTEN_CLOSEALL FUNCTION - JONAS (09.06.2001) */
unsigned short int listen_closeall(const char *const MessagePT, ...) {
struct Listen_Struct *ListenS = NULL;
struct Listen_Struct *ListenS_DEL = NULL;
unsigned short int Count = 0;
for (ListenS = Listen_Head ; ListenS != NULL ;) {
if (Listen_IsResolving(ListenS)) {
#if HAVE_ARES_CANCELQUERY
ares_cancelquery(Ares_Channel, ListenS);
#endif
++Count;
Listen_SetRemove(ListenS);
continue;
}
listen_stop(ListenS);
ListenS_DEL = ListenS;
ListenS = ListenS->Next;
listen_rem(ListenS_DEL);
}
return(Count);
}
syntax highlighted by Code2HTML, v. 0.9.1