diff --git a/doc/ircd.conf.example b/doc/ircd.conf.example
index 2305c302..5d7f984e 100644
--- a/doc/ircd.conf.example
+++ b/doc/ircd.conf.example
@@ -310,10 +310,6 @@ connect "irc.uplink.com" {
flags = compressed, topicburst;
#fingerprint = "c77106576abf7f9f90cca0f63874a60f2e40a64b";
-
- /* If the connection is IPv6, uncomment below.
- * Use 0::1, not ::1, for IPv6 localhost. */
- #aftype = ipv6;
};
connect "ssl.uplink.com" {
@@ -454,7 +450,7 @@ opm {
* to be effective.
* If omitted, it defaults to serverinfo::vhost6.
*/
- #listen_ipv6 = "0::1";
+ #listen_ipv6 = "::1";
/* IPv6 port to listen on.
* This should not be the same as any existing listeners.
diff --git a/doc/reference.conf b/doc/reference.conf
index aff7787c..731eadf8 100644
--- a/doc/reference.conf
+++ b/doc/reference.conf
@@ -571,17 +571,14 @@ connect "irc.uplink.com" {
};
connect "ipv6.lame.server" {
- /* Hosts that are IPv6 addresses must be in :: shortened form
- * if applicable. Addresses starting with a colon get an extra
- * zero prepended, for example: 0::1
- */
+ host = "192.0.2.1";
host = "2001:db8:3::8";
send_password = "password";
accept_password = "password";
port = 6666;
- /* aftype: controls whether the connection uses "ipv4" or "ipv6".
- * Default is ipv4.
+ /* aftype: controls whether the outgoing connection uses "ipv4" or "ipv6".
+ * Default is to try either at random.
*/
aftype = ipv6;
class = "server";
@@ -930,7 +927,7 @@ opm {
* to be effective.
* If omitted, it defaults to serverinfo::vhost6.
*/
- #listen_ipv6 = "0::1";
+ #listen_ipv6 = "::1";
/* IPv6 port to listen on.
* This should not be the same as any existing listeners.
diff --git a/doc/sgml/oper-guide/config.sgml b/doc/sgml/oper-guide/config.sgml
index 0d585124..798d6fcf 100644
--- a/doc/sgml/oper-guide/config.sgml
+++ b/doc/sgml/oper-guide/config.sgml
@@ -105,7 +105,7 @@ serverinfo {
vhost
- An optional text field which defines an IP from which to connect outward to other IRC servers.
+ An optional text field which defines an IPv4 address from which to connect outward to other IRC servers.
@@ -113,7 +113,7 @@ serverinfo {
vhost6
- An optional text field which defines an IPv6 IP from which to connect outward to other IRC servers.
+ An optional text field which defines an IPv6 address from which to connect outward to other IRC servers.
@@ -599,10 +599,6 @@ connect "name" {
Furthermore, if a hostname is used, it must have an A or AAAA
record (no CNAME) and it must be the primary
hostname for inbound connections to work.
-
- IPv6 addresses must be in :: shortened form; addresses which
- then start with a colon must be prepended with a zero,
- for example 0::1.
@@ -662,7 +658,7 @@ connect "name" {
aftype
- The protocol that should be used to connect with, either ipv4 or ipv6. This defaults to ipv4 unless host is a numeric IPv6 address.
+ The protocol that must be used to connect with, either ipv4 or ipv6. This defaults to neither, allowing connection using either address family.
diff --git a/include/s_conf.h b/include/s_conf.h
index dbbdce19..4c3bd5ee 100644
--- a/include/s_conf.h
+++ b/include/s_conf.h
@@ -282,14 +282,10 @@ struct server_info
char *description;
char *network_name;
int hub;
- struct sockaddr_in ip;
+ struct rb_sockaddr_storage bind4;
int default_max_clients;
#ifdef RB_IPV6
- struct sockaddr_in6 ip6;
-#endif
- int specific_ipv4_vhost;
-#ifdef RB_IPV6
- int specific_ipv6_vhost;
+ struct rb_sockaddr_storage bind6;
#endif
char *ssl_private_key;
char *ssl_ca_cert;
diff --git a/include/s_newconf.h b/include/s_newconf.h
index 22c24784..4218a828 100644
--- a/include/s_newconf.h
+++ b/include/s_newconf.h
@@ -178,7 +178,13 @@ extern const char *get_oper_privs(int flags);
struct server_conf
{
char *name;
- char *host;
+ char *connect_host;
+ struct rb_sockaddr_storage connect4;
+ uint16_t dns_query_connect4;
+#ifdef RB_IPV6
+ struct rb_sockaddr_storage connect6;
+ uint16_t dns_query_connect6;
+#endif
char *passwd;
char *spasswd;
char *certfp;
@@ -188,17 +194,20 @@ struct server_conf
time_t hold;
int aftype;
- struct rb_sockaddr_storage my_ipnum;
+ char *bind_host;
+ struct rb_sockaddr_storage bind4;
+ uint16_t dns_query_bind4;
+#ifdef RB_IPV6
+ struct rb_sockaddr_storage bind6;
+ uint16_t dns_query_bind6;
+#endif
char *class_name;
struct Class *class;
rb_dlink_node node;
-
- uint16_t dns_query;
};
#define SERVER_ILLEGAL 0x0001
-#define SERVER_VHOSTED 0x0002
#define SERVER_ENCRYPTED 0x0004
#define SERVER_COMPRESSED 0x0008
#define SERVER_TB 0x0010
@@ -206,7 +215,6 @@ struct server_conf
#define SERVER_SSL 0x0040
#define ServerConfIllegal(x) ((x)->flags & SERVER_ILLEGAL)
-#define ServerConfVhosted(x) ((x)->flags & SERVER_VHOSTED)
#define ServerConfEncrypted(x) ((x)->flags & SERVER_ENCRYPTED)
#define ServerConfCompressed(x) ((x)->flags & SERVER_COMPRESSED)
#define ServerConfTb(x) ((x)->flags & SERVER_TB)
diff --git a/ircd/newconf.c b/ircd/newconf.c
index 253d02b6..47a5924c 100644
--- a/ircd/newconf.c
+++ b/ircd/newconf.c
@@ -243,27 +243,31 @@ conf_set_serverinfo_network_name(void *data)
static void
conf_set_serverinfo_vhost(void *data)
{
- if(rb_inet_pton(AF_INET, (char *) data, &ServerInfo.ip.sin_addr) <= 0)
+ struct rb_sockaddr_storage addr;
+
+ if(rb_inet_pton_sock(data, (struct sockaddr *)&addr) <= 0 || GET_SS_FAMILY(&addr) != AF_INET)
{
conf_report_error("Invalid IPv4 address for server vhost (%s)", (char *) data);
return;
}
- ServerInfo.ip.sin_family = AF_INET;
- ServerInfo.specific_ipv4_vhost = 1;
+
+ ServerInfo.bind4 = addr;
}
static void
conf_set_serverinfo_vhost6(void *data)
{
+
#ifdef RB_IPV6
- if(rb_inet_pton(AF_INET6, (char *) data, &ServerInfo.ip6.sin6_addr) <= 0)
+ struct rb_sockaddr_storage addr;
+
+ if(rb_inet_pton_sock(data, (struct sockaddr *)&addr) <= 0 || GET_SS_FAMILY(&addr) != AF_INET6)
{
conf_report_error("Invalid IPv6 address for server vhost (%s)", (char *) data);
return;
}
- ServerInfo.specific_ipv6_vhost = 1;
- ServerInfo.ip6.sin6_family = AF_INET6;
+ ServerInfo.bind6 = addr;
#else
conf_report_error("Warning -- ignoring serverinfo::vhost6 -- IPv6 support not available.");
#endif
@@ -1301,7 +1305,12 @@ conf_end_connect(struct TopConf *tc)
return 0;
}
- if(EmptyString(yy_server->host))
+ if(EmptyString(yy_server->connect_host)
+ && GET_SS_FAMILY(&yy_server->connect4) != AF_INET
+#ifdef RB_IPV6
+ && GET_SS_FAMILY(&yy_server->connect6) != AF_INET6
+#endif
+ )
{
conf_report_error("Ignoring connect block for %s -- missing host.",
yy_server->name);
@@ -1326,23 +1335,57 @@ conf_end_connect(struct TopConf *tc)
static void
conf_set_connect_host(void *data)
{
- rb_free(yy_server->host);
- yy_server->host = rb_strdup(data);
- if (strchr(yy_server->host, ':'))
- yy_server->aftype = AF_INET6;
+ struct rb_sockaddr_storage addr;
+
+ if(rb_inet_pton_sock(data, (struct sockaddr *)&addr) <= 0)
+ {
+ rb_free(yy_server->connect_host);
+ yy_server->connect_host = rb_strdup(data);
+ }
+ else if(GET_SS_FAMILY(&addr) == AF_INET)
+ {
+ yy_server->connect4 = addr;
+ }
+#ifdef RB_IPV6
+ else if(GET_SS_FAMILY(&addr) == AF_INET6)
+ {
+ yy_server->connect6 = addr;
+ }
+#endif
+ else
+ {
+ conf_report_error("Unsupported IP address for server connect host (%s)",
+ (char *)data);
+ return;
+ }
}
static void
conf_set_connect_vhost(void *data)
{
- if(rb_inet_pton_sock(data, (struct sockaddr *)&yy_server->my_ipnum) <= 0)
+ struct rb_sockaddr_storage addr;
+
+ if(rb_inet_pton_sock(data, (struct sockaddr *)&addr) <= 0)
{
- conf_report_error("Invalid IP address for server connect vhost (%s)",
- (char *) data);
+ rb_free(yy_server->bind_host);
+ yy_server->bind_host = rb_strdup(data);
+ }
+ else if(GET_SS_FAMILY(&addr) == AF_INET)
+ {
+ yy_server->bind4 = addr;
+ }
+#ifdef RB_IPV6
+ else if(GET_SS_FAMILY(&addr) == AF_INET6)
+ {
+ yy_server->bind6 = addr;
+ }
+#endif
+ else
+ {
+ conf_report_error("Unsupported IP address for server connect vhost (%s)",
+ (char *)data);
return;
}
-
- yy_server->flags |= SERVER_VHOSTED;
}
static void
@@ -2071,7 +2114,7 @@ conf_end_opm(struct TopConf *tc)
else
{
char ip[HOSTIPLEN];
- if(!rb_inet_ntop_sock((struct sockaddr *)&ServerInfo.ip, ip, sizeof(ip)))
+ if(!rb_inet_ntop_sock((struct sockaddr *)&ServerInfo.bind4, ip, sizeof(ip)))
conf_report_error("No opm::listen_ipv4 nor serverinfo::vhost directive; cannot listen on IPv4");
else
conf_create_opm_listener(ip, yy_opm_port_ipv4);
@@ -2085,7 +2128,7 @@ conf_end_opm(struct TopConf *tc)
else
{
char ip[HOSTIPLEN];
- if(!rb_inet_ntop_sock((struct sockaddr *)&ServerInfo.ip6, ip, sizeof(ip)))
+ if(!rb_inet_ntop_sock((struct sockaddr *)&ServerInfo.bind6, ip, sizeof(ip)))
conf_report_error("No opm::listen_ipv6 nor serverinfo::vhost directive; cannot listen on IPv6");
else
conf_create_opm_listener(ip, yy_opm_port_ipv6);
diff --git a/ircd/s_conf.c b/ircd/s_conf.c
index dcb4911f..976c0ce7 100644
--- a/ircd/s_conf.c
+++ b/ircd/s_conf.c
@@ -680,11 +680,11 @@ set_default_conf(void)
ServerInfo.description = NULL;
ServerInfo.network_name = NULL;
- memset(&ServerInfo.ip, 0, sizeof(ServerInfo.ip));
- ServerInfo.specific_ipv4_vhost = 0;
+ memset(&ServerInfo.bind4, 0, sizeof(ServerInfo.bind4));
+ SET_SS_FAMILY(&ServerInfo.bind4, AF_UNSPEC);
#ifdef RB_IPV6
- memset(&ServerInfo.ip6, 0, sizeof(ServerInfo.ip6));
- ServerInfo.specific_ipv6_vhost = 0;
+ memset(&ServerInfo.bind6, 0, sizeof(ServerInfo.bind6));
+ SET_SS_FAMILY(&ServerInfo.bind6, AF_UNSPEC);
#endif
AdminInfo.name = NULL;
diff --git a/ircd/s_newconf.c b/ircd/s_newconf.c
index 3815f839..a9c66179 100644
--- a/ircd/s_newconf.c
+++ b/ircd/s_newconf.c
@@ -324,8 +324,24 @@ struct server_conf *
make_server_conf(void)
{
struct server_conf *server_p = rb_malloc(sizeof(struct server_conf));
- server_p->aftype = AF_INET;
- return server_p;
+
+ SET_SS_FAMILY(&server_p->connect4, AF_UNSPEC);
+ SET_SS_LEN(&server_p->connect4, sizeof(struct sockaddr_in));
+
+ SET_SS_FAMILY(&server_p->bind4, AF_UNSPEC);
+ SET_SS_LEN(&server_p->bind4, sizeof(struct sockaddr_in));
+
+#ifdef RB_IPV6
+ SET_SS_FAMILY(&server_p->connect6, AF_UNSPEC);
+ SET_SS_LEN(&server_p->connect6, sizeof(struct sockaddr_in6));
+
+ SET_SS_FAMILY(&server_p->bind6, AF_UNSPEC);
+ SET_SS_LEN(&server_p->bind6, sizeof(struct sockaddr_in6));
+#endif
+
+ server_p->aftype = AF_UNSPEC;
+
+ return rb_malloc(sizeof(struct server_conf));
}
void
@@ -348,13 +364,14 @@ free_server_conf(struct server_conf *server_p)
}
rb_free(server_p->name);
- rb_free(server_p->host);
+ rb_free(server_p->connect_host);
+ rb_free(server_p->bind_host);
rb_free(server_p->class_name);
rb_free(server_p);
}
/*
- * conf_dns_callback
+ * conf_connect_dns_callback
* inputs - pointer to struct ConfItem
* - pointer to adns reply
* output - none
@@ -364,14 +381,59 @@ free_server_conf(struct server_conf *server_p)
* if successful save hp in the conf item it was called with
*/
static void
-conf_dns_callback(const char *result, int status, int aftype, void *data)
+conf_connect_dns_callback(const char *result, int status, int aftype, void *data)
{
struct server_conf *server_p = data;
- if(status == 1)
- rb_inet_pton_sock(result, (struct sockaddr *)&server_p->my_ipnum);
+ if(aftype == AF_INET)
+ {
+ if(status == 1)
+ rb_inet_pton_sock(result, (struct sockaddr *)&server_p->connect4);
- server_p->dns_query = 0;
+ server_p->dns_query_connect4 = 0;
+ }
+#ifdef RB_IPV6
+ else if(aftype == AF_INET6)
+ {
+ if(status == 1)
+ rb_inet_pton_sock(result, (struct sockaddr *)&server_p->connect6);
+
+ server_p->dns_query_connect6 = 0;
+ }
+#endif
+}
+
+/*
+ * conf_bind_dns_callback
+ * inputs - pointer to struct ConfItem
+ * - pointer to adns reply
+ * output - none
+ * side effects - called when resolver query finishes
+ * if the query resulted in a successful search, hp will contain
+ * a non-null pointer, otherwise hp will be null.
+ * if successful save hp in the conf item it was called with
+ */
+static void
+conf_bind_dns_callback(const char *result, int status, int aftype, void *data)
+{
+ struct server_conf *server_p = data;
+
+ if(aftype == AF_INET)
+ {
+ if(status == 1)
+ rb_inet_pton_sock(result, (struct sockaddr *)&server_p->bind4);
+
+ server_p->dns_query_bind4 = 0;
+ }
+#ifdef RB_IPV6
+ else if(aftype == AF_INET6)
+ {
+ if(status == 1)
+ rb_inet_pton_sock(result, (struct sockaddr *)&server_p->bind6);
+
+ server_p->dns_query_bind6 = 0;
+ }
+#endif
}
void
@@ -395,11 +457,25 @@ add_server_conf(struct server_conf *server_p)
server_p->class_name = rb_strdup("default");
}
- if(strpbrk(server_p->host, "*?"))
- return;
+ if(server_p->connect_host && !strpbrk(server_p->connect_host, "*?"))
+ {
+ server_p->dns_query_connect4 =
+ lookup_hostname(server_p->connect_host, AF_INET, conf_connect_dns_callback, server_p);
+#ifdef RB_IPV6
+ server_p->dns_query_connect6 =
+ lookup_hostname(server_p->connect_host, AF_INET6, conf_connect_dns_callback, server_p);
+#endif
+ }
- server_p->dns_query =
- lookup_hostname(server_p->host, GET_SS_FAMILY(&server_p->my_ipnum), conf_dns_callback, server_p);
+ if(server_p->bind_host)
+ {
+ server_p->dns_query_bind4 =
+ lookup_hostname(server_p->bind_host, AF_INET, conf_bind_dns_callback, server_p);
+#ifdef RB_IPV6
+ server_p->dns_query_bind6 =
+ lookup_hostname(server_p->bind_host, AF_INET6, conf_bind_dns_callback, server_p);
+#endif
+ }
}
struct server_conf *
diff --git a/ircd/s_serv.c b/ircd/s_serv.c
index 734efb9e..28ed4286 100644
--- a/ircd/s_serv.c
+++ b/ircd/s_serv.c
@@ -363,6 +363,8 @@ check_server(const char *name, struct Client *client_p)
RB_DLINK_FOREACH(ptr, server_conf_list.head)
{
+ struct rb_sockaddr_storage client_addr;
+
tmp_p = ptr->data;
if(ServerConfIllegal(tmp_p))
@@ -373,10 +375,19 @@ check_server(const char *name, struct Client *client_p)
name_matched = true;
- /* XXX: Fix me for IPv6 */
- /* XXX sockhost is the IPv4 ip as a string */
- if(match(tmp_p->host, client_p->host) ||
- match(tmp_p->host, client_p->sockhost))
+ if(rb_inet_pton_sock(client_p->sockhost, (struct sockaddr *)&client_addr) <= 0)
+ SET_SS_FAMILY(&client_addr, AF_UNSPEC);
+
+ if((tmp_p->connect_host && match(tmp_p->connect_host, client_p->host))
+ || (GET_SS_FAMILY(&client_addr) == GET_SS_FAMILY(&tmp_p->connect4)
+ && comp_with_mask_sock((struct sockaddr *)&client_addr,
+ (struct sockaddr *)&tmp_p->connect4, 32))
+#ifdef RB_IPV6
+ || (GET_SS_FAMILY(&client_addr) == GET_SS_FAMILY(&tmp_p->connect6)
+ && comp_with_mask_sock((struct sockaddr *)&client_addr,
+ (struct sockaddr *)&tmp_p->connect6, 128))
+#endif
+ )
{
host_matched = true;
@@ -1010,7 +1021,8 @@ int
serv_connect(struct server_conf *server_p, struct Client *by)
{
struct Client *client_p;
- struct rb_sockaddr_storage myipnum;
+ struct rb_sockaddr_storage sa_connect;
+ struct rb_sockaddr_storage sa_bind;
char note[HOSTLEN + 10];
rb_fde_t *F;
@@ -1018,8 +1030,39 @@ serv_connect(struct server_conf *server_p, struct Client *by)
if(server_p == NULL)
return 0;
+#ifdef RB_IPV6
+ if(server_p->aftype != AF_UNSPEC
+ && GET_SS_FAMILY(&server_p->connect4) == AF_INET
+ && GET_SS_FAMILY(&server_p->connect6) == AF_INET6)
+ {
+ if(rand() % 2 == 0)
+ {
+ sa_connect = server_p->connect4;
+ sa_bind = server_p->bind4;
+ }
+ else
+ {
+ sa_connect = server_p->connect6;
+ sa_bind = server_p->bind6;
+ }
+ }
+ else if(server_p->aftype == AF_INET || GET_SS_FAMILY(&server_p->connect4) == AF_INET)
+#endif
+ {
+ sa_connect = server_p->connect4;
+ sa_bind = server_p->bind4;
+ }
+#ifdef RB_IPV6
+ else if(server_p->aftype == AF_INET6 || GET_SS_FAMILY(&server_p->connect6) == AF_INET6)
+ {
+ sa_connect = server_p->connect6;
+ sa_bind = server_p->bind6;
+ }
+#endif
+
/* log */
- rb_inet_ntop_sock((struct sockaddr *)&server_p->my_ipnum, buf, sizeof(buf));
+ buf[0] = 0;
+ rb_inet_ntop_sock((struct sockaddr *)&sa_connect, buf, sizeof(buf));
ilog(L_SERVER, "Connect to *[%s] @%s", server_p->name, buf);
/*
@@ -1037,7 +1080,12 @@ serv_connect(struct server_conf *server_p, struct Client *by)
}
/* create a socket for the server connection */
- if((F = rb_socket(GET_SS_FAMILY(&server_p->my_ipnum), SOCK_STREAM, 0, NULL)) == NULL)
+ if(GET_SS_FAMILY(&sa_connect) == AF_UNSPEC)
+ {
+ ilog_error("unspecified socket address family");
+ return 0;
+ }
+ else if((F = rb_socket(GET_SS_FAMILY(&sa_connect), SOCK_STREAM, 0, NULL)) == NULL)
{
ilog_error("opening a stream socket");
return 0;
@@ -1052,11 +1100,14 @@ serv_connect(struct server_conf *server_p, struct Client *by)
/* Copy in the server, hostname, fd */
rb_strlcpy(client_p->name, server_p->name, sizeof(client_p->name));
- rb_strlcpy(client_p->host, server_p->host, sizeof(client_p->host));
+ if(server_p->connect_host)
+ rb_strlcpy(client_p->host, server_p->connect_host, sizeof(client_p->host));
+ else
+ rb_strlcpy(client_p->host, buf, sizeof(client_p->host));
rb_strlcpy(client_p->sockhost, buf, sizeof(client_p->sockhost));
client_p->localClient->F = F;
/* shove the port number into the sockaddr */
- SET_SS_PORT(&server_p->my_ipnum, htons(server_p->port));
+ SET_SS_PORT(&sa_connect, htons(server_p->port));
/*
* Set up the initial server evilness, ripped straight from
@@ -1091,58 +1142,22 @@ serv_connect(struct server_conf *server_p, struct Client *by)
SetConnecting(client_p);
rb_dlinkAddTail(client_p, &client_p->node, &global_client_list);
- if(ServerConfVhosted(server_p))
+ if(GET_SS_FAMILY(&sa_bind) == AF_UNSPEC)
{
- memcpy(&myipnum, &server_p->my_ipnum, sizeof(myipnum));
- SET_SS_FAMILY(&myipnum, GET_SS_FAMILY(&server_p->my_ipnum));
- SET_SS_PORT(&myipnum, 0);
-
- }
- else if(GET_SS_FAMILY(&server_p->my_ipnum) == AF_INET && ServerInfo.specific_ipv4_vhost)
- {
- memcpy(&myipnum, &ServerInfo.ip, sizeof(myipnum));
- SET_SS_FAMILY(&myipnum, AF_INET);
- SET_SS_PORT(&myipnum, 0);
- SET_SS_LEN(&myipnum, sizeof(struct sockaddr_in));
- }
-
+ if(GET_SS_FAMILY(&sa_connect) == GET_SS_FAMILY(&ServerInfo.bind4))
+ sa_bind = ServerInfo.bind4;
#ifdef RB_IPV6
- else if((GET_SS_FAMILY(&server_p->my_ipnum) == AF_INET6) && ServerInfo.specific_ipv6_vhost)
- {
- memcpy(&myipnum, &ServerInfo.ip6, sizeof(myipnum));
- SET_SS_FAMILY(&myipnum, AF_INET6);
- SET_SS_PORT(&myipnum, 0);
- SET_SS_LEN(&myipnum, sizeof(struct sockaddr_in6));
- }
+ if(GET_SS_FAMILY(&sa_connect) == GET_SS_FAMILY(&ServerInfo.bind6))
+ sa_bind = ServerInfo.bind6;
#endif
- else
- {
- if(ServerConfSSL(server_p))
- {
- rb_connect_tcp(client_p->localClient->F,
- (struct sockaddr *)&server_p->my_ipnum, NULL, 0,
- serv_connect_ssl_callback, client_p,
- ConfigFileEntry.connect_timeout);
- }
- else
- rb_connect_tcp(client_p->localClient->F,
- (struct sockaddr *)&server_p->my_ipnum, NULL, 0,
- serv_connect_callback, client_p,
- ConfigFileEntry.connect_timeout);
-
- return 1;
}
- if(ServerConfSSL(server_p))
- rb_connect_tcp(client_p->localClient->F, (struct sockaddr *)&server_p->my_ipnum,
- (struct sockaddr *)&myipnum,
- GET_SS_LEN(&myipnum), serv_connect_ssl_callback, client_p,
- ConfigFileEntry.connect_timeout);
- else
- rb_connect_tcp(client_p->localClient->F, (struct sockaddr *)&server_p->my_ipnum,
- (struct sockaddr *)&myipnum,
- GET_SS_LEN(&myipnum), serv_connect_callback, client_p,
- ConfigFileEntry.connect_timeout);
+ rb_connect_tcp(client_p->localClient->F,
+ (struct sockaddr *)&sa_connect,
+ GET_SS_FAMILY(&sa_bind) == AF_UNSPEC ? NULL : (struct sockaddr *)&sa_bind,
+ GET_SS_LEN(&sa_bind),
+ ServerConfSSL(server_p) ? serv_connect_ssl_callback : serv_connect_callback,
+ client_p, ConfigFileEntry.connect_timeout);
return 1;
}