1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-26 01:32:25 +00:00

Support for doing DNS at the proxy end. I've invented a new type of

SockAddr, which just contains an unresolved hostname and is created
by a stub function in *net.c. It's an error to pass this to most of
the real-meat functions in *net.c; these fake addresses should have
been dealt with by the time they get down that far. proxy.c now
contains name_lookup(), a wrapper on sk_namelookup() which decides
whether or not to do real DNS, and the individual proxy
implementations each deal sensibly with being handed an unresolved
address and avoid ever passing one down to *net.c.

[originally from svn r2353]
This commit is contained in:
Simon Tatham 2002-12-18 16:23:11 +00:00
parent e1cc16e6be
commit a564ad3140
14 changed files with 227 additions and 65 deletions

View File

@ -1,4 +1,4 @@
\versionid $Id: config.but,v 1.46 2002/12/18 12:18:54 simon Exp $ \versionid $Id: config.but,v 1.47 2002/12/18 16:23:10 simon Exp $
\C{config} Configuring PuTTY \C{config} Configuring PuTTY
@ -1445,6 +1445,43 @@ list does not explicitly contain them. It is very unlikely that this
behaviour would ever cause problems, but if it does you can change behaviour would ever cause problems, but if it does you can change
it by enabling \q{Consider proxying local host connections}. it by enabling \q{Consider proxying local host connections}.
Note that if you are doing DNS at the proxy (see
\k{config-proxy-dns}), you should make sure that your proxy
exclusion settings do not depend on knowing the IP address of a
host. If the name is passed on to the proxy without PuTTY looking it
up, it will never know the IP address and cannot check it against
your list.
\S{config-proxy-dns} Name resolution when using a proxy
\cfg{winhelp-topic}{proxy.dns}
If you are using a proxy to access a private network, it can make a
difference whether DNS name resolution is performed by PuTTY itself
(on the client machine) or performed by the proxy.
The \q{Do DNS name lookup at proxy end} configuration option allows
you to control this. If you set it to \q{No}, PuTTY will always do
its own DNS, and will always pass an IP address to the proxy. If you
set it to \q{Yes}, PuTTY will always pass host names straight to the
proxy without trying to look them up first.
If you set this option to \q{Auto} (the default), PuTTY will do
something it considers appropriate for each type of proxy. Telnet
and HTTP proxies will have host names passed straight to them; SOCKS
proxies will not.
Note that if you are doing DNS at the proxy, you should make sure
that your proxy exclusion settings (see \k{config-proxy-exclude}) do
not depend on knowing the IP address of a host. If the name is
passed on to the proxy without PuTTY looking it up, it will never
know the IP address and cannot check it against your list.
The original SOCKS 4 protocol does not support proxy-side DNS. There
is a protocol extension (SOCKS 4A) which does support it, but not
all SOCKS 4 servers provide this extension. If you enable proxy DNS
and your SOCKS 4 server cannot deal with it, this might be why.
\S{config-proxy-auth} Username and password \S{config-proxy-auth} Username and password
\cfg{winhelp-topic}{proxy.auth} \cfg{winhelp-topic}{proxy.auth}

View File

@ -68,6 +68,7 @@ Socket new_connection(SockAddr addr, char *hostname,
int port, int privport, int port, int privport,
int oobinline, int nodelay, Plug plug); int oobinline, int nodelay, Plug plug);
Socket new_listener(char *srcaddr, int port, Plug plug, int local_host_only); Socket new_listener(char *srcaddr, int port, Plug plug, int local_host_only);
SockAddr name_lookup(char *host, int port, char **canonicalname);
/* socket functions */ /* socket functions */
@ -75,10 +76,11 @@ void sk_init(void); /* called once at program startup */
void sk_cleanup(void); /* called just before program exit */ void sk_cleanup(void); /* called just before program exit */
SockAddr sk_namelookup(char *host, char **canonicalname); SockAddr sk_namelookup(char *host, char **canonicalname);
SockAddr sk_nonamelookup(char *host);
void sk_getaddr(SockAddr addr, char *buf, int buflen); void sk_getaddr(SockAddr addr, char *buf, int buflen);
int sk_hostname_is_local(char *name); int sk_hostname_is_local(char *name);
int sk_address_is_local(SockAddr addr); int sk_address_is_local(SockAddr addr);
enum { ADDRTYPE_IPV4, ADDRTYPE_IPV6 }; enum { ADDRTYPE_IPV4, ADDRTYPE_IPV6, ADDRTYPE_NAME };
int sk_addrtype(SockAddr addr); int sk_addrtype(SockAddr addr);
void sk_addrcopy(SockAddr addr, char *buf); void sk_addrcopy(SockAddr addr, char *buf);
void sk_addr_free(SockAddr addr); void sk_addr_free(SockAddr addr);

View File

@ -126,7 +126,7 @@ char *pfd_newconnect(Socket *s, char *hostname, int port, void *c)
/* /*
* Try to find host. * Try to find host.
*/ */
addr = sk_namelookup(hostname, &dummy_realhost); addr = name_lookup(hostname, port, &dummy_realhost);
if ((err = sk_addr_error(addr))) if ((err = sk_addr_error(addr)))
return err; return err;

87
proxy.c
View File

@ -14,6 +14,10 @@
#include "network.h" #include "network.h"
#include "proxy.h" #include "proxy.h"
#define do_proxy_dns \
(cfg.proxy_dns == 2 || \
(cfg.proxy_dns == 1 && cfg.proxy_type != PROXY_SOCKS))
/* /*
* Call this when proxy negotiation is complete, so that this * Call this when proxy negotiation is complete, so that this
* socket can begin working normally. * socket can begin working normally.
@ -240,6 +244,10 @@ static int plug_proxy_accepting (Plug p, void *sock)
return plug_accepting(ps->plug, sock); return plug_accepting(ps->plug, sock);
} }
/*
* This function can accept a NULL pointer as `addr', in which case
* it will only check the host name.
*/
static int proxy_for_destination (SockAddr addr, char * hostname, int port) static int proxy_for_destination (SockAddr addr, char * hostname, int port)
{ {
int s = 0, e = 0; int s = 0, e = 0;
@ -252,13 +260,16 @@ static int proxy_for_destination (SockAddr addr, char * hostname, int port)
* representations of `localhost'. * representations of `localhost'.
*/ */
if (!cfg.even_proxy_localhost && if (!cfg.even_proxy_localhost &&
(sk_hostname_is_local(hostname) || sk_address_is_local(addr))) (sk_hostname_is_local(hostname) ||
(addr && sk_address_is_local(addr))))
return 0; /* do not proxy */ return 0; /* do not proxy */
/* we want a string representation of the IP address for comparisons */ /* we want a string representation of the IP address for comparisons */
if (addr) {
sk_getaddr(addr, hostip, 64); sk_getaddr(addr, hostip, 64);
hostip_len = strlen(hostip); hostip_len = strlen(hostip);
}
hostname_len = strlen(hostname); hostname_len = strlen(hostname);
exclude_list = cfg.proxy_exclude_list; exclude_list = cfg.proxy_exclude_list;
@ -285,8 +296,8 @@ static int proxy_for_destination (SockAddr addr, char * hostname, int port)
if (exclude_list[s] == '*') { if (exclude_list[s] == '*') {
/* wildcard at beginning of entry */ /* wildcard at beginning of entry */
if (strnicmp(hostip + hostip_len - (e - s - 1), if ((addr && strnicmp(hostip + hostip_len - (e - s - 1),
exclude_list + s + 1, e - s - 1) == 0 || exclude_list + s + 1, e - s - 1) == 0) ||
strnicmp(hostname + hostname_len - (e - s - 1), strnicmp(hostname + hostname_len - (e - s - 1),
exclude_list + s + 1, e - s - 1) == 0) exclude_list + s + 1, e - s - 1) == 0)
return 0; /* IP/hostname range excluded. do not use proxy. */ return 0; /* IP/hostname range excluded. do not use proxy. */
@ -294,7 +305,7 @@ static int proxy_for_destination (SockAddr addr, char * hostname, int port)
} else if (exclude_list[e-1] == '*') { } else if (exclude_list[e-1] == '*') {
/* wildcard at end of entry */ /* wildcard at end of entry */
if (strnicmp(hostip, exclude_list + s, e - s - 1) == 0 || if ((addr && strnicmp(hostip, exclude_list + s, e - s - 1) == 0) ||
strnicmp(hostname, exclude_list + s, e - s - 1) == 0) strnicmp(hostname, exclude_list + s, e - s - 1) == 0)
return 0; /* IP/hostname range excluded. do not use proxy. */ return 0; /* IP/hostname range excluded. do not use proxy. */
@ -303,7 +314,7 @@ static int proxy_for_destination (SockAddr addr, char * hostname, int port)
* match (ie. a specific IP) * match (ie. a specific IP)
*/ */
if (stricmp(hostip, exclude_list + s) == 0) if (addr && stricmp(hostip, exclude_list + s) == 0)
return 0; /* IP/hostname excluded. do not use proxy. */ return 0; /* IP/hostname excluded. do not use proxy. */
if (stricmp(hostname, exclude_list + s) == 0) if (stricmp(hostname, exclude_list + s) == 0)
return 0; /* IP/hostname excluded. do not use proxy. */ return 0; /* IP/hostname excluded. do not use proxy. */
@ -316,6 +327,17 @@ static int proxy_for_destination (SockAddr addr, char * hostname, int port)
return 1; return 1;
} }
SockAddr name_lookup(char *host, int port, char **canonicalname)
{
if (cfg.proxy_type != PROXY_NONE &&
do_proxy_dns && proxy_for_destination(NULL, host, port)) {
*canonicalname = dupstr(host);
return sk_nonamelookup(host);
}
return sk_namelookup(host, canonicalname);
}
Socket new_connection(SockAddr addr, char *hostname, Socket new_connection(SockAddr addr, char *hostname,
int port, int privport, int port, int privport,
int oobinline, int nodelay, Plug plug) int oobinline, int nodelay, Plug plug)
@ -471,9 +493,9 @@ int proxy_http_negotiate (Proxy_Socket p, int change)
* for this proxy method, it's just a simple HTTP * for this proxy method, it's just a simple HTTP
* request * request
*/ */
char *buf, dest[64]; char *buf, dest[512];
sk_getaddr(p->remote_addr, dest, 64); sk_getaddr(p->remote_addr, dest, lenof(dest));
buf = dupprintf("CONNECT %s:%i HTTP/1.1\r\nHost: %s:%i\r\n", buf = dupprintf("CONNECT %s:%i HTTP/1.1\r\nHost: %s:%i\r\n",
dest, p->remote_port, dest, p->remote_port); dest, p->remote_port, dest, p->remote_port);
@ -649,16 +671,25 @@ int proxy_socks4_negotiate (Proxy_Socket p, int change)
* user ID (variable length, null terminated string) * user ID (variable length, null terminated string)
*/ */
int length; int length, type, namelen;
char * command; char *command, addr[4], hostname[512];
if (sk_addrtype(p->remote_addr) != ADDRTYPE_IPV4) { type = sk_addrtype(p->remote_addr);
if (type == ADDRTYPE_IPV6) {
plug_closing(p->plug, "Proxy error: SOCKS version 4 does" plug_closing(p->plug, "Proxy error: SOCKS version 4 does"
" not support IPv6", PROXY_ERROR_GENERAL, 0); " not support IPv6", PROXY_ERROR_GENERAL, 0);
return 1; return 1;
} else if (type == ADDRTYPE_IPV4) {
namelen = 0;
sk_addrcopy(p->remote_addr, addr);
} else { /* type == ADDRTYPE_NAME */
sk_getaddr(p->remote_addr, hostname, lenof(hostname));
namelen = strlen(hostname) + 1; /* include the NUL */
addr[0] = addr[1] = addr[2] = 0;
addr[3] = 1;
} }
length = strlen(cfg.proxy_username) + 9; length = strlen(cfg.proxy_username) + namelen + 9;
command = (char*) smalloc(length); command = (char*) smalloc(length);
strcpy(command + 8, cfg.proxy_username); strcpy(command + 8, cfg.proxy_username);
@ -670,7 +701,11 @@ int proxy_socks4_negotiate (Proxy_Socket p, int change)
command[3] = (char) p->remote_port & 0xff; command[3] = (char) p->remote_port & 0xff;
/* address */ /* address */
sk_addrcopy(p->remote_addr, command + 4); memcpy(command + 4, addr, 4);
/* hostname */
memcpy(command + 8 + strlen(cfg.proxy_username) + 1,
hostname, namelen);
sk_write(p->sub_socket, command, length); sk_write(p->sub_socket, command, length);
sfree(command); sfree(command);
@ -939,24 +974,30 @@ int proxy_socks5_negotiate (Proxy_Socket p, int change)
* dest. port (2 bytes) [network order] * dest. port (2 bytes) [network order]
*/ */
char command[22]; char command[512];
int len; int len;
int type;
if (sk_addrtype(p->remote_addr) == ADDRTYPE_IPV4) { type = sk_addrtype(p->remote_addr);
len = 10; if (type == ADDRTYPE_IPV4) {
len = 10; /* 4 hdr + 4 addr + 2 trailer */
command[3] = 1; /* IPv4 */ command[3] = 1; /* IPv4 */
} else { sk_addrcopy(p->remote_addr, command+4);
len = 22; } else if (type == ADDRTYPE_IPV6) {
len = 22; /* 4 hdr + 16 addr + 2 trailer */
command[3] = 4; /* IPv6 */ command[3] = 4; /* IPv6 */
sk_addrcopy(p->remote_addr, command+4);
} else if (type == ADDRTYPE_NAME) {
command[3] = 3;
sk_getaddr(p->remote_addr, command+5, 256);
command[4] = strlen(command+5);
len = 7 + command[4]; /* 4 hdr, 1 len, N addr, 2 trailer */
} }
command[0] = 5; /* version 5 */ command[0] = 5; /* version 5 */
command[1] = 1; /* CONNECT command */ command[1] = 1; /* CONNECT command */
command[2] = 0x00; command[2] = 0x00;
/* address */
sk_addrcopy(p->remote_addr, command+4);
/* port */ /* port */
command[len-2] = (char) (p->remote_port >> 8) & 0xff; command[len-2] = (char) (p->remote_port >> 8) & 0xff;
command[len-1] = (char) p->remote_port & 0xff; command[len-1] = (char) p->remote_port & 0xff;
@ -1230,8 +1271,8 @@ int proxy_telnet_negotiate (Proxy_Socket p, int change)
} }
else if (strnicmp(cfg.proxy_telnet_command + eo, else if (strnicmp(cfg.proxy_telnet_command + eo,
"host", 4) == 0) { "host", 4) == 0) {
char dest[64]; char dest[512];
sk_getaddr(p->remote_addr, dest, 64); sk_getaddr(p->remote_addr, dest, lenof(dest));
sk_write(p->sub_socket, dest, strlen(dest)); sk_write(p->sub_socket, dest, strlen(dest));
eo += 4; eo += 4;
} }

View File

@ -214,6 +214,7 @@ struct config_tag {
int tcp_nodelay; int tcp_nodelay;
/* Proxy options */ /* Proxy options */
char proxy_exclude_list[512]; char proxy_exclude_list[512];
enum { PROXYDNS_NO, PROXYDNS_AUTO, PROXYDNS_YES } proxy_dns;
int even_proxy_localhost; int even_proxy_localhost;
enum { PROXY_NONE, PROXY_HTTP, PROXY_SOCKS, PROXY_TELNET } proxy_type; enum { PROXY_NONE, PROXY_HTTP, PROXY_SOCKS, PROXY_TELNET } proxy_type;
char proxy_host[512]; char proxy_host[512];

2
raw.c
View File

@ -95,7 +95,7 @@ static char *raw_init(void *frontend_handle, void **backend_handle,
logevent(raw->frontend, buf); logevent(raw->frontend, buf);
sfree(buf); sfree(buf);
} }
addr = sk_namelookup(host, realhost); addr = name_lookup(host, port, realhost);
if ((err = sk_addr_error(addr))) if ((err = sk_addr_error(addr)))
return err; return err;

View File

@ -126,7 +126,7 @@ static char *rlogin_init(void *frontend_handle, void **backend_handle,
logevent(rlogin->frontend, buf); logevent(rlogin->frontend, buf);
sfree(buf); sfree(buf);
} }
addr = sk_namelookup(host, realhost); addr = name_lookup(host, port, realhost);
if ((err = sk_addr_error(addr))) if ((err = sk_addr_error(addr)))
return err; return err;

View File

@ -150,6 +150,7 @@ void save_settings(char *section, int do_host, Config * cfg)
/* proxy settings */ /* proxy settings */
write_setting_s(sesskey, "ProxyExcludeList", cfg->proxy_exclude_list); write_setting_s(sesskey, "ProxyExcludeList", cfg->proxy_exclude_list);
write_setting_i(sesskey, "ProxyDNS", cfg->proxy_dns);
write_setting_i(sesskey, "ProxyLocalhost", cfg->even_proxy_localhost); write_setting_i(sesskey, "ProxyLocalhost", cfg->even_proxy_localhost);
write_setting_i(sesskey, "ProxyType", cfg->proxy_type); write_setting_i(sesskey, "ProxyType", cfg->proxy_type);
write_setting_s(sesskey, "ProxyHost", cfg->proxy_host); write_setting_s(sesskey, "ProxyHost", cfg->proxy_host);
@ -384,6 +385,7 @@ void load_settings(char *section, int do_host, Config * cfg)
/* proxy settings */ /* proxy settings */
gpps(sesskey, "ProxyExcludeList", "", cfg->proxy_exclude_list, gpps(sesskey, "ProxyExcludeList", "", cfg->proxy_exclude_list,
sizeof(cfg->proxy_exclude_list)); sizeof(cfg->proxy_exclude_list));
gppi(sesskey, "ProxyDNS", PROXYDNS_AUTO, &i); cfg->proxy_dns = i;
gppi(sesskey, "ProxyLocalhost", 0, &cfg->even_proxy_localhost); gppi(sesskey, "ProxyLocalhost", 0, &cfg->even_proxy_localhost);
gppi(sesskey, "ProxyType", PROXY_NONE, &i); cfg->proxy_type = i; gppi(sesskey, "ProxyType", PROXY_NONE, &i); cfg->proxy_type = i;
gpps(sesskey, "ProxyHost", "proxy", cfg->proxy_host, gpps(sesskey, "ProxyHost", "proxy", cfg->proxy_host,

2
ssh.c
View File

@ -2072,7 +2072,7 @@ static char *connect_to_host(Ssh ssh, char *host, int port,
* Try to find host. * Try to find host.
*/ */
logeventf(ssh, "Looking up host \"%s\"", host); logeventf(ssh, "Looking up host \"%s\"", host);
addr = sk_namelookup(host, realhost); addr = name_lookup(host, port, realhost);
if ((err = sk_addr_error(addr))) if ((err = sk_addr_error(addr)))
return err; return err;

View File

@ -678,7 +678,7 @@ static char *telnet_init(void *frontend_handle, void **backend_handle,
logevent(telnet->frontend, buf); logevent(telnet->frontend, buf);
sfree(buf); sfree(buf);
} }
addr = sk_namelookup(host, realhost); addr = name_lookup(host, port, realhost);
if ((err = sk_addr_error(addr))) if ((err = sk_addr_error(addr)))
return err; return err;

View File

@ -57,12 +57,18 @@ typedef struct Socket_tag *Actual_Socket;
struct SockAddr_tag { struct SockAddr_tag {
char *error; char *error;
/* address family this belongs to, AF_INET for IPv4, AF_INET6 for IPv6. */ /*
* Which address family this address belongs to. AF_INET for
* IPv4; AF_INET6 for IPv6; AF_UNSPEC indicates that name
* resolution has not been done and a simple host name is held
* in this SockAddr structure.
*/
int family; int family;
unsigned long address; /* Address IPv4 style. */ unsigned long address; /* Address IPv4 style. */
#ifdef IPV6 #ifdef IPV6
struct addrinfo *ai; /* Address IPv6 style. */ struct addrinfo *ai; /* Address IPv6 style. */
#endif #endif
char hostname[512]; /* Store an unresolved host name. */
}; };
static tree234 *sktree; static tree234 *sktree;
@ -194,19 +200,32 @@ SockAddr sk_namelookup(char *host, char **canonicalname)
return ret; return ret;
} }
SockAddr sk_nonamelookup(char *host)
{
SockAddr ret = smalloc(sizeof(struct SockAddr_tag));
ret->family = AF_UNSPEC;
strncpy(ret->hostname, host, lenof(ret->hostname));
ret->hostname[lenof(ret->hostname)-1] = '\0';
return ret;
}
void sk_getaddr(SockAddr addr, char *buf, int buflen) void sk_getaddr(SockAddr addr, char *buf, int buflen)
{ {
#ifdef IPV6 #ifdef IPV6
if (addr->family == AF_INET) { if (addr->family == AF_INET6) {
FIXME; /* I don't know how to get a text form of an IPv6 address. */
} else
#endif #endif
if (addr->family == AF_INET) {
struct in_addr a; struct in_addr a;
a.s_addr = htonl(addr->address); a.s_addr = htonl(addr->address);
strncpy(buf, inet_ntoa(a), buflen); strncpy(buf, inet_ntoa(a), buflen);
#ifdef IPV6 buf[buflen-1] = '\0';
} else { } else {
FIXME; /* I don't know how to get a text form of an IPv6 address. */ assert(addr->family == AF_UNSPEC);
strncpy(buf, addr->hostname, buflen);
buf[buflen-1] = '\0';
} }
#endif
} }
int sk_hostname_is_local(char *name) int sk_hostname_is_local(char *name)
@ -217,36 +236,42 @@ int sk_hostname_is_local(char *name)
int sk_address_is_local(SockAddr addr) int sk_address_is_local(SockAddr addr)
{ {
#ifdef IPV6 #ifdef IPV6
if (addr->family == AF_INET) { if (addr->family == AF_INET6) {
FIXME; /* someone who can compile for IPV6 had better do this bit */
} else
#endif #endif
if (addr->family == AF_INET) {
struct in_addr a; struct in_addr a;
a.s_addr = htonl(addr->address); a.s_addr = htonl(addr->address);
return ipv4_is_loopback(a); return ipv4_is_loopback(a);
#ifdef IPV6
} else { } else {
FIXME; /* someone who can compile for IPV6 had better do this bit */ assert(addr->family == AF_UNSPEC);
return 0; /* we don't know; assume not */
} }
#endif
} }
int sk_addrtype(SockAddr addr) int sk_addrtype(SockAddr addr)
{ {
return (addr->family == AF_INET ? ADDRTYPE_IPV4 : ADDRTYPE_IPV6); return (addr->family == AF_INET ? ADDRTYPE_IPV4 :
#ifdef IPV6
addr->family == AF_INET6 ? ADDRTYPE_IPV6 :
#endif
ADDRTYPE_NAME);
} }
void sk_addrcopy(SockAddr addr, char *buf) void sk_addrcopy(SockAddr addr, char *buf)
{ {
assert(addr->family != AF_UNSPEC);
#ifdef IPV6 #ifdef IPV6
if (addr->family == AF_INET) { if (addr->family == AF_INET6) {
memcpy(buf, (char*) addr->ai, 16);
} else
#endif #endif
if (addr->family == AF_INET) {
struct in_addr a; struct in_addr a;
a.s_addr = htonl(addr->address); a.s_addr = htonl(addr->address);
memcpy(buf, (char*) &a.s_addr, 4); memcpy(buf, (char*) &a.s_addr, 4);
#ifdef IPV6
} else {
memcpy(buf, (char*) addr->ai, 16);
} }
#endif
} }
void sk_addr_free(SockAddr addr) void sk_addr_free(SockAddr addr)
@ -371,6 +396,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
/* /*
* Open socket. * Open socket.
*/ */
assert(addr->family != AF_UNSPEC);
s = socket(addr->family, SOCK_STREAM, 0); s = socket(addr->family, SOCK_STREAM, 0);
ret->s = s; ret->s = s;

View File

@ -455,6 +455,10 @@ enum { IDCX_ABOUT =
IDC_PROXYEXCLUDESTATIC, IDC_PROXYEXCLUDESTATIC,
IDC_PROXYEXCLUDEEDIT, IDC_PROXYEXCLUDEEDIT,
IDC_PROXYLOCALHOST, IDC_PROXYLOCALHOST,
IDC_PROXYDNSSTATIC,
IDC_PROXYDNSNO,
IDC_PROXYDNSAUTO,
IDC_PROXYDNSYES,
IDC_PROXYUSERSTATIC, IDC_PROXYUSERSTATIC,
IDC_PROXYUSEREDIT, IDC_PROXYUSEREDIT,
IDC_PROXYPASSSTATIC, IDC_PROXYPASSSTATIC,
@ -885,6 +889,11 @@ char *help_context_cmd(int id)
case IDC_PROXYEXCLUDEEDIT: case IDC_PROXYEXCLUDEEDIT:
case IDC_PROXYLOCALHOST: case IDC_PROXYLOCALHOST:
return "JI(`',`proxy.exclude')"; return "JI(`',`proxy.exclude')";
case IDC_PROXYDNSSTATIC:
case IDC_PROXYDNSNO:
case IDC_PROXYDNSAUTO:
case IDC_PROXYDNSYES:
return "JI(`',`proxy.dns')";
case IDC_PROXYUSERSTATIC: case IDC_PROXYUSERSTATIC:
case IDC_PROXYUSEREDIT: case IDC_PROXYUSEREDIT:
case IDC_PROXYPASSSTATIC: case IDC_PROXYPASSSTATIC:
@ -1352,6 +1361,10 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
SetDlgItemInt(hwnd, IDC_PROXYPORTEDIT, cfg.proxy_port, FALSE); SetDlgItemInt(hwnd, IDC_PROXYPORTEDIT, cfg.proxy_port, FALSE);
SetDlgItemText(hwnd, IDC_PROXYEXCLUDEEDIT, cfg.proxy_exclude_list); SetDlgItemText(hwnd, IDC_PROXYEXCLUDEEDIT, cfg.proxy_exclude_list);
CheckDlgButton(hwnd, IDC_PROXYLOCALHOST, cfg.even_proxy_localhost); CheckDlgButton(hwnd, IDC_PROXYLOCALHOST, cfg.even_proxy_localhost);
CheckRadioButton(hwnd, IDC_PROXYDNSNO, IDC_PROXYDNSYES,
cfg.proxy_dns == PROXYDNS_NO ? IDC_PROXYDNSNO :
cfg.proxy_dns == PROXYDNS_YES ? IDC_PROXYDNSYES :
IDC_PROXYDNSAUTO);
SetDlgItemText(hwnd, IDC_PROXYTELNETCMDEDIT, cfg.proxy_telnet_command); SetDlgItemText(hwnd, IDC_PROXYTELNETCMDEDIT, cfg.proxy_telnet_command);
SetDlgItemText(hwnd, IDC_PROXYUSEREDIT, cfg.proxy_username); SetDlgItemText(hwnd, IDC_PROXYUSEREDIT, cfg.proxy_username);
SetDlgItemText(hwnd, IDC_PROXYPASSEDIT, cfg.proxy_password); SetDlgItemText(hwnd, IDC_PROXYPASSEDIT, cfg.proxy_password);
@ -1853,7 +1866,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
} }
if (panel == proxypanelstart) { if (panel == proxypanelstart) {
/* The Proxy panel. Accelerators used: [acgoh] ntslypeuwmv */ /* The Proxy panel. Accelerators used: [acgoh] ntslypeuwmvxd */
struct ctlpos cp; struct ctlpos cp;
ctlposinit(&cp, hwnd, 80, 3, 13); ctlposinit(&cp, hwnd, 80, 3, 13);
if (dlgtype == 0) { if (dlgtype == 0) {
@ -1873,6 +1886,11 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
IDC_PROXYEXCLUDEEDIT, 100, NULL); IDC_PROXYEXCLUDEEDIT, 100, NULL);
checkbox(&cp, "Consider pro&xying local host connections", checkbox(&cp, "Consider pro&xying local host connections",
IDC_PROXYLOCALHOST); IDC_PROXYLOCALHOST);
radioline(&cp, "Do &DNS name lookup at proxy end:",
IDC_PROXYDNSSTATIC, 3,
"No", IDC_PROXYDNSNO,
"Auto", IDC_PROXYDNSAUTO,
"Yes", IDC_PROXYDNSYES, NULL);
staticedit(&cp, "&Username", IDC_PROXYUSERSTATIC, staticedit(&cp, "&Username", IDC_PROXYUSERSTATIC,
IDC_PROXYUSEREDIT, 60); IDC_PROXYUSEREDIT, 60);
staticpassedit(&cp, "Pass&word", IDC_PROXYPASSSTATIC, staticpassedit(&cp, "Pass&word", IDC_PROXYPASSSTATIC,
@ -3034,6 +3052,17 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
cfg.even_proxy_localhost = cfg.even_proxy_localhost =
IsDlgButtonChecked(hwnd, IDC_PROXYLOCALHOST); IsDlgButtonChecked(hwnd, IDC_PROXYLOCALHOST);
break; break;
case IDC_PROXYDNSNO:
case IDC_PROXYDNSAUTO:
case IDC_PROXYDNSYES:
if (HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DOUBLECLICKED) {
cfg.proxy_dns =
IsDlgButtonChecked(hwnd, IDC_PROXYDNSNO) ? PROXYDNS_NO :
IsDlgButtonChecked(hwnd, IDC_PROXYDNSYES) ? PROXYDNS_YES :
PROXYDNS_AUTO;
}
break;
case IDC_PROXYTYPENONE: case IDC_PROXYTYPENONE:
case IDC_PROXYTYPEHTTP: case IDC_PROXYTYPEHTTP:
case IDC_PROXYTYPESOCKS: case IDC_PROXYTYPESOCKS:

View File

@ -90,12 +90,18 @@ typedef struct Socket_tag *Actual_Socket;
struct SockAddr_tag { struct SockAddr_tag {
char *error; char *error;
/* address family this belongs to, AF_INET for IPv4, AF_INET6 for IPv6. */ /*
* Which address family this address belongs to. AF_INET for
* IPv4; AF_INET6 for IPv6; AF_UNSPEC indicates that name
* resolution has not been done and a simple host name is held
* in this SockAddr structure.
*/
int family; int family;
unsigned long address; /* Address IPv4 style. */ unsigned long address; /* Address IPv4 style. */
#ifdef IPV6 #ifdef IPV6
struct addrinfo *ai; /* Address IPv6 style. */ struct addrinfo *ai; /* Address IPv6 style. */
#endif #endif
char hostname[512]; /* Store an unresolved host name. */
}; };
static tree234 *sktree; static tree234 *sktree;
@ -356,19 +362,32 @@ SockAddr sk_namelookup(char *host, char **canonicalname)
return ret; return ret;
} }
SockAddr sk_nonamelookup(char *host)
{
SockAddr ret = smalloc(sizeof(struct SockAddr_tag));
ret->family = AF_UNSPEC;
strncpy(ret->hostname, host, lenof(ret->hostname));
ret->hostname[lenof(ret->hostname)-1] = '\0';
return ret;
}
void sk_getaddr(SockAddr addr, char *buf, int buflen) void sk_getaddr(SockAddr addr, char *buf, int buflen)
{ {
#ifdef IPV6 #ifdef IPV6
if (addr->family == AF_INET) { if (addr->family == AF_INET6) {
FIXME; /* I don't know how to get a text form of an IPv6 address. */
} else
#endif #endif
if (addr->family == AF_INET) {
struct in_addr a; struct in_addr a;
a.s_addr = htonl(addr->address); a.s_addr = htonl(addr->address);
strncpy(buf, inet_ntoa(a), buflen); strncpy(buf, inet_ntoa(a), buflen);
#ifdef IPV6 buf[buflen-1] = '\0';
} else { } else {
FIXME; /* I don't know how to get a text form of an IPv6 address. */ assert(addr->family == AF_UNSPEC);
strncpy(buf, addr->hostname, buflen);
buf[buflen-1] = '\0';
} }
#endif
} }
int sk_hostname_is_local(char *name) int sk_hostname_is_local(char *name)
@ -379,36 +398,42 @@ int sk_hostname_is_local(char *name)
int sk_address_is_local(SockAddr addr) int sk_address_is_local(SockAddr addr)
{ {
#ifdef IPV6 #ifdef IPV6
if (addr->family == AF_INET) { if (addr->family == AF_INET6) {
FIXME; /* someone who can compile for IPV6 had better do this bit */
} else
#endif #endif
if (addr->family == AF_INET) {
struct in_addr a; struct in_addr a;
a.s_addr = htonl(addr->address); a.s_addr = htonl(addr->address);
return ipv4_is_loopback(a); return ipv4_is_loopback(a);
#ifdef IPV6
} else { } else {
FIXME; /* someone who can compile for IPV6 had better do this bit */ assert(addr->family == AF_UNSPEC);
return 0; /* we don't know; assume not */
} }
#endif
} }
int sk_addrtype(SockAddr addr) int sk_addrtype(SockAddr addr)
{ {
return (addr->family == AF_INET ? ADDRTYPE_IPV4 : ADDRTYPE_IPV6); return (addr->family == AF_INET ? ADDRTYPE_IPV4 :
#ifdef IPV6
addr->family == AF_INET6 ? ADDRTYPE_IPV6 :
#endif
ADDRTYPE_NAME);
} }
void sk_addrcopy(SockAddr addr, char *buf) void sk_addrcopy(SockAddr addr, char *buf)
{ {
assert(addr->family != AF_UNSPEC);
#ifdef IPV6 #ifdef IPV6
if (addr->family == AF_INET) { if (addr->family == AF_INET6) {
memcpy(buf, (char*) addr->ai, 16);
} else
#endif #endif
if (addr->family == AF_INET) {
struct in_addr a; struct in_addr a;
a.s_addr = htonl(addr->address); a.s_addr = htonl(addr->address);
memcpy(buf, (char*) &a.s_addr, 4); memcpy(buf, (char*) &a.s_addr, 4);
#ifdef IPV6
} else {
memcpy(buf, (char*) addr->ai, 16);
} }
#endif
} }
void sk_addr_free(SockAddr addr) void sk_addr_free(SockAddr addr)
@ -543,6 +568,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
/* /*
* Open socket. * Open socket.
*/ */
assert(addr->family != AF_UNSPEC);
s = socket(addr->family, SOCK_STREAM, 0); s = socket(addr->family, SOCK_STREAM, 0);
ret->s = s; ret->s = s;
@ -731,10 +757,8 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only)
ret->oobinline = 0; ret->oobinline = 0;
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on)); setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
#ifdef IPV6 #ifdef IPV6
if (addr->family == AF_INET6) { if (addr->family == AF_INET6) {
memset(&a6, 0, sizeof(a6)); memset(&a6, 0, sizeof(a6));

View File

@ -177,7 +177,7 @@ char *x11_init(Socket * s, char *display, void *c, void *auth)
/* /*
* Try to find host. * Try to find host.
*/ */
addr = sk_namelookup(host, &dummy_realhost); addr = name_lookup(host, port, &dummy_realhost);
if ((err = sk_addr_error(addr))) if ((err = sk_addr_error(addr)))
return err; return err;