mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 09:27:59 +00:00
Experimental Rlogin support, thanks to Delian Delchev. Local flow
control is unsupported, and server-to-client comms may fail for want of working TCP Urgent. [originally from svn r875]
This commit is contained in:
parent
72cdcc611a
commit
ca90be26a8
3
Makefile
3
Makefile
@ -65,7 +65,7 @@ RES=res
|
||||
GOBJS1 = window.$(OBJ) windlg.$(OBJ) winctrls.$(OBJ) terminal.$(OBJ)
|
||||
GOBJS2 = xlat.$(OBJ) sizetip.$(OBJ)
|
||||
##-- objects putty puttytel plink
|
||||
LOBJS1 = telnet.$(OBJ) raw.$(OBJ) ldisc.$(OBJ) winnet.$(OBJ)
|
||||
LOBJS1 = telnet.$(OBJ) raw.$(OBJ) rlogin.$(OBJ) ldisc.$(OBJ) winnet.$(OBJ)
|
||||
##-- objects putty plink
|
||||
POBJS = be_all.$(OBJ)
|
||||
##-- objects puttytel
|
||||
@ -224,6 +224,7 @@ terminal.$(OBJ): terminal.c putty.h puttymem.h network.h
|
||||
sizetip.$(OBJ): sizetip.c putty.h puttymem.h network.h winstuff.h
|
||||
telnet.$(OBJ): telnet.c putty.h puttymem.h network.h
|
||||
raw.$(OBJ): raw.c putty.h puttymem.h network.h
|
||||
rlogin.$(OBJ): rlogin.c putty.h puttymem.h network.h
|
||||
xlat.$(OBJ): xlat.c putty.h puttymem.h network.h
|
||||
ldisc.$(OBJ): ldisc.c putty.h puttymem.h network.h
|
||||
misc.$(OBJ): misc.c putty.h puttymem.h network.h
|
||||
|
1
be_all.c
1
be_all.c
@ -10,6 +10,7 @@
|
||||
struct backend_list backends[] = {
|
||||
{PROT_SSH, "ssh", &ssh_backend},
|
||||
{PROT_TELNET, "telnet", &telnet_backend},
|
||||
{PROT_RLOGIN, "rlogin", &rlogin_backend},
|
||||
{PROT_RAW, "raw", &raw_backend},
|
||||
{0, NULL}
|
||||
};
|
||||
|
@ -11,6 +11,7 @@
|
||||
struct backend_list backends[] = {
|
||||
{PROT_SSH, "ssh", NULL},
|
||||
{PROT_TELNET, "telnet", NULL},
|
||||
{PROT_RLOGIN, "rlogin", NULL},
|
||||
{PROT_RAW, "raw", NULL},
|
||||
{0, NULL}
|
||||
};
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
struct backend_list backends[] = {
|
||||
{PROT_TELNET, "telnet", &telnet_backend},
|
||||
{PROT_RLOGIN, "rlogin", &rlogin_backend},
|
||||
{PROT_RAW, "raw", &raw_backend},
|
||||
{0, NULL}
|
||||
};
|
||||
|
@ -26,7 +26,7 @@ void sk_init(void); /* called once at program startup */
|
||||
SockAddr sk_namelookup(char *host, char **canonicalname);
|
||||
void sk_addr_free(SockAddr addr);
|
||||
|
||||
Socket sk_new(SockAddr addr, int port, sk_receiver_t receiver);
|
||||
Socket sk_new(SockAddr addr, int port, int privport, sk_receiver_t receiver);
|
||||
void sk_close(Socket s);
|
||||
void sk_write(Socket s, char *buf, int len);
|
||||
void sk_write_oob(Socket s, char *buf, int len);
|
||||
|
9
putty.h
9
putty.h
@ -137,7 +137,7 @@ typedef struct {
|
||||
/* Basic options */
|
||||
char host[512];
|
||||
int port;
|
||||
enum { PROT_RAW, PROT_TELNET, PROT_SSH } protocol;
|
||||
enum { PROT_RAW, PROT_TELNET, PROT_RLOGIN, PROT_SSH } protocol;
|
||||
int close_on_exit;
|
||||
int warn_on_close;
|
||||
int ping_interval; /* in seconds */
|
||||
@ -156,6 +156,7 @@ typedef struct {
|
||||
char termspeed[32];
|
||||
char environmt[1024]; /* VAR\tvalue\0VAR\tvalue\0\0 */
|
||||
char username[32];
|
||||
char localusername[32];
|
||||
int rfc_environ;
|
||||
/* Keyboard options */
|
||||
int bksp_is_delete;
|
||||
@ -333,6 +334,12 @@ void term_copyall(void);
|
||||
|
||||
extern Backend raw_backend;
|
||||
|
||||
/*
|
||||
* Exports from rlogin.c.
|
||||
*/
|
||||
|
||||
extern Backend rlogin_backend;
|
||||
|
||||
/*
|
||||
* Exports from telnet.c.
|
||||
*/
|
||||
|
2
raw.c
2
raw.c
@ -59,7 +59,7 @@ static char *raw_init (char *host, int port, char **realhost) {
|
||||
/*
|
||||
* Open socket.
|
||||
*/
|
||||
s = sk_new(addr, port, raw_receive);
|
||||
s = sk_new(addr, port, 0, raw_receive);
|
||||
if ( (err = sk_socket_error(s)) )
|
||||
return err;
|
||||
|
||||
|
149
rlogin.c
Normal file
149
rlogin.c
Normal file
@ -0,0 +1,149 @@
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "putty.h"
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
static Socket s = NULL;
|
||||
|
||||
static void rlogin_size(void);
|
||||
|
||||
static int sb_opt, sb_len;
|
||||
static char *sb_buf = NULL;
|
||||
static int sb_size = 0;
|
||||
#define SB_DELTA 1024
|
||||
|
||||
static void c_write (char *buf, int len) {
|
||||
from_backend(0, buf, len);
|
||||
}
|
||||
|
||||
static int rlogin_receive (Socket s, int urgent, char *data, int len) {
|
||||
if (!len) {
|
||||
/* Connection has closed. */
|
||||
sk_close(s);
|
||||
s = NULL;
|
||||
return 0;
|
||||
}
|
||||
if (urgent == 2) {
|
||||
char c;
|
||||
int i;
|
||||
|
||||
c = *data++; len--;
|
||||
if (c == 0x80)
|
||||
rlogin_size();
|
||||
/*
|
||||
* We should flush everything (aka Telnet SYNCH) if we see
|
||||
* 0x02, and we should turn off and on _local_ flow control
|
||||
* on 0x10 and 0x20 respectively. I'm not convinced it's
|
||||
* worth it...
|
||||
*/
|
||||
}
|
||||
c_write(data, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called to set up the rlogin connection.
|
||||
*
|
||||
* Returns an error message, or NULL on success.
|
||||
*
|
||||
* Also places the canonical host name into `realhost'.
|
||||
*/
|
||||
static char *rlogin_init (char *host, int port, char **realhost) {
|
||||
SockAddr addr;
|
||||
char *err;
|
||||
|
||||
/*
|
||||
* Try to find host.
|
||||
*/
|
||||
addr = sk_namelookup(host, realhost);
|
||||
if ( (err = sk_addr_error(addr)) )
|
||||
return err;
|
||||
|
||||
if (port < 0)
|
||||
port = 513; /* default rlogin port */
|
||||
|
||||
/*
|
||||
* Open socket.
|
||||
*/
|
||||
s = sk_new(addr, port, 1, rlogin_receive);
|
||||
if ( (err = sk_socket_error(s)) )
|
||||
return err;
|
||||
|
||||
sk_addr_free(addr);
|
||||
|
||||
/*
|
||||
* Send local username, remote username, terminal/speed
|
||||
*/
|
||||
|
||||
{
|
||||
char z = 0;
|
||||
char *p;
|
||||
sk_write(s, &z, 1);
|
||||
sk_write(s, cfg.localusername, strlen(cfg.localusername));
|
||||
sk_write(s, &z, 1);
|
||||
sk_write(s, cfg.username, strlen(cfg.username));
|
||||
sk_write(s, &z, 1);
|
||||
sk_write(s, cfg.termtype, strlen(cfg.termtype));
|
||||
sk_write(s, "/", 1);
|
||||
for(p = cfg.termspeed; isdigit(*p); p++);
|
||||
sk_write(s, cfg.termspeed, p - cfg.termspeed);
|
||||
sk_write(s, &z, 1);
|
||||
}
|
||||
|
||||
begin_session();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called to send data down the rlogin connection.
|
||||
*/
|
||||
static void rlogin_send (char *buf, int len) {
|
||||
|
||||
if (s == NULL)
|
||||
return;
|
||||
|
||||
sk_write(s, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Called to set the size of the window
|
||||
*/
|
||||
static void rlogin_size(void) {
|
||||
char b[12] = { 0xFF, 0xFF, 0x73, 0x73, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
b[6] = cols >> 8; b[7] = cols & 0xFF;
|
||||
b[4] = rows >> 8; b[5] = rows & 0xFF;
|
||||
sk_write(s, b, 12);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send rlogin special codes.
|
||||
*/
|
||||
static void rlogin_special (Telnet_Special code) {
|
||||
/* Do nothing! */
|
||||
return;
|
||||
}
|
||||
|
||||
static Socket rlogin_socket(void) { return s; }
|
||||
|
||||
static int rlogin_sendok(void) { return 1; }
|
||||
|
||||
Backend rlogin_backend = {
|
||||
rlogin_init,
|
||||
rlogin_send,
|
||||
rlogin_size,
|
||||
rlogin_special,
|
||||
rlogin_socket,
|
||||
rlogin_sendok,
|
||||
1
|
||||
};
|
@ -68,6 +68,7 @@ void save_settings (char *section, int do_host, Config *cfg) {
|
||||
write_setting_s (sesskey, "Environment", buf);
|
||||
}
|
||||
write_setting_s (sesskey, "UserName", cfg->username);
|
||||
write_setting_s (sesskey, "LocalUserName", cfg->localusername);
|
||||
write_setting_i (sesskey, "NoPTY", cfg->nopty);
|
||||
write_setting_i (sesskey, "Compression", cfg->compression);
|
||||
write_setting_i (sesskey, "AgentFwd", cfg->agentfwd);
|
||||
@ -199,6 +200,7 @@ void load_settings (char *section, int do_host, Config *cfg) {
|
||||
*q = '\0';
|
||||
}
|
||||
gpps (sesskey, "UserName", "", cfg->username, sizeof(cfg->username));
|
||||
gpps (sesskey, "LocalUserName", "", cfg->localusername, sizeof(cfg->localusername));
|
||||
gppi (sesskey, "NoPTY", 0, &cfg->nopty);
|
||||
gppi (sesskey, "Compression", 0, &cfg->compression);
|
||||
gppi (sesskey, "AgentFwd", 0, &cfg->agentfwd);
|
||||
|
2
ssh.c
2
ssh.c
@ -1184,7 +1184,7 @@ static char *connect_to_host(char *host, int port, char **realhost)
|
||||
/*
|
||||
* Open socket.
|
||||
*/
|
||||
s = sk_new(addr, port, ssh_receive);
|
||||
s = sk_new(addr, port, 0, ssh_receive);
|
||||
if ( (err = sk_socket_error(s)) )
|
||||
return err;
|
||||
|
||||
|
2
telnet.c
2
telnet.c
@ -495,7 +495,7 @@ static char *telnet_init (char *host, int port, char **realhost) {
|
||||
/*
|
||||
* Open socket.
|
||||
*/
|
||||
s = sk_new(addr, port, telnet_receive);
|
||||
s = sk_new(addr, port, 0, telnet_receive);
|
||||
if ( (err = sk_socket_error(s)) )
|
||||
return err;
|
||||
|
||||
|
66
windlg.c
66
windlg.c
@ -189,6 +189,7 @@ enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
|
||||
IDC_PROTSTATIC,
|
||||
IDC_PROTRAW,
|
||||
IDC_PROTTELNET,
|
||||
IDC_PROTRLOGIN,
|
||||
IDC_PROTSSH,
|
||||
IDC_SESSSTATIC,
|
||||
IDC_SESSEDIT,
|
||||
@ -317,6 +318,16 @@ enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TVSTATIC, IDCX_TREEVIEW, controlstartvalue,
|
||||
IDC_EMRFC,
|
||||
telnetpanelend,
|
||||
|
||||
rloginpanelstart,
|
||||
IDC_TITLE_RLOGIN,
|
||||
IDC_BOX_RLOGIN1, IDC_BOXT_RLOGIN1,
|
||||
IDC_BOX_RLOGIN2, IDC_BOXT_RLOGIN2,
|
||||
IDC_R_TSSTATIC,
|
||||
IDC_R_TSEDIT,
|
||||
IDC_RLLUSERSTATIC,
|
||||
IDC_RLLUSEREDIT,
|
||||
rloginpanelend,
|
||||
|
||||
sshpanelstart,
|
||||
IDC_TITLE_SSH,
|
||||
IDC_BOX_SSH1, IDC_BOXT_SSH1,
|
||||
@ -433,7 +444,8 @@ static void init_dlg_ctrls(HWND hwnd) {
|
||||
SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
|
||||
CheckRadioButton (hwnd, IDC_PROTRAW, IDC_PROTSSH,
|
||||
cfg.protocol==PROT_SSH ? IDC_PROTSSH :
|
||||
cfg.protocol==PROT_TELNET ? IDC_PROTTELNET : IDC_PROTRAW );
|
||||
cfg.protocol==PROT_TELNET ? IDC_PROTTELNET :
|
||||
cfg.protocol==PROT_RLOGIN ? IDC_PROTRLOGIN : IDC_PROTRAW );
|
||||
SetDlgItemInt (hwnd, IDC_PINGEDIT, cfg.ping_interval, FALSE);
|
||||
|
||||
CheckRadioButton (hwnd, IDC_DEL008, IDC_DEL127,
|
||||
@ -487,6 +499,8 @@ static void init_dlg_ctrls(HWND hwnd) {
|
||||
|
||||
SetDlgItemText (hwnd, IDC_TTEDIT, cfg.termtype);
|
||||
SetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed);
|
||||
SetDlgItemText (hwnd, IDC_R_TSEDIT, cfg.termspeed);
|
||||
SetDlgItemText (hwnd, IDC_RLLUSEREDIT, cfg.localusername);
|
||||
SetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username);
|
||||
SetDlgItemText (hwnd, IDC_LGFEDIT, cfg.logfilename);
|
||||
CheckRadioButton(hwnd, IDC_LSTATOFF, IDC_LSTATRAW,
|
||||
@ -693,13 +707,15 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
|
||||
"&Port", IDC_PORTSTATIC, IDC_PORT, 25, NULL);
|
||||
if (backends[2].backend == NULL) {
|
||||
/* this is PuTTYtel, so only two protocols available */
|
||||
radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
|
||||
"&Raw", IDC_PROTRAW,
|
||||
"&Telnet", IDC_PROTTELNET, NULL);
|
||||
} else {
|
||||
radioline(&cp, "Protocol:", IDC_PROTSTATIC, 3,
|
||||
radioline(&cp, "Protocol:", IDC_PROTSTATIC, 4,
|
||||
"&Raw", IDC_PROTRAW,
|
||||
"&Telnet", IDC_PROTTELNET,
|
||||
"R&login", IDC_PROTRLOGIN, NULL);
|
||||
} else {
|
||||
radioline(&cp, "Protocol:", IDC_PROTSTATIC, 4,
|
||||
"&Raw", IDC_PROTRAW,
|
||||
"&Telnet", IDC_PROTTELNET,
|
||||
"R&login", IDC_PROTRLOGIN,
|
||||
#ifdef FWHACK
|
||||
"SS&H/hack",
|
||||
#else
|
||||
@ -993,6 +1009,23 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The Rlogin Panel */
|
||||
{
|
||||
struct ctlpos cp;
|
||||
ctlposinit(&cp, hwnd, 80, 3, 13);
|
||||
if (dlgtype == 0) {
|
||||
bartitle(&cp, "Options controlling Rlogin connections", IDC_TITLE_RLOGIN);
|
||||
beginbox(&cp, "Data to send to the server",
|
||||
IDC_BOX_RLOGIN1, IDC_BOXT_RLOGIN1);
|
||||
staticedit(&cp, "Terminal-&speed string", IDC_R_TSSTATIC, IDC_R_TSEDIT, 50);
|
||||
staticedit(&cp, "&Local username:", IDC_RLLUSERSTATIC, IDC_RLLUSEREDIT, 50);
|
||||
endbox(&cp);
|
||||
|
||||
treeview_insert(&tvfaff, 1, "Rlogin");
|
||||
}
|
||||
}
|
||||
|
||||
/* The SSH panel. Accelerators used: [acgo] rmakwp123bd */
|
||||
if (backends[2].backend != NULL) {
|
||||
struct ctlpos cp;
|
||||
@ -1095,6 +1128,8 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
|
||||
hide(hwnd, FALSE, connectionpanelstart, connectionpanelend);
|
||||
if (!strcmp(buffer, "Telnet"))
|
||||
hide(hwnd, FALSE, telnetpanelstart, telnetpanelend);
|
||||
if (!strcmp(buffer, "Rlogin"))
|
||||
hide(hwnd, FALSE, rloginpanelstart, rloginpanelend);
|
||||
if (!strcmp(buffer, "SSH"))
|
||||
hide(hwnd, FALSE, sshpanelstart, sshpanelend);
|
||||
if (!strcmp(buffer, "Selection"))
|
||||
@ -1123,16 +1158,19 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
|
||||
EndDialog (hwnd, 0);
|
||||
return 0;
|
||||
case IDC_PROTTELNET:
|
||||
case IDC_PROTRLOGIN:
|
||||
case IDC_PROTSSH:
|
||||
case IDC_PROTRAW:
|
||||
if (HIWORD(wParam) == BN_CLICKED ||
|
||||
HIWORD(wParam) == BN_DOUBLECLICKED) {
|
||||
int i = IsDlgButtonChecked (hwnd, IDC_PROTSSH);
|
||||
int j = IsDlgButtonChecked (hwnd, IDC_PROTTELNET);
|
||||
cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : PROT_RAW ;
|
||||
if ((cfg.protocol == PROT_SSH && cfg.port == 23) ||
|
||||
(cfg.protocol == PROT_TELNET && cfg.port == 22)) {
|
||||
cfg.port = i ? 22 : 23;
|
||||
int k = IsDlgButtonChecked (hwnd, IDC_PROTRLOGIN);
|
||||
cfg.protocol = i ? PROT_SSH : j ? PROT_TELNET : k ? PROT_RLOGIN : PROT_RAW ;
|
||||
if ((cfg.protocol == PROT_SSH && cfg.port != 22) ||
|
||||
(cfg.protocol == PROT_TELNET && cfg.port != 23) ||
|
||||
(cfg.protocol == PROT_RLOGIN && cfg.port != 513)) {
|
||||
cfg.port = i ? 22 : j ? 23 : 513;
|
||||
SetDlgItemInt (hwnd, IDC_PORT, cfg.port, FALSE);
|
||||
}
|
||||
}
|
||||
@ -1517,8 +1555,9 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
|
||||
}
|
||||
break;
|
||||
case IDC_TSEDIT:
|
||||
case IDC_R_TSEDIT:
|
||||
if (HIWORD(wParam) == EN_CHANGE)
|
||||
GetDlgItemText (hwnd, IDC_TSEDIT, cfg.termspeed,
|
||||
GetDlgItemText (hwnd, LOWORD(wParam), cfg.termspeed,
|
||||
sizeof(cfg.termspeed)-1);
|
||||
break;
|
||||
case IDC_LOGEDIT:
|
||||
@ -1526,6 +1565,11 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg,
|
||||
GetDlgItemText (hwnd, IDC_LOGEDIT, cfg.username,
|
||||
sizeof(cfg.username)-1);
|
||||
break;
|
||||
case IDC_RLLUSEREDIT:
|
||||
if (HIWORD(wParam) == EN_CHANGE)
|
||||
GetDlgItemText (hwnd, IDC_RLLUSEREDIT, cfg.localusername,
|
||||
sizeof(cfg.localusername)-1);
|
||||
break;
|
||||
case IDC_EMBSD:
|
||||
case IDC_EMRFC:
|
||||
cfg.rfc_environ = IsDlgButtonChecked (hwnd, IDC_EMRFC);
|
||||
|
67
winnet.c
67
winnet.c
@ -288,7 +288,7 @@ void sk_addr_free(SockAddr addr) {
|
||||
sfree(addr);
|
||||
}
|
||||
|
||||
Socket sk_new(SockAddr addr, int port, sk_receiver_t receiver) {
|
||||
Socket sk_new(SockAddr addr, int port, int privport, sk_receiver_t receiver) {
|
||||
SOCKET s;
|
||||
#ifdef IPV6
|
||||
SOCKADDR_IN6 a6;
|
||||
@ -298,6 +298,7 @@ Socket sk_new(SockAddr addr, int port, sk_receiver_t receiver) {
|
||||
char *errstr;
|
||||
Socket ret;
|
||||
extern char *do_select(SOCKET skt, int startup);
|
||||
short localport;
|
||||
|
||||
/*
|
||||
* Create Socket structure.
|
||||
@ -325,28 +326,56 @@ Socket sk_new(SockAddr addr, int port, sk_receiver_t receiver) {
|
||||
/*
|
||||
* Bind to local address.
|
||||
*/
|
||||
#ifdef IPV6
|
||||
if (addr->family == AF_INET6)
|
||||
{
|
||||
memset(&a6,0,sizeof(a6));
|
||||
a6.sin6_family = AF_INET6;
|
||||
/*a6.sin6_addr = in6addr_any;*/ /* == 0 */
|
||||
a6.sin6_port = htons(0);
|
||||
}
|
||||
if (privport)
|
||||
localport = 1023; /* count from 1023 downwards */
|
||||
else
|
||||
{
|
||||
#endif
|
||||
a.sin_family = AF_INET;
|
||||
a.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
a.sin_port = htons(0);
|
||||
localport = 0; /* just use port 0 (ie winsock picks) */
|
||||
|
||||
/* Loop round trying to bind */
|
||||
while (1) {
|
||||
int retcode;
|
||||
|
||||
#ifdef IPV6
|
||||
}
|
||||
if (bind (s, (addr->family == AF_INET6) ? (struct sockaddr *)&a6 : (struct sockaddr *)&a, (addr->family == AF_INET6) ? sizeof(a6) : sizeof(a)) == SOCKET_ERROR)
|
||||
#else
|
||||
if (bind (s, (struct sockaddr *)&a, sizeof(a)) == SOCKET_ERROR)
|
||||
if (addr->family == AF_INET6)
|
||||
{
|
||||
memset(&a6,0,sizeof(a6));
|
||||
a6.sin6_family = AF_INET6;
|
||||
/*a6.sin6_addr = in6addr_any;*/ /* == 0 */
|
||||
a6.sin6_port = htons(localport);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif
|
||||
a.sin_family = AF_INET;
|
||||
a.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
a.sin_port = htons(localport);
|
||||
#ifdef IPV6
|
||||
}
|
||||
retcode = bind (s, (addr->family == AF_INET6 ?
|
||||
(struct sockaddr *)&a6 :
|
||||
(struct sockaddr *)&a),
|
||||
(addr->family == AF_INET6 ? sizeof(a6) : sizeof(a)));
|
||||
#else
|
||||
retcode = bind (s, (struct sockaddr *)&a, sizeof(a));
|
||||
#endif
|
||||
if (retcode != SOCKET_ERROR) {
|
||||
err = 0;
|
||||
break; /* done */
|
||||
} else {
|
||||
err = WSAGetLastError();
|
||||
if (err != WSAEADDRINUSE) /* failed, for a bad reason */
|
||||
break;
|
||||
}
|
||||
|
||||
if (localport == 0)
|
||||
break; /* we're only looping once */
|
||||
localport--;
|
||||
if (localport == 0)
|
||||
break; /* we might have got to the end */
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
err = WSAGetLastError();
|
||||
ret->error = winsock_error_string(err);
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user