mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-03-22 06:38:37 -05: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
|
# build, since at the time of writing this <multimon.h> is
|
||||||
# known not to be available in Cygwin.
|
# 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
|
# - COMPAT=/DMSVC4
|
||||||
# - RCFL=/DMSVC4
|
# - RCFL=/DMSVC4
|
||||||
# Makes a couple of minor changes so that PuTTY compiles using
|
# 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);
|
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 */
|
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 {
|
struct portfwd_data {
|
||||||
union control *addbutton, *rembutton, *listbox;
|
union control *addbutton, *rembutton, *listbox;
|
||||||
union control *sourcebox, *destbox, *direction;
|
union control *sourcebox, *destbox, *direction;
|
||||||
|
union control *addressfamily;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void portfwd_handler(union control *ctrl, void *dlg,
|
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.
|
* Default is Local.
|
||||||
*/
|
*/
|
||||||
dlg_radiobutton_set(ctrl, dlg, 0);
|
dlg_radiobutton_set(ctrl, dlg, 0);
|
||||||
|
} else if (ctrl == pfd->addressfamily) {
|
||||||
|
dlg_radiobutton_set(ctrl, dlg, 0);
|
||||||
}
|
}
|
||||||
} else if (event == EVENT_ACTION) {
|
} else if (event == EVENT_ACTION) {
|
||||||
if (ctrl == pfd->addbutton) {
|
if (ctrl == pfd->addbutton) {
|
||||||
char str[sizeof(cfg->portfwd)];
|
char str[sizeof(cfg->portfwd)];
|
||||||
char *p;
|
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)
|
if (whichbutton == 0)
|
||||||
str[0] = 'L';
|
type = 'L';
|
||||||
else if (whichbutton == 1)
|
else if (whichbutton == 1)
|
||||||
str[0] = 'R';
|
type = 'R';
|
||||||
else
|
else
|
||||||
str[0] = 'D';
|
type = 'D';
|
||||||
dlg_editbox_get(pfd->sourcebox, dlg, str+1, sizeof(str) - 2);
|
str[i++] = type;
|
||||||
if (!str[1]) {
|
|
||||||
|
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");
|
dlg_error_msg(dlg, "You need to specify a source port number");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
p = str + strlen(str);
|
p = str + strlen(str);
|
||||||
if (str[0] != 'D') {
|
if (type != 'D') {
|
||||||
*p++ = '\t';
|
*p++ = '\t';
|
||||||
dlg_editbox_get(pfd->destbox, dlg, p,
|
dlg_editbox_get(pfd->destbox, dlg, p,
|
||||||
sizeof(str)-1 - (p - str));
|
sizeof(str)-1 - (p - str));
|
||||||
@ -1344,9 +1359,59 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
|
|||||||
if (protocol >= 0) {
|
if (protocol >= 0) {
|
||||||
ctrl_settitle(b, "Connection", "Options controlling the connection");
|
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) {
|
if (!midsession) {
|
||||||
s = ctrl_getset(b, "Connection", "data",
|
s = ctrl_getset(b, "Connection", "tcp",
|
||||||
"Data to send to the server");
|
"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,
|
ctrl_editbox(s, "Terminal-type string", 't', 50,
|
||||||
HELPCTX(connection_termtype),
|
HELPCTX(connection_termtype),
|
||||||
dlg_stdeditbox_handler, I(offsetof(Config,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),
|
HELPCTX(connection_termspeed),
|
||||||
dlg_stdeditbox_handler, I(offsetof(Config,termspeed)),
|
dlg_stdeditbox_handler, I(offsetof(Config,termspeed)),
|
||||||
I(sizeof(((Config *)0)->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);
|
ctrl_columns(s, 2, 80, 20);
|
||||||
ed = (struct environ_data *)
|
ed = (struct environ_data *)
|
||||||
ctrl_alloc(b, sizeof(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;
|
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) {
|
if (!midsession) {
|
||||||
@ -1664,15 +1706,14 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
|
|||||||
dlg_stdfilesel_handler, I(offsetof(Config, keyfile)));
|
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) {
|
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',
|
ctrl_checkbox(s, "Enable X11 forwarding", 'e',
|
||||||
HELPCTX(ssh_tunnels_x11),
|
HELPCTX(ssh_tunnels_x11),
|
||||||
dlg_stdcheckbox_handler,I(offsetof(Config,x11_forward)));
|
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);
|
"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",
|
s = ctrl_getset(b, "Connection/SSH/Tunnels", "portfwd",
|
||||||
"Port forwarding");
|
"Port forwarding");
|
||||||
ctrl_checkbox(s, "Local ports accept connections from other hosts",'t',
|
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),
|
"Remote", 'm', P(NULL),
|
||||||
"Dynamic", 'y', P(NULL),
|
"Dynamic", 'y', P(NULL),
|
||||||
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_tabdelay(s, pfd->addbutton);
|
||||||
ctrl_columns(s, 1, 100);
|
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
|
The Connection panel allows you to configure options that apply to
|
||||||
more than one type of connection.
|
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
|
\S{config-keepalive} Using keepalives to prevent disconnection
|
||||||
|
|
||||||
\cfg{winhelp-topic}{connection.keepalive}
|
\cfg{winhelp-topic}{connection.keepalive}
|
||||||
@ -1678,6 +1598,111 @@ are terminated than for keeping a connection alive.
|
|||||||
|
|
||||||
TCP keepalives are disabled by default.
|
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
|
\H{config-proxy} The Proxy panel
|
||||||
|
|
||||||
\cfg{winhelp-topic}{proxy.main}
|
\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}).
|
This key must be in PuTTY's native format (\c{*.PPK}).
|
||||||
|
|
||||||
\H{config-ssh-tunnels} The Tunnels panel
|
\H{config-ssh-x11} The X11 panel
|
||||||
|
|
||||||
The Tunnels panel allows you to configure tunnelling of other
|
|
||||||
connection types through an SSH connection.
|
|
||||||
|
|
||||||
\S{config-ssh-x11} X11 forwarding
|
|
||||||
|
|
||||||
\cfg{winhelp-topic}{ssh.tunnels.x11}
|
\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
|
If your server lets you run X Window System applications, X11
|
||||||
forwarding allows you to securely give those applications access to
|
forwarding allows you to securely give those applications access to
|
||||||
a local X display on your PC.
|
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
|
See \k{using-x-forwarding} for more information about X11
|
||||||
forwarding.
|
forwarding.
|
||||||
|
|
||||||
\S2{config-ssh-x11auth} Remote X11 authentication
|
\S{config-ssh-x11auth} Remote X11 authentication
|
||||||
|
|
||||||
\cfg{winhelp-topic}{ssh.tunnels.x11auth}
|
\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
|
PuTTY's default is \cw{MIT-MAGIC-COOKIE-1}. If you change it, you
|
||||||
should be sure you know what you're doing.
|
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}
|
\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
|
Port forwarding allows you to tunnel other types of network
|
||||||
connection down an SSH session. See \k{using-port-forwarding} for a
|
connection down an SSH session. See \k{using-port-forwarding} for a
|
||||||
general discussion of port forwarding and how it works.
|
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
|
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).
|
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
|
\H{config-ssh-bugs} The Bugs panel
|
||||||
|
|
||||||
Not all SSH servers work properly. Various existing servers have
|
Not all SSH servers work properly. Various existing servers have
|
||||||
|
@ -68,6 +68,7 @@ use Plink:
|
|||||||
\c -A -a enable / disable agent forwarding
|
\c -A -a enable / disable agent forwarding
|
||||||
\c -t -T enable / disable pty allocation
|
\c -t -T enable / disable pty allocation
|
||||||
\c -1 -2 force use of particular protocol version
|
\c -1 -2 force use of particular protocol version
|
||||||
|
\c -4 -6 force use of IPv4 or IPv6
|
||||||
\c -C enable compression
|
\c -C enable compression
|
||||||
\c -i key private key file for authentication
|
\c -i key private key file for authentication
|
||||||
\c -s remote command is an SSH subsystem (SSH-2 only)
|
\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 -l user connect with specified username
|
||||||
\c -pw passw login with specified password
|
\c -pw passw login with specified password
|
||||||
\c -1 -2 force use of particular SSH protocol version
|
\c -1 -2 force use of particular SSH protocol version
|
||||||
|
\c -4 -6 force use of IPv4 or IPv6
|
||||||
\c -C enable compression
|
\c -C enable compression
|
||||||
\c -i key private key file for authentication
|
\c -i key private key file for authentication
|
||||||
\c -batch disable all interactive prompts
|
\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
|
protocol version as \q{1 only} or \q{2 only} in the SSH panel of the
|
||||||
PuTTY configuration box (see \k{config-ssh-prot}).
|
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}
|
\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
|
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
|
* Network functions exported to the world. These choose whether to call
|
||||||
* MacTCP or OpenTransport and behave accordingly.
|
* 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)
|
if (stack != NULL)
|
||||||
@ -137,7 +137,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
|||||||
return NULL;
|
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)
|
if (stack != NULL)
|
||||||
|
@ -82,9 +82,9 @@ Socket new_connection(SockAddr addr, char *hostname,
|
|||||||
int oobinline, int nodelay, int keepalive,
|
int oobinline, int nodelay, int keepalive,
|
||||||
Plug plug, const Config *cfg);
|
Plug plug, const Config *cfg);
|
||||||
Socket new_listener(char *srcaddr, int port, Plug plug, int local_host_only,
|
Socket new_listener(char *srcaddr, int port, Plug plug, int local_host_only,
|
||||||
const Config *cfg);
|
const Config *cfg, int addressfamily);
|
||||||
SockAddr name_lookup(char *host, int port, char **canonicalname,
|
SockAddr name_lookup(char *host, int port, char **canonicalname,
|
||||||
const Config *cfg);
|
const Config *cfg, int addressfamily);
|
||||||
|
|
||||||
/* platform-dependent callback from new_connection() */
|
/* platform-dependent callback from new_connection() */
|
||||||
/* (same caveat about addr as 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_init(void); /* called once at program startup */
|
||||||
void sk_cleanup(void); /* called just before program exit */
|
void sk_cleanup(void); /* called just before program exit */
|
||||||
|
|
||||||
SockAddr sk_namelookup(const char *host, char **canonicalname);
|
SockAddr sk_namelookup(const char *host, char **canonicalname, int address_family);
|
||||||
SockAddr sk_nonamelookup(const char *host);
|
SockAddr sk_nonamelookup(const char *host);
|
||||||
void sk_getaddr(SockAddr addr, char *buf, int buflen);
|
void sk_getaddr(SockAddr addr, char *buf, int buflen);
|
||||||
int sk_hostname_is_local(char *name);
|
int sk_hostname_is_local(char *name);
|
||||||
int sk_address_is_local(SockAddr addr);
|
int sk_address_is_local(SockAddr addr);
|
||||||
enum { ADDRTYPE_IPV4, ADDRTYPE_IPV6, ADDRTYPE_NAME };
|
|
||||||
int sk_addrtype(SockAddr addr);
|
int sk_addrtype(SockAddr addr);
|
||||||
void sk_addrcopy(SockAddr addr, char *buf);
|
void sk_addrcopy(SockAddr addr, char *buf);
|
||||||
void sk_addr_free(SockAddr addr);
|
void sk_addr_free(SockAddr addr);
|
||||||
@ -113,7 +112,7 @@ void sk_addr_free(SockAddr addr);
|
|||||||
Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
||||||
int nodelay, int keepalive, Plug p);
|
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);
|
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
|
* Called when receiving a PORT OPEN from the server
|
||||||
*/
|
*/
|
||||||
const char *pfd_newconnect(Socket *s, char *hostname, int port,
|
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 = {
|
static const struct plug_function_table fn_table = {
|
||||||
pfd_closing,
|
pfd_closing,
|
||||||
@ -371,7 +371,7 @@ const char *pfd_newconnect(Socket *s, char *hostname, int port,
|
|||||||
/*
|
/*
|
||||||
* Try to find host.
|
* 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) {
|
if ((err = sk_addr_error(addr)) != NULL) {
|
||||||
sk_addr_free(addr);
|
sk_addr_free(addr);
|
||||||
return err;
|
return err;
|
||||||
@ -463,7 +463,7 @@ static int pfd_accepting(Plug p, OSSocket sock)
|
|||||||
*/
|
*/
|
||||||
const char *pfd_addforward(char *desthost, int destport, char *srcaddr,
|
const char *pfd_addforward(char *desthost, int destport, char *srcaddr,
|
||||||
int port, void *backhandle, const Config *cfg,
|
int port, void *backhandle, const Config *cfg,
|
||||||
void **sockdata)
|
void **sockdata, int address_family)
|
||||||
{
|
{
|
||||||
static const struct plug_function_table fn_table = {
|
static const struct plug_function_table fn_table = {
|
||||||
pfd_closing,
|
pfd_closing,
|
||||||
@ -494,7 +494,7 @@ const char *pfd_addforward(char *desthost, int destport, char *srcaddr,
|
|||||||
pr->backhandle = backhandle;
|
pr->backhandle = backhandle;
|
||||||
|
|
||||||
pr->s = s = new_listener(srcaddr, port, (Plug) pr,
|
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) {
|
if ((err = sk_socket_error(s)) != NULL) {
|
||||||
sfree(pr);
|
sfree(pr);
|
||||||
return err;
|
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,
|
SockAddr name_lookup(char *host, int port, char **canonicalname,
|
||||||
const Config *cfg)
|
const Config *cfg, int addressfamily)
|
||||||
{
|
{
|
||||||
if (cfg->proxy_type != PROXY_NONE &&
|
if (cfg->proxy_type != PROXY_NONE &&
|
||||||
do_proxy_dns(cfg) &&
|
do_proxy_dns(cfg) &&
|
||||||
@ -351,7 +351,7 @@ SockAddr name_lookup(char *host, int port, char **canonicalname,
|
|||||||
return sk_nonamelookup(host);
|
return sk_nonamelookup(host);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sk_namelookup(host, canonicalname);
|
return sk_namelookup(host, canonicalname, addressfamily);
|
||||||
}
|
}
|
||||||
|
|
||||||
Socket new_connection(SockAddr addr, char *hostname,
|
Socket new_connection(SockAddr addr, char *hostname,
|
||||||
@ -433,7 +433,7 @@ Socket new_connection(SockAddr addr, char *hostname,
|
|||||||
|
|
||||||
/* look-up proxy */
|
/* look-up proxy */
|
||||||
proxy_addr = sk_namelookup(cfg->proxy_host,
|
proxy_addr = sk_namelookup(cfg->proxy_host,
|
||||||
&proxy_canonical_name);
|
&proxy_canonical_name, cfg->addressfamily);
|
||||||
if (sk_addr_error(proxy_addr) != NULL) {
|
if (sk_addr_error(proxy_addr) != NULL) {
|
||||||
ret->error = "Proxy error: Unable to resolve proxy host name";
|
ret->error = "Proxy error: Unable to resolve proxy host name";
|
||||||
return (Socket)ret;
|
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,
|
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: SOCKS (and potentially others) support inbound
|
||||||
* TODO: connections via the proxy. support them.
|
* 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')
|
if (host == NULL || host[0] == '\0')
|
||||||
bump("Empty host name");
|
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),
|
* If we haven't loaded session details already (e.g., from -load),
|
||||||
* try looking for a session called "host".
|
* 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.
|
* 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)
|
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
|
/* We ignore a leading colon, since the hostname cannot be
|
||||||
empty. We also ignore a colon as second character because
|
empty. We also ignore a colon as second character because
|
||||||
of filenames like f:myfile.txt. */
|
of filenames like f:myfile.txt. */
|
||||||
@ -1928,7 +1947,7 @@ static void toremote(int argc, char *argv[])
|
|||||||
*targ++ = '\0';
|
*targ++ = '\0';
|
||||||
if (*targ == '\0')
|
if (*targ == '\0')
|
||||||
targ = ".";
|
targ = ".";
|
||||||
/* Substitute "." for emtpy target */
|
/* Substitute "." for empty target */
|
||||||
|
|
||||||
/* Separate host and username */
|
/* Separate host and username */
|
||||||
user = host;
|
user = host;
|
||||||
@ -2129,6 +2148,7 @@ static void usage(void)
|
|||||||
printf(" -l user connect with specified username\n");
|
printf(" -l user connect with specified username\n");
|
||||||
printf(" -pw passw login with specified password\n");
|
printf(" -pw passw login with specified password\n");
|
||||||
printf(" -1 -2 force use of particular SSH protocol version\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(" -C enable compression\n");
|
||||||
printf(" -i key private key file for authentication\n");
|
printf(" -i key private key file for authentication\n");
|
||||||
printf(" -batch disable all interactive prompts\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(" -P port connect to specified port\n");
|
||||||
printf(" -pw passw login with specified password\n");
|
printf(" -pw passw login with specified password\n");
|
||||||
printf(" -1 -2 force use of particular SSH protocol version\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(" -C enable compression\n");
|
||||||
printf(" -i key private key file for authentication\n");
|
printf(" -i key private key file for authentication\n");
|
||||||
printf(" -batch disable all interactive prompts\n");
|
printf(" -batch disable all interactive prompts\n");
|
||||||
|
11
putty.h
11
putty.h
@ -314,6 +314,16 @@ enum {
|
|||||||
FUNKY_SCO
|
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 {
|
struct backend_tag {
|
||||||
const char *(*init) (void *frontend_handle, void **backend_handle,
|
const char *(*init) (void *frontend_handle, void **backend_handle,
|
||||||
Config *cfg,
|
Config *cfg,
|
||||||
@ -375,6 +385,7 @@ struct config_tag {
|
|||||||
char host[512];
|
char host[512];
|
||||||
int port;
|
int port;
|
||||||
int protocol;
|
int protocol;
|
||||||
|
int addressfamily;
|
||||||
int close_on_exit;
|
int close_on_exit;
|
||||||
int warn_on_close;
|
int warn_on_close;
|
||||||
int ping_interval; /* in seconds */
|
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;
|
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);
|
logevent(raw->frontend, buf);
|
||||||
sfree(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) {
|
if ((err = sk_addr_error(addr)) != NULL) {
|
||||||
sk_addr_free(addr);
|
sk_addr_free(addr);
|
||||||
return err;
|
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;
|
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);
|
logevent(rlogin->frontend, buf);
|
||||||
sfree(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) {
|
if ((err = sk_addr_error(addr)) != NULL) {
|
||||||
sk_addr_free(addr);
|
sk_addr_free(addr);
|
||||||
return err;
|
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, "TerminalType", cfg->termtype);
|
||||||
write_setting_s(sesskey, "TerminalSpeed", cfg->termspeed);
|
write_setting_s(sesskey, "TerminalSpeed", cfg->termspeed);
|
||||||
|
|
||||||
|
/* Address family selection */
|
||||||
|
write_setting_i(sesskey, "AddressFamily", cfg->addressfamily);
|
||||||
|
|
||||||
/* proxy settings */
|
/* proxy settings */
|
||||||
write_setting_s(sesskey, "ProxyExcludeList", cfg->proxy_exclude_list);
|
write_setting_s(sesskey, "ProxyExcludeList", cfg->proxy_exclude_list);
|
||||||
write_setting_i(sesskey, "ProxyDNS", (cfg->proxy_dns+2)%3);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Address family selection */
|
||||||
|
gppi(sesskey, "AddressFamily", ADDRTYPE_UNSPEC, &cfg->addressfamily);
|
||||||
|
|
||||||
/* The CloseOnExit numbers are arranged in a different order from
|
/* The CloseOnExit numbers are arranged in a different order from
|
||||||
* the standard FORCE_ON / FORCE_OFF / AUTO. */
|
* the standard FORCE_ON / FORCE_OFF / AUTO. */
|
||||||
gppi(sesskey, "CloseOnExit", 1, &i); cfg->close_on_exit = (i+1)%3;
|
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;
|
unsigned sport, dport;
|
||||||
char *saddr, *daddr;
|
char *saddr, *daddr;
|
||||||
struct ssh_rportfwd *remote;
|
struct ssh_rportfwd *remote;
|
||||||
|
int addressfamily;
|
||||||
void *local;
|
void *local;
|
||||||
};
|
};
|
||||||
#define free_portfwd(pf) ( \
|
#define free_portfwd(pf) ( \
|
||||||
@ -2449,8 +2450,11 @@ static const char *connect_to_host(Ssh ssh, char *host, int port,
|
|||||||
/*
|
/*
|
||||||
* Try to find host.
|
* Try to find host.
|
||||||
*/
|
*/
|
||||||
logeventf(ssh, "Looking up host \"%s\"", host);
|
logeventf(ssh, "Looking up host \"%s\"%s", host,
|
||||||
addr = name_lookup(host, port, realhost, &ssh->cfg);
|
(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) {
|
if ((err = sk_addr_error(addr)) != NULL) {
|
||||||
sk_addr_free(addr);
|
sk_addr_free(addr);
|
||||||
return err;
|
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)
|
static void ssh_setup_portfwd(Ssh ssh, const Config *cfg)
|
||||||
{
|
{
|
||||||
char type;
|
char address_family, type;
|
||||||
int n;
|
int n;
|
||||||
int sport,dport,sserv,dserv;
|
int sport,dport,sserv,dserv;
|
||||||
char sports[256], dports[256], saddr[256], host[256];
|
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) {
|
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';
|
saddr[0] = '\0';
|
||||||
|
|
||||||
n = 0;
|
n = 0;
|
||||||
while (*portfwd_strptr && *portfwd_strptr != '\t') {
|
while (*portfwd_strptr && *portfwd_strptr != '\t') {
|
||||||
if (*portfwd_strptr == ':') {
|
if (*portfwd_strptr == ':') {
|
||||||
@ -3774,6 +3792,9 @@ static void ssh_setup_portfwd(Ssh ssh, const Config *cfg)
|
|||||||
pfrec->dport = dport;
|
pfrec->dport = dport;
|
||||||
pfrec->local = NULL;
|
pfrec->local = NULL;
|
||||||
pfrec->remote = NULL;
|
pfrec->remote = NULL;
|
||||||
|
pfrec->addressfamily = (address_family == '4' ? ADDRTYPE_IPV4 :
|
||||||
|
address_family == '6' ? ADDRTYPE_IPV6 :
|
||||||
|
ADDRTYPE_UNSPEC);
|
||||||
|
|
||||||
epfrec = add234(ssh->portfwds, pfrec);
|
epfrec = add234(ssh->portfwds, pfrec);
|
||||||
if (epfrec != 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,
|
const char *err = pfd_addforward(host, dport,
|
||||||
*saddr ? saddr : NULL,
|
*saddr ? saddr : NULL,
|
||||||
sport, ssh, &ssh->cfg,
|
sport, ssh, &ssh->cfg,
|
||||||
&pfrec->local);
|
&pfrec->local,
|
||||||
if (err) {
|
pfrec->addressfamily);
|
||||||
logeventf(ssh, "Local port %s forward to %s"
|
|
||||||
" failed: %s", sportdesc, dportdesc, err);
|
logeventf(ssh, "Local %sport %s forward to %s%s%s",
|
||||||
} else {
|
pfrec->addressfamily == ADDRTYPE_IPV4 ? "IPv4 " :
|
||||||
logeventf(ssh, "Local port %s forwarding to %s",
|
pfrec->addressfamily == ADDRTYPE_IPV6 ? "IPv6 " : "",
|
||||||
sportdesc, dportdesc);
|
sportdesc, dportdesc,
|
||||||
}
|
err ? " failed: " : "", err);
|
||||||
|
|
||||||
sfree(dportdesc);
|
sfree(dportdesc);
|
||||||
} else if (type == 'D') {
|
} else if (type == 'D') {
|
||||||
const char *err = pfd_addforward(NULL, -1,
|
const char *err = pfd_addforward(NULL, -1,
|
||||||
*saddr ? saddr : NULL,
|
*saddr ? saddr : NULL,
|
||||||
sport, ssh, &ssh->cfg,
|
sport, ssh, &ssh->cfg,
|
||||||
&pfrec->local);
|
&pfrec->local,
|
||||||
if (err) {
|
pfrec->addressfamily);
|
||||||
logeventf(ssh, "Local port %s SOCKS dynamic forward"
|
|
||||||
" setup failed: %s", sportdesc, err);
|
logeventf(ssh, "Local %sport %s SOCKS dynamic forward%s%s",
|
||||||
} else {
|
pfrec->addressfamily == ADDRTYPE_IPV4 ? "IPv4 " :
|
||||||
logeventf(ssh, "Local port %s doing SOCKS"
|
pfrec->addressfamily == ADDRTYPE_IPV6 ? "IPv6 " : "",
|
||||||
" dynamic forwarding", sportdesc);
|
sportdesc,
|
||||||
}
|
err ? " setup failed: " : "", err);
|
||||||
} else {
|
} else {
|
||||||
struct ssh_rportfwd *pf;
|
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
|
/* Remote side is trying to open a channel to talk to a
|
||||||
* forwarded port. Give them back a local channel number. */
|
* forwarded port. Give them back a local channel number. */
|
||||||
struct ssh_channel *c;
|
struct ssh_channel *c;
|
||||||
struct ssh_rportfwd pf;
|
struct ssh_rportfwd pf, *pfp;
|
||||||
int remoteid;
|
int remoteid;
|
||||||
int hostsize, port;
|
int hostsize, port;
|
||||||
char *host, buf[1024];
|
char *host, buf[1024];
|
||||||
@ -4062,8 +4084,9 @@ static void ssh1_msg_port_open(Ssh ssh, struct Packet *pktin)
|
|||||||
memcpy(pf.dhost, host, hostsize);
|
memcpy(pf.dhost, host, hostsize);
|
||||||
pf.dhost[hostsize] = '\0';
|
pf.dhost[hostsize] = '\0';
|
||||||
pf.dport = port;
|
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",
|
sprintf(buf, "Rejected remote port open request for %s:%d",
|
||||||
pf.dhost, port);
|
pf.dhost, port);
|
||||||
logevent(buf);
|
logevent(buf);
|
||||||
@ -4074,7 +4097,7 @@ static void ssh1_msg_port_open(Ssh ssh, struct Packet *pktin)
|
|||||||
pf.dhost, port);
|
pf.dhost, port);
|
||||||
logevent(buf);
|
logevent(buf);
|
||||||
e = pfd_newconnect(&c->u.pfd.s, pf.dhost, port,
|
e = pfd_newconnect(&c->u.pfd.s, pf.dhost, port,
|
||||||
c, &ssh->cfg);
|
c, &ssh->cfg, pfp->pfrec->addressfamily);
|
||||||
if (e != NULL) {
|
if (e != NULL) {
|
||||||
char buf[256];
|
char buf[256];
|
||||||
sprintf(buf, "Port open failed: %s", e);
|
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,
|
const char *e = pfd_newconnect(&c->u.pfd.s,
|
||||||
realpf->dhost,
|
realpf->dhost,
|
||||||
realpf->dport, c,
|
realpf->dport, c,
|
||||||
&ssh->cfg);
|
&ssh->cfg,
|
||||||
|
realpf->pfrec->addressfamily);
|
||||||
logeventf(ssh, "Attempting to forward remote port to "
|
logeventf(ssh, "Attempting to forward remote port to "
|
||||||
"%s:%d", realpf->dhost, realpf->dport);
|
"%s:%d", realpf->dhost, realpf->dport);
|
||||||
if (e != NULL) {
|
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 */
|
/* Exports from portfwd.c */
|
||||||
extern const char *pfd_newconnect(Socket * s, char *hostname, int port,
|
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 */
|
/* desthost == NULL indicates dynamic (SOCKS) port forwarding */
|
||||||
extern const char *pfd_addforward(char *desthost, int destport, char *srcaddr,
|
extern const char *pfd_addforward(char *desthost, int destport, char *srcaddr,
|
||||||
int port, void *backhandle,
|
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_close(Socket s);
|
||||||
extern void pfd_terminate(void *sockdata);
|
extern void pfd_terminate(void *sockdata);
|
||||||
extern int pfd_send(Socket s, char *data, int len);
|
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;
|
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);
|
logevent(telnet->frontend, buf);
|
||||||
sfree(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) {
|
if ((err = sk_addr_error(addr)) != NULL) {
|
||||||
sk_addr_free(addr);
|
sk_addr_free(addr);
|
||||||
return err;
|
return err;
|
||||||
|
63
unix/uxnet.c
63
unix/uxnet.c
@ -69,7 +69,7 @@ struct SockAddr_tag {
|
|||||||
* in this SockAddr structure.
|
* in this SockAddr structure.
|
||||||
*/
|
*/
|
||||||
int family;
|
int family;
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
struct addrinfo *ai; /* Address IPv6 style. */
|
struct addrinfo *ai; /* Address IPv6 style. */
|
||||||
#else
|
#else
|
||||||
unsigned long address; /* Address IPv4 style. */
|
unsigned long address; /* Address IPv4 style. */
|
||||||
@ -125,10 +125,10 @@ const char *error_string(int error)
|
|||||||
return strerror(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);
|
SockAddr ret = snew(struct SockAddr_tag);
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
struct addrinfo hints;
|
struct addrinfo hints;
|
||||||
int err;
|
int err;
|
||||||
#else
|
#else
|
||||||
@ -143,9 +143,9 @@ SockAddr sk_namelookup(const char *host, char **canonicalname)
|
|||||||
*realhost = '\0';
|
*realhost = '\0';
|
||||||
ret->error = NULL;
|
ret->error = NULL;
|
||||||
|
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
hints.ai_flags = AI_CANONNAME;
|
hints.ai_flags = AI_CANONNAME;
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = address_family;
|
||||||
hints.ai_socktype = 0;
|
hints.ai_socktype = 0;
|
||||||
hints.ai_protocol = 0;
|
hints.ai_protocol = 0;
|
||||||
hints.ai_addrlen = 0;
|
hints.ai_addrlen = 0;
|
||||||
@ -219,7 +219,7 @@ void sk_getaddr(SockAddr addr, char *buf, int buflen)
|
|||||||
strncpy(buf, addr->hostname, buflen);
|
strncpy(buf, addr->hostname, buflen);
|
||||||
buf[buflen-1] = '\0';
|
buf[buflen-1] = '\0';
|
||||||
} else {
|
} else {
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
if (getnameinfo(addr->ai->ai_addr, addr->ai->ai_addrlen, buf, buflen,
|
if (getnameinfo(addr->ai->ai_addr, addr->ai->ai_addrlen, buf, buflen,
|
||||||
NULL, 0, NI_NUMERICHOST) != 0) {
|
NULL, 0, NI_NUMERICHOST) != 0) {
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
@ -246,7 +246,7 @@ int sk_address_is_local(SockAddr addr)
|
|||||||
if (addr->family == AF_UNSPEC)
|
if (addr->family == AF_UNSPEC)
|
||||||
return 0; /* we don't know; assume not */
|
return 0; /* we don't know; assume not */
|
||||||
else {
|
else {
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
if (addr->family == AF_INET)
|
if (addr->family == AF_INET)
|
||||||
return ipv4_is_loopback(
|
return ipv4_is_loopback(
|
||||||
((struct sockaddr_in *)addr->ai->ai_addr)->sin_addr);
|
((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)
|
int sk_addrtype(SockAddr addr)
|
||||||
{
|
{
|
||||||
return (addr->family == AF_INET ? ADDRTYPE_IPV4 :
|
return (addr->family == AF_INET ? ADDRTYPE_IPV4 :
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
addr->family == AF_INET6 ? ADDRTYPE_IPV6 :
|
addr->family == AF_INET6 ? ADDRTYPE_IPV6 :
|
||||||
#endif
|
#endif
|
||||||
ADDRTYPE_NAME);
|
ADDRTYPE_NAME);
|
||||||
@ -276,7 +276,7 @@ int sk_addrtype(SockAddr addr)
|
|||||||
void sk_addrcopy(SockAddr addr, char *buf)
|
void sk_addrcopy(SockAddr addr, char *buf)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
if (addr->family == AF_INET)
|
if (addr->family == AF_INET)
|
||||||
memcpy(buf, &((struct sockaddr_in *)addr->ai->ai_addr)->sin_addr,
|
memcpy(buf, &((struct sockaddr_in *)addr->ai->ai_addr)->sin_addr,
|
||||||
sizeof(struct in_addr));
|
sizeof(struct in_addr));
|
||||||
@ -297,7 +297,7 @@ void sk_addrcopy(SockAddr addr, char *buf)
|
|||||||
void sk_addr_free(SockAddr addr)
|
void sk_addr_free(SockAddr addr)
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
if (addr->ai != NULL)
|
if (addr->ai != NULL)
|
||||||
freeaddrinfo(addr->ai);
|
freeaddrinfo(addr->ai);
|
||||||
#endif
|
#endif
|
||||||
@ -381,7 +381,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
|||||||
int nodelay, int keepalive, Plug plug)
|
int nodelay, int keepalive, Plug plug)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
struct sockaddr_in6 a6;
|
struct sockaddr_in6 a6;
|
||||||
#endif
|
#endif
|
||||||
struct sockaddr_in a;
|
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 */
|
/* BSD IP stacks need sockaddr_in zeroed before filling in */
|
||||||
memset(&a,'\0',sizeof(struct sockaddr_in));
|
memset(&a,'\0',sizeof(struct sockaddr_in));
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
memset(&a6,'\0',sizeof(struct sockaddr_in6));
|
memset(&a6,'\0',sizeof(struct sockaddr_in6));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -459,7 +459,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
|||||||
while (1) {
|
while (1) {
|
||||||
int retcode;
|
int retcode;
|
||||||
|
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
if (addr->family == AF_INET6) {
|
if (addr->family == AF_INET6) {
|
||||||
/* XXX use getaddrinfo to get a local address? */
|
/* XXX use getaddrinfo to get a local address? */
|
||||||
a6.sin6_family = AF_INET6;
|
a6.sin6_family = AF_INET6;
|
||||||
@ -501,7 +501,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
|||||||
* Connect to remote address.
|
* Connect to remote address.
|
||||||
*/
|
*/
|
||||||
switch(addr->family) {
|
switch(addr->family) {
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
/* XXX would be better to have got getaddrinfo() to fill in the port. */
|
/* XXX would be better to have got getaddrinfo() to fill in the port. */
|
||||||
((struct sockaddr_in *)addr->ai->ai_addr)->sin_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;
|
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;
|
int s;
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
#if 0
|
|
||||||
struct sockaddr_in6 a6;
|
|
||||||
#endif
|
|
||||||
struct addrinfo hints, *ai;
|
struct addrinfo hints, *ai;
|
||||||
char portstr[6];
|
char portstr[6];
|
||||||
#endif
|
#endif
|
||||||
@ -597,10 +594,32 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only)
|
|||||||
ret->oobpending = FALSE;
|
ret->oobpending = FALSE;
|
||||||
ret->listener = 1;
|
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.
|
* 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;
|
ret->s = s;
|
||||||
|
|
||||||
if (s < 0) {
|
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 */
|
/* BSD IP stacks need sockaddr_in zeroed before filling in */
|
||||||
memset(&a,'\0',sizeof(struct sockaddr_in));
|
memset(&a,'\0',sizeof(struct sockaddr_in));
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
#if 0
|
#if 0
|
||||||
memset(&a6,'\0',sizeof(struct sockaddr_in6));
|
memset(&a6,'\0',sizeof(struct sockaddr_in6));
|
||||||
#endif
|
#endif
|
||||||
hints.ai_flags = AI_NUMERICHOST;
|
hints.ai_flags = AI_NUMERICHOST;
|
||||||
hints.ai_family = AF_UNSPEC;
|
hints.ai_family = address_family;
|
||||||
hints.ai_socktype = 0;
|
hints.ai_socktype = 0;
|
||||||
hints.ai_protocol = 0;
|
hints.ai_protocol = 0;
|
||||||
hints.ai_addrlen = 0;
|
hints.ai_addrlen = 0;
|
||||||
|
@ -227,6 +227,7 @@ static void usage(void)
|
|||||||
printf(" -A -a enable / disable agent forwarding\n");
|
printf(" -A -a enable / disable agent forwarding\n");
|
||||||
printf(" -t -T enable / disable pty allocation\n");
|
printf(" -t -T enable / disable pty allocation\n");
|
||||||
printf(" -1 -2 force use of particular protocol version\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(" -C enable compression\n");
|
||||||
printf(" -i key private key file for authentication\n");
|
printf(" -i key private key file for authentication\n");
|
||||||
printf(" -s remote command is an SSH subsystem (SSH-2 only)\n");
|
printf(" -s remote command is an SSH subsystem (SSH-2 only)\n");
|
||||||
|
@ -49,7 +49,7 @@ BEGIN
|
|||||||
END
|
END
|
||||||
|
|
||||||
/* Accelerators used: aco */
|
/* 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
|
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
CAPTION "PuTTY Configuration"
|
CAPTION "PuTTY Configuration"
|
||||||
FONT 8, "MS Shell Dlg"
|
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
|
* Otherwise, we're creating the controls for a particular
|
||||||
* panel.
|
* panel.
|
||||||
*/
|
*/
|
||||||
ctlposinit(&cp, hwnd, 80, 3, 13);
|
ctlposinit(&cp, hwnd, 100, 3, 13);
|
||||||
wc = &ctrls_panel;
|
wc = &ctrls_panel;
|
||||||
base_id = IDCX_PANELBASE;
|
base_id = IDCX_PANELBASE;
|
||||||
}
|
}
|
||||||
@ -361,7 +361,7 @@ static int CALLBACK GenericMainDlgProc(HWND hwnd, UINT msg,
|
|||||||
HWND tvstatic;
|
HWND tvstatic;
|
||||||
|
|
||||||
r.left = 3;
|
r.left = 3;
|
||||||
r.right = r.left + 75;
|
r.right = r.left + 95;
|
||||||
r.top = 3;
|
r.top = 3;
|
||||||
r.bottom = r.top + 10;
|
r.bottom = r.top + 10;
|
||||||
MapDialogRect(hwnd, &r);
|
MapDialogRect(hwnd, &r);
|
||||||
@ -375,7 +375,7 @@ static int CALLBACK GenericMainDlgProc(HWND hwnd, UINT msg,
|
|||||||
SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
|
SendMessage(tvstatic, WM_SETFONT, font, MAKELPARAM(TRUE, 0));
|
||||||
|
|
||||||
r.left = 3;
|
r.left = 3;
|
||||||
r.right = r.left + 75;
|
r.right = r.left + 95;
|
||||||
r.top = 13;
|
r.top = 13;
|
||||||
r.bottom = r.top + 219;
|
r.bottom = r.top + 219;
|
||||||
MapDialogRect(hwnd, &r);
|
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.
|
* Remove any remaining whitespace from the hostname.
|
||||||
|
@ -66,6 +66,7 @@
|
|||||||
#define WINHELP_CTX_connection_username "connection.username"
|
#define WINHELP_CTX_connection_username "connection.username"
|
||||||
#define WINHELP_CTX_connection_keepalive "connection.keepalive"
|
#define WINHELP_CTX_connection_keepalive "connection.keepalive"
|
||||||
#define WINHELP_CTX_connection_nodelay "connection.nodelay"
|
#define WINHELP_CTX_connection_nodelay "connection.nodelay"
|
||||||
|
#define WINHELP_CTX_connection_ipversion "connection.ipversion"
|
||||||
#define WINHELP_CTX_connection_tcpkeepalive "connection.tcpkeepalive"
|
#define WINHELP_CTX_connection_tcpkeepalive "connection.tcpkeepalive"
|
||||||
#define WINHELP_CTX_proxy_type "proxy.type"
|
#define WINHELP_CTX_proxy_type "proxy.type"
|
||||||
#define WINHELP_CTX_proxy_main "proxy.main"
|
#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_x11auth "ssh.tunnels.x11auth"
|
||||||
#define WINHELP_CTX_ssh_tunnels_portfwd "ssh.tunnels.portfwd"
|
#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_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_ignore1 "ssh.bugs.ignore1"
|
||||||
#define WINHELP_CTX_ssh_bugs_plainpw1 "ssh.bugs.plainpw1"
|
#define WINHELP_CTX_ssh_bugs_plainpw1 "ssh.bugs.plainpw1"
|
||||||
#define WINHELP_CTX_ssh_bugs_rsa1 "ssh.bugs.rsa1"
|
#define WINHELP_CTX_ssh_bugs_rsa1 "ssh.bugs.rsa1"
|
||||||
|
@ -50,8 +50,14 @@ char *get_username(void)
|
|||||||
char *user;
|
char *user;
|
||||||
|
|
||||||
namelen = 0;
|
namelen = 0;
|
||||||
if (GetUserName(NULL, &namelen) == FALSE)
|
if (GetUserName(NULL, &namelen) == FALSE) {
|
||||||
return NULL;
|
/*
|
||||||
|
* 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);
|
user = snewn(namelen, char);
|
||||||
GetUserName(user, &namelen);
|
GetUserName(user, &namelen);
|
||||||
|
210
windows/winnet.c
210
windows/winnet.c
@ -1,43 +1,10 @@
|
|||||||
/*
|
/*
|
||||||
* Windows networking abstraction.
|
* Windows networking abstraction.
|
||||||
*
|
*
|
||||||
* Due to this clean abstraction it was possible
|
* For the IPv6 code in here I am indebted to Jeroen Massar and
|
||||||
* to easily implement IPv6 support :)
|
* unfix.org.
|
||||||
*
|
|
||||||
* 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...
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* 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 <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@ -48,8 +15,10 @@
|
|||||||
#include "tree234.h"
|
#include "tree234.h"
|
||||||
|
|
||||||
#include <ws2tcpip.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
|
#endif
|
||||||
|
|
||||||
#define ipv4_is_loopback(addr) \
|
#define ipv4_is_loopback(addr) \
|
||||||
@ -92,11 +61,16 @@ struct SockAddr_tag {
|
|||||||
* IPv4; AF_INET6 for IPv6; AF_UNSPEC indicates that name
|
* IPv4; AF_INET6 for IPv6; AF_UNSPEC indicates that name
|
||||||
* resolution has not been done and a simple host name is held
|
* resolution has not been done and a simple host name is held
|
||||||
* in this SockAddr structure.
|
* 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;
|
int family;
|
||||||
unsigned long address; /* Address IPv4 style. */
|
unsigned long address; /* Address IPv4 style. */
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
struct addrinfo *ai; /* Address IPv6 style. */
|
struct addrinfo *ai; /* Address AF-independent (IPv4+IPv6) style. */
|
||||||
#endif
|
#endif
|
||||||
char hostname[512]; /* Store an unresolved host name. */
|
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);
|
SockAddr ret = snew(struct SockAddr_tag);
|
||||||
unsigned long a;
|
unsigned long a;
|
||||||
@ -334,11 +309,15 @@ SockAddr sk_namelookup(const char *host, char **canonicalname)
|
|||||||
|
|
||||||
/* Clear the structure and default to IPv4. */
|
/* Clear the structure and default to IPv4. */
|
||||||
memset(ret, 0, sizeof(struct SockAddr_tag));
|
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';
|
*realhost = '\0';
|
||||||
|
|
||||||
if ((a = p_inet_addr(host)) == (unsigned long) INADDR_NONE) {
|
if ((a = p_inet_addr(host)) == (unsigned long) INADDR_NONE) {
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
|
|
||||||
/* Try to get the getaddrinfo() function from wship6.dll */
|
/* Try to get the getaddrinfo() function from wship6.dll */
|
||||||
/* This way one doesn't need to have IPv6 dll's to use PuTTY and
|
/* 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");
|
"getaddrinfo");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Use fGetAddrInfo when it's available (which usually also
|
* Use fGetAddrInfo when it's available
|
||||||
* means IPv6 is installed...)
|
|
||||||
*/
|
*/
|
||||||
if (fGetAddrInfo) {
|
if (fGetAddrInfo) {
|
||||||
/*debug(("Resolving \"%s\" with getaddrinfo() (IPv4+IPv6 capable)...\n", host)); */
|
struct addrinfo hints;
|
||||||
if (fGetAddrInfo(host, NULL, NULL, &ret->ai) == 0)
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_family = ret->family;
|
||||||
|
if (fGetAddrInfo(host, NULL, &hints, &ret->ai) == 0)
|
||||||
ret->family = ret->ai->ai_family;
|
ret->family = ret->ai->ai_family;
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Otherwise use the IPv4-only gethostbyname...
|
* Otherwise use the IPv4-only gethostbyname...
|
||||||
* (NOTE: we don't use gethostbyname as a
|
* (NOTE: we don't use gethostbyname as a fallback!)
|
||||||
* fallback!)
|
|
||||||
*/
|
*/
|
||||||
if (ret->family == 0) {
|
if (ret->family == 0) {
|
||||||
/*debug(("Resolving \"%s\" with gethostbyname() (IPv4 only)...\n", host)); */
|
|
||||||
if ( (h = p_gethostbyname(host)) )
|
if ( (h = p_gethostbyname(host)) )
|
||||||
ret->family = AF_INET;
|
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();
|
DWORD err = p_WSAGetLastError();
|
||||||
ret->error = (err == WSAENETDOWN ? "Network is down" :
|
ret->error = (err == WSAENETDOWN ? "Network is down" :
|
||||||
err ==
|
err ==
|
||||||
WSAHOST_NOT_FOUND ? "Host does not exist" : err
|
WSAHOST_NOT_FOUND ? "Host does not exist" : err
|
||||||
== WSATRY_AGAIN ? "Host not found" :
|
== WSATRY_AGAIN ? "Host not found" :
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
fGetAddrInfo ? "getaddrinfo: unknown error" :
|
fGetAddrInfo ? "getaddrinfo: unknown error" :
|
||||||
#endif
|
#endif
|
||||||
"gethostbyname: unknown error");
|
"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 {
|
} else {
|
||||||
ret->error = NULL;
|
ret->error = NULL;
|
||||||
|
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
/* If we got an address info use that... */
|
/* If we got an address info use that... */
|
||||||
if (ret->ai) {
|
if (ret->ai) {
|
||||||
typedef int (CALLBACK * FGETNAMEINFO)
|
typedef int (CALLBACK * FGETNAMEINFO)
|
||||||
@ -445,7 +409,7 @@ SockAddr sk_namelookup(const char *host, char **canonicalname)
|
|||||||
strncpy(realhost, h->h_name, sizeof(realhost));
|
strncpy(realhost, h->h_name, sizeof(realhost));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
FreeLibrary(dllWSHIP6);
|
FreeLibrary(dllWSHIP6);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
@ -475,9 +439,30 @@ SockAddr sk_nonamelookup(const char *host)
|
|||||||
|
|
||||||
void sk_getaddr(SockAddr addr, char *buf, int buflen)
|
void sk_getaddr(SockAddr addr, char *buf, int buflen)
|
||||||
{
|
{
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
if (addr->family == AF_INET6) {
|
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
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (addr->family == AF_INET) {
|
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);
|
strncpy(buf, p_inet_ntoa(a), buflen);
|
||||||
buf[buflen-1] = '\0';
|
buf[buflen-1] = '\0';
|
||||||
} else {
|
} else {
|
||||||
assert(addr->family == AF_UNSPEC);
|
|
||||||
strncpy(buf, addr->hostname, buflen);
|
strncpy(buf, addr->hostname, buflen);
|
||||||
buf[buflen-1] = '\0';
|
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)
|
int sk_address_is_local(SockAddr addr)
|
||||||
{
|
{
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
if (addr->family == AF_INET6) {
|
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
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (addr->family == AF_INET) {
|
if (addr->family == AF_INET) {
|
||||||
@ -548,7 +532,7 @@ int sk_address_is_local(SockAddr addr)
|
|||||||
int sk_addrtype(SockAddr addr)
|
int sk_addrtype(SockAddr addr)
|
||||||
{
|
{
|
||||||
return (addr->family == AF_INET ? ADDRTYPE_IPV4 :
|
return (addr->family == AF_INET ? ADDRTYPE_IPV4 :
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
addr->family == AF_INET6 ? ADDRTYPE_IPV6 :
|
addr->family == AF_INET6 ? ADDRTYPE_IPV6 :
|
||||||
#endif
|
#endif
|
||||||
ADDRTYPE_NAME);
|
ADDRTYPE_NAME);
|
||||||
@ -557,7 +541,7 @@ int sk_addrtype(SockAddr addr)
|
|||||||
void sk_addrcopy(SockAddr addr, char *buf)
|
void sk_addrcopy(SockAddr addr, char *buf)
|
||||||
{
|
{
|
||||||
assert(addr->family != AF_UNSPEC);
|
assert(addr->family != AF_UNSPEC);
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
if (addr->family == AF_INET6) {
|
if (addr->family == AF_INET6) {
|
||||||
memcpy(buf, (char*) addr->ai, 16);
|
memcpy(buf, (char*) addr->ai, 16);
|
||||||
} else
|
} else
|
||||||
@ -673,7 +657,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
|||||||
};
|
};
|
||||||
|
|
||||||
SOCKET s;
|
SOCKET s;
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
SOCKADDR_IN6 a6;
|
SOCKADDR_IN6 a6;
|
||||||
#endif
|
#endif
|
||||||
SOCKADDR_IN a;
|
SOCKADDR_IN a;
|
||||||
@ -701,7 +685,14 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
|||||||
/*
|
/*
|
||||||
* Open socket.
|
* 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);
|
s = p_socket(addr->family, SOCK_STREAM, 0);
|
||||||
ret->s = s;
|
ret->s = s;
|
||||||
|
|
||||||
@ -739,11 +730,11 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
|||||||
while (1) {
|
while (1) {
|
||||||
int retcode;
|
int retcode;
|
||||||
|
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
if (addr->family == AF_INET6) {
|
if (addr->family == AF_INET6) {
|
||||||
memset(&a6, 0, sizeof(a6));
|
memset(&a6, 0, sizeof(a6));
|
||||||
a6.sin6_family = AF_INET6;
|
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);
|
a6.sin6_port = p_htons(localport);
|
||||||
} else
|
} else
|
||||||
#endif
|
#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_addr.s_addr = p_htonl(INADDR_ANY);
|
||||||
a.sin_port = p_htons(localport);
|
a.sin_port = p_htons(localport);
|
||||||
}
|
}
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
retcode = p_bind(s, (addr->family == AF_INET6 ?
|
retcode = p_bind(s, (addr->family == AF_INET6 ?
|
||||||
(struct sockaddr *) &a6 :
|
(struct sockaddr *) &a6 :
|
||||||
(struct sockaddr *) &a),
|
(struct sockaddr *) &a),
|
||||||
@ -785,7 +776,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
|||||||
/*
|
/*
|
||||||
* Connect to remote address.
|
* Connect to remote address.
|
||||||
*/
|
*/
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
if (addr->family == AF_INET6) {
|
if (addr->family == AF_INET6) {
|
||||||
memset(&a, 0, sizeof(a));
|
memset(&a, 0, sizeof(a));
|
||||||
a6.sin6_family = AF_INET6;
|
a6.sin6_family = AF_INET6;
|
||||||
@ -809,7 +800,7 @@ Socket sk_new(SockAddr addr, int port, int privport, int oobinline,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((
|
if ((
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
p_connect(s, ((addr->family == AF_INET6) ?
|
p_connect(s, ((addr->family == AF_INET6) ?
|
||||||
(struct sockaddr *) &a6 : (struct sockaddr *) &a),
|
(struct sockaddr *) &a6 : (struct sockaddr *) &a),
|
||||||
(addr->family == AF_INET6) ? sizeof(a6) : sizeof(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;
|
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 = {
|
static const struct socket_function_table fn_table = {
|
||||||
sk_tcp_plug,
|
sk_tcp_plug,
|
||||||
@ -859,10 +851,11 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only)
|
|||||||
};
|
};
|
||||||
|
|
||||||
SOCKET s;
|
SOCKET s;
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
SOCKADDR_IN6 a6;
|
SOCKADDR_IN6 a6;
|
||||||
#endif
|
#endif
|
||||||
SOCKADDR_IN a;
|
SOCKADDR_IN a;
|
||||||
|
|
||||||
DWORD err;
|
DWORD err;
|
||||||
char *errstr;
|
char *errstr;
|
||||||
Actual_Socket ret;
|
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->localhost_only = local_host_only;
|
||||||
ret->pending_error = 0;
|
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.
|
* Open socket.
|
||||||
*/
|
*/
|
||||||
s = p_socket(AF_INET, SOCK_STREAM, 0);
|
s = p_socket(address_family, SOCK_STREAM, 0);
|
||||||
ret->s = s;
|
ret->s = s;
|
||||||
|
|
||||||
if (s == INVALID_SOCKET) {
|
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));
|
p_setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&on, sizeof(on));
|
||||||
|
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
if (addr->family == AF_INET6) {
|
if (address_family == AF_INET6) {
|
||||||
memset(&a6, 0, sizeof(a6));
|
memset(&a6, 0, sizeof(a6));
|
||||||
a6.sin6_family = AF_INET6;
|
a6.sin6_family = AF_INET6;
|
||||||
/* FIXME: srcaddr is ignored for IPv6, because I (SGT) don't
|
/* 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)
|
if (local_host_only)
|
||||||
a6.sin6_addr = in6addr_loopback;
|
a6.sin6_addr = in6addr_loopback;
|
||||||
else
|
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);
|
a.sin_port = p_htons((short)port);
|
||||||
}
|
}
|
||||||
#ifdef IPV6
|
#ifndef NO_IPV6
|
||||||
retcode = p_bind(s, (addr->family == AF_INET6 ?
|
retcode = p_bind(s, (address_family == AF_INET6 ?
|
||||||
(struct sockaddr *) &a6 :
|
(struct sockaddr *) &a6 :
|
||||||
(struct sockaddr *) &a),
|
(struct sockaddr *) &a),
|
||||||
(addr->family ==
|
(address_family ==
|
||||||
AF_INET6 ? sizeof(a6) : sizeof(a)));
|
AF_INET6 ? sizeof(a6) : sizeof(a)));
|
||||||
#else
|
#else
|
||||||
retcode = p_bind(s, (struct sockaddr *) &a, sizeof(a));
|
retcode = p_bind(s, (struct sockaddr *) &a, sizeof(a));
|
||||||
@ -1229,11 +1244,15 @@ int select_result(WPARAM wParam, LPARAM lParam)
|
|||||||
return open;
|
return open;
|
||||||
case FD_ACCEPT:
|
case FD_ACCEPT:
|
||||||
{
|
{
|
||||||
|
#ifdef NO_IPV6
|
||||||
struct sockaddr_in isa;
|
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 */
|
SOCKET t; /* socket of connection */
|
||||||
|
|
||||||
memset(&isa, 0, sizeof(struct sockaddr_in));
|
memset(&isa, 0, sizeof(isa));
|
||||||
err = 0;
|
err = 0;
|
||||||
t = p_accept(s->s,(struct sockaddr *)&isa,&addrlen);
|
t = p_accept(s->s,(struct sockaddr *)&isa,&addrlen);
|
||||||
if (t == INVALID_SOCKET)
|
if (t == INVALID_SOCKET)
|
||||||
@ -1242,8 +1261,13 @@ int select_result(WPARAM wParam, LPARAM lParam)
|
|||||||
if (err == WSATRY_AGAIN)
|
if (err == WSATRY_AGAIN)
|
||||||
break;
|
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)) {
|
if (s->localhost_only && !ipv4_is_local_addr(isa.sin_addr)) {
|
||||||
|
#endif
|
||||||
p_closesocket(t); /* dodgy WinSock let nonlocal through */
|
p_closesocket(t); /* dodgy WinSock let nonlocal through */
|
||||||
} else if (plug_accepting(s->plug, (void*)t)) {
|
} else if (plug_accepting(s->plug, (void*)t)) {
|
||||||
p_closesocket(t); /* denied or error */
|
p_closesocket(t); /* denied or error */
|
||||||
|
@ -231,6 +231,7 @@ static void usage(void)
|
|||||||
printf(" -A -a enable / disable agent forwarding\n");
|
printf(" -A -a enable / disable agent forwarding\n");
|
||||||
printf(" -t -T enable / disable pty allocation\n");
|
printf(" -t -T enable / disable pty allocation\n");
|
||||||
printf(" -1 -2 force use of particular protocol version\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(" -C enable compression\n");
|
||||||
printf(" -i key private key file for authentication\n");
|
printf(" -i key private key file for authentication\n");
|
||||||
printf(" -s remote command is an SSH subsystem (SSH-2 only)\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.
|
* 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) {
|
if ((err = sk_addr_error(addr)) != NULL) {
|
||||||
sk_addr_free(addr);
|
sk_addr_free(addr);
|
||||||
return err;
|
return err;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user