Support for doing DNS at the proxy end. I've invented a new type of
authorsimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Wed, 18 Dec 2002 16:23:11 +0000 (16:23 +0000)
committersimon <simon@cda61777-01e9-0310-a592-d414129be87e>
Wed, 18 Dec 2002 16:23:11 +0000 (16:23 +0000)
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.

git-svn-id: svn://svn.tartarus.org/sgt/putty@2353 cda61777-01e9-0310-a592-d414129be87e

14 files changed:
doc/config.but
network.h
portfwd.c
proxy.c
putty.h
raw.c
rlogin.c
settings.c
ssh.c
telnet.c
unix/uxnet.c
windlg.c
winnet.c
x11fwd.c

index dfe7da5..909d60f 100644 (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
 
@@ -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
 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
 
 \cfg{winhelp-topic}{proxy.auth}
index 17a7321..e9ad518 100644 (file)
--- a/network.h
+++ b/network.h
@@ -68,6 +68,7 @@ Socket new_connection(SockAddr addr, char *hostname,
                      int port, int privport,
                      int oobinline, int nodelay, Plug plug);
 Socket new_listener(char *srcaddr, int port, Plug plug, int local_host_only);
+SockAddr name_lookup(char *host, int port, char **canonicalname);
 
 /* socket functions */
 
@@ -75,10 +76,11 @@ void sk_init(void);                /* called once at program startup */
 void sk_cleanup(void);                /* called just before program exit */
 
 SockAddr sk_namelookup(char *host, char **canonicalname);
+SockAddr sk_nonamelookup(char *host);
 void sk_getaddr(SockAddr addr, char *buf, int buflen);
 int sk_hostname_is_local(char *name);
 int sk_address_is_local(SockAddr addr);
-enum { ADDRTYPE_IPV4, ADDRTYPE_IPV6 };
+enum { ADDRTYPE_IPV4, ADDRTYPE_IPV6, ADDRTYPE_NAME };
 int sk_addrtype(SockAddr addr);
 void sk_addrcopy(SockAddr addr, char *buf);
 void sk_addr_free(SockAddr addr);
index dd8e655..dc865f6 100644 (file)
--- a/portfwd.c
+++ b/portfwd.c
@@ -126,7 +126,7 @@ char *pfd_newconnect(Socket *s, char *hostname, int port, void *c)
     /*
      * Try to find host.
      */
-    addr = sk_namelookup(hostname, &dummy_realhost);
+    addr = name_lookup(hostname, port, &dummy_realhost);
     if ((err = sk_addr_error(addr)))
        return err;
 
diff --git a/proxy.c b/proxy.c
index 3313abf..d43ad7b 100644 (file)
--- a/proxy.c
+++ b/proxy.c
 #include "network.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
  * socket can begin working normally.
@@ -240,6 +244,10 @@ static int plug_proxy_accepting (Plug p, void *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)
 {
     int s = 0, e = 0;
@@ -252,13 +260,16 @@ static int proxy_for_destination (SockAddr addr, char * hostname, int port)
      * representations of `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 */
 
     /* we want a string representation of the IP address for comparisons */
-    sk_getaddr(addr, hostip, 64);
+    if (addr) {
+       sk_getaddr(addr, hostip, 64);
+       hostip_len = strlen(hostip);
+    }
 
-    hostip_len = strlen(hostip);
     hostname_len = strlen(hostname);
 
     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] == '*') {
            /* wildcard at beginning of entry */
 
-           if (strnicmp(hostip + hostip_len - (e - s - 1),
-                        exclude_list + s + 1, e - s - 1) == 0 ||
+           if ((addr && strnicmp(hostip + hostip_len - (e - s - 1),
+                                 exclude_list + s + 1, e - s - 1) == 0) ||
                strnicmp(hostname + hostname_len - (e - s - 1),
                         exclude_list + s + 1, e - s - 1) == 0)
                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] == '*') {
            /* 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)
                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)
             */
 
-           if (stricmp(hostip, exclude_list + s) == 0)
+           if (addr && stricmp(hostip, exclude_list + s) == 0)
                return 0; /* IP/hostname excluded. do not use proxy. */
            if (stricmp(hostname, exclude_list + s) == 0)
                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;
 }
 
+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,
                      int port, int privport,
                      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
         * 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",
                        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)
         */
 
-       int length;
-       char * command;
+       int length, type, namelen;
+       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"
                         " not support IPv6", PROXY_ERROR_GENERAL, 0);
            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);
        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;
 
        /* 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);
        sfree(command);
@@ -939,24 +974,30 @@ int proxy_socks5_negotiate (Proxy_Socket p, int change)
             *  dest. port (2 bytes) [network order]
             */
 
-           char command[22];
+           char command[512];
            int len;
+           int type;
 
-           if (sk_addrtype(p->remote_addr) == ADDRTYPE_IPV4) {
-               len = 10;
+           type = sk_addrtype(p->remote_addr);
+           if (type == ADDRTYPE_IPV4) {
+               len = 10;              /* 4 hdr + 4 addr + 2 trailer */
                command[3] = 1; /* IPv4 */
-           } else {
-               len = 22;
+               sk_addrcopy(p->remote_addr, command+4);
+           } else if (type == ADDRTYPE_IPV6) {
+               len = 22;              /* 4 hdr + 16 addr + 2 trailer */
                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[1] = 1; /* CONNECT command */
            command[2] = 0x00;
 
-           /* address */
-           sk_addrcopy(p->remote_addr, command+4);
-
            /* port */
            command[len-2] = (char) (p->remote_port >> 8) & 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,
                                  "host", 4) == 0) {
-                   char dest[64];
-                   sk_getaddr(p->remote_addr, dest, 64);
+                   char dest[512];
+                   sk_getaddr(p->remote_addr, dest, lenof(dest));
                    sk_write(p->sub_socket, dest, strlen(dest));
                    eo += 4;
                }
diff --git a/putty.h b/putty.h
index 144ed06..8953125 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -214,6 +214,7 @@ struct config_tag {
     int tcp_nodelay;
     /* Proxy options */
     char proxy_exclude_list[512];
+    enum { PROXYDNS_NO, PROXYDNS_AUTO, PROXYDNS_YES } proxy_dns;
     int even_proxy_localhost;
     enum { PROXY_NONE, PROXY_HTTP, PROXY_SOCKS, PROXY_TELNET } proxy_type;
     char proxy_host[512];
diff --git a/raw.c b/raw.c
index 7aaafb3..8e8f7e0 100644 (file)
--- a/raw.c
+++ b/raw.c
@@ -95,7 +95,7 @@ static char *raw_init(void *frontend_handle, void **backend_handle,
        logevent(raw->frontend, buf);
        sfree(buf);
     }
-    addr = sk_namelookup(host, realhost);
+    addr = name_lookup(host, port, realhost);
     if ((err = sk_addr_error(addr)))
        return err;
 
index b43804d..2cc2a21 100644 (file)
--- a/rlogin.c
+++ b/rlogin.c
@@ -126,7 +126,7 @@ static char *rlogin_init(void *frontend_handle, void **backend_handle,
        logevent(rlogin->frontend, buf);
        sfree(buf);
     }
-    addr = sk_namelookup(host, realhost);
+    addr = name_lookup(host, port, realhost);
     if ((err = sk_addr_error(addr)))
        return err;
 
index fe90f11..ce21d2c 100644 (file)
@@ -150,6 +150,7 @@ void save_settings(char *section, int do_host, Config * cfg)
 
     /* proxy settings */
     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, "ProxyType", cfg->proxy_type);
     write_setting_s(sesskey, "ProxyHost", cfg->proxy_host);
@@ -384,6 +385,7 @@ void load_settings(char *section, int do_host, Config * cfg)
     /* proxy settings */
     gpps(sesskey, "ProxyExcludeList", "", 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, "ProxyType", PROXY_NONE, &i); cfg->proxy_type = i;
     gpps(sesskey, "ProxyHost", "proxy", cfg->proxy_host,
diff --git a/ssh.c b/ssh.c
index 3275365..62f2a8e 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -2072,7 +2072,7 @@ static char *connect_to_host(Ssh ssh, char *host, int port,
      * Try to find 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)))
        return err;
 
index cae64d8..ad0ffeb 100644 (file)
--- a/telnet.c
+++ b/telnet.c
@@ -678,7 +678,7 @@ static char *telnet_init(void *frontend_handle, void **backend_handle,
        logevent(telnet->frontend, buf);
        sfree(buf);
     }
-    addr = sk_namelookup(host, realhost);
+    addr = name_lookup(host, port, realhost);
     if ((err = sk_addr_error(addr)))
        return err;
 
index cad943a..3440d19 100644 (file)
@@ -57,12 +57,18 @@ typedef struct Socket_tag *Actual_Socket;
 
 struct SockAddr_tag {
     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;
     unsigned long address;            /* Address IPv4 style. */
 #ifdef IPV6
     struct addrinfo *ai;              /* Address IPv6 style. */
 #endif
+    char hostname[512];                       /* Store an unresolved host name. */
 };
 
 static tree234 *sktree;
@@ -194,19 +200,32 @@ SockAddr sk_namelookup(char *host, char **canonicalname)
     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)
 {
 #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
+    if (addr->family == AF_INET) {
        struct in_addr a;
        a.s_addr = htonl(addr->address);
        strncpy(buf, inet_ntoa(a), buflen);
-#ifdef IPV6
+       buf[buflen-1] = '\0';
     } 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)
@@ -217,36 +236,42 @@ int sk_hostname_is_local(char *name)
 int sk_address_is_local(SockAddr addr)
 {
 #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
+    if (addr->family == AF_INET) {
        struct in_addr a;
        a.s_addr = htonl(addr->address);
        return ipv4_is_loopback(a);
-#ifdef IPV6
     } 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)
 {
-    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)
 {
+    assert(addr->family != AF_UNSPEC);
 #ifdef IPV6
-    if (addr->family == AF_INET) {
+    if (addr->family == AF_INET6) {
+       memcpy(buf, (char*) addr->ai, 16);
+    } else
 #endif
+    if (addr->family == AF_INET) {
        struct in_addr a;
        a.s_addr = htonl(addr->address);
        memcpy(buf, (char*) &a.s_addr, 4);
-#ifdef IPV6
-    } else {
-       memcpy(buf, (char*) addr->ai, 16);
     }
-#endif
 }
 
 void sk_addr_free(SockAddr addr)
@@ -371,6 +396,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
     /*
      * Open socket.
      */
+    assert(addr->family != AF_UNSPEC);
     s = socket(addr->family, SOCK_STREAM, 0);
     ret->s = s;
 
index 40880ec..a8603e6 100644 (file)
--- a/windlg.c
+++ b/windlg.c
@@ -455,6 +455,10 @@ enum { IDCX_ABOUT =
     IDC_PROXYEXCLUDESTATIC,
     IDC_PROXYEXCLUDEEDIT,
     IDC_PROXYLOCALHOST,
+    IDC_PROXYDNSSTATIC,
+    IDC_PROXYDNSNO,
+    IDC_PROXYDNSAUTO,
+    IDC_PROXYDNSYES,
     IDC_PROXYUSERSTATIC,
     IDC_PROXYUSEREDIT,
     IDC_PROXYPASSSTATIC,
@@ -885,6 +889,11 @@ char *help_context_cmd(int id)
       case IDC_PROXYEXCLUDEEDIT:
       case IDC_PROXYLOCALHOST:
         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_PROXYUSEREDIT:
       case IDC_PROXYPASSSTATIC:
@@ -1352,6 +1361,10 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
     SetDlgItemInt(hwnd, IDC_PROXYPORTEDIT, cfg.proxy_port, FALSE);
     SetDlgItemText(hwnd, IDC_PROXYEXCLUDEEDIT, cfg.proxy_exclude_list);
     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_PROXYUSEREDIT, cfg.proxy_username);
     SetDlgItemText(hwnd, IDC_PROXYPASSEDIT, cfg.proxy_password);
@@ -1853,7 +1866,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
     }
 
     if (panel == proxypanelstart) {
-       /* The Proxy panel. Accelerators used: [acgoh] ntslypeuwmv */
+       /* The Proxy panel. Accelerators used: [acgoh] ntslypeuwmvxd */
        struct ctlpos cp;
        ctlposinit(&cp, hwnd, 80, 3, 13);
        if (dlgtype == 0) {
@@ -1873,6 +1886,11 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
                      IDC_PROXYEXCLUDEEDIT, 100, NULL);
            checkbox(&cp, "Consider pro&xying local host connections",
                     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,
                       IDC_PROXYUSEREDIT, 60);
            staticpassedit(&cp, "Pass&word", IDC_PROXYPASSSTATIC,
@@ -3034,6 +3052,17 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
                    cfg.even_proxy_localhost =
                    IsDlgButtonChecked(hwnd, IDC_PROXYLOCALHOST);
                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_PROXYTYPEHTTP:
              case IDC_PROXYTYPESOCKS:
index b66cde6..e94075b 100644 (file)
--- a/winnet.c
+++ b/winnet.c
@@ -90,12 +90,18 @@ typedef struct Socket_tag *Actual_Socket;
 
 struct SockAddr_tag {
     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;
     unsigned long address;            /* Address IPv4 style. */
 #ifdef IPV6
     struct addrinfo *ai;              /* Address IPv6 style. */
 #endif
+    char hostname[512];                       /* Store an unresolved host name. */
 };
 
 static tree234 *sktree;
@@ -356,19 +362,32 @@ SockAddr sk_namelookup(char *host, char **canonicalname)
     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)
 {
 #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
+    if (addr->family == AF_INET) {
        struct in_addr a;
        a.s_addr = htonl(addr->address);
        strncpy(buf, inet_ntoa(a), buflen);
-#ifdef IPV6
+       buf[buflen-1] = '\0';
     } 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)
@@ -379,36 +398,42 @@ int sk_hostname_is_local(char *name)
 int sk_address_is_local(SockAddr addr)
 {
 #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
+    if (addr->family == AF_INET) {
        struct in_addr a;
        a.s_addr = htonl(addr->address);
        return ipv4_is_loopback(a);
-#ifdef IPV6
     } 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)
 {
-    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)
 {
+    assert(addr->family != AF_UNSPEC);
 #ifdef IPV6
-    if (addr->family == AF_INET) {
+    if (addr->family == AF_INET6) {
+       memcpy(buf, (char*) addr->ai, 16);
+    } else
 #endif
+    if (addr->family == AF_INET) {
        struct in_addr a;
        a.s_addr = htonl(addr->address);
        memcpy(buf, (char*) &a.s_addr, 4);
-#ifdef IPV6
-    } else {
-       memcpy(buf, (char*) addr->ai, 16);
     }
-#endif
 }
 
 void sk_addr_free(SockAddr addr)
@@ -543,6 +568,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
     /*
      * Open socket.
      */
+    assert(addr->family != AF_UNSPEC);
     s = socket(addr->family, SOCK_STREAM, 0);
     ret->s = s;
 
@@ -731,10 +757,8 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only)
 
     ret->oobinline = 0;
 
-
     setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
 
-
 #ifdef IPV6
        if (addr->family == AF_INET6) {
            memset(&a6, 0, sizeof(a6));
index c6e3637..35d1d17 100644 (file)
--- a/x11fwd.c
+++ b/x11fwd.c
@@ -177,7 +177,7 @@ char *x11_init(Socket * s, char *display, void *c, void *auth)
     /*
      * Try to find host.
      */
-    addr = sk_namelookup(host, &dummy_realhost);
+    addr = name_lookup(host, port, &dummy_realhost);
     if ((err = sk_addr_error(addr)))
        return err;