mirror of
https://github.com/irssi/irssi.git
synced 2025-02-02 15:08:01 -05:00
IPv6 fixes. Everything now keeps both v4 and v6 addresses in memory and
at connect() time it's decided which one should be used. git-svn-id: http://svn.irssi.org/repos/irssi/trunk@1334 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
parent
5afb3c1454
commit
4c7b07ed3f
@ -1,8 +1,9 @@
|
||||
|
||||
@SYNTAX:connect@
|
||||
|
||||
-ircnet the IRCNet
|
||||
-host the host
|
||||
-4, -6: specify explicitly whether to use IPv4 or IPv6 address
|
||||
-ircnet: the IRCNet
|
||||
-host: the host
|
||||
|
||||
This command makes irssi to connect to specified server.
|
||||
Current connections are kept and a new one is created.
|
||||
|
@ -1,6 +1,7 @@
|
||||
|
||||
@SYNTAX:server@
|
||||
|
||||
-4, -6: specify explicitly whether to use IPv4 or IPv6 address
|
||||
-auto: Automatically connect to server at startup (default)
|
||||
-noauto: Don't connect to server at startup
|
||||
-ircnet: Specify what IRC network this server belongs to
|
||||
|
@ -47,10 +47,14 @@
|
||||
#include "nls.h"
|
||||
|
||||
#define g_free_not_null(a) \
|
||||
if (a) g_free(a);
|
||||
G_STMT_START { \
|
||||
if (a) g_free(a); \
|
||||
} G_STMT_END
|
||||
|
||||
#define g_free_and_null(a) \
|
||||
if (a) { g_free(a); (a) = NULL; }
|
||||
G_STMT_START { \
|
||||
if (a) { g_free(a); (a) = NULL; } \
|
||||
} G_STMT_END
|
||||
|
||||
#define G_INPUT_READ (1 << 0)
|
||||
#define G_INPUT_WRITE (1 << 1)
|
||||
|
@ -89,13 +89,10 @@ static SERVER_CONNECT_REC *get_server_connect(const char *data, int *plus_addr)
|
||||
|
||||
host = g_hash_table_lookup(optlist, "host");
|
||||
if (host != NULL && *host != '\0') {
|
||||
IPADDR ip;
|
||||
IPADDR ip4, ip6;
|
||||
|
||||
if (net_gethostbyname(host, &ip, conn->family) == 0) {
|
||||
if (conn->own_ip == NULL)
|
||||
conn->own_ip = g_new(IPADDR, 1);
|
||||
memcpy(conn->own_ip, &ip, sizeof(IPADDR));
|
||||
}
|
||||
if (net_gethostbyname(host, &ip4, &ip6) == 0)
|
||||
server_connect_own_ip_save(conn, &ip4, &ip6);
|
||||
}
|
||||
|
||||
cmd_params_free(free_arg);
|
||||
|
@ -9,4 +9,4 @@ char *realname;
|
||||
|
||||
char *own_host; /* address to use when connecting this server */
|
||||
char *autosendcmd; /* command to send after connecting to this ircnet */
|
||||
IPADDR *own_ip; /* resolved own_address if not NULL */
|
||||
IPADDR *own_ip4, *own_ip6; /* resolved own_address if not NULL */
|
||||
|
@ -73,7 +73,7 @@ static int g_io_channel_read_block(GIOChannel *channel, void *data, int len)
|
||||
|
||||
/* nonblocking gethostbyname(), ip (IPADDR) + error (int, 0 = not error) is
|
||||
written to pipe when found PID of the resolver child is returned */
|
||||
int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, int family)
|
||||
int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe)
|
||||
{
|
||||
RESOLVED_IP_REC rec;
|
||||
const char *errorstr;
|
||||
@ -100,7 +100,7 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, int family)
|
||||
|
||||
/* child */
|
||||
memset(&rec, 0, sizeof(rec));
|
||||
rec.error = net_gethostbyname(addr, &rec.ip, family);
|
||||
rec.error = net_gethostbyname(addr, &rec.ip4, &rec.ip6);
|
||||
if (rec.error == 0) {
|
||||
errorstr = NULL;
|
||||
} else {
|
||||
@ -186,6 +186,7 @@ static void simple_readpipe(SIMPLE_THREAD_REC *rec, GIOChannel *pipe)
|
||||
{
|
||||
RESOLVED_IP_REC iprec;
|
||||
GIOChannel *handle;
|
||||
IPADDR *ip;
|
||||
|
||||
g_return_if_fail(rec != NULL);
|
||||
|
||||
@ -199,8 +200,9 @@ static void simple_readpipe(SIMPLE_THREAD_REC *rec, GIOChannel *pipe)
|
||||
g_io_channel_close(rec->pipes[1]);
|
||||
g_io_channel_unref(rec->pipes[1]);
|
||||
|
||||
ip = iprec.ip4.family != 0 ? &iprec.ip4 : &iprec.ip6;
|
||||
handle = iprec.error == -1 ? NULL :
|
||||
net_connect_ip(&iprec.ip, rec->port, rec->my_ip);
|
||||
net_connect_ip(ip, rec->port, rec->my_ip);
|
||||
|
||||
g_free_not_null(rec->my_ip);
|
||||
|
||||
@ -242,8 +244,7 @@ int net_connect_nonblock(const char *server, int port, const IPADDR *my_ip,
|
||||
rec->pipes[1] = g_io_channel_unix_new(fd[1]);
|
||||
|
||||
/* start nonblocking host name lookup */
|
||||
net_gethostbyname_nonblock(server, rec->pipes[1],
|
||||
my_ip == NULL ? 0 : my_ip->family);
|
||||
net_gethostbyname_nonblock(server, rec->pipes[1]);
|
||||
rec->tag = g_input_add(rec->pipes[0], G_INPUT_READ,
|
||||
(GInputFunction) simple_readpipe, rec);
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "network.h"
|
||||
|
||||
typedef struct {
|
||||
IPADDR ip; /* resolved ip addres */
|
||||
IPADDR ip4, ip6; /* resolved ip addresses */
|
||||
int error; /* error, 0 = no error, -1 = error: */
|
||||
int errlen; /* error text length */
|
||||
char *errorstr; /* error string - dynamically allocated, you'll
|
||||
@ -24,7 +24,7 @@ typedef void (*NET_CALLBACK) (GIOChannel *, void *);
|
||||
typedef void (*NET_HOST_CALLBACK) (RESOLVED_NAME_REC *, void *);
|
||||
|
||||
/* nonblocking gethostbyname(), PID of the resolver child is returned. */
|
||||
int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, int family);
|
||||
int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe);
|
||||
/* Get host's name, call func when finished */
|
||||
int net_gethostbyaddr_nonblock(IPADDR *ip, NET_HOST_CALLBACK func, void *data);
|
||||
/* get the resolved IP address. returns -1 if some error occured with read() */
|
||||
|
@ -47,8 +47,6 @@ union sockaddr_union {
|
||||
# define g_io_channel_new(handle) g_io_channel_unix_new(handle)
|
||||
#endif
|
||||
|
||||
static unsigned short default_family = 0;
|
||||
|
||||
/* Cygwin need this, don't know others.. */
|
||||
/*#define BLOCKING_SOCKETS 1*/
|
||||
|
||||
@ -138,16 +136,37 @@ int sin_get_port(union sockaddr_union *so)
|
||||
/* Connect to socket */
|
||||
GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip)
|
||||
{
|
||||
IPADDR ip;
|
||||
IPADDR ip4, ip6, *ip;
|
||||
int family;
|
||||
|
||||
g_return_val_if_fail(addr != NULL, NULL);
|
||||
|
||||
family = my_ip == NULL ? 0 : my_ip->family;
|
||||
if (net_gethostbyname(addr, &ip, family) == -1)
|
||||
if (net_gethostbyname(addr, &ip4, &ip6) == -1)
|
||||
return NULL;
|
||||
|
||||
return net_connect_ip(&ip, port, my_ip);
|
||||
if (my_ip == NULL) {
|
||||
/* prefer IPv4 addresses */
|
||||
ip = ip4.family != 0 ? &ip4 : &ip6;
|
||||
} else if (IPADDR_IS_V6(my_ip)) {
|
||||
/* my_ip is IPv6 address, use it if possible */
|
||||
if (ip6.family != 0)
|
||||
ip = &ip6;
|
||||
else {
|
||||
my_ip = NULL;
|
||||
ip = &ip4;
|
||||
}
|
||||
} else {
|
||||
/* my_ip is IPv4 address, use it if possible */
|
||||
if (ip4.family != 0)
|
||||
ip = &ip4;
|
||||
else {
|
||||
my_ip = NULL;
|
||||
ip = &ip6;
|
||||
}
|
||||
}
|
||||
|
||||
return net_connect_ip(ip, port, my_ip);
|
||||
}
|
||||
|
||||
/* Connect to socket with ip address */
|
||||
@ -156,6 +175,11 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
|
||||
union sockaddr_union so;
|
||||
int handle, ret, opt = 1;
|
||||
|
||||
if (my_ip != NULL && ip->family != my_ip->family) {
|
||||
g_warning("net_connect_ip(): ip->family != my_ip->family");
|
||||
my_ip = NULL;
|
||||
}
|
||||
|
||||
/* create the socket */
|
||||
memset(&so, 0, sizeof(so));
|
||||
so.sin.sin_family = ip->family;
|
||||
@ -334,28 +358,28 @@ int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get IP address for host. family specifies if we should prefer to
|
||||
IPv4 or IPv6 address (0 = default, AF_INET or AF_INET6).
|
||||
returns 0 = ok, others = error code for net_gethosterror() */
|
||||
int net_gethostbyname(const char *addr, IPADDR *ip, int family)
|
||||
/* Get IP addresses for host, both IPv4 and IPv6 if possible.
|
||||
If ip->family is 0, the address wasn't found.
|
||||
Returns 0 = ok, others = error code for net_gethosterror() */
|
||||
int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6)
|
||||
{
|
||||
#ifdef HAVE_IPV6
|
||||
union sockaddr_union *so;
|
||||
struct addrinfo hints, *ai;
|
||||
struct addrinfo hints, *ai, *origai;
|
||||
char hbuf[NI_MAXHOST];
|
||||
int host_error;
|
||||
int host_error, count;
|
||||
#else
|
||||
struct hostent *hp;
|
||||
#endif
|
||||
|
||||
g_return_val_if_fail(addr != NULL, -1);
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
memset(ip, 0, sizeof(IPADDR));
|
||||
memset(ip4, 0, sizeof(IPADDR));
|
||||
memset(ip6, 0, sizeof(IPADDR));
|
||||
|
||||
#ifdef HAVE_IPV6
|
||||
memset(&hints, 0, sizeof(struct addrinfo));
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
hints.ai_family = family != 0 ? family : default_family;
|
||||
|
||||
/* save error to host_error for later use */
|
||||
host_error = getaddrinfo(addr, NULL, &hints, &ai);
|
||||
@ -366,27 +390,31 @@ int net_gethostbyname(const char *addr, IPADDR *ip, int family)
|
||||
sizeof(hbuf), NULL, 0, NI_NUMERICHOST))
|
||||
return 1;
|
||||
|
||||
so = (union sockaddr_union *) ai->ai_addr;
|
||||
sin_get_ip(so, ip);
|
||||
freeaddrinfo(ai);
|
||||
origai = ai; count = 0;
|
||||
while (ai != NULL && count < 2) {
|
||||
so = (union sockaddr_union *) ai->ai_addr;
|
||||
|
||||
if (ai->ai_family == AF_INET6 && ip6->family == 0) {
|
||||
sin_get_ip(so, ip6);
|
||||
count++;
|
||||
} else if (ai->ai_family == AF_INET && ip4->family == 0) {
|
||||
sin_get_ip(so, ip4);
|
||||
count++;
|
||||
}
|
||||
ai = ai->ai_next;
|
||||
}
|
||||
freeaddrinfo(origai);
|
||||
#else
|
||||
hp = gethostbyname(addr);
|
||||
if (hp == NULL) return h_errno;
|
||||
|
||||
ip->family = AF_INET;
|
||||
memcpy(&ip->addr, hp->h_addr, 4);
|
||||
ip4->family = AF_INET;
|
||||
memcpy(&ip4->addr, hp->h_addr, 4);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the default address family to use with host resolving
|
||||
(AF_INET or AF_INET6) */
|
||||
void net_host_resolver_set_default_family(unsigned short family)
|
||||
{
|
||||
default_family = family;
|
||||
}
|
||||
|
||||
/* Get name for host, *name should be g_free()'d unless it's NULL.
|
||||
Return values are the same as with net_gethostbyname() */
|
||||
int net_gethostbyaddr(IPADDR *ip, char **name)
|
||||
|
@ -33,7 +33,7 @@ struct _IPADDR {
|
||||
# define MAX_IP_LEN 20
|
||||
#endif
|
||||
|
||||
#define is_ipv6_addr(ip) ((ip)->family != AF_INET)
|
||||
#define IPADDR_IS_V6(ip) ((ip)->family != AF_INET)
|
||||
|
||||
/* returns 1 if IPADDRs are the same */
|
||||
int net_ip_compare(IPADDR *ip1, IPADDR *ip2);
|
||||
@ -58,13 +58,10 @@ int net_receive(GIOChannel *handle, char *buf, int len);
|
||||
/* Transmit data, return number of bytes sent, -1 = error */
|
||||
int net_transmit(GIOChannel *handle, const char *data, int len);
|
||||
|
||||
/* Get IP address for host. family specifies if we should prefer to
|
||||
IPv4 or IPv6 address (0 = default, AF_INET or AF_INET6).
|
||||
returns 0 = ok, others = error code for net_gethosterror() */
|
||||
int net_gethostbyname(const char *addr, IPADDR *ip, int family);
|
||||
/* Set the default address family to use with host resolving
|
||||
(AF_INET or AF_INET6) */
|
||||
void net_host_resolver_set_default_family(unsigned short family);
|
||||
/* Get IP addresses for host, both IPv4 and IPv6 if possible.
|
||||
If ip->family is 0, the address wasn't found.
|
||||
Returns 0 = ok, others = error code for net_gethosterror() */
|
||||
int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6);
|
||||
/* Get name for host, *name should be g_free()'d unless it's NULL.
|
||||
Return values are the same as with net_gethostbyname() */
|
||||
int net_gethostbyaddr(IPADDR *ip, char **name);
|
||||
|
@ -13,7 +13,7 @@ char *address;
|
||||
int port;
|
||||
char *chatnet;
|
||||
|
||||
IPADDR *own_ip;
|
||||
IPADDR *own_ip4, *own_ip6;
|
||||
|
||||
char *password;
|
||||
char *nick;
|
||||
|
@ -9,7 +9,7 @@ int port;
|
||||
char *password;
|
||||
|
||||
char *own_host; /* address to use when connecting this server */
|
||||
IPADDR *own_ip; /* resolved own_address if not NULL */
|
||||
IPADDR *own_ip4, *own_ip6; /* resolved own_address if not NULL */
|
||||
|
||||
time_t last_connect; /* to avoid reconnecting too fast.. */
|
||||
|
||||
|
@ -142,9 +142,13 @@ server_connect_copy_skeleton(SERVER_CONNECT_REC *src, int connect_info)
|
||||
dest->username = g_strdup(src->username);
|
||||
dest->realname = g_strdup(src->realname);
|
||||
|
||||
if (src->own_ip != NULL) {
|
||||
dest->own_ip = g_new(IPADDR, 1);
|
||||
memcpy(dest->own_ip, src->own_ip, sizeof(IPADDR));
|
||||
if (src->own_ip4 != NULL) {
|
||||
dest->own_ip4 = g_new(IPADDR, 1);
|
||||
memcpy(dest->own_ip4, src->own_ip4, sizeof(IPADDR));
|
||||
}
|
||||
if (src->own_ip6 != NULL) {
|
||||
dest->own_ip6 = g_new(IPADDR, 1);
|
||||
memcpy(dest->own_ip6, src->own_ip6, sizeof(IPADDR));
|
||||
}
|
||||
|
||||
dest->channels = g_strdup(src->channels);
|
||||
|
@ -33,48 +33,61 @@ GSList *setupservers;
|
||||
|
||||
char *old_source_host;
|
||||
int source_host_ok; /* Use source_host_ip .. */
|
||||
IPADDR *source_host_ip; /* Resolved address */
|
||||
IPADDR *source_host_ip4, *source_host_ip6; /* Resolved address */
|
||||
|
||||
static void save_ips(IPADDR *ip4, IPADDR *ip6,
|
||||
IPADDR **save_ip4, IPADDR **save_ip6)
|
||||
{
|
||||
if (ip4->family == 0)
|
||||
g_free_and_null(*save_ip4);
|
||||
else {
|
||||
if (*save_ip4 == NULL)
|
||||
*save_ip4 = g_new(IPADDR, 1);
|
||||
memcpy(*save_ip4, &ip4, sizeof(IPADDR));
|
||||
}
|
||||
|
||||
if (ip6->family == 0)
|
||||
g_free_and_null(*save_ip6);
|
||||
else {
|
||||
if (*save_ip6 == NULL)
|
||||
*save_ip6 = g_new(IPADDR, 1);
|
||||
memcpy(*save_ip6, &ip6, sizeof(IPADDR));
|
||||
}
|
||||
}
|
||||
|
||||
static void get_source_host_ip(void)
|
||||
{
|
||||
IPADDR ip;
|
||||
const char *hostname;
|
||||
IPADDR ip4, ip6;
|
||||
|
||||
if (source_host_ok)
|
||||
return;
|
||||
|
||||
/* FIXME: This will block! */
|
||||
source_host_ok = *settings_get_str("hostname") != '\0' &&
|
||||
net_gethostbyname(settings_get_str("hostname"), &ip, 0) == 0;
|
||||
if (source_host_ok) {
|
||||
if (source_host_ip == NULL)
|
||||
source_host_ip = g_new(IPADDR, 1);
|
||||
memcpy(source_host_ip, &ip, sizeof(IPADDR));
|
||||
hostname = settings_get_str("hostname");
|
||||
source_host_ok = *hostname != '\0' &&
|
||||
net_gethostbyname(hostname, &ip4, &ip6) == 0;
|
||||
|
||||
if (source_host_ok)
|
||||
save_ips(&ip4, &ip6, &source_host_ip4, &source_host_ip6);
|
||||
else {
|
||||
g_free_and_null(source_host_ip4);
|
||||
g_free_and_null(source_host_ip6);
|
||||
}
|
||||
}
|
||||
|
||||
static void conn_set_ip(SERVER_CONNECT_REC *conn,
|
||||
IPADDR **own_ip, const char *own_host)
|
||||
static void conn_set_ip(SERVER_CONNECT_REC *conn, const char *own_host,
|
||||
IPADDR **own_ip4, IPADDR **own_ip6)
|
||||
{
|
||||
IPADDR ip;
|
||||
IPADDR ip4, ip6;
|
||||
|
||||
if (*own_ip != NULL) {
|
||||
/* use already resolved IP */
|
||||
if (conn->own_ip == NULL)
|
||||
conn->own_ip = g_new(IPADDR, 1);
|
||||
memcpy(conn->own_ip, *own_ip, sizeof(IPADDR));
|
||||
return;
|
||||
if (*own_ip4 == NULL && *own_ip6 == NULL) {
|
||||
/* resolve the IP */
|
||||
if (net_gethostbyname(own_host, &ip4, &ip6) == 0)
|
||||
save_ips(&ip4, &ip6, own_ip4, own_ip6);
|
||||
}
|
||||
|
||||
|
||||
/* resolve the IP and use it */
|
||||
if (net_gethostbyname(own_host, &ip, conn->family) == 0) {
|
||||
if (conn->own_ip == NULL)
|
||||
conn->own_ip = g_new(IPADDR, 1);
|
||||
memcpy(conn->own_ip, &ip, sizeof(IPADDR));
|
||||
|
||||
*own_ip = g_new(IPADDR, 1);
|
||||
memcpy(*own_ip, &ip, sizeof(IPADDR));
|
||||
}
|
||||
server_connect_own_ip_save(conn, *own_ip4, *own_ip6);
|
||||
}
|
||||
|
||||
/* Fill information to connection from server setup record */
|
||||
@ -84,8 +97,10 @@ void server_setup_fill_reconn(SERVER_CONNECT_REC *conn,
|
||||
g_return_if_fail(IS_SERVER_CONNECT(conn));
|
||||
g_return_if_fail(IS_SERVER_SETUP(sserver));
|
||||
|
||||
if (sserver->own_host != NULL)
|
||||
conn_set_ip(conn, &sserver->own_ip, sserver->own_host);
|
||||
if (sserver->own_host != NULL) {
|
||||
conn_set_ip(conn, sserver->own_host,
|
||||
&sserver->own_ip4, &sserver->own_ip6);
|
||||
}
|
||||
|
||||
if (sserver->chatnet != NULL && conn->chatnet == NULL)
|
||||
conn->chatnet = g_strdup(sserver->chatnet);
|
||||
@ -119,10 +134,13 @@ static void server_setup_fill(SERVER_CONNECT_REC *conn,
|
||||
}
|
||||
|
||||
/* source IP */
|
||||
get_source_host_ip();
|
||||
if (source_host_ok) {
|
||||
conn->own_ip = g_new(IPADDR, 1);
|
||||
memcpy(conn->own_ip, source_host_ip, sizeof(IPADDR));
|
||||
if (source_host_ip4 != NULL) {
|
||||
conn->own_ip4 = g_new(IPADDR, 1);
|
||||
memcpy(conn->own_ip4, source_host_ip4, sizeof(IPADDR));
|
||||
}
|
||||
if (source_host_ip6 != NULL) {
|
||||
conn->own_ip6 = g_new(IPADDR, 1);
|
||||
memcpy(conn->own_ip6, source_host_ip6, sizeof(IPADDR));
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,8 +179,10 @@ static void server_setup_fill_chatnet(SERVER_CONNECT_REC *conn,
|
||||
g_free(conn->realname);
|
||||
conn->realname = g_strdup(chatnet->realname);;
|
||||
}
|
||||
if (chatnet->own_host != NULL)
|
||||
conn_set_ip(conn, &chatnet->own_ip, chatnet->own_host);
|
||||
if (chatnet->own_host != NULL) {
|
||||
conn_set_ip(conn, chatnet->own_host,
|
||||
&chatnet->own_ip4, &chatnet->own_ip6);
|
||||
}
|
||||
|
||||
signal_emit("server setup fill chatnet", 2, conn, chatnet);
|
||||
}
|
||||
@ -414,7 +434,8 @@ static void server_setup_destroy(SERVER_SETUP_REC *rec)
|
||||
signal_emit("server setup destroyed", 1, rec);
|
||||
|
||||
g_free_not_null(rec->own_host);
|
||||
g_free_not_null(rec->own_ip);
|
||||
g_free_not_null(rec->own_ip4);
|
||||
g_free_not_null(rec->own_ip6);
|
||||
g_free_not_null(rec->chatnet);
|
||||
g_free_not_null(rec->password);
|
||||
g_free(rec->address);
|
||||
@ -453,17 +474,11 @@ static void read_servers(void)
|
||||
|
||||
static void read_settings(void)
|
||||
{
|
||||
unsigned short family;
|
||||
|
||||
family = settings_get_bool("resolve_prefer_ipv6") ? AF_INET6 : AF_INET;
|
||||
net_host_resolver_set_default_family(family);
|
||||
|
||||
if (old_source_host == NULL ||
|
||||
strcmp(old_source_host, settings_get_str("hostname")) != 0) {
|
||||
g_free_not_null(old_source_host);
|
||||
old_source_host = g_strdup(settings_get_str("hostname"));
|
||||
|
||||
g_free_and_null(source_host_ip);
|
||||
source_host_ok = FALSE;
|
||||
get_source_host_ip();
|
||||
}
|
||||
@ -472,7 +487,6 @@ static void read_settings(void)
|
||||
void servers_setup_init(void)
|
||||
{
|
||||
settings_add_str("server", "hostname", "");
|
||||
settings_add_bool("server", "resolve_prefer_ipv6", FALSE);
|
||||
|
||||
settings_add_str("server", "nick", NULL);
|
||||
settings_add_str("server", "user_name", NULL);
|
||||
@ -484,7 +498,7 @@ void servers_setup_init(void)
|
||||
settings_add_str("proxy", "proxy_string", "CONNECT %s %d");
|
||||
|
||||
setupservers = NULL;
|
||||
source_host_ip = NULL;
|
||||
source_host_ip4 = source_host_ip6 = NULL;
|
||||
old_source_host = NULL;
|
||||
read_settings();
|
||||
|
||||
@ -495,7 +509,8 @@ void servers_setup_init(void)
|
||||
|
||||
void servers_setup_deinit(void)
|
||||
{
|
||||
g_free_not_null(source_host_ip);
|
||||
g_free_not_null(source_host_ip4);
|
||||
g_free_not_null(source_host_ip6);
|
||||
g_free_not_null(old_source_host);
|
||||
|
||||
while (setupservers != NULL)
|
||||
|
@ -16,7 +16,7 @@ struct _SERVER_SETUP_REC {
|
||||
|
||||
extern GSList *setupservers;
|
||||
|
||||
extern IPADDR *source_host_ip; /* Resolved address */
|
||||
extern IPADDR *source_host_ip4, *source_host_ip6; /* Resolved address */
|
||||
extern int source_host_ok; /* Use source_host_ip .. */
|
||||
|
||||
/* Fill reconnection specific information to connection
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "net-sendbuffer.h"
|
||||
#include "misc.h"
|
||||
#include "rawlog.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include "servers.h"
|
||||
#include "servers-reconnect.h"
|
||||
@ -154,8 +155,10 @@ static void server_connect_callback_readpipe(SERVER_REC *server)
|
||||
{
|
||||
SERVER_CONNECT_REC *conn;
|
||||
RESOLVED_IP_REC iprec;
|
||||
const char *errormsg;
|
||||
GIOChannel *handle;
|
||||
IPADDR *ip, *own_ip;
|
||||
const char *errormsg;
|
||||
int port;
|
||||
|
||||
g_return_if_fail(IS_SERVER(server));
|
||||
|
||||
@ -172,14 +175,23 @@ static void server_connect_callback_readpipe(SERVER_REC *server)
|
||||
server->connect_pipe[0] = NULL;
|
||||
server->connect_pipe[1] = NULL;
|
||||
|
||||
if (iprec.error == 0)
|
||||
signal_emit("server connecting", 2, server, &iprec.ip);
|
||||
/* figure out if we should use IPv4 or v6 address */
|
||||
ip = iprec.error != 0 ? NULL : iprec.ip6.family == 0 ||
|
||||
server->connrec->family == AF_INET ?
|
||||
&iprec.ip4 : &iprec.ip6;
|
||||
if (iprec.ip4.family != 0 && server->connrec->family == 0 &&
|
||||
!settings_get_bool("resolve_prefer_ipv6"))
|
||||
ip = &iprec.ip4;
|
||||
|
||||
conn = server->connrec;
|
||||
handle = iprec.error != 0 ? NULL :
|
||||
net_connect_ip(&iprec.ip, conn->proxy != NULL ?
|
||||
conn->proxy_port : conn->port,
|
||||
conn->own_ip != NULL ? conn->own_ip : NULL);
|
||||
conn = server->connrec;
|
||||
port = conn->proxy != NULL ? conn->proxy_port : conn->port;
|
||||
own_ip = ip == NULL ? NULL :
|
||||
(IPADDR_IS_V6(ip) ? conn->own_ip6 : conn->own_ip4);
|
||||
|
||||
if (ip != NULL)
|
||||
signal_emit("server connecting", 2, server, ip);
|
||||
|
||||
handle = ip == NULL ? NULL : net_connect_ip(ip, port, own_ip);
|
||||
if (handle == NULL) {
|
||||
/* failed */
|
||||
if (iprec.error == 0 || !net_hosterror_notfound(iprec.error)) {
|
||||
@ -259,15 +271,11 @@ int server_start_connect(SERVER_REC *server)
|
||||
server->connect_pipe[0] = g_io_channel_unix_new(fd[0]);
|
||||
server->connect_pipe[1] = g_io_channel_unix_new(fd[1]);
|
||||
|
||||
if (server->connrec->family == 0 && server->connrec->own_ip != NULL)
|
||||
server->connrec->family = server->connrec->own_ip->family;
|
||||
|
||||
connect_address = server->connrec->proxy != NULL ?
|
||||
server->connrec->proxy : server->connrec->address;
|
||||
server->connect_pid =
|
||||
net_gethostbyname_nonblock(connect_address,
|
||||
server->connect_pipe[1],
|
||||
server->connrec->family);
|
||||
server->connect_pipe[1]);
|
||||
server->connect_tag =
|
||||
g_input_add(server->connect_pipe[0], G_INPUT_READ,
|
||||
(GInputFunction) server_connect_callback_readpipe,
|
||||
@ -405,7 +413,8 @@ void server_connect_free(SERVER_CONNECT_REC *conn)
|
||||
g_free_not_null(conn->address);
|
||||
g_free_not_null(conn->chatnet);
|
||||
|
||||
g_free_not_null(conn->own_ip);
|
||||
g_free_not_null(conn->own_ip4);
|
||||
g_free_not_null(conn->own_ip6);
|
||||
|
||||
g_free_not_null(conn->password);
|
||||
g_free_not_null(conn->nick);
|
||||
@ -417,6 +426,30 @@ void server_connect_free(SERVER_CONNECT_REC *conn)
|
||||
g_free(conn);
|
||||
}
|
||||
|
||||
/* Update own IPv4 and IPv6 records */
|
||||
void server_connect_own_ip_save(SERVER_CONNECT_REC *conn,
|
||||
IPADDR *ip4, IPADDR *ip6)
|
||||
{
|
||||
if (ip4 == NULL || ip4->family == 0)
|
||||
g_free_and_null(conn->own_ip4);
|
||||
if (ip6 == NULL || ip6->family == 0)
|
||||
g_free_and_null(conn->own_ip6);
|
||||
|
||||
if (ip4 != NULL && ip4->family != 0) {
|
||||
/* IPv4 address was found */
|
||||
if (conn->own_ip4 != NULL)
|
||||
conn->own_ip4 = g_new0(IPADDR, 1);
|
||||
memcpy(conn->own_ip4, ip4, sizeof(IPADDR));
|
||||
}
|
||||
|
||||
if (ip6 != NULL && ip6->family != 0) {
|
||||
/* IPv6 address was found */
|
||||
if (conn->own_ip6 != NULL)
|
||||
conn->own_ip6 = g_new0(IPADDR, 1);
|
||||
memcpy(conn->own_ip6, ip6, sizeof(IPADDR));
|
||||
}
|
||||
}
|
||||
|
||||
/* `optlist' should contain only one unknown key - the server tag.
|
||||
returns NULL if there was unknown -option */
|
||||
SERVER_REC *cmd_options_get_server(const char *cmd,
|
||||
@ -459,6 +492,7 @@ SERVER_REC *cmd_options_get_server(const char *cmd,
|
||||
|
||||
void servers_init(void)
|
||||
{
|
||||
settings_add_bool("server", "resolve_prefer_ipv6", FALSE);
|
||||
lookup_servers = servers = NULL;
|
||||
|
||||
servers_reconnect_init();
|
||||
|
@ -50,6 +50,10 @@ void server_connect_finished(SERVER_REC *server);
|
||||
/* connection to server failed */
|
||||
void server_connect_failed(SERVER_REC *server, const char *msg);
|
||||
|
||||
/* Update own IPv4 and IPv6 records */
|
||||
void server_connect_own_ip_save(SERVER_CONNECT_REC *conn,
|
||||
IPADDR *ip4, IPADDR *ip6);
|
||||
|
||||
/* `optlist' should contain only one unknown key - the server tag.
|
||||
returns NULL if there was unknown -option */
|
||||
SERVER_REC *cmd_options_get_server(const char *cmd,
|
||||
|
@ -135,7 +135,7 @@ static void cmd_server_add(const char *data)
|
||||
if (*password != '\0') g_free_and_null(rec->password);
|
||||
if (g_hash_table_lookup(optlist, "host")) {
|
||||
g_free_and_null(rec->own_host);
|
||||
rec->own_ip = NULL;
|
||||
rec->own_ip4 = rec->own_ip6 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@ static void cmd_server_add(const char *data)
|
||||
value = g_hash_table_lookup(optlist, "host");
|
||||
if (value != NULL && *value != '\0') {
|
||||
rec->own_host = g_strdup(value);
|
||||
rec->own_ip = NULL;
|
||||
rec->own_ip4 = rec->own_ip6 = NULL;
|
||||
}
|
||||
|
||||
signal_emit("server add fill", 2, rec, optlist);
|
||||
|
@ -106,7 +106,7 @@ static void cmd_ircnet_add(const char *data)
|
||||
if (g_hash_table_lookup(optlist, "realname")) g_free_and_null(rec->realname);
|
||||
if (g_hash_table_lookup(optlist, "host")) {
|
||||
g_free_and_null(rec->own_host);
|
||||
rec->own_ip = NULL;
|
||||
rec->own_ip4 = rec->own_ip6 = NULL;
|
||||
}
|
||||
if (g_hash_table_lookup(optlist, "autosendcmd")) g_free_and_null(rec->autosendcmd);
|
||||
}
|
||||
@ -137,7 +137,7 @@ static void cmd_ircnet_add(const char *data)
|
||||
value = g_hash_table_lookup(optlist, "host");
|
||||
if (value != NULL && *value != '\0') {
|
||||
rec->own_host = g_strdup(value);
|
||||
rec->own_ip = NULL;
|
||||
rec->own_ip4 = rec->own_ip6 = NULL;
|
||||
}
|
||||
|
||||
value = g_hash_table_lookup(optlist, "autosendcmd");
|
||||
|
@ -362,6 +362,8 @@ static void sig_chat_connected(CHAT_DCC_REC *dcc)
|
||||
|
||||
static void dcc_chat_connect(CHAT_DCC_REC *dcc)
|
||||
{
|
||||
IPADDR *own_ip;
|
||||
|
||||
g_return_if_fail(IS_DCC_CHAT(dcc));
|
||||
|
||||
if (dcc->addrstr[0] == '\0' ||
|
||||
@ -370,8 +372,8 @@ static void dcc_chat_connect(CHAT_DCC_REC *dcc)
|
||||
return;
|
||||
}
|
||||
|
||||
dcc->handle = net_connect_ip(&dcc->addr, dcc->port,
|
||||
source_host_ok ? source_host_ip : NULL);
|
||||
own_ip = IPADDR_IS_V6(&dcc->addr) ? source_host_ip6 : source_host_ip4;
|
||||
dcc->handle = net_connect_ip(&dcc->addr, dcc->port, own_ip);
|
||||
if (dcc->handle != NULL) {
|
||||
dcc->tagconn = g_input_add(dcc->handle,
|
||||
G_INPUT_WRITE | G_INPUT_READ,
|
||||
|
@ -212,14 +212,15 @@ static void sig_dccget_connected(GET_DCC_REC *dcc)
|
||||
|
||||
void dcc_get_connect(GET_DCC_REC *dcc)
|
||||
{
|
||||
IPADDR *own_ip;
|
||||
|
||||
if (dcc->get_type == DCC_GET_DEFAULT) {
|
||||
dcc->get_type = settings_get_bool("dcc_autorename") ?
|
||||
DCC_GET_RENAME : DCC_GET_OVERWRITE;
|
||||
}
|
||||
|
||||
|
||||
dcc->handle = net_connect_ip(&dcc->addr, dcc->port,
|
||||
source_host_ok ? source_host_ip : NULL);
|
||||
own_ip = IPADDR_IS_V6(&dcc->addr) ? source_host_ip6 : source_host_ip4;
|
||||
dcc->handle = net_connect_ip(&dcc->addr, dcc->port, own_ip);
|
||||
if (dcc->handle != NULL) {
|
||||
dcc->tagconn =
|
||||
g_input_add(dcc->handle,
|
||||
|
@ -154,7 +154,7 @@ void dcc_ip2str(IPADDR *ip, char *host)
|
||||
{
|
||||
unsigned long addr;
|
||||
|
||||
if (is_ipv6_addr(ip)) {
|
||||
if (IPADDR_IS_V6(ip)) {
|
||||
/* IPv6 */
|
||||
net_ip2host(ip, host);
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user