summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Sirainen <cras@irssi.org>2001-02-09 21:26:50 +0000
committercras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564>2001-02-09 21:26:50 +0000
commit8938a0f42b178a3bf26ad6976013ad57fb1e5bb2 (patch)
treebb2d5b6588d9db712f89e8d3159d8ece1d943e56
parent6358c2d62727113c15d389dd0e6460ba9a72f941 (diff)
downloadirssi-8938a0f42b178a3bf26ad6976013ad57fb1e5bb2.zip
/CONNECT, /SERVER: added -4 and -6 options for specifying if we should
connect to IPv4 or IPv6 address of the server. If -host or /SET hostname is set irssi determines from it if it should use IPv4 or v6. git-svn-id: http://svn.irssi.org/repos/irssi/trunk@1192 dbcabf3a-b0e7-0310-adc4-f8d773084564
-rw-r--r--src/core/net-nonblock.c7
-rw-r--r--src/core/net-nonblock.h2
-rw-r--r--src/core/network.c16
-rw-r--r--src/core/network.h7
-rw-r--r--src/core/server-connect-rec.h1
-rw-r--r--src/core/servers-setup.c4
-rw-r--r--src/core/servers.c8
-rw-r--r--src/irc/core/irc-commands.c16
8 files changed, 39 insertions, 22 deletions
diff --git a/src/core/net-nonblock.c b/src/core/net-nonblock.c
index 2b38e79b..4b9ab283 100644
--- a/src/core/net-nonblock.c
+++ b/src/core/net-nonblock.c
@@ -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 net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, int family)
{
RESOLVED_IP_REC rec;
const char *errorstr;
@@ -100,7 +100,7 @@ int net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe)
/* child */
memset(&rec, 0, sizeof(rec));
- rec.error = net_gethostbyname(addr, &rec.ip);
+ rec.error = net_gethostbyname(addr, &rec.ip, family);
if (rec.error == 0) {
errorstr = NULL;
} else {
@@ -239,7 +239,8 @@ 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]);
+ net_gethostbyname_nonblock(server, rec->pipes[1],
+ my_ip == NULL ? 0 : my_ip->family);
rec->tag = g_input_add(rec->pipes[0], G_INPUT_READ,
(GInputFunction) simple_readpipe, rec);
diff --git a/src/core/net-nonblock.h b/src/core/net-nonblock.h
index ced58eea..7ee85823 100644
--- a/src/core/net-nonblock.h
+++ b/src/core/net-nonblock.h
@@ -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 net_gethostbyname_nonblock(const char *addr, GIOChannel *pipe, int family);
/* 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() */
diff --git a/src/core/network.c b/src/core/network.c
index 96e77ee8..149b047e 100644
--- a/src/core/network.c
+++ b/src/core/network.c
@@ -137,10 +137,12 @@ int sin_get_port(union sockaddr_union *so)
GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip)
{
IPADDR ip;
+ int family;
g_return_val_if_fail(addr != NULL, NULL);
- if (net_gethostbyname(addr, &ip) == -1)
+ family = my_ip == NULL ? 0 : my_ip->family;
+ if (net_gethostbyname(addr, &ip, family) == -1)
return NULL;
return net_connect_ip(&ip, port, my_ip);
@@ -332,11 +334,11 @@ int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port)
/* Get IP address for host, returns 0 = ok,
others = error code for net_gethosterror() */
-int net_gethostbyname(const char *addr, IPADDR *ip)
+int net_gethostbyname(const char *addr, IPADDR *ip, int family)
{
#ifdef HAVE_IPV6
union sockaddr_union *so;
- struct addrinfo req, *ai;
+ struct addrinfo hints, *ai;
char hbuf[NI_MAXHOST];
int host_error;
#else
@@ -347,11 +349,13 @@ int net_gethostbyname(const char *addr, IPADDR *ip)
#ifdef HAVE_IPV6
memset(ip, 0, sizeof(IPADDR));
- memset(&req, 0, sizeof(struct addrinfo));
- req.ai_socktype = SOCK_STREAM;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = family;
/* save error to host_error for later use */
- host_error = getaddrinfo(addr, NULL, &req, &ai);
+ host_error = getaddrinfo(addr, NULL, &hints, &ai);
if (host_error != 0)
return host_error;
diff --git a/src/core/network.h b/src/core/network.h
index 94f2596b..810b11c7 100644
--- a/src/core/network.h
+++ b/src/core/network.h
@@ -50,9 +50,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, returns 0 = ok,
- others = error code for net_gethosterror() */
-int net_gethostbyname(const char *addr, IPADDR *ip);
+/* Get IP address for host. family specifies if we should prefer to
+ IPv4 or IPv6 address (0 = don't care, 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 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);
diff --git a/src/core/server-connect-rec.h b/src/core/server-connect-rec.h
index 0155dd2a..6378fd83 100644
--- a/src/core/server-connect-rec.h
+++ b/src/core/server-connect-rec.h
@@ -8,6 +8,7 @@ char *proxy;
int proxy_port;
char *proxy_string;
+unsigned short family; /* 0 = don't care, AF_INET or AF_INET6 */
char *address;
int port;
char *chatnet;
diff --git a/src/core/servers-setup.c b/src/core/servers-setup.c
index 8bce2f86..395edbf4 100644
--- a/src/core/servers-setup.c
+++ b/src/core/servers-setup.c
@@ -42,7 +42,7 @@ static void get_source_host_ip(void)
/* FIXME: This will block! */
source_host_ok = *settings_get_str("hostname") != '\0' &&
- net_gethostbyname(settings_get_str("hostname"), &ip) == 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);
@@ -65,7 +65,7 @@ static void conn_set_ip(SERVER_CONNECT_REC *conn,
/* resolve the IP and use it */
- if (net_gethostbyname(own_host, &ip) == 0) {
+ 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));
diff --git a/src/core/servers.c b/src/core/servers.c
index ac0f5bef..0972174d 100644
--- a/src/core/servers.c
+++ b/src/core/servers.c
@@ -256,13 +256,17 @@ 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]);
+ 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->connect_pipe[1],
+ server->connrec->family);
server->connect_tag =
g_input_add(server->connect_pipe[0], G_INPUT_READ,
(GInputFunction) server_connect_callback_readpipe,
diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c
index 2c0f151d..3c32b3ec 100644
--- a/src/irc/core/irc-commands.c
+++ b/src/irc/core/irc-commands.c
@@ -64,7 +64,8 @@ static SERVER_REC *irc_connect_server(const char *data)
g_return_val_if_fail(data != NULL, NULL);
if (!cmd_get_params(data, &free_arg, 4 | PARAM_FLAG_OPTIONS,
- "connect", &optlist, &addr, &portstr, &password, &nick))
+ "connect", &optlist, &addr, &portstr,
+ &password, &nick))
return NULL;
if (*addr == '+') addr++;
if (*addr == '\0') {
@@ -78,6 +79,11 @@ static SERVER_REC *irc_connect_server(const char *data)
/* connect to server */
conn = server_create_conn(addr, atoi(portstr), password, nick);
+ if (g_hash_table_lookup(optlist, "6") != NULL)
+ conn->family = AF_INET6;
+ else if (g_hash_table_lookup(optlist, "4") != NULL)
+ conn->family = AF_INET;
+
ircnet = g_hash_table_lookup(optlist, "ircnet");
if (ircnet != NULL && *ircnet != '\0') {
g_free_not_null(conn->chatnet);
@@ -87,7 +93,7 @@ static SERVER_REC *irc_connect_server(const char *data)
if (host != NULL && *host != '\0') {
IPADDR ip;
- if (net_gethostbyname(host, &ip) == 0) {
+ 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));
@@ -99,7 +105,7 @@ static SERVER_REC *irc_connect_server(const char *data)
return server;
}
-/* SYNTAX: CONNECT [-ircnet <ircnet>] [-host <hostname>]
+/* SYNTAX: CONNECT [-4 | -6] [-ircnet <ircnet>] [-host <hostname>]
<address>|<ircnet> [<port> [<password> [<nick>]]] */
static void cmd_connect(const char *data)
{
@@ -137,7 +143,7 @@ static RECONNECT_REC *find_reconnect_server(const char *addr, int port)
return match;
}
-/* SYNTAX: SERVER [-ircnet <ircnet>] [-host <hostname>]
+/* SYNTAX: SERVER [-4 | -6] [-ircnet <ircnet>] [-host <hostname>]
[+]<address>|<ircnet> [<port> [<password> [<nick>]]] */
static void cmd_server(const char *data, IRC_SERVER_REC *server,
void *item)
@@ -1212,7 +1218,7 @@ void irc_commands_init(void)
signal_add("whois event", (SIGNAL_FUNC) event_whois);
signal_add("whowas event", (SIGNAL_FUNC) event_whowas);
- command_set_options("connect", "+ircnet +host");
+ command_set_options("connect", "4 6 +ircnet +host");
command_set_options("topic", "delete");
command_set_options("list", "yes");
command_set_options("away", "one all");