mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 09:27:59 +00:00
Integrate unfix.org's IPv6 patches up to level 10, with rather a lot
of polishing to bring them to what I think should in principle be release quality. Unlike the unfix.org patches themselves, this checkin enables IPv6 by default; if you want to leave it out, you have to build with COMPAT=-DNO_IPV6. I have tested that this compiles on Visual C 7 (so the nightlies _should_ acquire IPv6 support without missing a beat), but since I don't have IPv6 set up myself I haven't actually tested that it _works_. It still seems to make correct IPv4 connections, but that's all I've been able to verify for myself. Further testing is needed. [originally from svn r5047] [this svn revision also touched putty-wishlist]
This commit is contained in:
parent
7573f3733f
commit
6daf6faede
5
Recipe
5
Recipe
@ -72,6 +72,11 @@
|
||||
# build, since at the time of writing this <multimon.h> is
|
||||
# known not to be available in Cygwin.
|
||||
#
|
||||
# - COMPAT=/DNO_IPV6
|
||||
# Disables PuTTY's ability to make IPv6 connections, enabling
|
||||
# it to compile under development environments which do not
|
||||
# support IPv6 in their header files.
|
||||
#
|
||||
# - COMPAT=/DMSVC4
|
||||
# - RCFL=/DMSVC4
|
||||
# Makes a couple of minor changes so that PuTTY compiles using
|
||||
|
11
cmdline.c
11
cmdline.c
@ -348,6 +348,17 @@ int cmdline_process_param(char *p, char *value, int need_save, Config *cfg)
|
||||
cfg->keyfile = filename_from_str(value);
|
||||
}
|
||||
|
||||
if (!strcmp(p, "-4") || !strcmp(p, "-ipv4")) {
|
||||
RETURN(1);
|
||||
SAVEABLE(1);
|
||||
cfg->addressfamily = ADDRTYPE_IPV4;
|
||||
}
|
||||
if (!strcmp(p, "-6") || !strcmp(p, "-ipv6")) {
|
||||
RETURN(1);
|
||||
SAVEABLE(1);
|
||||
cfg->addressfamily = ADDRTYPE_IPV6;
|
||||
}
|
||||
|
||||
return ret; /* unrecognised */
|
||||
}
|
||||
|
||||
|
146
config.c
146
config.c
@ -666,6 +666,7 @@ static void environ_handler(union control *ctrl, void *dlg,
|
||||
struct portfwd_data {
|
||||
union control *addbutton, *rembutton, *listbox;
|
||||
union control *sourcebox, *destbox, *direction;
|
||||
union control *addressfamily;
|
||||
};
|
||||
|
||||
static void portfwd_handler(union control *ctrl, void *dlg,
|
||||
@ -690,25 +691,39 @@ static void portfwd_handler(union control *ctrl, void *dlg,
|
||||
* Default is Local.
|
||||
*/
|
||||
dlg_radiobutton_set(ctrl, dlg, 0);
|
||||
} else if (ctrl == pfd->addressfamily) {
|
||||
dlg_radiobutton_set(ctrl, dlg, 0);
|
||||
}
|
||||
} else if (event == EVENT_ACTION) {
|
||||
if (ctrl == pfd->addbutton) {
|
||||
char str[sizeof(cfg->portfwd)];
|
||||
char *p;
|
||||
int whichbutton = dlg_radiobutton_get(pfd->direction, dlg);
|
||||
int i, type;
|
||||
int whichbutton;
|
||||
|
||||
i = 0;
|
||||
whichbutton = dlg_radiobutton_get(pfd->addressfamily, dlg);
|
||||
if (whichbutton == 1)
|
||||
str[i++] = '4';
|
||||
else if (whichbutton == 2)
|
||||
str[i++] = '6';
|
||||
|
||||
whichbutton = dlg_radiobutton_get(pfd->direction, dlg);
|
||||
if (whichbutton == 0)
|
||||
str[0] = 'L';
|
||||
type = 'L';
|
||||
else if (whichbutton == 1)
|
||||
str[0] = 'R';
|
||||
type = 'R';
|
||||
else
|
||||
str[0] = 'D';
|
||||
dlg_editbox_get(pfd->sourcebox, dlg, str+1, sizeof(str) - 2);
|
||||
if (!str[1]) {
|
||||
type = 'D';
|
||||
str[i++] = type;
|
||||
|
||||
dlg_editbox_get(pfd->sourcebox, dlg, str+i, sizeof(str) - i);
|
||||
if (!str[2]) {
|
||||
dlg_error_msg(dlg, "You need to specify a source port number");
|
||||
return;
|
||||
}
|
||||
p = str + strlen(str);
|
||||
if (str[0] != 'D') {
|
||||
if (type != 'D') {
|
||||
*p++ = '\t';
|
||||
dlg_editbox_get(pfd->destbox, dlg, p,
|
||||
sizeof(str)-1 - (p - str));
|
||||
@ -1344,9 +1359,59 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
|
||||
if (protocol >= 0) {
|
||||
ctrl_settitle(b, "Connection", "Options controlling the connection");
|
||||
|
||||
s = ctrl_getset(b, "Connection", "keepalive",
|
||||
"Sending of null packets to keep session active");
|
||||
ctrl_editbox(s, "Seconds between keepalives (0 to turn off)", 'k', 20,
|
||||
HELPCTX(connection_keepalive),
|
||||
dlg_stdeditbox_handler, I(offsetof(Config,ping_interval)),
|
||||
I(-1));
|
||||
|
||||
if (!midsession) {
|
||||
s = ctrl_getset(b, "Connection", "data",
|
||||
"Data to send to the server");
|
||||
s = ctrl_getset(b, "Connection", "tcp",
|
||||
"Low-level TCP connection options");
|
||||
ctrl_checkbox(s, "Disable Nagle's algorithm (TCP_NODELAY option)",
|
||||
'n', HELPCTX(connection_nodelay),
|
||||
dlg_stdcheckbox_handler,
|
||||
I(offsetof(Config,tcp_nodelay)));
|
||||
ctrl_checkbox(s, "Enable TCP keepalives (SO_KEEPALIVE option)",
|
||||
'p', HELPCTX(connection_tcpkeepalive),
|
||||
dlg_stdcheckbox_handler,
|
||||
I(offsetof(Config,tcp_keepalives)));
|
||||
s = ctrl_getset(b, "Connection", "ipversion",
|
||||
"Internet protocol version");
|
||||
ctrl_radiobuttons(s, NULL, NO_SHORTCUT,
|
||||
#ifndef NO_IPV6
|
||||
3,
|
||||
#else
|
||||
2,
|
||||
#endif
|
||||
HELPCTX(connection_ipversion),
|
||||
dlg_stdradiobutton_handler,
|
||||
I(offsetof(Config, addressfamily)),
|
||||
"Auto", NO_SHORTCUT, I(ADDRTYPE_UNSPEC),
|
||||
"IPv4", NO_SHORTCUT, I(ADDRTYPE_IPV4),
|
||||
#ifndef NO_IPV6
|
||||
"IPv6", NO_SHORTCUT, I(ADDRTYPE_IPV6),
|
||||
#endif
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* A sub-panel Connection/Data, containing options that
|
||||
* decide on data to send to the server.
|
||||
*/
|
||||
if (!midsession) {
|
||||
ctrl_settitle(b, "Connection/Data", "Data to send to the server");
|
||||
|
||||
s = ctrl_getset(b, "Connection/Data", "login",
|
||||
"Login details");
|
||||
ctrl_editbox(s, "Auto-login username", 'u', 50,
|
||||
HELPCTX(connection_username),
|
||||
dlg_stdeditbox_handler, I(offsetof(Config,username)),
|
||||
I(sizeof(((Config *)0)->username)));
|
||||
|
||||
s = ctrl_getset(b, "Connection/Data", "term",
|
||||
"Terminal details");
|
||||
ctrl_editbox(s, "Terminal-type string", 't', 50,
|
||||
HELPCTX(connection_termtype),
|
||||
dlg_stdeditbox_handler, I(offsetof(Config,termtype)),
|
||||
@ -1355,12 +1420,9 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
|
||||
HELPCTX(connection_termspeed),
|
||||
dlg_stdeditbox_handler, I(offsetof(Config,termspeed)),
|
||||
I(sizeof(((Config *)0)->termspeed)));
|
||||
ctrl_editbox(s, "Auto-login username", 'u', 50,
|
||||
HELPCTX(connection_username),
|
||||
dlg_stdeditbox_handler, I(offsetof(Config,username)),
|
||||
I(sizeof(((Config *)0)->username)));
|
||||
|
||||
ctrl_text(s, "Environment variables:", HELPCTX(telnet_environ));
|
||||
s = ctrl_getset(b, "Connection/Data", "env",
|
||||
"Environment variables");
|
||||
ctrl_columns(s, 2, 80, 20);
|
||||
ed = (struct environ_data *)
|
||||
ctrl_alloc(b, sizeof(struct environ_data));
|
||||
@ -1391,26 +1453,6 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
|
||||
ed->listbox->listbox.percentages[1] = 70;
|
||||
}
|
||||
|
||||
s = ctrl_getset(b, "Connection", "keepalive",
|
||||
"Sending of null packets to keep session active");
|
||||
ctrl_editbox(s, "Seconds between keepalives (0 to turn off)", 'k', 20,
|
||||
HELPCTX(connection_keepalive),
|
||||
dlg_stdeditbox_handler, I(offsetof(Config,ping_interval)),
|
||||
I(-1));
|
||||
|
||||
if (!midsession) {
|
||||
s = ctrl_getset(b, "Connection", "tcp",
|
||||
"Low-level TCP connection options");
|
||||
ctrl_checkbox(s, "Disable Nagle's algorithm (TCP_NODELAY option)",
|
||||
'n', HELPCTX(connection_nodelay),
|
||||
dlg_stdcheckbox_handler,
|
||||
I(offsetof(Config,tcp_nodelay)));
|
||||
ctrl_checkbox(s, "Enable TCP keepalives (SO_KEEPALIVE option)",
|
||||
'p', HELPCTX(connection_tcpkeepalive),
|
||||
dlg_stdcheckbox_handler,
|
||||
I(offsetof(Config,tcp_keepalives)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!midsession) {
|
||||
@ -1664,15 +1706,14 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
|
||||
dlg_stdfilesel_handler, I(offsetof(Config, keyfile)));
|
||||
}
|
||||
|
||||
/*
|
||||
* The Connection/SSH/Tunnels panel. Some of this _is_
|
||||
* still available in mid-session.
|
||||
*/
|
||||
ctrl_settitle(b, "Connection/SSH/Tunnels",
|
||||
"Options controlling SSH tunnelling");
|
||||
|
||||
if (!midsession) {
|
||||
s = ctrl_getset(b, "Connection/SSH/Tunnels", "x11", "X11 forwarding");
|
||||
/*
|
||||
* The Connection/SSH/X11 panel.
|
||||
*/
|
||||
ctrl_settitle(b, "Connection/SSH/X11",
|
||||
"Options controlling SSH X11 forwarding");
|
||||
|
||||
s = ctrl_getset(b, "Connection/SSH/X11", "x11", "X11 forwarding");
|
||||
ctrl_checkbox(s, "Enable X11 forwarding", 'e',
|
||||
HELPCTX(ssh_tunnels_x11),
|
||||
dlg_stdcheckbox_handler,I(offsetof(Config,x11_forward)));
|
||||
@ -1688,6 +1729,12 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
|
||||
"XDM-Authorization-1", I(X11_XDM), NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* The Tunnels panel _is_ still available in mid-session.
|
||||
*/
|
||||
ctrl_settitle(b, "Connection/SSH/Tunnels",
|
||||
"Options controlling SSH port forwarding");
|
||||
|
||||
s = ctrl_getset(b, "Connection/SSH/Tunnels", "portfwd",
|
||||
"Port forwarding");
|
||||
ctrl_checkbox(s, "Local ports accept connections from other hosts",'t',
|
||||
@ -1741,6 +1788,21 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
|
||||
"Remote", 'm', P(NULL),
|
||||
"Dynamic", 'y', P(NULL),
|
||||
NULL);
|
||||
pfd->addressfamily =
|
||||
ctrl_radiobuttons(s, NULL, NO_SHORTCUT,
|
||||
#ifndef NO_IPV6
|
||||
3,
|
||||
#else
|
||||
2,
|
||||
#endif
|
||||
HELPCTX(ssh_tunnels_portfwd_ipversion),
|
||||
portfwd_handler, P(pfd),
|
||||
"Auto", NO_SHORTCUT, I(ADDRTYPE_UNSPEC),
|
||||
"IPv4", NO_SHORTCUT, I(ADDRTYPE_IPV4),
|
||||
#ifndef NO_IPV6
|
||||
"IPv6", NO_SHORTCUT, I(ADDRTYPE_IPV6),
|
||||
#endif
|
||||
NULL);
|
||||
ctrl_tabdelay(s, pfd->addbutton);
|
||||
ctrl_columns(s, 1, 100);
|
||||
|
||||
|
224
doc/config.but
224
doc/config.but
@ -1506,86 +1506,6 @@ background.)
|
||||
The Connection panel allows you to configure options that apply to
|
||||
more than one type of connection.
|
||||
|
||||
\S{config-termtype} \q{Terminal-type string}
|
||||
|
||||
\cfg{winhelp-topic}{connection.termtype}
|
||||
|
||||
Most servers you might connect to with PuTTY are designed to be
|
||||
connected to from lots of different types of terminal. In order to
|
||||
send the right control sequences to each one, the server will need
|
||||
to know what type of terminal it is dealing with. Therefore, each of
|
||||
the SSH, Telnet and Rlogin protocols allow a text string to be sent
|
||||
down the connection describing the terminal.
|
||||
|
||||
PuTTY attempts to emulate the Unix \c{xterm} program, and by default
|
||||
it reflects this by sending \c{xterm} as a terminal-type string. If
|
||||
you find this is not doing what you want - perhaps the remote
|
||||
system reports \q{Unknown terminal type} - you could try setting
|
||||
this to something different, such as \c{vt220}.
|
||||
|
||||
If you're not sure whether a problem is due to the terminal type
|
||||
setting or not, you probably need to consult the manual for your
|
||||
application or your server.
|
||||
|
||||
\S{config-termspeed} \q{Terminal speeds}
|
||||
|
||||
\cfg{winhelp-topic}{connection.termspeed}
|
||||
|
||||
The Telnet, Rlogin, and SSH protocols allow the client to specify
|
||||
terminal speeds to the server.
|
||||
|
||||
This parameter does \e{not} affect the actual speed of the connection,
|
||||
which is always \q{as fast as possible}; it is just a hint that is
|
||||
sometimes used by server software to modify its behaviour. For
|
||||
instance, if a slow speed is indicated, the server may switch to a
|
||||
less bandwidth-hungry display mode.
|
||||
|
||||
The value is usually meaningless in a network environment, but
|
||||
PuTTY lets you configure it, in case you find the server is reacting
|
||||
badly to the default value.
|
||||
|
||||
The format is a pair of numbers separated by a comma, for instance,
|
||||
\c{38400,38400}. The first number represents the output speed
|
||||
(\e{from} the server) in bits per second, and the second is the input
|
||||
speed (\e{to} the server). (Only the first is used in the Rlogin
|
||||
protocol.)
|
||||
|
||||
This option has no effect on Raw connections.
|
||||
|
||||
\S{config-username} \q{Auto-login username}
|
||||
|
||||
\cfg{winhelp-topic}{connection.username}
|
||||
|
||||
All three of the SSH, Telnet and Rlogin protocols allow you to
|
||||
specify what user name you want to log in as, without having to type
|
||||
it explicitly every time. (Some Telnet servers don't support this.)
|
||||
|
||||
In this box you can type that user name.
|
||||
|
||||
\S{config-environ} Setting environment variables on the server
|
||||
|
||||
\cfg{winhelp-topic}{telnet.environ}
|
||||
|
||||
The Telnet protocol provides a means for the client to pass
|
||||
environment variables to the server. Many Telnet servers have
|
||||
stopped supporting this feature due to security flaws, but PuTTY
|
||||
still supports it for the benefit of any servers which have found
|
||||
other ways around the security problems than just disabling the
|
||||
whole mechanism.
|
||||
|
||||
Version 2 of the SSH protocol also provides a similar mechanism,
|
||||
which is easier to implement without security flaws. Newer SSH2
|
||||
servers are more likely to support it than older ones.
|
||||
|
||||
This configuration data is not used in the SSHv1, rlogin or raw
|
||||
protocols.
|
||||
|
||||
To add an environment variable to the list transmitted down the
|
||||
connection, you enter the variable name in the \q{Variable} box,
|
||||
enter its value in the \q{Value} box, and press the \q{Add} button.
|
||||
To remove one from the list, select it in the list box and press
|
||||
\q{Remove}.
|
||||
|
||||
\S{config-keepalive} Using keepalives to prevent disconnection
|
||||
|
||||
\cfg{winhelp-topic}{connection.keepalive}
|
||||
@ -1678,6 +1598,111 @@ are terminated than for keeping a connection alive.
|
||||
|
||||
TCP keepalives are disabled by default.
|
||||
|
||||
\S{config-address-family} \q{Internet protocol}
|
||||
|
||||
\cfg{winhelp-topic}{connection.ipversion}
|
||||
|
||||
This option allows the user to select between the old and new
|
||||
Internet protocols and addressing schemes (IPv4 and IPv6). The
|
||||
default setting is \q{Auto}, which means PuTTY will do something
|
||||
sensible and try to guess which protocol you wanted. (If you specify
|
||||
a literal Internet address, it will use whichever protocol that
|
||||
address implies. If you provide a hostname, it will see what kinds
|
||||
of address exist for that hostname; it will use IPv6 if there is an
|
||||
IPv6 address available, and fall back to IPv4 if not.)
|
||||
|
||||
If you need to force PuTTY to use a particular protocol, you can
|
||||
explicitly set this to \q{IPv4} or \q{IPv6}.
|
||||
|
||||
\H{config-data} The Data panel
|
||||
|
||||
The Data panel allows you to configure various pieces of data which
|
||||
can be sent to the server to affect your connection at the far end.
|
||||
|
||||
Each options on this panel applies to more than one protocol.
|
||||
Options which apply to only one protocol appear on that protocol's
|
||||
configuration panels.
|
||||
|
||||
\S{config-username} \q{Auto-login username}
|
||||
|
||||
\cfg{winhelp-topic}{connection.username}
|
||||
|
||||
All three of the SSH, Telnet and Rlogin protocols allow you to
|
||||
specify what user name you want to log in as, without having to type
|
||||
it explicitly every time. (Some Telnet servers don't support this.)
|
||||
|
||||
In this box you can type that user name.
|
||||
|
||||
\S{config-termtype} \q{Terminal-type string}
|
||||
|
||||
\cfg{winhelp-topic}{connection.termtype}
|
||||
|
||||
Most servers you might connect to with PuTTY are designed to be
|
||||
connected to from lots of different types of terminal. In order to
|
||||
send the right control sequences to each one, the server will need
|
||||
to know what type of terminal it is dealing with. Therefore, each of
|
||||
the SSH, Telnet and Rlogin protocols allow a text string to be sent
|
||||
down the connection describing the terminal.
|
||||
|
||||
PuTTY attempts to emulate the Unix \c{xterm} program, and by default
|
||||
it reflects this by sending \c{xterm} as a terminal-type string. If
|
||||
you find this is not doing what you want - perhaps the remote
|
||||
system reports \q{Unknown terminal type} - you could try setting
|
||||
this to something different, such as \c{vt220}.
|
||||
|
||||
If you're not sure whether a problem is due to the terminal type
|
||||
setting or not, you probably need to consult the manual for your
|
||||
application or your server.
|
||||
|
||||
\S{config-termspeed} \q{Terminal speeds}
|
||||
|
||||
\cfg{winhelp-topic}{connection.termspeed}
|
||||
|
||||
The Telnet, Rlogin, and SSH protocols allow the client to specify
|
||||
terminal speeds to the server.
|
||||
|
||||
This parameter does \e{not} affect the actual speed of the connection,
|
||||
which is always \q{as fast as possible}; it is just a hint that is
|
||||
sometimes used by server software to modify its behaviour. For
|
||||
instance, if a slow speed is indicated, the server may switch to a
|
||||
less bandwidth-hungry display mode.
|
||||
|
||||
The value is usually meaningless in a network environment, but
|
||||
PuTTY lets you configure it, in case you find the server is reacting
|
||||
badly to the default value.
|
||||
|
||||
The format is a pair of numbers separated by a comma, for instance,
|
||||
\c{38400,38400}. The first number represents the output speed
|
||||
(\e{from} the server) in bits per second, and the second is the input
|
||||
speed (\e{to} the server). (Only the first is used in the Rlogin
|
||||
protocol.)
|
||||
|
||||
This option has no effect on Raw connections.
|
||||
|
||||
\S{config-environ} Setting environment variables on the server
|
||||
|
||||
\cfg{winhelp-topic}{telnet.environ}
|
||||
|
||||
The Telnet protocol provides a means for the client to pass
|
||||
environment variables to the server. Many Telnet servers have
|
||||
stopped supporting this feature due to security flaws, but PuTTY
|
||||
still supports it for the benefit of any servers which have found
|
||||
other ways around the security problems than just disabling the
|
||||
whole mechanism.
|
||||
|
||||
Version 2 of the SSH protocol also provides a similar mechanism,
|
||||
which is easier to implement without security flaws. Newer SSH2
|
||||
servers are more likely to support it than older ones.
|
||||
|
||||
This configuration data is not used in the SSHv1, rlogin or raw
|
||||
protocols.
|
||||
|
||||
To add an environment variable to the list transmitted down the
|
||||
connection, you enter the variable name in the \q{Variable} box,
|
||||
enter its value in the \q{Value} box, and press the \q{Add} button.
|
||||
To remove one from the list, select it in the list box and press
|
||||
\q{Remove}.
|
||||
|
||||
\H{config-proxy} The Proxy panel
|
||||
|
||||
\cfg{winhelp-topic}{proxy.main}
|
||||
@ -2298,15 +2323,13 @@ about public key authentication in SSH.
|
||||
|
||||
This key must be in PuTTY's native format (\c{*.PPK}).
|
||||
|
||||
\H{config-ssh-tunnels} The Tunnels panel
|
||||
|
||||
The Tunnels panel allows you to configure tunnelling of other
|
||||
connection types through an SSH connection.
|
||||
|
||||
\S{config-ssh-x11} X11 forwarding
|
||||
\H{config-ssh-x11} The X11 panel
|
||||
|
||||
\cfg{winhelp-topic}{ssh.tunnels.x11}
|
||||
|
||||
The X11 panel allows you to configure forwarding of X11 over an
|
||||
SSH connection.
|
||||
|
||||
If your server lets you run X Window System applications, X11
|
||||
forwarding allows you to securely give those applications access to
|
||||
a local X display on your PC.
|
||||
@ -2320,7 +2343,7 @@ primary local display (\c{:0}) if that fails.
|
||||
See \k{using-x-forwarding} for more information about X11
|
||||
forwarding.
|
||||
|
||||
\S2{config-ssh-x11auth} Remote X11 authentication
|
||||
\S{config-ssh-x11auth} Remote X11 authentication
|
||||
|
||||
\cfg{winhelp-topic}{ssh.tunnels.x11auth}
|
||||
|
||||
@ -2367,10 +2390,13 @@ connections fail.
|
||||
PuTTY's default is \cw{MIT-MAGIC-COOKIE-1}. If you change it, you
|
||||
should be sure you know what you're doing.
|
||||
|
||||
\S{config-ssh-portfwd} Port forwarding
|
||||
\H{config-ssh-portfwd} The Tunnels panel
|
||||
|
||||
\cfg{winhelp-topic}{ssh.tunnels.portfwd}
|
||||
|
||||
The Tunnels panel allows you to configure tunnelling of arbitrary
|
||||
connection types through an SSH connection.
|
||||
|
||||
Port forwarding allows you to tunnel other types of network
|
||||
connection down an SSH session. See \k{using-port-forwarding} for a
|
||||
general discussion of port forwarding and how it works.
|
||||
@ -2453,6 +2479,28 @@ SSH server machine can connect to the forwarded port.) Note that
|
||||
this feature is only available in the SSH 2 protocol, and not all
|
||||
SSH 2 servers support it (OpenSSH 3.0 does not, for example).
|
||||
|
||||
\S{config-ssh-portfwd-address-family} Selecting Internet protocol
|
||||
version for forwarded ports
|
||||
|
||||
\cfg{winhelp-topic}{ssh.tunnels.portfwd.ipversion}
|
||||
|
||||
This switch allows you to select a specific Internet protocol (IPv4
|
||||
or IPv6) for the local end of a forwarded port. By default, it is
|
||||
set on \q{Auto}, which means that:
|
||||
|
||||
\b for a local-to-remote port forwarding, PuTTY will listen for
|
||||
incoming connections in both IPv4 and (if available) IPv6
|
||||
|
||||
\b for a remote-to-local port forwarding, PuTTY will choose a
|
||||
sensible protocol for the outgoing connection.
|
||||
|
||||
\# FIXME: work out what this paragraph means, reword it for clarity,
|
||||
\# and reinstate it.
|
||||
Note that on Windows the address space for IPv4 and IPv6 is
|
||||
completely disjunct, so listening on IPv6 won't make PuTTY listen on
|
||||
IPv4. This behaviour may be different on most remote hosts when they
|
||||
are not operating Windows.
|
||||
|
||||
\H{config-ssh-bugs} The Bugs panel
|
||||
|
||||
Not all SSH servers work properly. Various existing servers have
|
||||
|
@ -68,6 +68,7 @@ use Plink:
|
||||
\c -A -a enable / disable agent forwarding
|
||||
\c -t -T enable / disable pty allocation
|
||||
\c -1 -2 force use of particular protocol version
|
||||
\c -4 -6 force use of IPv4 or IPv6
|
||||
\c -C enable compression
|
||||
\c -i key private key file for authentication
|
||||
\c -s remote command is an SSH subsystem (SSH-2 only)
|
||||
|
@ -55,6 +55,7 @@ use PSCP:
|
||||
\c -l user connect with specified username
|
||||
\c -pw passw login with specified password
|
||||
\c -1 -2 force use of particular SSH protocol version
|
||||
\c -4 -6 force use of IPv4 or IPv6
|
||||
\c -C enable compression
|
||||
\c -i key private key file for authentication
|
||||
\c -batch disable all interactive prompts
|
||||
|
@ -754,6 +754,16 @@ These options are equivalent to selecting your preferred SSH
|
||||
protocol version as \q{1 only} or \q{2 only} in the SSH panel of the
|
||||
PuTTY configuration box (see \k{config-ssh-prot}).
|
||||
|
||||
\S2{using-cmdline-ipversion} \i\c{-4} and \i\c{-6}: specify an
|
||||
\i{Internet protocol version}
|
||||
|
||||
The \c{-4} and \c{-6} options force PuTTY to use the older Internet
|
||||
protocol \i{IPv4} or the newer \i{IPv6}.
|
||||
|
||||
These options are equivalent to selecting your preferred Internet
|
||||
protocol version as \q{IPv4} or \q{IPv6} in the Connection panel of
|
||||
the PuTTY configuration box (see \k{config-address-family}).
|
||||
|
||||
\S2{using-cmdline-identity} \i\c{-i}: specify an SSH \i{private key}
|
||||
|
||||
The \c{-i} option allows you to specify the name of a private key
|
||||
|
@ -56,7 +56,7 @@ void sk_init(void)
|
||||
* Network functions exported to the world. These choose whether to call
|
||||
* MacTCP or OpenTransport and behave accordingly.
|
||||
*/
|
||||
SockAddr sk_namelookup(char const *host, char **canonicalname)
|
||||
SockAddr sk_namelookup(char const *host, char **canonicalname, int address_family)
|
||||
{
|
||||
|
||||
if (stack != NULL)
|
||||
@ -137,7 +137,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only)
|
||||
Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, int address_family)
|
||||
{
|
||||
|
||||
if (stack != NULL)
|
||||
|
@ -82,9 +82,9 @@ Socket new_connection(SockAddr addr, char *hostname,
|
||||
int oobinline, int nodelay, int keepalive,
|
||||
Plug plug, const Config *cfg);
|
||||
Socket new_listener(char *srcaddr, int port, Plug plug, int local_host_only,
|
||||
const Config *cfg);
|
||||
const Config *cfg, int addressfamily);
|
||||
SockAddr name_lookup(char *host, int port, char **canonicalname,
|
||||
const Config *cfg);
|
||||
const Config *cfg, int addressfamily);
|
||||
|
||||
/* platform-dependent callback from new_connection() */
|
||||
/* (same caveat about addr as new_connection()) */
|
||||
@ -98,12 +98,11 @@ Socket platform_new_connection(SockAddr addr, char *hostname,
|
||||
void sk_init(void); /* called once at program startup */
|
||||
void sk_cleanup(void); /* called just before program exit */
|
||||
|
||||
SockAddr sk_namelookup(const char *host, char **canonicalname);
|
||||
SockAddr sk_namelookup(const char *host, char **canonicalname, int address_family);
|
||||
SockAddr sk_nonamelookup(const 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, ADDRTYPE_NAME };
|
||||
int sk_addrtype(SockAddr addr);
|
||||
void sk_addrcopy(SockAddr addr, char *buf);
|
||||
void sk_addr_free(SockAddr addr);
|
||||
@ -113,7 +112,7 @@ void sk_addr_free(SockAddr addr);
|
||||
Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||
int nodelay, int keepalive, Plug p);
|
||||
|
||||
Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only);
|
||||
Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, int address_family);
|
||||
|
||||
Socket sk_register(OSSocket sock, Plug plug);
|
||||
|
||||
|
@ -354,7 +354,7 @@ static void pfd_sent(Plug plug, int bufsize)
|
||||
* Called when receiving a PORT OPEN from the server
|
||||
*/
|
||||
const char *pfd_newconnect(Socket *s, char *hostname, int port,
|
||||
void *c, const Config *cfg)
|
||||
void *c, const Config *cfg, int addressfamily)
|
||||
{
|
||||
static const struct plug_function_table fn_table = {
|
||||
pfd_closing,
|
||||
@ -371,7 +371,7 @@ const char *pfd_newconnect(Socket *s, char *hostname, int port,
|
||||
/*
|
||||
* Try to find host.
|
||||
*/
|
||||
addr = name_lookup(hostname, port, &dummy_realhost, cfg);
|
||||
addr = name_lookup(hostname, port, &dummy_realhost, cfg, addressfamily);
|
||||
if ((err = sk_addr_error(addr)) != NULL) {
|
||||
sk_addr_free(addr);
|
||||
return err;
|
||||
@ -463,7 +463,7 @@ static int pfd_accepting(Plug p, OSSocket sock)
|
||||
*/
|
||||
const char *pfd_addforward(char *desthost, int destport, char *srcaddr,
|
||||
int port, void *backhandle, const Config *cfg,
|
||||
void **sockdata)
|
||||
void **sockdata, int address_family)
|
||||
{
|
||||
static const struct plug_function_table fn_table = {
|
||||
pfd_closing,
|
||||
@ -494,7 +494,7 @@ const char *pfd_addforward(char *desthost, int destport, char *srcaddr,
|
||||
pr->backhandle = backhandle;
|
||||
|
||||
pr->s = s = new_listener(srcaddr, port, (Plug) pr,
|
||||
!cfg->lport_acceptall, cfg);
|
||||
!cfg->lport_acceptall, cfg, address_family);
|
||||
if ((err = sk_socket_error(s)) != NULL) {
|
||||
sfree(pr);
|
||||
return err;
|
||||
|
10
proxy.c
10
proxy.c
@ -342,7 +342,7 @@ static int proxy_for_destination (SockAddr addr, char *hostname, int port,
|
||||
}
|
||||
|
||||
SockAddr name_lookup(char *host, int port, char **canonicalname,
|
||||
const Config *cfg)
|
||||
const Config *cfg, int addressfamily)
|
||||
{
|
||||
if (cfg->proxy_type != PROXY_NONE &&
|
||||
do_proxy_dns(cfg) &&
|
||||
@ -351,7 +351,7 @@ SockAddr name_lookup(char *host, int port, char **canonicalname,
|
||||
return sk_nonamelookup(host);
|
||||
}
|
||||
|
||||
return sk_namelookup(host, canonicalname);
|
||||
return sk_namelookup(host, canonicalname, addressfamily);
|
||||
}
|
||||
|
||||
Socket new_connection(SockAddr addr, char *hostname,
|
||||
@ -433,7 +433,7 @@ Socket new_connection(SockAddr addr, char *hostname,
|
||||
|
||||
/* look-up proxy */
|
||||
proxy_addr = sk_namelookup(cfg->proxy_host,
|
||||
&proxy_canonical_name);
|
||||
&proxy_canonical_name, cfg->addressfamily);
|
||||
if (sk_addr_error(proxy_addr) != NULL) {
|
||||
ret->error = "Proxy error: Unable to resolve proxy host name";
|
||||
return (Socket)ret;
|
||||
@ -461,13 +461,13 @@ Socket new_connection(SockAddr addr, char *hostname,
|
||||
}
|
||||
|
||||
Socket new_listener(char *srcaddr, int port, Plug plug, int local_host_only,
|
||||
const Config *cfg)
|
||||
const Config *cfg, int addressfamily)
|
||||
{
|
||||
/* TODO: SOCKS (and potentially others) support inbound
|
||||
* TODO: connections via the proxy. support them.
|
||||
*/
|
||||
|
||||
return sk_newlistener(srcaddr, port, plug, local_host_only);
|
||||
return sk_newlistener(srcaddr, port, plug, local_host_only, addressfamily);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
|
32
pscp.c
32
pscp.c
@ -321,6 +321,17 @@ static void do_cmd(char *host, char *user, char *cmd)
|
||||
if (host == NULL || host[0] == '\0')
|
||||
bump("Empty host name");
|
||||
|
||||
/*
|
||||
* Remove fiddly bits of address: remove a colon suffix, and
|
||||
* the square brackets around an IPv6 literal address.
|
||||
*/
|
||||
if (host[0] == '[') {
|
||||
host++;
|
||||
host[strcspn(host, "]")] = '\0';
|
||||
} else {
|
||||
host[strcspn(host, ":")] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* If we haven't loaded session details already (e.g., from -load),
|
||||
* try looking for a session called "host".
|
||||
@ -381,11 +392,6 @@ static void do_cmd(char *host, char *user, char *cmd)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Trim a colon suffix off the hostname if it's there.
|
||||
*/
|
||||
cfg.host[strcspn(cfg.host, ":")] = '\0';
|
||||
|
||||
/*
|
||||
* Remove any remaining whitespace from the hostname.
|
||||
*/
|
||||
@ -533,6 +539,19 @@ static void print_stats(char *name, unsigned long size, unsigned long done,
|
||||
*/
|
||||
static char *colon(char *str)
|
||||
{
|
||||
/* Check and process IPv6 literal addresses
|
||||
* (eg: 'jeroen@[2001:db8::1]:myfile.txt') */
|
||||
char *ipv6 = strchr(str, '[');
|
||||
if (ipv6) {
|
||||
str = strchr(str, ']');
|
||||
if (str) {
|
||||
/* Terminate on the closing bracket */
|
||||
*str++ = '\0';
|
||||
return (str);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* We ignore a leading colon, since the hostname cannot be
|
||||
empty. We also ignore a colon as second character because
|
||||
of filenames like f:myfile.txt. */
|
||||
@ -1928,7 +1947,7 @@ static void toremote(int argc, char *argv[])
|
||||
*targ++ = '\0';
|
||||
if (*targ == '\0')
|
||||
targ = ".";
|
||||
/* Substitute "." for emtpy target */
|
||||
/* Substitute "." for empty target */
|
||||
|
||||
/* Separate host and username */
|
||||
user = host;
|
||||
@ -2129,6 +2148,7 @@ static void usage(void)
|
||||
printf(" -l user connect with specified username\n");
|
||||
printf(" -pw passw login with specified password\n");
|
||||
printf(" -1 -2 force use of particular SSH protocol version\n");
|
||||
printf(" -4 -6 force use of IPv4 or IPv6\n");
|
||||
printf(" -C enable compression\n");
|
||||
printf(" -i key private key file for authentication\n");
|
||||
printf(" -batch disable all interactive prompts\n");
|
||||
|
1
psftp.c
1
psftp.c
@ -2446,6 +2446,7 @@ static void usage(void)
|
||||
printf(" -P port connect to specified port\n");
|
||||
printf(" -pw passw login with specified password\n");
|
||||
printf(" -1 -2 force use of particular SSH protocol version\n");
|
||||
printf(" -4 -6 force use of IPv4 or IPv6\n");
|
||||
printf(" -C enable compression\n");
|
||||
printf(" -i key private key file for authentication\n");
|
||||
printf(" -batch disable all interactive prompts\n");
|
||||
|
11
putty.h
11
putty.h
@ -314,6 +314,16 @@ enum {
|
||||
FUNKY_SCO
|
||||
};
|
||||
|
||||
enum {
|
||||
/*
|
||||
* Network address types. Used for specifying choice of IPv4/v6
|
||||
* in config; also used in proxy.c to indicate whether a given
|
||||
* host name has already been resolved or will be resolved at
|
||||
* the proxy end.
|
||||
*/
|
||||
ADDRTYPE_UNSPEC, ADDRTYPE_IPV4, ADDRTYPE_IPV6, ADDRTYPE_NAME
|
||||
};
|
||||
|
||||
struct backend_tag {
|
||||
const char *(*init) (void *frontend_handle, void **backend_handle,
|
||||
Config *cfg,
|
||||
@ -375,6 +385,7 @@ struct config_tag {
|
||||
char host[512];
|
||||
int port;
|
||||
int protocol;
|
||||
int addressfamily;
|
||||
int close_on_exit;
|
||||
int warn_on_close;
|
||||
int ping_interval; /* in seconds */
|
||||
|
7
raw.c
7
raw.c
@ -94,11 +94,14 @@ static const char *raw_init(void *frontend_handle, void **backend_handle,
|
||||
*/
|
||||
{
|
||||
char *buf;
|
||||
buf = dupprintf("Looking up host \"%s\"", host);
|
||||
buf = dupprintf("Looking up host \"%s\"%s", host,
|
||||
(cfg->addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
|
||||
(cfg->addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" :
|
||||
"")));
|
||||
logevent(raw->frontend, buf);
|
||||
sfree(buf);
|
||||
}
|
||||
addr = name_lookup(host, port, realhost, cfg);
|
||||
addr = name_lookup(host, port, realhost, cfg, cfg->addressfamily);
|
||||
if ((err = sk_addr_error(addr)) != NULL) {
|
||||
sk_addr_free(addr);
|
||||
return err;
|
||||
|
7
rlogin.c
7
rlogin.c
@ -126,11 +126,14 @@ static const char *rlogin_init(void *frontend_handle, void **backend_handle,
|
||||
*/
|
||||
{
|
||||
char *buf;
|
||||
buf = dupprintf("Looking up host \"%s\"", host);
|
||||
buf = dupprintf("Looking up host \"%s\"%s", host,
|
||||
(cfg->addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
|
||||
(cfg->addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" :
|
||||
"")));
|
||||
logevent(rlogin->frontend, buf);
|
||||
sfree(buf);
|
||||
}
|
||||
addr = name_lookup(host, port, realhost, cfg);
|
||||
addr = name_lookup(host, port, realhost, cfg, cfg->addressfamily);
|
||||
if ((err = sk_addr_error(addr)) != NULL) {
|
||||
sk_addr_free(addr);
|
||||
return err;
|
||||
|
@ -197,6 +197,9 @@ void save_open_settings(void *sesskey, int do_host, Config *cfg)
|
||||
write_setting_s(sesskey, "TerminalType", cfg->termtype);
|
||||
write_setting_s(sesskey, "TerminalSpeed", cfg->termspeed);
|
||||
|
||||
/* Address family selection */
|
||||
write_setting_i(sesskey, "AddressFamily", cfg->addressfamily);
|
||||
|
||||
/* proxy settings */
|
||||
write_setting_s(sesskey, "ProxyExcludeList", cfg->proxy_exclude_list);
|
||||
write_setting_i(sesskey, "ProxyDNS", (cfg->proxy_dns+2)%3);
|
||||
@ -420,6 +423,9 @@ void load_open_settings(void *sesskey, int do_host, Config *cfg)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Address family selection */
|
||||
gppi(sesskey, "AddressFamily", ADDRTYPE_UNSPEC, &cfg->addressfamily);
|
||||
|
||||
/* The CloseOnExit numbers are arranged in a different order from
|
||||
* the standard FORCE_ON / FORCE_OFF / AUTO. */
|
||||
gppi(sesskey, "CloseOnExit", 1, &i); cfg->close_on_exit = (i+1)%3;
|
||||
|
72
ssh.c
72
ssh.c
@ -521,6 +521,7 @@ struct ssh_portfwd {
|
||||
unsigned sport, dport;
|
||||
char *saddr, *daddr;
|
||||
struct ssh_rportfwd *remote;
|
||||
int addressfamily;
|
||||
void *local;
|
||||
};
|
||||
#define free_portfwd(pf) ( \
|
||||
@ -2449,8 +2450,11 @@ static const char *connect_to_host(Ssh ssh, char *host, int port,
|
||||
/*
|
||||
* Try to find host.
|
||||
*/
|
||||
logeventf(ssh, "Looking up host \"%s\"", host);
|
||||
addr = name_lookup(host, port, realhost, &ssh->cfg);
|
||||
logeventf(ssh, "Looking up host \"%s\"%s", host,
|
||||
(ssh->cfg.addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
|
||||
(ssh->cfg.addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" : "")));
|
||||
addr = name_lookup(host, port, realhost, &ssh->cfg,
|
||||
ssh->cfg.addressfamily);
|
||||
if ((err = sk_addr_error(addr)) != NULL) {
|
||||
sk_addr_free(addr);
|
||||
return err;
|
||||
@ -3666,7 +3670,7 @@ static void ssh_rportfwd_succfail(Ssh ssh, struct Packet *pktin, void *ctx)
|
||||
|
||||
static void ssh_setup_portfwd(Ssh ssh, const Config *cfg)
|
||||
{
|
||||
char type;
|
||||
char address_family, type;
|
||||
int n;
|
||||
int sport,dport,sserv,dserv;
|
||||
char sports[256], dports[256], saddr[256], host[256];
|
||||
@ -3690,8 +3694,22 @@ static void ssh_setup_portfwd(Ssh ssh, const Config *cfg)
|
||||
}
|
||||
|
||||
while (*portfwd_strptr) {
|
||||
type = *portfwd_strptr++;
|
||||
address_family = 'A';
|
||||
type = 'L';
|
||||
while (*portfwd_strptr && *portfwd_strptr != '\t') {
|
||||
if (*portfwd_strptr == 'A' ||
|
||||
*portfwd_strptr == '4' ||
|
||||
*portfwd_strptr == '6')
|
||||
address_family = *portfwd_strptr;
|
||||
else if (*portfwd_strptr == 'L' ||
|
||||
*portfwd_strptr == 'R' ||
|
||||
*portfwd_strptr == 'D')
|
||||
type = *portfwd_strptr;
|
||||
portfwd_strptr++;
|
||||
}
|
||||
|
||||
saddr[0] = '\0';
|
||||
|
||||
n = 0;
|
||||
while (*portfwd_strptr && *portfwd_strptr != '\t') {
|
||||
if (*portfwd_strptr == ':') {
|
||||
@ -3774,6 +3792,9 @@ static void ssh_setup_portfwd(Ssh ssh, const Config *cfg)
|
||||
pfrec->dport = dport;
|
||||
pfrec->local = NULL;
|
||||
pfrec->remote = NULL;
|
||||
pfrec->addressfamily = (address_family == '4' ? ADDRTYPE_IPV4 :
|
||||
address_family == '6' ? ADDRTYPE_IPV6 :
|
||||
ADDRTYPE_UNSPEC);
|
||||
|
||||
epfrec = add234(ssh->portfwds, pfrec);
|
||||
if (epfrec != pfrec) {
|
||||
@ -3793,27 +3814,28 @@ static void ssh_setup_portfwd(Ssh ssh, const Config *cfg)
|
||||
const char *err = pfd_addforward(host, dport,
|
||||
*saddr ? saddr : NULL,
|
||||
sport, ssh, &ssh->cfg,
|
||||
&pfrec->local);
|
||||
if (err) {
|
||||
logeventf(ssh, "Local port %s forward to %s"
|
||||
" failed: %s", sportdesc, dportdesc, err);
|
||||
} else {
|
||||
logeventf(ssh, "Local port %s forwarding to %s",
|
||||
sportdesc, dportdesc);
|
||||
}
|
||||
&pfrec->local,
|
||||
pfrec->addressfamily);
|
||||
|
||||
logeventf(ssh, "Local %sport %s forward to %s%s%s",
|
||||
pfrec->addressfamily == ADDRTYPE_IPV4 ? "IPv4 " :
|
||||
pfrec->addressfamily == ADDRTYPE_IPV6 ? "IPv6 " : "",
|
||||
sportdesc, dportdesc,
|
||||
err ? " failed: " : "", err);
|
||||
|
||||
sfree(dportdesc);
|
||||
} else if (type == 'D') {
|
||||
const char *err = pfd_addforward(NULL, -1,
|
||||
*saddr ? saddr : NULL,
|
||||
sport, ssh, &ssh->cfg,
|
||||
&pfrec->local);
|
||||
if (err) {
|
||||
logeventf(ssh, "Local port %s SOCKS dynamic forward"
|
||||
" setup failed: %s", sportdesc, err);
|
||||
} else {
|
||||
logeventf(ssh, "Local port %s doing SOCKS"
|
||||
" dynamic forwarding", sportdesc);
|
||||
}
|
||||
&pfrec->local,
|
||||
pfrec->addressfamily);
|
||||
|
||||
logeventf(ssh, "Local %sport %s SOCKS dynamic forward%s%s",
|
||||
pfrec->addressfamily == ADDRTYPE_IPV4 ? "IPv4 " :
|
||||
pfrec->addressfamily == ADDRTYPE_IPV6 ? "IPv6 " : "",
|
||||
sportdesc,
|
||||
err ? " setup failed: " : "", err);
|
||||
} else {
|
||||
struct ssh_rportfwd *pf;
|
||||
|
||||
@ -4045,7 +4067,7 @@ static void ssh1_msg_port_open(Ssh ssh, struct Packet *pktin)
|
||||
/* Remote side is trying to open a channel to talk to a
|
||||
* forwarded port. Give them back a local channel number. */
|
||||
struct ssh_channel *c;
|
||||
struct ssh_rportfwd pf;
|
||||
struct ssh_rportfwd pf, *pfp;
|
||||
int remoteid;
|
||||
int hostsize, port;
|
||||
char *host, buf[1024];
|
||||
@ -4062,8 +4084,9 @@ static void ssh1_msg_port_open(Ssh ssh, struct Packet *pktin)
|
||||
memcpy(pf.dhost, host, hostsize);
|
||||
pf.dhost[hostsize] = '\0';
|
||||
pf.dport = port;
|
||||
pfp = find234(ssh->rportfwds, &pf, NULL);
|
||||
|
||||
if (find234(ssh->rportfwds, &pf, NULL) == NULL) {
|
||||
if (pfp == NULL) {
|
||||
sprintf(buf, "Rejected remote port open request for %s:%d",
|
||||
pf.dhost, port);
|
||||
logevent(buf);
|
||||
@ -4074,7 +4097,7 @@ static void ssh1_msg_port_open(Ssh ssh, struct Packet *pktin)
|
||||
pf.dhost, port);
|
||||
logevent(buf);
|
||||
e = pfd_newconnect(&c->u.pfd.s, pf.dhost, port,
|
||||
c, &ssh->cfg);
|
||||
c, &ssh->cfg, pfp->pfrec->addressfamily);
|
||||
if (e != NULL) {
|
||||
char buf[256];
|
||||
sprintf(buf, "Port open failed: %s", e);
|
||||
@ -5799,7 +5822,8 @@ static void ssh2_msg_channel_open(Ssh ssh, struct Packet *pktin)
|
||||
const char *e = pfd_newconnect(&c->u.pfd.s,
|
||||
realpf->dhost,
|
||||
realpf->dport, c,
|
||||
&ssh->cfg);
|
||||
&ssh->cfg,
|
||||
realpf->pfrec->addressfamily);
|
||||
logeventf(ssh, "Attempting to forward remote port to "
|
||||
"%s:%d", realpf->dhost, realpf->dport);
|
||||
if (e != NULL) {
|
||||
|
6
ssh.h
6
ssh.h
@ -270,11 +270,13 @@ void ssh_send_port_open(void *channel, char *hostname, int port, char *org);
|
||||
|
||||
/* Exports from portfwd.c */
|
||||
extern const char *pfd_newconnect(Socket * s, char *hostname, int port,
|
||||
void *c, const Config *cfg);
|
||||
void *c, const Config *cfg,
|
||||
int addressfamily);
|
||||
/* desthost == NULL indicates dynamic (SOCKS) port forwarding */
|
||||
extern const char *pfd_addforward(char *desthost, int destport, char *srcaddr,
|
||||
int port, void *backhandle,
|
||||
const Config *cfg, void **sockdata);
|
||||
const Config *cfg, void **sockdata,
|
||||
int address_family);
|
||||
extern void pfd_close(Socket s);
|
||||
extern void pfd_terminate(void *sockdata);
|
||||
extern int pfd_send(Socket s, char *data, int len);
|
||||
|
7
telnet.c
7
telnet.c
@ -715,11 +715,14 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
|
||||
*/
|
||||
{
|
||||
char *buf;
|
||||
buf = dupprintf("Looking up host \"%s\"", host);
|
||||
buf = dupprintf("Looking up host \"%s\"%s", host,
|
||||
(cfg->addressfamily == ADDRTYPE_IPV4 ? " (IPv4)" :
|
||||
(cfg->addressfamily == ADDRTYPE_IPV6 ? " (IPv6)" :
|
||||
"")));
|
||||
logevent(telnet->frontend, buf);
|
||||
sfree(buf);
|
||||
}
|
||||
addr = name_lookup(host, port, realhost, &telnet->cfg);
|
||||
addr = name_lookup(host, port, realhost, &telnet->cfg, cfg->addressfamily);
|
||||
if ((err = sk_addr_error(addr)) != NULL) {
|
||||
sk_addr_free(addr);
|
||||
return err;
|
||||
|
63
unix/uxnet.c
63
unix/uxnet.c
@ -69,7 +69,7 @@ struct SockAddr_tag {
|
||||
* in this SockAddr structure.
|
||||
*/
|
||||
int family;
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
struct addrinfo *ai; /* Address IPv6 style. */
|
||||
#else
|
||||
unsigned long address; /* Address IPv4 style. */
|
||||
@ -125,10 +125,10 @@ const char *error_string(int error)
|
||||
return strerror(error);
|
||||
}
|
||||
|
||||
SockAddr sk_namelookup(const char *host, char **canonicalname)
|
||||
SockAddr sk_namelookup(const char *host, char **canonicalname, int address_family)
|
||||
{
|
||||
SockAddr ret = snew(struct SockAddr_tag);
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
struct addrinfo hints;
|
||||
int err;
|
||||
#else
|
||||
@ -143,9 +143,9 @@ SockAddr sk_namelookup(const char *host, char **canonicalname)
|
||||
*realhost = '\0';
|
||||
ret->error = NULL;
|
||||
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
hints.ai_flags = AI_CANONNAME;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_family = address_family;
|
||||
hints.ai_socktype = 0;
|
||||
hints.ai_protocol = 0;
|
||||
hints.ai_addrlen = 0;
|
||||
@ -219,7 +219,7 @@ void sk_getaddr(SockAddr addr, char *buf, int buflen)
|
||||
strncpy(buf, addr->hostname, buflen);
|
||||
buf[buflen-1] = '\0';
|
||||
} else {
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
if (getnameinfo(addr->ai->ai_addr, addr->ai->ai_addrlen, buf, buflen,
|
||||
NULL, 0, NI_NUMERICHOST) != 0) {
|
||||
buf[0] = '\0';
|
||||
@ -246,7 +246,7 @@ int sk_address_is_local(SockAddr addr)
|
||||
if (addr->family == AF_UNSPEC)
|
||||
return 0; /* we don't know; assume not */
|
||||
else {
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
if (addr->family == AF_INET)
|
||||
return ipv4_is_loopback(
|
||||
((struct sockaddr_in *)addr->ai->ai_addr)->sin_addr);
|
||||
@ -267,7 +267,7 @@ int sk_address_is_local(SockAddr addr)
|
||||
int sk_addrtype(SockAddr addr)
|
||||
{
|
||||
return (addr->family == AF_INET ? ADDRTYPE_IPV4 :
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
addr->family == AF_INET6 ? ADDRTYPE_IPV6 :
|
||||
#endif
|
||||
ADDRTYPE_NAME);
|
||||
@ -276,7 +276,7 @@ int sk_addrtype(SockAddr addr)
|
||||
void sk_addrcopy(SockAddr addr, char *buf)
|
||||
{
|
||||
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
if (addr->family == AF_INET)
|
||||
memcpy(buf, &((struct sockaddr_in *)addr->ai->ai_addr)->sin_addr,
|
||||
sizeof(struct in_addr));
|
||||
@ -297,7 +297,7 @@ void sk_addrcopy(SockAddr addr, char *buf)
|
||||
void sk_addr_free(SockAddr addr)
|
||||
{
|
||||
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
if (addr->ai != NULL)
|
||||
freeaddrinfo(addr->ai);
|
||||
#endif
|
||||
@ -381,7 +381,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||
int nodelay, int keepalive, Plug plug)
|
||||
{
|
||||
int s;
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
struct sockaddr_in6 a6;
|
||||
#endif
|
||||
struct sockaddr_in a;
|
||||
@ -448,7 +448,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||
|
||||
/* BSD IP stacks need sockaddr_in zeroed before filling in */
|
||||
memset(&a,'\0',sizeof(struct sockaddr_in));
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
memset(&a6,'\0',sizeof(struct sockaddr_in6));
|
||||
#endif
|
||||
|
||||
@ -459,7 +459,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||
while (1) {
|
||||
int retcode;
|
||||
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
if (addr->family == AF_INET6) {
|
||||
/* XXX use getaddrinfo to get a local address? */
|
||||
a6.sin6_family = AF_INET6;
|
||||
@ -501,7 +501,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||
* Connect to remote address.
|
||||
*/
|
||||
switch(addr->family) {
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
case AF_INET:
|
||||
/* XXX would be better to have got getaddrinfo() to fill in the port. */
|
||||
((struct sockaddr_in *)addr->ai->ai_addr)->sin_port =
|
||||
@ -564,13 +564,10 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||
return (Socket) ret;
|
||||
}
|
||||
|
||||
Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only)
|
||||
Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, int address_family)
|
||||
{
|
||||
int s;
|
||||
#ifdef IPV6
|
||||
#if 0
|
||||
struct sockaddr_in6 a6;
|
||||
#endif
|
||||
#ifndef NO_IPV6
|
||||
struct addrinfo hints, *ai;
|
||||
char portstr[6];
|
||||
#endif
|
||||
@ -597,10 +594,32 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only)
|
||||
ret->oobpending = FALSE;
|
||||
ret->listener = 1;
|
||||
|
||||
/*
|
||||
* Translate address_family from platform-independent constants
|
||||
* into local reality.
|
||||
*/
|
||||
address_family = (address_family == ADDRTYPE_IPV4 ? AF_INET :
|
||||
address_family == ADDRTYPE_IPV6 ? AF_INET6 : AF_UNSPEC);
|
||||
|
||||
#ifndef NO_IPV6
|
||||
/* Let's default to IPv6.
|
||||
* If the stack doesn't support IPv6, we will fall back to IPv4. */
|
||||
if (address_family == AF_UNSPEC) address_family = AF_INET6;
|
||||
#else
|
||||
/* No other choice, default to IPv4 */
|
||||
if (address_family == AF_UNSPEC) address_family = AF_INET;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Open socket.
|
||||
*/
|
||||
s = socket(AF_INET, SOCK_STREAM, 0);
|
||||
s = socket(address_family, SOCK_STREAM, 0);
|
||||
|
||||
/* If the host doesn't support IPv6 try fallback to IPv4. */
|
||||
if (s < 0 && address_family == AF_INET6) {
|
||||
address_family = AF_INET;
|
||||
s = socket(address_family, SOCK_STREAM, 0);
|
||||
}
|
||||
ret->s = s;
|
||||
|
||||
if (s < 0) {
|
||||
@ -614,12 +633,12 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only)
|
||||
|
||||
/* BSD IP stacks need sockaddr_in zeroed before filling in */
|
||||
memset(&a,'\0',sizeof(struct sockaddr_in));
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
#if 0
|
||||
memset(&a6,'\0',sizeof(struct sockaddr_in6));
|
||||
#endif
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_family = address_family;
|
||||
hints.ai_socktype = 0;
|
||||
hints.ai_protocol = 0;
|
||||
hints.ai_addrlen = 0;
|
||||
|
@ -227,6 +227,7 @@ static void usage(void)
|
||||
printf(" -A -a enable / disable agent forwarding\n");
|
||||
printf(" -t -T enable / disable pty allocation\n");
|
||||
printf(" -1 -2 force use of particular protocol version\n");
|
||||
printf(" -4 -6 force use of IPv4 or IPv6\n");
|
||||
printf(" -C enable compression\n");
|
||||
printf(" -i key private key file for authentication\n");
|
||||
printf(" -s remote command is an SSH subsystem (SSH-2 only)\n");
|
||||
|
@ -49,7 +49,7 @@ BEGIN
|
||||
END
|
||||
|
||||
/* Accelerators used: aco */
|
||||
IDD_MAINBOX DIALOG DISCARDABLE 0, 0, 280, 252
|
||||
IDD_MAINBOX DIALOG DISCARDABLE 0, 0, 300, 252
|
||||
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "PuTTY Configuration"
|
||||
FONT 8, "MS Shell Dlg"
|
||||
|
@ -300,7 +300,7 @@ static void create_controls(HWND hwnd, char *path)
|
||||
* Otherwise, we're creating the controls for a particular
|
||||
* panel.
|
||||
*/
|
||||
ctlposinit(&cp, hwnd, 80, 3, 13);
|
||||
ctlposinit(&cp, hwnd, 100, 3, 13);
|
||||
wc = &ctrls_panel;
|
||||
base_id = IDCX_PANELBASE;
|
||||
}
|
||||
@ -361,7 +361,7 @@ static int CALLBACK GenericMainDlgProc(HWND hwnd, UINT msg,
|
||||
HWND tvstatic;
|
||||
|
||||
r.left = 3;
|
||||
r.right = r.left + 75;
|
||||
r.right = r.left + 95;
|
||||
r.top = 3;
|
||||
r.bottom = r.top + 10;
|
||||
MapDialogRect(hwnd, &r);
|
||||
@ -375,7 +375,7 @@ static int CALLBACK GenericMainDlgProc(HWND hwnd, UINT msg,
|
||||
SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
|
||||
|
||||
r.left = 3;
|
||||
r.right = r.left + 75;
|
||||
r.right = r.left + 95;
|
||||
r.top = 13;
|
||||
r.bottom = r.top + 219;
|
||||
MapDialogRect(hwnd, &r);
|
||||
|
@ -542,9 +542,20 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
||||
}
|
||||
|
||||
/*
|
||||
* Trim a colon suffix off the hostname if it's there.
|
||||
* Trim a colon suffix off the hostname if it's there. In
|
||||
* order to protect IPv6 address literals against this
|
||||
* treatment, we do not do this if there's _more_ than one
|
||||
* colon.
|
||||
*/
|
||||
cfg.host[strcspn(cfg.host, ":")] = '\0';
|
||||
{
|
||||
char *c = strchr(cfg.host, ':');
|
||||
|
||||
if (c) {
|
||||
char *d = strchr(c+1, ':');
|
||||
if (!d)
|
||||
*c = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove any remaining whitespace from the hostname.
|
||||
|
@ -66,6 +66,7 @@
|
||||
#define WINHELP_CTX_connection_username "connection.username"
|
||||
#define WINHELP_CTX_connection_keepalive "connection.keepalive"
|
||||
#define WINHELP_CTX_connection_nodelay "connection.nodelay"
|
||||
#define WINHELP_CTX_connection_ipversion "connection.ipversion"
|
||||
#define WINHELP_CTX_connection_tcpkeepalive "connection.tcpkeepalive"
|
||||
#define WINHELP_CTX_proxy_type "proxy.type"
|
||||
#define WINHELP_CTX_proxy_main "proxy.main"
|
||||
@ -112,6 +113,7 @@
|
||||
#define WINHELP_CTX_ssh_tunnels_x11auth "ssh.tunnels.x11auth"
|
||||
#define WINHELP_CTX_ssh_tunnels_portfwd "ssh.tunnels.portfwd"
|
||||
#define WINHELP_CTX_ssh_tunnels_portfwd_localhost "ssh.tunnels.portfwd.localhost"
|
||||
#define WINHELP_CTX_ssh_tunnels_portfwd_ipversion "ssh.tunnels.portfwd.ipversion"
|
||||
#define WINHELP_CTX_ssh_bugs_ignore1 "ssh.bugs.ignore1"
|
||||
#define WINHELP_CTX_ssh_bugs_plainpw1 "ssh.bugs.plainpw1"
|
||||
#define WINHELP_CTX_ssh_bugs_rsa1 "ssh.bugs.rsa1"
|
||||
|
@ -50,8 +50,14 @@ char *get_username(void)
|
||||
char *user;
|
||||
|
||||
namelen = 0;
|
||||
if (GetUserName(NULL, &namelen) == FALSE)
|
||||
return NULL;
|
||||
if (GetUserName(NULL, &namelen) == FALSE) {
|
||||
/*
|
||||
* Apparently this doesn't work at least on Windows XP SP2.
|
||||
* Thus assume a maximum of 256. It will fail again if it
|
||||
* doesn't fit.
|
||||
*/
|
||||
namelen = 256;
|
||||
}
|
||||
|
||||
user = snewn(namelen, char);
|
||||
GetUserName(user, &namelen);
|
||||
|
212
windows/winnet.c
212
windows/winnet.c
@ -1,43 +1,10 @@
|
||||
/*
|
||||
* Windows networking abstraction.
|
||||
*
|
||||
* Due to this clean abstraction it was possible
|
||||
* to easily implement IPv6 support :)
|
||||
*
|
||||
* IPv6 patch 1 (27 October 2000) Jeroen Massar <jeroen@unfix.org>
|
||||
* - Preliminary hacked IPv6 support.
|
||||
* - Connecting to IPv6 address (eg fec0:4242:4242:100:2d0:b7ff:fe8f:5d42) works.
|
||||
* - Connecting to IPv6 hostname (eg heaven.ipv6.unfix.org) works.
|
||||
* - Compiles as either IPv4 or IPv6.
|
||||
*
|
||||
* IPv6 patch 2 (29 October 2000) Jeroen Massar <jeroen@unfix.org>
|
||||
* - When compiled as IPv6 it also allows connecting to IPv4 hosts.
|
||||
* - Added some more documentation.
|
||||
*
|
||||
* IPv6 patch 3 (18 November 2000) Jeroen Massar <jeroen@unfix.org>
|
||||
* - It now supports dynamically loading the IPv6 resolver dll's.
|
||||
* This way we should be able to distribute one (1) binary
|
||||
* which supports both IPv4 and IPv6.
|
||||
* - getaddrinfo() and getnameinfo() are loaded dynamicaly if possible.
|
||||
* - in6addr_any is defined in this file so we don't need to link to wship6.lib
|
||||
* - The patch is now more unified so that we can still
|
||||
* remove all IPv6 support by undef'ing IPV6.
|
||||
* But where it fallsback to IPv4 it uses the IPv4 code which is already in place...
|
||||
* - Canonical name resolving works.
|
||||
*
|
||||
* IPv6 patch 4 (07 January 2001) Jeroen Massar <jeroen@unfix.org>
|
||||
* - patch against CVS of today, will be submitted to the bugs list
|
||||
* as a 'cvs diff -u' on Simon's request...
|
||||
*
|
||||
* For the IPv6 code in here I am indebted to Jeroen Massar and
|
||||
* unfix.org.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define IPV6 to have IPv6 on-the-fly-loading support.
|
||||
* This means that one doesn't have to have an IPv6 stack to use it.
|
||||
* But if an IPv6 stack is found it is used with a fallback to IPv4.
|
||||
*/
|
||||
/* #define IPV6 1 */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
@ -48,8 +15,10 @@
|
||||
#include "tree234.h"
|
||||
|
||||
#include <ws2tcpip.h>
|
||||
#ifdef IPV6
|
||||
#include <tpipv6.h>
|
||||
|
||||
#ifndef NO_IPV6
|
||||
const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
|
||||
const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
|
||||
#endif
|
||||
|
||||
#define ipv4_is_loopback(addr) \
|
||||
@ -92,11 +61,16 @@ struct SockAddr_tag {
|
||||
* 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.
|
||||
* The hostname field is also used when the hostname has both
|
||||
* an IPv6 and IPv4 address and the IPv6 connection attempt
|
||||
* fails. We then try the IPv4 address.
|
||||
* This 'family' should become an option in the GUI and
|
||||
* on the commandline for selecting a default protocol.
|
||||
*/
|
||||
int family;
|
||||
unsigned long address; /* Address IPv4 style. */
|
||||
#ifdef IPV6
|
||||
struct addrinfo *ai; /* Address IPv6 style. */
|
||||
#ifndef NO_IPV6
|
||||
struct addrinfo *ai; /* Address AF-independent (IPv4+IPv6) style. */
|
||||
#endif
|
||||
char hostname[512]; /* Store an unresolved host name. */
|
||||
};
|
||||
@ -325,7 +299,8 @@ char *winsock_error_string(int error)
|
||||
}
|
||||
}
|
||||
|
||||
SockAddr sk_namelookup(const char *host, char **canonicalname)
|
||||
SockAddr sk_namelookup(const char *host, char **canonicalname,
|
||||
int address_family)
|
||||
{
|
||||
SockAddr ret = snew(struct SockAddr_tag);
|
||||
unsigned long a;
|
||||
@ -334,11 +309,15 @@ SockAddr sk_namelookup(const char *host, char **canonicalname)
|
||||
|
||||
/* Clear the structure and default to IPv4. */
|
||||
memset(ret, 0, sizeof(struct SockAddr_tag));
|
||||
ret->family = 0; /* We set this one when we have resolved the host. */
|
||||
ret->family = (address_family == ADDRTYPE_IPV4 ? AF_INET :
|
||||
#ifndef NO_IPV6
|
||||
address_family == ADDRTYPE_IPV6 ? AF_INET6 :
|
||||
#endif
|
||||
AF_UNSPEC);
|
||||
*realhost = '\0';
|
||||
|
||||
if ((a = p_inet_addr(host)) == (unsigned long) INADDR_NONE) {
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
|
||||
/* Try to get the getaddrinfo() function from wship6.dll */
|
||||
/* This way one doesn't need to have IPv6 dll's to use PuTTY and
|
||||
@ -356,56 +335,41 @@ SockAddr sk_namelookup(const char *host, char **canonicalname)
|
||||
"getaddrinfo");
|
||||
|
||||
/*
|
||||
* Use fGetAddrInfo when it's available (which usually also
|
||||
* means IPv6 is installed...)
|
||||
* Use fGetAddrInfo when it's available
|
||||
*/
|
||||
if (fGetAddrInfo) {
|
||||
/*debug(("Resolving \"%s\" with getaddrinfo() (IPv4+IPv6 capable)...\n", host)); */
|
||||
if (fGetAddrInfo(host, NULL, NULL, &ret->ai) == 0)
|
||||
ret->family = ret->ai->ai_family;
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = ret->family;
|
||||
if (fGetAddrInfo(host, NULL, &hints, &ret->ai) == 0)
|
||||
ret->family = ret->ai->ai_family;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
/*
|
||||
* Otherwise use the IPv4-only gethostbyname...
|
||||
* (NOTE: we don't use gethostbyname as a
|
||||
* fallback!)
|
||||
* (NOTE: we don't use gethostbyname as a fallback!)
|
||||
*/
|
||||
if (ret->family == 0) {
|
||||
/*debug(("Resolving \"%s\" with gethostbyname() (IPv4 only)...\n", host)); */
|
||||
if ( (h = p_gethostbyname(host)) )
|
||||
ret->family = AF_INET;
|
||||
}
|
||||
}
|
||||
/*debug(("Done resolving...(family is %d) AF_INET = %d, AF_INET6 = %d\n", ret->family, AF_INET, AF_INET6)); */
|
||||
|
||||
if (ret->family == 0) {
|
||||
if (ret->family == AF_UNSPEC) {
|
||||
DWORD err = p_WSAGetLastError();
|
||||
ret->error = (err == WSAENETDOWN ? "Network is down" :
|
||||
err ==
|
||||
WSAHOST_NOT_FOUND ? "Host does not exist" : err
|
||||
== WSATRY_AGAIN ? "Host not found" :
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
fGetAddrInfo ? "getaddrinfo: unknown error" :
|
||||
#endif
|
||||
"gethostbyname: unknown error");
|
||||
#ifdef DEBUG
|
||||
{
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||
FORMAT_MESSAGE_FROM_SYSTEM |
|
||||
FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err,
|
||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR) & lpMsgBuf, 0, NULL);
|
||||
/*debug(("Error %ld: %s (h=%lx)\n", err, lpMsgBuf, h)); */
|
||||
/* Free the buffer. */
|
||||
LocalFree(lpMsgBuf);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
ret->error = NULL;
|
||||
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
/* If we got an address info use that... */
|
||||
if (ret->ai) {
|
||||
typedef int (CALLBACK * FGETNAMEINFO)
|
||||
@ -445,7 +409,7 @@ SockAddr sk_namelookup(const char *host, char **canonicalname)
|
||||
strncpy(realhost, h->h_name, sizeof(realhost));
|
||||
}
|
||||
}
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
FreeLibrary(dllWSHIP6);
|
||||
#endif
|
||||
} else {
|
||||
@ -475,9 +439,30 @@ SockAddr sk_nonamelookup(const char *host)
|
||||
|
||||
void sk_getaddr(SockAddr addr, char *buf, int buflen)
|
||||
{
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
if (addr->family == AF_INET6) {
|
||||
FIXME; /* I don't know how to get a text form of an IPv6 address. */
|
||||
/* Try to get the WSAAddressToStringA() function from wship6.dll */
|
||||
/* This way one doesn't need to have IPv6 dll's to use PuTTY and
|
||||
* it will fallback to IPv4. */
|
||||
typedef int (CALLBACK * FADDRTOSTR) (LPSOCKADDR lpsaAddress,
|
||||
DWORD dwAddressLength,
|
||||
LPWSAPROTOCOL_INFO lpProtocolInfo,
|
||||
OUT LPTSTR lpszAddressString,
|
||||
IN OUT LPDWORD lpdwAddressStringLength
|
||||
);
|
||||
FADDRTOSTR fAddrToStr = NULL;
|
||||
|
||||
HINSTANCE dllWS2 = LoadLibrary("ws2_32.dll");
|
||||
if (dllWS2) {
|
||||
fAddrToStr = (FADDRTOSTR)GetProcAddress(dllWS2,
|
||||
"WSAAddressToStringA");
|
||||
if (fAddrToStr) {
|
||||
fAddrToStr(addr->ai->ai_addr, addr->ai->ai_addrlen,
|
||||
NULL, buf, &buflen);
|
||||
}
|
||||
else strncpy(buf, "IPv6", buflen);
|
||||
FreeLibrary(dllWS2);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (addr->family == AF_INET) {
|
||||
@ -486,7 +471,6 @@ void sk_getaddr(SockAddr addr, char *buf, int buflen)
|
||||
strncpy(buf, p_inet_ntoa(a), buflen);
|
||||
buf[buflen-1] = '\0';
|
||||
} else {
|
||||
assert(addr->family == AF_UNSPEC);
|
||||
strncpy(buf, addr->hostname, buflen);
|
||||
buf[buflen-1] = '\0';
|
||||
}
|
||||
@ -530,9 +514,9 @@ static int ipv4_is_local_addr(struct in_addr addr)
|
||||
|
||||
int sk_address_is_local(SockAddr addr)
|
||||
{
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
if (addr->family == AF_INET6) {
|
||||
FIXME; /* someone who can compile for IPV6 had better do this bit */
|
||||
return IN6_IS_ADDR_LOOPBACK((const struct in6_addr *)addr->ai->ai_addr);
|
||||
} else
|
||||
#endif
|
||||
if (addr->family == AF_INET) {
|
||||
@ -548,7 +532,7 @@ int sk_address_is_local(SockAddr addr)
|
||||
int sk_addrtype(SockAddr addr)
|
||||
{
|
||||
return (addr->family == AF_INET ? ADDRTYPE_IPV4 :
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
addr->family == AF_INET6 ? ADDRTYPE_IPV6 :
|
||||
#endif
|
||||
ADDRTYPE_NAME);
|
||||
@ -557,7 +541,7 @@ int sk_addrtype(SockAddr addr)
|
||||
void sk_addrcopy(SockAddr addr, char *buf)
|
||||
{
|
||||
assert(addr->family != AF_UNSPEC);
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
if (addr->family == AF_INET6) {
|
||||
memcpy(buf, (char*) addr->ai, 16);
|
||||
} else
|
||||
@ -673,7 +657,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||
};
|
||||
|
||||
SOCKET s;
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
SOCKADDR_IN6 a6;
|
||||
#endif
|
||||
SOCKADDR_IN a;
|
||||
@ -701,7 +685,14 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||
/*
|
||||
* Open socket.
|
||||
*/
|
||||
assert(addr->family != AF_UNSPEC);
|
||||
#ifndef NO_IPV6
|
||||
/* Let's default to IPv6, this shouldn't hurt anybody
|
||||
* If the stack supports IPv6 it will also allow IPv4 connections. */
|
||||
if (addr->family == AF_UNSPEC) addr->family = AF_INET6;
|
||||
#else
|
||||
/* No other choice, default to IPv4 */
|
||||
if (addr->family == AF_UNSPEC) addr->family = AF_INET;
|
||||
#endif
|
||||
s = p_socket(addr->family, SOCK_STREAM, 0);
|
||||
ret->s = s;
|
||||
|
||||
@ -739,11 +730,11 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||
while (1) {
|
||||
int retcode;
|
||||
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
if (addr->family == AF_INET6) {
|
||||
memset(&a6, 0, sizeof(a6));
|
||||
a6.sin6_family = AF_INET6;
|
||||
/*a6.sin6_addr = in6addr_any; *//* == 0 */
|
||||
/*a6.sin6_addr = in6addr_any; */ /* == 0 done by memset() */
|
||||
a6.sin6_port = p_htons(localport);
|
||||
} else
|
||||
#endif
|
||||
@ -752,7 +743,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||
a.sin_addr.s_addr = p_htonl(INADDR_ANY);
|
||||
a.sin_port = p_htons(localport);
|
||||
}
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
retcode = p_bind(s, (addr->family == AF_INET6 ?
|
||||
(struct sockaddr *) &a6 :
|
||||
(struct sockaddr *) &a),
|
||||
@ -785,7 +776,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||
/*
|
||||
* Connect to remote address.
|
||||
*/
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
if (addr->family == AF_INET6) {
|
||||
memset(&a, 0, sizeof(a));
|
||||
a6.sin6_family = AF_INET6;
|
||||
@ -809,7 +800,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||
}
|
||||
|
||||
if ((
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
p_connect(s, ((addr->family == AF_INET6) ?
|
||||
(struct sockaddr *) &a6 : (struct sockaddr *) &a),
|
||||
(addr->family == AF_INET6) ? sizeof(a6) : sizeof(a))
|
||||
@ -844,7 +835,8 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||
return (Socket) ret;
|
||||
}
|
||||
|
||||
Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only)
|
||||
Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only,
|
||||
int address_family)
|
||||
{
|
||||
static const struct socket_function_table fn_table = {
|
||||
sk_tcp_plug,
|
||||
@ -859,10 +851,11 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only)
|
||||
};
|
||||
|
||||
SOCKET s;
|
||||
#ifdef IPV6
|
||||
#ifndef NO_IPV6
|
||||
SOCKADDR_IN6 a6;
|
||||
#endif
|
||||
SOCKADDR_IN a;
|
||||
|
||||
DWORD err;
|
||||
char *errstr;
|
||||
Actual_Socket ret;
|
||||
@ -884,10 +877,29 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only)
|
||||
ret->localhost_only = local_host_only;
|
||||
ret->pending_error = 0;
|
||||
|
||||
/*
|
||||
* Translate address_family from platform-independent constants
|
||||
* into local reality.
|
||||
*/
|
||||
address_family = (address_family == ADDRTYPE_IPV4 ? AF_INET :
|
||||
#ifndef NO_IPV6
|
||||
address_family == ADDRTYPE_IPV6 ? AF_INET6 :
|
||||
#endif
|
||||
AF_UNSPEC);
|
||||
|
||||
#ifndef NO_IPV6
|
||||
/* Let's default to IPv6, this shouldn't hurt anybody
|
||||
* If the stack supports IPv6 it will also allow IPv4 connections. */
|
||||
if (address_family == AF_UNSPEC) address_family = AF_INET6;
|
||||
#else
|
||||
/* No other choice, default to IPv4 */
|
||||
if (address_family == AF_UNSPEC) address_family = AF_INET;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Open socket.
|
||||
*/
|
||||
s = p_socket(AF_INET, SOCK_STREAM, 0);
|
||||
s = p_socket(address_family, SOCK_STREAM, 0);
|
||||
ret->s = s;
|
||||
|
||||
if (s == INVALID_SOCKET) {
|
||||
@ -900,12 +912,15 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only)
|
||||
|
||||
p_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
|
||||
|
||||
#ifdef IPV6
|
||||
if (addr->family == AF_INET6) {
|
||||
#ifndef NO_IPV6
|
||||
if (address_family == AF_INET6) {
|
||||
memset(&a6, 0, sizeof(a6));
|
||||
a6.sin6_family = AF_INET6;
|
||||
/* FIXME: srcaddr is ignored for IPv6, because I (SGT) don't
|
||||
* know how to do it. :-) */
|
||||
* know how to do it. :-)
|
||||
* (jeroen:) saddr is specified as an address.. eg 2001:db8::1
|
||||
* Thus we need either a parser that understands [2001:db8::1]:80
|
||||
* style addresses and/or enhance this to understand hostnames too. */
|
||||
if (local_host_only)
|
||||
a6.sin6_addr = in6addr_loopback;
|
||||
else
|
||||
@ -942,11 +957,11 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only)
|
||||
|
||||
a.sin_port = p_htons((short)port);
|
||||
}
|
||||
#ifdef IPV6
|
||||
retcode = p_bind(s, (addr->family == AF_INET6 ?
|
||||
#ifndef NO_IPV6
|
||||
retcode = p_bind(s, (address_family == AF_INET6 ?
|
||||
(struct sockaddr *) &a6 :
|
||||
(struct sockaddr *) &a),
|
||||
(addr->family ==
|
||||
(address_family ==
|
||||
AF_INET6 ? sizeof(a6) : sizeof(a)));
|
||||
#else
|
||||
retcode = p_bind(s, (struct sockaddr *) &a, sizeof(a));
|
||||
@ -1229,11 +1244,15 @@ int select_result(WPARAM wParam, LPARAM lParam)
|
||||
return open;
|
||||
case FD_ACCEPT:
|
||||
{
|
||||
#ifdef NO_IPV6
|
||||
struct sockaddr_in isa;
|
||||
int addrlen = sizeof(struct sockaddr_in);
|
||||
#else
|
||||
struct sockaddr_storage isa;
|
||||
#endif
|
||||
int addrlen = sizeof(isa);
|
||||
SOCKET t; /* socket of connection */
|
||||
|
||||
memset(&isa, 0, sizeof(struct sockaddr_in));
|
||||
memset(&isa, 0, sizeof(isa));
|
||||
err = 0;
|
||||
t = p_accept(s->s,(struct sockaddr *)&isa,&addrlen);
|
||||
if (t == INVALID_SOCKET)
|
||||
@ -1242,8 +1261,13 @@ int select_result(WPARAM wParam, LPARAM lParam)
|
||||
if (err == WSATRY_AGAIN)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef NO_IPV6
|
||||
if (isa.ss_family == AF_INET &&
|
||||
s->localhost_only &&
|
||||
!ipv4_is_local_addr(((struct sockaddr_in *)&isa)->sin_addr)) {
|
||||
#else
|
||||
if (s->localhost_only && !ipv4_is_local_addr(isa.sin_addr)) {
|
||||
#endif
|
||||
p_closesocket(t); /* dodgy WinSock let nonlocal through */
|
||||
} else if (plug_accepting(s->plug, (void*)t)) {
|
||||
p_closesocket(t); /* denied or error */
|
||||
|
@ -231,6 +231,7 @@ static void usage(void)
|
||||
printf(" -A -a enable / disable agent forwarding\n");
|
||||
printf(" -t -T enable / disable pty allocation\n");
|
||||
printf(" -1 -2 force use of particular protocol version\n");
|
||||
printf(" -4 -6 force use of IPv4 or IPv6\n");
|
||||
printf(" -C enable compression\n");
|
||||
printf(" -i key private key file for authentication\n");
|
||||
printf(" -s remote command is an SSH subsystem (SSH-2 only)\n");
|
||||
|
2
x11fwd.c
2
x11fwd.c
@ -301,7 +301,7 @@ const char *x11_init(Socket * s, char *display, void *c, void *auth,
|
||||
/*
|
||||
* Try to find host.
|
||||
*/
|
||||
addr = name_lookup(host, port, &dummy_realhost, cfg);
|
||||
addr = name_lookup(host, port, &dummy_realhost, cfg, ADDRTYPE_UNSPEC);
|
||||
if ((err = sk_addr_error(addr)) != NULL) {
|
||||
sk_addr_free(addr);
|
||||
return err;
|
||||
|
Loading…
Reference in New Issue
Block a user