#include "version.h"
#include <arpa/inet.h>
-#include <arpa/nameser.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
-#include <resolv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
#endif /* USE_POLL */
-#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffffff
-#endif
-
struct Client* LocalClientArray[MAXCONNECTIONS];
int HighestFd = -1;
-struct sockaddr_in VirtualHost;
+struct irc_sockaddr VirtualHost;
static char readbuf[SERVER_TCP_WINDOW];
/*
* a non-null pointer, otherwise reply will be null.
* if successful start the connection, otherwise notify opers
*/
-static void connect_dns_callback(void* vptr, struct hostent* hp)
+static void connect_dns_callback(void* vptr, struct DNSReply* hp)
{
struct ConfItem* aconf = (struct ConfItem*) vptr;
assert(aconf);
aconf->dns_pending = 0;
if (hp) {
- memcpy(&aconf->ipnum, hp->h_addr, sizeof(struct in_addr));
+ memcpy(&aconf->address, &hp->addr, sizeof(aconf->address));
MyFree(hp);
connect_server(aconf, 0);
}
*/
static int connect_inet(struct ConfItem* aconf, struct Client* cptr)
{
- static struct sockaddr_in sin;
+ const struct irc_sockaddr *local;
IOResult result;
assert(0 != aconf);
assert(0 != cptr);
* Might as well get sockhost from here, the connection is attempted
* with it so if it fails its useless.
*/
- cli_fd(cptr) = socket(AF_INET, SOCK_STREAM, 0);
- if (-1 == cli_fd(cptr)) {
- cli_error(cptr) = errno;
- report_error(SOCKET_ERROR_MSG, cli_name(cptr), errno);
- return 0;
- }
- if (cli_fd(cptr) >= MAXCLIENTS) {
- report_error(CONNLIMIT_ERROR_MSG, cli_name(cptr), 0);
- close(cli_fd(cptr));
- cli_fd(cptr) = -1;
- return 0;
- }
- /*
- * Bind to a local IP# (with unknown port - let unix decide) so
- * we have some chance of knowing the IP# that gets used for a host
- * with more than one IP#.
- *
- * No we don't bind it, not all OS's can handle connecting with
- * an already bound socket, different ip# might occur anyway
- * leading to a freezing select() on this side for some time.
- * I had this on my Linux 1.1.88 --Run
- */
-
- /*
- * No, we do bind it if we have virtual host support. If we don't
- * explicitly bind it, it will default to IN_ADDR_ANY and we lose
- * due to the other server not allowing our base IP --smg
- */
- if (feature_bool(FEAT_VIRTUAL_HOST) &&
- bind(cli_fd(cptr), (struct sockaddr*) &VirtualHost,
- sizeof(VirtualHost))) {
- report_error(BIND_ERROR_MSG, cli_name(cptr), errno);
- close(cli_fd(cptr));
- cli_fd(cptr) = -1;
+ if (irc_in_addr_valid(&aconf->origin.addr))
+ local = &aconf->origin;
+ else
+ local = &VirtualHost;
+ cli_fd(cptr) = os_socket(local, SOCK_STREAM, cli_name(cptr));
+ if (cli_fd(cptr) < 0)
return 0;
- }
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = aconf->ipnum.s_addr;
- sin.sin_port = htons(aconf->port);
/*
* save connection info in client
*/
- (cli_ip(cptr)).s_addr = aconf->ipnum.s_addr;
- cli_port(cptr) = aconf->port;
- ircd_ntoa_r(cli_sock_ip(cptr), (const char*) &(cli_ip(cptr)));
+ memcpy(&cli_ip(cptr), &aconf->address.addr, sizeof(cli_ip(cptr)));
+ cli_port(cptr) = aconf->address.port;
+ ircd_ntoa_r(cli_sock_ip(cptr), &cli_ip(cptr));
/*
* we want a big buffer for server connections
*/
cli_fd(cptr) = -1;
return 0;
}
- /*
- * ALWAYS set sockets non-blocking
- */
- if (!os_set_nonblocking(cli_fd(cptr))) {
- cli_error(cptr) = errno;
- report_error(NONB_ERROR_MSG, cli_name(cptr), errno);
- close(cli_fd(cptr));
- cli_fd(cptr) = -1;
- return 0;
- }
- if ((result = os_connect_nonb(cli_fd(cptr), &sin)) == IO_FAILURE) {
+ if ((result = os_connect_nonb(cli_fd(cptr), &aconf->address)) == IO_FAILURE) {
cli_error(cptr) = errno;
report_error(CONNECT_ERROR_MSG, cli_name(cptr), errno);
close(cli_fd(cptr));
assert(MyConnect(cptr));
if (cli_dns_reply(cptr)) {
+ MyFree(cli_dns_reply(cptr)->h_name);
MyFree(cli_dns_reply(cptr));
cli_dns_reply(cptr) = 0;
}
* passed off to the auth handler for dns and ident queries.
*--------------------------------------------------------------------------*/
void add_connection(struct Listener* listener, int fd) {
- struct sockaddr_in addr;
+ struct irc_sockaddr addr;
struct Client *new_client;
time_t next_target = 0;
/* 12345678901234567890123456789012345679012345678901234567890123456 */
const char* const register_message =
"ERROR :Unable to complete your registration\r\n";
-
+
assert(0 != listener);
-
/*
* Removed preliminary access check. Full check is performed in m_server and
* m_user instead. Also connection time out help to get rid of unwanted
- * connections.
+ * connections.
*/
if (!os_get_peername(fd, &addr) || !os_set_nonblocking(fd)) {
++ServerStats->is_ref;
*
* If they're throttled, murder them, but tell them why first.
*/
- if (!IPcheck_local_connect(addr.sin_addr, &next_target) && !listener->server)
+ if (!IPcheck_local_connect(&addr.addr, &next_target) && !listener->server)
{
++ServerStats->is_ref;
write(fd, throttle_message, strlen(throttle_message));
return;
}
- new_client = make_client(0, ((listener->server) ?
+ new_client = make_client(0, ((listener->server) ?
STAT_UNKNOWN_SERVER : STAT_UNKNOWN_USER));
/*
* Copy ascii address to 'sockhost' just in case. Then we have something
- * valid to put into error messages...
+ * valid to put into error messages...
*/
SetIPChecked(new_client);
- ircd_ntoa_r(cli_sock_ip(new_client), (const char*) &addr.sin_addr);
+ ircd_ntoa_r(cli_sock_ip(new_client), &addr.addr);
strcpy(cli_sockhost(new_client), cli_sock_ip(new_client));
- (cli_ip(new_client)).s_addr = addr.sin_addr.s_addr;
- cli_port(new_client) = ntohs(addr.sin_port);
+ memcpy(&cli_ip(new_client), &addr.addr, sizeof(cli_ip(new_client)));
+ cli_port(new_client) = addr.port;
if (next_target)
cli_nexttarget(new_client) = next_target;
return 0;
}
Debug((DEBUG_NOTICE, "Connect to %s[@%s]", aconf->name,
- ircd_ntoa((const char*) &aconf->ipnum)));
+ ircd_ntoa(&aconf->address.addr)));
if ((cptr = FindClient(aconf->name))) {
if (IsServer(cptr) || IsMe(cptr)) {
}
}
/*
- * If we dont know the IP# for this host and itis a hostname and
+ * If we dont know the IP# for this host and it is a hostname and
* not a ip# string, then try and find the appropriate host record.
*/
- if (INADDR_NONE == aconf->ipnum.s_addr) {
- if (INADDR_NONE == (aconf->ipnum.s_addr = inet_addr(aconf->host))) {
- char buf[HOSTLEN + 1];
- struct DNSQuery query;
-
- query.vptr = aconf;
- query.callback = connect_dns_callback;
- host_from_uh(buf, aconf->host, HOSTLEN);
- buf[HOSTLEN] = '\0';
-
- gethost_byname(buf, &query);
- aconf->dns_pending = 1;
- }
+ if (!irc_in_addr_valid(&aconf->address.addr)
+ && !ircd_aton(&aconf->address.addr, aconf->host)) {
+ char buf[HOSTLEN + 1];
+ struct DNSQuery query;
+
+ query.vptr = aconf;
+ query.callback = connect_dns_callback;
+ host_from_uh(buf, aconf->host, HOSTLEN);
+ buf[HOSTLEN] = '\0';
+
+ gethost_byname(buf, &query);
+ aconf->dns_pending = 1;
return 0;
}
cptr = make_client(NULL, STAT_UNKNOWN_SERVER);
completed_connection(cptr) : 1;
}
-/*
- * Setup local socket structure to use for binding to.
- */
-void set_virtual_host(struct in_addr addr)
-{
- memset(&VirtualHost, 0, sizeof(VirtualHost));
- VirtualHost.sin_family = AF_INET;
- VirtualHost.sin_addr.s_addr = addr.s_addr;
-}
-
/*
* Find the real hostname for the host running the server (or one which
* matches the server's name) and its primary IP#. Hostname is stored