From 8938a0f42b178a3bf26ad6976013ad57fb1e5bb2 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Fri, 9 Feb 2001 21:26:50 +0000 Subject: [PATCH] /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 --- src/core/net-nonblock.c | 7 ++++--- src/core/net-nonblock.h | 2 +- src/core/network.c | 16 ++++++++++------ src/core/network.h | 7 ++++--- src/core/server-connect-rec.h | 1 + src/core/servers-setup.c | 4 ++-- src/core/servers.c | 8 ++++++-- src/irc/core/irc-commands.c | 16 +++++++++++----- 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 ] [-host ] +/* SYNTAX: CONNECT [-4 | -6] [-ircnet ] [-host ]
| [ [ []]] */ 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 ] [-host ] +/* SYNTAX: SERVER [-4 | -6] [-ircnet ] [-host ] [+]
| [ [ []]] */ 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");